pax_global_header00006660000000000000000000000064132562070110014507gustar00rootroot0000000000000052 comment=5c95315ffbaf6f64bd3a2970a001ecce51c10032 jackson-databind-jackson-databind-2.9.5/000077500000000000000000000000001325620701100201125ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/.gitattributes000066400000000000000000000003311325620701100230020ustar00rootroot00000000000000# Do not merge `pom.xml` from older version, as it will typically conflict # # note: also need: # git config --global merge.ours.driver true # (and if ever need to disable change `true` to `false` pom.xml merge=ours jackson-databind-jackson-databind-2.9.5/.github/000077500000000000000000000000001325620701100214525ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/.github/ISSUE_TEMPLATE.md000066400000000000000000000016421325620701100241620ustar00rootroot00000000000000We appreciate issues as very valuable contributions, but just to make sure here are things that are important to do before filing an issue: * Only report issues (and perhaps request new features, FEATURE):,Usage Questions should be asked on [Jackson-users](https://groups.google.com/forum/#!search/jackson-users) list -- you are more likely to get help that way (and we will promptly close questions-as-issues) * Check to see if this issue has already been reported (quick glance at existing issues): no deep search necessary, just quick sanity check * Include version information for Jackson version you use * (optional but highly recommended) Verify that the problem occurs with the latest patch of same minor version; and even better, if possible, try using the latest stable patch version * For example: if you observe an issue with version `2.4.1`, first upgrade to `2.4.6` to ensure problem has not already been fixed. jackson-databind-jackson-databind-2.9.5/.gitignore000066400000000000000000000002541325620701100221030ustar00rootroot00000000000000# use glob syntax. syntax: glob *.class *~ *.bak *.off *.old .DS_Store # building target # Eclipse .classpath .project .settings # IDEA .idea *.iml *.ipr *.iws /target jackson-databind-jackson-databind-2.9.5/.travis.yml000066400000000000000000000017201325620701100222230ustar00rootroot00000000000000language: java # Since Jackson 2.7, build requires jdk7, although module itself works on jdk6 still (for now) jdk: - openjdk7 - openjdk8 # Below this line is configuration for deploying to the Sonatype OSS repo # http://blog.xeiam.com/2013/05/configure-travis-ci-to-deploy-snapshots.html before_install: "git clone -b travis `git config --get remote.origin.url` target/travis" after_success: - "mvn source:jar javadoc:jar deploy --settings target/travis/settings.xml" - "mvn -B cobertura:cobertura coveralls:report" # whitelist branches: only: - master - "2.9" env: global: - secure: "ZIFMeNzZCvLYWICiUyHFSm8Ypz6lYFbF/+LGz6a+Sh8B9tSnvYvlrE4gSFJj3NzRWY0RG/vizoyFEpVgxOnzXDMLuuy/dreupnHR1FfVmiaiceK4JHRwAzl0lQzr2hdVwJbqpX0GfrxKmbg8Jvv9WPKtfM6X4167ElVj4O/8IRc=" - secure: "VOC/J8eFbM2OeysBp0Gx0G73MySRATCoN7hc9Ok0kJXE/dbE/2KOoFlTwwxUgErwJXkjJKKXafYcbq/22S7wkaoDW5XAvplSu3skxdE0NRGVzozcDMXO5UoGlt9Ti4XIBMCvy7bB/NO+J5IgNedCtcNnBsrGZCdodW3DTYtqQLs=" jackson-databind-jackson-databind-2.9.5/README.md000066400000000000000000000427541325620701100214050ustar00rootroot00000000000000# Overview This project contains the general-purpose data-binding functionality and tree-model for [Jackson Data Processor](http://wiki.fasterxml.com/JacksonHome). It builds on [core streaming parser/generator](../../../jackson-core) package, and uses [Jackson Annotations](../../../jackson-annotations) for configuration. Project is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0). While the original use case for Jackson was JSON data-binding, it can now be used for other data formats as well, as long as parser and generator implementations exist. Naming of classes uses word 'JSON' in many places even though there is no actual hard dependency to JSON format. [![Build Status](https://travis-ci.org/FasterXML/jackson-databind.svg?branch=master)](https://travis-ci.org/FasterXML/jackson-databind) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.fasterxml.jackson.core/jackson-databind/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.fasterxml.jackson.core/jackson-databind) [![Javadoc](https://javadoc-emblem.rhcloud.com/doc/com.fasterxml.jackson.core/jackson-databind/badge.svg)](http://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind) [![Coverage Status](https://coveralls.io/repos/github/FasterXML/jackson-databind/badge.svg?branch=master)](https://coveralls.io/github/FasterXML/jackson-databind?branch=master) ----- # Get it! ## Maven Functionality of this package is contained in Java package `com.fasterxml.jackson.databind`, and can be used using following Maven dependency: ```xml ... 2.9.0 ... ... com.fasterxml.jackson.core jackson-databind ${jackson.version} ... ``` Since package also depends on `jackson-core` and `jackson-annotations` packages, you will need to download these if not using Maven; and you may also want to add them as Maven dependency to ensure that compatible versions are used. If so, also add: ```xml ... com.fasterxml.jackson.core jackson-annotations ${jackson.version} com.fasterxml.jackson.core jackson-core ${jackson.version} ... ``` but note that this is optional, and only necessary if there are conflicts between jackson core dependencies through transitive dependencies. ## Non-Maven For non-Maven use cases, you download jars from [Central Maven repository](http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/). Databind jar is also a functional OSGi bundle, with proper import/export declarations, so it can be use on OSGi container as is. ----- # Use It! More comprehensive documentation can be found from [Jackson-docs](../../../jackson-docs) repository; as well as from [Wiki](../../wiki) of this project. But here are brief introductionary tutorials, in recommended order of reading. ## 1 minute tutorial: POJOs to JSON and back The most common usage is to take piece of JSON, and construct a Plain Old Java Object ("POJO") out of it. So let's start there. With simple 2-property POJO like this: ```java // Note: can use getters/setters as well; here we just use public fields directly: public class MyValue { public String name; public int age; // NOTE: if using getters/setters, can keep fields `protected` or `private` } ``` we will need a `com.fasterxml.jackson.databind.ObjectMapper` instance, used for all data-binding, so let's construct one: ```java ObjectMapper mapper = new ObjectMapper(); // create once, reuse ``` The default instance is fine for our use -- we will learn later on how to configure mapper instance if necessary. Usage is simple: ```java MyValue value = mapper.readValue(new File("data.json"), MyValue.class); // or: value = mapper.readValue(new URL("http://some.com/api/entry.json"), MyValue.class); // or: value = mapper.readValue("{\"name\":\"Bob\", \"age\":13}", MyValue.class); ``` And if we want to write JSON, we do the reverse: ```java mapper.writeValue(new File("result.json"), myResultObject); // or: byte[] jsonBytes = mapper.writeValueAsBytes(myResultObject); // or: String jsonString = mapper.writeValueAsString(myResultObject); ``` So far so good? ## 3 minute tutorial: Generic collections, Tree Model Beyond dealing with simple Bean-style POJOs, you can also handle JDK `List`s, `Map`s: ```java Map scoreByName = mapper.readValue(jsonSource, Map.class); List names = mapper.readValue(jsonSource, List.class); // and can obviously write out as well mapper.writeValue(new File("names.json"), names); ``` as long as JSON structure matches, and types are simple. If you have POJO values, you need to indicate actual type (note: this is NOT needed for POJO properties with `List` etc types): ```java Map results = mapper.readValue(jsonSource, new TypeReference>() { } ); // why extra work? Java Type Erasure will prevent type detection otherwise ``` (note: no extra effort needed for serialization, regardless of generic types) But wait! There is more! While dealing with `Map`s, `List`s and other "simple" Object types (Strings, Numbers, Booleans) can be simple, Object traversal can be cumbersome. This is where Jackson's [Tree model](https://github.com/FasterXML/jackson-databind/wiki/JacksonTreeModel) can come in handy: ```java // can be read as generic JsonNode, if it can be Object or Array; or, // if known to be Object, as ObjectNode, if array, ArrayNode etc: ObjectNode root = mapper.readTree("stuff.json"); String name = root.get("name").asText(); int age = root.get("age").asInt(); // can modify as well: this adds child Object as property 'other', set property 'type' root.with("other").put("type", "student"); String json = mapper.writeValueAsString(root); // with above, we end up with something like as 'json' String: // { // "name" : "Bob", "age" : 13, // "other" : { // "type" : "student" // } // } ``` Tree Model can be more convenient than data-binding, especially in cases where structure is highly dynamic, or does not map nicely to Java classes. ## 5 minute tutorial: Streaming parser, generator As convenient as data-binding (to/from POJOs) can be; and as flexible as Tree model can be, there is one more canonical processing model available: incremental (aka "streaming") model. It is the underlying processing model that data-binding and Tree Model both build upon, but it is also exposed to users who want ultimate performance and/or control over parsing or generation details. For in-depth explanation, look at [Jackson Core component](https://github.com/FasterXML/jackson-core). But let's look at a simple teaser to whet your appetite. ```java JsonFactory f = mapper.getFactory(); // may alternatively construct directly too // First: write simple JSON output File jsonFile = new JsonFile("test.json"); JsonGenerator g = f.createGenerator(jsonFile); // write JSON: { "message" : "Hello world!" } g.writeStartObject(); g.writeStringField("message", "Hello world!"); g.writeEndObject(); g.close(); // Second: read file back JsonParser p = f.createParser(jsonFile); JsonToken t = p.nextToken(); // Should be JsonToken.START_OBJECT t = p.nextToken(); // JsonToken.FIELD_NAME if ((t != JsonToken.FIELD_NAME) || !"message".equals(p.getCurrentName())) { // handle error } t = p.nextToken(); if (t != JsonToken.VALUE_STRING) { // similarly } String msg = p.getText(); System.out.printf("My message to you is: %s!\n", msg); p.close(); ``` ## 10 minute tutorial: configuration There are two entry-level configuration mechanisms you are likely to use: [Features](https://github.com/FasterXML/jackson-databind/wiki/JacksonFeatures) and [Annotations](https://github.com/FasterXML/jackson-annotations). ### Commonly used Features Here are examples of configuration features that you are most likely to need to know about. Let's start with higher-level data-binding configuration. ```java // SerializationFeature for changing how JSON is written // to enable standard indentation ("pretty-printing"): mapper.enable(SerializationFeature.INDENT_OUTPUT); // to allow serialization of "empty" POJOs (no properties to serialize) // (without this setting, an exception is thrown in those cases) mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); // to write java.util.Date, Calendar as number (timestamp): mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // DeserializationFeature for changing how JSON is read as POJOs: // to prevent exception when encountering unknown property: mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); // to allow coercion of JSON empty String ("") to null Object value: mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); ``` In addition, you may need to change some of low-level JSON parsing, generation details: ```java // JsonParser.Feature for configuring parsing settings: // to allow C/C++ style comments in JSON (non-standard, disabled by default) // (note: with Jackson 2.5, there is also `mapper.enable(feature)` / `mapper.disable(feature)`) mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); // to allow (non-standard) unquoted field names in JSON: mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); // to allow use of apostrophes (single quotes), non standard mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); // JsonGenerator.Feature for configuring low-level JSON generation: // to force escaping of non-ASCII characters: mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true); ``` Full set of features are explained on [Jackson Features](https://github.com/FasterXML/jackson-databind/wiki/JacksonFeatures) page. ### Annotations: changing property names The simplest annotation-based approach is to use `@JsonProperty` annotation like so: ```java public class MyBean { private String _name; // without annotation, we'd get "theName", but we want "name": @JsonProperty("name") public String getTheName() { return _name; } // note: it is enough to add annotation on just getter OR setter; // so we can omit it here public void setTheName(String n) { _name = n; } } ``` There are other mechanisms to use for systematic naming changes: see [Custom Naming Convention](https://github.com/FasterXML/jackson-databind/wiki/JacksonCustomNamingConvention) for details. Note, too, that you can use [Mix-in Annotations](https://github.com/FasterXML/jackson-databind/wiki/JacksonMixinAnnotations) to associate all annotations. ### Annotations: Ignoring properties There are two main annotations that can be used to to ignore properties: `@JsonIgnore` for individual properties; and `@JsonIgnoreProperties` for per-class definition ```java // means that if we see "foo" or "bar" in JSON, they will be quietly skipped // regardless of whether POJO has such properties @JsonIgnoreProperties({ "foo", "bar" }) public class MyBean { // will not be written as JSON; nor assigned from JSON: @JsonIgnore public String internal; // no annotation, public field is read/written normally public String external; @JsonIgnore public void setCode(int c) { _code = c; } // note: will also be ignored because setter has annotation! public int getCode() { return _code; } } ``` As with renaming, note that annotations are "shared" between matching fields, getters and setters: if only one has `@JsonIgnore`, it affects others. But it is also possible to use "split" annotations, to for example: ```java public class ReadButDontWriteProps { private String _name; @JsonProperty public void setName(String n) { _name = n; } @JsonIgnore public String getName() { return _name; } } ``` in this case, no "name" property would be written out (since 'getter' is ignored); but if "name" property was found from JSON, it would be assigned to POJO property! For a more complete explanation of all possible ways of ignoring properties when writing out JSON, check ["Filtering properties"](http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html) article. ### Annotations: using custom constructor Unlike many other data-binding packages, Jackson does not require you to define "default constructor" (constructor that does not take arguments). While it will use one if nothing else is available, you can easily define that an argument-taking constructor is used: ```java public class CtorBean { public final String name; public final int age; @JsonCreator // constructor can be public, private, whatever private CtorBean(@JsonProperty("name") String name, @JsonProperty("age") int age) { this.name = name; this.age = age; } } ``` Constructors are especially useful in supporting use of [Immutable objects](http://www.cowtowncoder.com/blog/archives/2010/08/entry_409.html). Alternatively, you can also define "factory methods": ```java public class FactoryBean { // fields etc omitted for brewity @JsonCreator public static FactoryBean create(@JsonProperty("name") String name) { // construct and return an instance } } ``` Note that use of a "creator method" (`@JsonCreator` with `@JsonProperty` annotated arguments) does not preclude use of setters: you can mix and match properties from constructor/factory method with ones that are set via setters or directly using fields. ## Tutorial: fancier stuff, conversions One useful (but not very widely known) feature of Jackson is its ability to do arbitrary POJO-to-POJO conversions. Conceptually you can think of conversions as sequence of 2 steps: first, writing a POJO as JSON, and second, binding that JSON into another kind of POJO. Implementation just skips actual generation of JSON, and uses more efficient intermediate representation. Conversions work between any compatible types, and invocation is as simple as: ```java ResultType result = mapper.convertValue(sourceObject, ResultType.class); ``` and as long as source and result types are compatible -- that is, if to-JSON, from-JSON sequence would succeed -- things will "just work". But here are couple of potentially useful use cases: ```java // Convert from List to int[] List sourceList = ...; int[] ints = mapper.convertValue(sourceList, int[].class); // Convert a POJO into Map! Map propertyMap = mapper.convertValue(pojoValue, Map.class); // ... and back PojoType pojo = mapper.convertValue(propertyMap, PojoType.class); // decode Base64! (default byte[] representation is base64-encoded String) String base64 = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"; byte[] binary = mapper.convertValue(base64, byte[].class); ``` Basically, Jackson can work as a replacement for many Apache Commons components, for tasks like base64 encoding/decoding, and handling of "dyna beans" (Maps to/from POJOs). # Contribute! We would love to get your contribution, whether it's in form of bug reports, Requests for Enhancement (RFE), documentation, or code patches. The primary mechanism for all of above is [GitHub Issues system](https://github.com/FasterXML/jackson-databind/issues). ## Basic rules for Code Contributions There is really just one main rule, which is that to accept any code contribution, we need to get a filled Contributor License Agreement (CLA) from the author. One CLA is enough for any number of contributions, but we need one. Or, rather, companies that use our code want it. It keeps their lawyers less unhappy about Open Source usage. ## Limitation on Dependencies by Core Components One additional limitation exists for so-called core components (streaming api, jackson-annotations and jackson-databind): no additional dependendies are allowed beyond: * Core components may rely on any methods included in the supported JDK * Minimum JDK version is 1.6 as of Jackson 2.4 and above (1.5 was baseline with 2.3 and earlier) * Jackson-databind (this package) depends on the other two (annotations, streaming). This means that anything that has to rely on additional APIs or libraries needs to be built as an extension, usually a Jackson module. ----- # Differences from Jackson 1.x Project contains versions 2.0 and above: source code for earlier (1.x) versions was available from [Codehaus](http://jackson.codehaus.org) SVN repository, but due to Codehaus closure is currently (July 2015) not officially available. We may try to create Jackson1x repository at Github in future (if you care about this, ping Jackson team via mailing lists, or file an issue for this project). Main differences compared to 1.0 "mapper" jar are: * Maven build instead of Ant * Java package is now `com.fasterxml.jackson.databind` (instead of `org.codehaus.jackson.map`) ----- # Further reading * [Overall Jackson Docs](../../../jackson-docs) * [Project wiki page](https://github.com/FasterXML/jackson-databind/wiki) Related: * [Core annotations](https://github.com/FasterXML/jackson-annotations) package defines annotations commonly used for configuring databinding details * [Core parser/generator](https://github.com/FasterXML/jackson-core) package defines low-level incremental/streaming parsers, generators * [Jackson Project Home](http://wiki.fasterxml.com/JacksonHome) has additional documentation (although much of it for Jackson 1.x) jackson-databind-jackson-databind-2.9.5/attic/000077500000000000000000000000001325620701100212165ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/attic/ContainerBuilder.java000066400000000000000000000151441325620701100253170ustar00rootroot00000000000000package com.fasterxml.jackson.databind.util; import java.lang.reflect.Array; import java.util.*; /** * Helper class used for constructing "untyped" {@link java.util.List}, * {@link java.util.Map} and Object[] values. * Could help performance if a single instance can be used for building * nested Maps, Lists/Object[] of relatively small size. * Whether use makes sense depends; currently this class is not used. */ public final class ContainerBuilder { private final static int MAX_BUF = 1000; /** * Buffer in which contents are being buffered (except for cases where * size has grown too big to bother with separate buffer) */ private Object[] b; /** * Pointer to the next available slot in temporary buffer. */ private int tail; /** * When building potentially multiple containers, we need to keep track of * the starting pointer for the current container. */ private int start; /** * In cases where size of buffered contents has grown big enough that buffering * does not make sense, an actual {@link java.util.List} will be constructed * earlier and used instead of buffering. */ private List list; /** * Similar to list, we may sometimes eagerly construct result * {@link java.util.Map} and skip actual buffering. */ private Map map; public ContainerBuilder(int bufSize) { b = new Object[bufSize & ~1]; } public boolean canReuse() { return (list == null) && (map == null); } public int bufferLength() { return b.length; } /* /********************************************************** /* Public API /********************************************************** */ public int start() { if (list != null || map != null) { throw new IllegalStateException(); } final int prevStart = start; start = tail; return prevStart; } public int startList(Object value) { if (list != null || map != null) { throw new IllegalStateException(); } final int prevStart = start; start = tail; add(value); return prevStart; } public int startMap(String key, Object value) { if (list != null || map != null) { throw new IllegalStateException(); } final int prevStart = start; start = tail; put(key, value); return prevStart; } public void add(Object value) { if (list != null) { list.add(value); } else if (tail >= b.length) { _expandList(value); } else { b[tail++] = value; } } public void put(String key, Object value) { if (map != null) { map.put(key, value); } else if ((tail + 2) > b.length) { _expandMap(key, value); } else { b[tail++] = key; b[tail++] = value; } } public List finishList(int prevStart) { List l = list; if (l == null) { l = _buildList(true); } else { list = null; } start = prevStart; return l; } public Object[] finishArray(int prevStart) { Object[] result; if (list == null) { result = Arrays.copyOfRange(b, start, tail); } else { result = list.toArray(new Object[tail - start]); list = null; } start = prevStart; return result; } public Object[] finishArray(int prevStart, Class elemType) { final int size = tail-start; @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(elemType, size); if (list == null) { System.arraycopy(b, start, result, 0, size); } else { result = list.toArray(result); list = null; } start = prevStart; return result; } public Map finishMap(int prevStart) { Map m = map; if (m == null) { m = _buildMap(true); } else { map = null; } start = prevStart; return m; } /* /********************************************************** /* Internal methods /********************************************************** */ private void _expandList(Object value) { if (b.length < MAX_BUF) { // can still expand b = Arrays.copyOf(b, b.length << 1); b[tail++] = value; } else { list = _buildList(false); list.add(value); } } private List _buildList(boolean isComplete) { int currLen = tail - start; if (isComplete) { if (currLen < 2) { currLen = 2; } } else { if (currLen < 20) { currLen = 20; } else if (currLen < MAX_BUF) { currLen += (currLen>>1); } else { currLen += (currLen>>2); } } List l = new ArrayList(currLen); for (int i = start; i < tail; ++i) { l.add(b[i]); } tail = start; // reset buffered entries return l; } private void _expandMap(String key, Object value) { if (b.length < MAX_BUF) { // can still expand b = Arrays.copyOf(b, b.length << 1); b[tail++] = key; b[tail++] = value; } else { map = _buildMap(false); map.put(key, value); } } private Map _buildMap(boolean isComplete) { int size = (tail - start) >> 1; if (isComplete) { // when complete, optimize to smallest size if (size <= 3) { // 3 or fewer entries, hash table of 4 size = 4; } else if (size <= 40) { size += (size>>1); } else { size += (size>>2) + (size>>4); // * 1.3125 } } else { if (size < 10) { size = 16; } else if (size < MAX_BUF) { size += (size>>1); } else { size += (size/3); } } Map m = new LinkedHashMap(size, 0.8f); for (int i = start; i < tail; i += 2) { m.put((String) b[i], b[i+1]); } tail = start; // reset buffered entries return m; } } jackson-databind-jackson-databind-2.9.5/attic/MappingIteratorDeserializer.java000066400000000000000000000030321325620701100275270ustar00rootroot00000000000000package com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; public class MappingIteratorDeserializer extends StdDeserializer> implements ContextualDeserializer { private static final long serialVersionUID = 1L; protected final JavaType _valueType; protected final JsonDeserializer _valueDeserializer; public MappingIteratorDeserializer(JavaType valueType) { this(valueType, null); } protected MappingIteratorDeserializer(JavaType valueType, JsonDeserializer vdeser) { super(MappingIterator.class); _valueType = valueType; _valueDeserializer = vdeser; } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty prop) throws JsonMappingException { JsonDeserializer deser = ctxt.findContextualValueDeserializer(_valueType, prop); return (deser == _valueDeserializer) ? this : new MappingIteratorDeserializer(_valueType, deser); } @Override public MappingIterator deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { MappingIterator mit = new MappingIterator(_valueType, p, ctxt, _valueDeserializer, false, null); return mit; } } jackson-databind-jackson-databind-2.9.5/attic/README.md000066400000000000000000000002551325620701100224770ustar00rootroot00000000000000Place where formerly used code is moved if it seems possible (or perhaps even likely) it might be reused at some point. Or, for some experimental code that isn't yet used. jackson-databind-jackson-databind-2.9.5/attic/TypeBindings.java000066400000000000000000000271651325620701100244730ustar00rootroot00000000000000package com.fasterxml.jackson.databind.type; import java.lang.reflect.*; import java.util.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Helper class used for resolving type parameters for given class */ public class TypeBindings { private final static JavaType[] NO_TYPES = new JavaType[0]; /** * Marker to use for (temporarily) unbound references. */ public final static JavaType UNBOUND = new SimpleType(Object.class); /** * Factory to use for constructing resolved related types. */ protected final TypeFactory _typeFactory; /** * @since 2.7 */ protected final ClassStack _classStack; /** * Context type used for resolving all types, if specified. May be null, * in which case {@link #_contextClass} is used instead. */ protected final JavaType _contextType; /** * Specific class to use for resolving all types, for methods and fields * class and its superclasses and -interfaces contain. */ protected final Class _contextClass; /** * Lazily-instantiated bindings of resolved type parameters */ protected Map _bindings; /** * Also: we may temporarily want to mark certain named types * as resolved (but without exact type); if so, we'll just store * names here. */ protected HashSet _placeholders; /** * Sometimes it is necessary to allow hierarchic resolution of types: specifically * in cases where there are local bindings (for methods, constructors). If so, * we'll just use simple delegation model. */ private final TypeBindings _parentBindings; /* /********************************************************** /* Construction /********************************************************** */ public TypeBindings(TypeFactory typeFactory, ClassStack stack, Class cc) { this(typeFactory, null, stack, cc, null); } public TypeBindings(TypeFactory typeFactory, ClassStack stack, JavaType type) { this(typeFactory, null, stack, type.getRawClass(), type); } /** * Constructor used to create "child" instances; mostly to * allow delegation from explicitly defined local overrides * (local type variables for methods, constructors) to * contextual (class-defined) ones. */ public TypeBindings childInstance() { return new TypeBindings(_typeFactory, this, _classStack, _contextClass, _contextType); } private TypeBindings(TypeFactory tf, TypeBindings parent, ClassStack stack, Class cc, JavaType type) { _typeFactory = tf; _parentBindings = parent; _classStack = stack; _contextClass = cc; _contextType = type; } /* /********************************************************** /* Pass-through type resolution methods /********************************************************** */ public JavaType resolveType(Class cls) { return _typeFactory._constructType(_classStack, cls, this); } public JavaType resolveType(Type type) { return _typeFactory._constructType(_classStack, type, this); } /* /********************************************************** /* Accesors /********************************************************** */ public JavaType findType(String name, boolean mustFind) { if (_bindings == null) { _resolve(); } JavaType t = _bindings.get(name); if (t != null) { return t; } if (_placeholders != null && _placeholders.contains(name)) { return UNBOUND; } if (_parentBindings != null) { return _parentBindings.findType(name, mustFind); } // nothing found, so... // Should we throw an exception or just return null? /* 18-Feb-2011, tatu: There are some tricky type bindings within * java.util, such as HashMap$KeySet; so let's punt the problem * (honestly not sure what to do -- they are unbound for good, I think) */ if (_contextClass != null) { if (ClassUtil.getEnclosingClass(_contextClass) != null) { // [JACKSON-572]: Actually, let's skip this for all non-static inner classes // (which will also cover 'java.util' type cases... if (!Modifier.isStatic(_contextClass.getModifiers())) { return UNBOUND; } } } if (!mustFind) { return null; } String className; if (_contextClass != null) { className = _contextClass.getName(); } else if (_contextType != null) { className = _contextType.toString(); } else { className = "UNKNOWN"; } throw new IllegalArgumentException("Type variable '"+name +"' can not be resolved (with context of class "+className+")"); //t = UNBOUND; } public void addBinding(String name, JavaType type) { // note: emptyMap() is unmodifiable, hence second check is needed: if (_bindings == null || _bindings.size() == 0) { _bindings = new LinkedHashMap(); } _bindings.put(name, type); } public JavaType[] typesAsArray() { if (_bindings == null) { _resolve(); } if (_bindings.size() == 0) { return NO_TYPES; } return _bindings.values().toArray(new JavaType[_bindings.size()]); } /* /********************************************************** /* Internal methods /********************************************************** */ // Only for tests! protected int getBindingCount() { if (_bindings == null) { _resolve(); } return _bindings.size(); } protected void _resolve() { _resolveBindings(_contextClass); // finally: may have root level type info too if (_contextType != null) { int count = _contextType.containedTypeCount(); if (count > 0) { for (int i = 0; i < count; ++i) { String name = _contextType.containedTypeName(i); JavaType type = _contextType.containedType(i); addBinding(name, type); } } } // nothing bound? mark with empty map to prevent further calls if (_bindings == null) { _bindings = Collections.emptyMap(); } } public void _addPlaceholder(String name) { if (_placeholders == null) { _placeholders = new HashSet(); } _placeholders.add(name); } protected void _resolveBindings(Type t) { if (t == null) return; Class raw; if (t instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) t; Type[] args = pt.getActualTypeArguments(); if (args != null && args.length > 0) { Class rawType = (Class) pt.getRawType(); TypeVariable[] vars = rawType.getTypeParameters(); if (vars.length != args.length) { throw new IllegalArgumentException("Strange parametrized type (in class "+rawType.getName()+"): number of type arguments != number of type parameters ("+args.length+" vs "+vars.length+")"); } for (int i = 0, len = args.length; i < len; ++i) { TypeVariable var = vars[i]; String name = var.getName(); if (_bindings == null) { _bindings = new LinkedHashMap(); } else { // 24-Mar-2010, tatu: Better ensure that we do not overwrite something // collected earlier (since we descend towards super-classes): if (_bindings.containsKey(name)) continue; } // first: add a placeholder to prevent infinite loops _addPlaceholder(name); // then resolve type _bindings.put(name, _typeFactory._constructType(_classStack, args[i], this)); } } raw = (Class)pt.getRawType(); } else if (t instanceof Class) { raw = (Class) t; /* [JACKSON-677]: If this is an inner class then the generics are defined on the * enclosing class so we have to check there as well. We don't * need to call getEnclosingClass since anonymous classes declare * generics */ Class decl = ClassUtil.getDeclaringClass(raw); /* 08-Feb-2013, tatu: Except that if context is also super-class, we must * skip it; context will be checked anyway, and we'd get StackOverflow if * we went there. */ if (decl != null && !decl.isAssignableFrom(raw)) { _resolveBindings(decl); } /* 24-Mar-2010, tatu: Can not have true generics definitions, but can * have lower bounds ("") in declaration itself */ TypeVariable[] vars = raw.getTypeParameters(); if (vars != null && vars.length > 0) { JavaType[] typeParams = null; if (_contextType != null && raw.isAssignableFrom(_contextType.getRawClass())) { typeParams = _typeFactory.findTypeParameters(_contextType, raw); } for (int i = 0; i < vars.length; i++) { TypeVariable var = vars[i]; String name = var.getName(); Type varType = var.getBounds()[0]; if (varType != null) { if (_bindings == null) { _bindings = new LinkedHashMap(); } else { // and no overwriting... if (_bindings.containsKey(name)) continue; } _addPlaceholder(name); // to prevent infinite loops if (typeParams != null && typeParams.length > i) { _bindings.put(name, typeParams[i]); } else { _bindings.put(name, _typeFactory._constructType(_classStack, varType, this)); } } } } } else { // probably can't be any of these... so let's skip for now //if (type instanceof GenericArrayType) { //if (type instanceof TypeVariable) { // if (type instanceof WildcardType) { return; } // but even if it's not a parameterized type, its super types may be: _resolveBindings(ClassUtil.getGenericSuperclass(raw)); for (Type intType : raw.getGenericInterfaces()) { _resolveBindings(intType); } } @Override public String toString() { if (_bindings == null) { _resolve(); } StringBuilder sb = new StringBuilder("[TypeBindings for "); if (_contextType != null) { sb.append(_contextType.toString()); } else { sb.append(_contextClass.getName()); } sb.append(": ").append(_bindings).append("]"); return sb.toString(); } } jackson-databind-jackson-databind-2.9.5/create-test-report.sh000077500000000000000000000000501325620701100241750ustar00rootroot00000000000000#!/bin/sh mvn surefire-report:report jackson-databind-jackson-databind-2.9.5/pom.xml000066400000000000000000000133501325620701100214310ustar00rootroot00000000000000 4.0.0 com.fasterxml.jackson jackson-base 2.9.5 com.fasterxml.jackson.core jackson-databind 2.9.5 jackson-databind bundle General data-binding functionality for Jackson: works on core streaming API http://github.com/FasterXML/jackson 2008 scm:git:git@github.com:FasterXML/jackson-databind.git scm:git:git@github.com:FasterXML/jackson-databind.git http://github.com/FasterXML/jackson-databind jackson-databind-2.9.5 1.7 1.7 com.fasterxml.jackson.databind.*;version=${project.version} com/fasterxml/jackson/databind/cfg com.fasterxml.jackson.databind.cfg com.fasterxml.jackson.databind com.fasterxml.jackson.core jackson-annotations ${jackson.version.annotations} com.fasterxml.jackson.core jackson-core ${jackson.version.core} org.powermock powermock-module-junit4 1.7.3 test org.powermock powermock-api-mockito 1.7.3 test javax.measure jsr-275 1.0.0 test maven-enforcer-plugin enforce-properties validate enforce org.apache.maven.plugins ${version.plugin.surefire} maven-surefire-plugin javax.measure:jsr-275 com/fasterxml/jackson/failing/*.java org.apache.maven.plugins maven-javadoc-plugin http://fasterxml.github.com/jackson-annotations/javadoc/2.9 http://fasterxml.github.com/jackson-core/javadoc/2.9 com.google.code.maven-replacer-plugin replacer org.eluder.coveralls coveralls-maven-plugin 4.3.0 org.codehaus.mojo cobertura-maven-plugin release true true jackson-databind-jackson-databind-2.9.5/profile.sh000077500000000000000000000002151325620701100221070ustar00rootroot00000000000000#!/bin/sh java -Xmx256m -server -cp lib/\*:target/classes:target/test-classes \ -Xrunhprof:cpu=samples,depth=10,verbose=n,interval=2 \ $* jackson-databind-jackson-databind-2.9.5/release-notes/000077500000000000000000000000001325620701100226605ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/release-notes/CREDITS-2.x000066400000000000000000000614771325620701100243240ustar00rootroot00000000000000Here are people who have contributed to the development of Jackson JSON processor databind core component, version 2.x (version numbers in brackets indicate release in which the problem was fixed) (note: for older credits, check out release notes for 1.x versions) Tatu Saloranta, tatu.saloranta@iki.fi: author Pascal GŽlinas: * Contributed fixes to 'MappingIterator' handling (Pull#58 and Pull#59) (2.1.0) * Reported #220: ContainerNode missing 'createNumber(BigInteger)' (2.2.2) Joern Huxhorn: (huxi@github) * Suggested [JACKSON-636]: Add 'SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS' to allow forced sorting of Maps during serialization (2.0.0) * Reported #479: NPE on trying to deserialize a `String[]` that contains null (2.4.1) * Reported #1411: MapSerializer._orderEntries should check for null keys (2.7.9) James Roper: * Requested [JACKSON-732]: Allow 'AnnotationIntrospector.findContentDeserializer()' (and similar) to return instance, not just Class for instance (2.0.0) * Suggested [JACKSON-800]: Adding a method for letting modules register DeserializationProblemHandlers (2.0.0) Casey Lucas: * Reported [JACKSON-798]: Problem with external type id, creators (2.0.0) Tammo van Lessen: * Reported [JACKSON-811]: Problems with @JsonIdentityInfo, abstract types (2.0.0) * Reported [JACKSON-814]: Parsing RFC822/RFC1123 dates failes on non-US locales (2.0.0) Raymond Myers: * Suggested [JACKSON-810]: Deserialization Feature: Allow unknown Enum values via 'DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL' (2.0.0) Ryan Gardner: * Contributed #5 -- Add support for maps with java.util.Locale keys to the set of StdKeyDeserializers (2.0.1) Razvan Dragut: * Suggested [JACKSON-850]: Allow use of zero-arg factory methods as "default creator" (2.1.0) Duncan Atkinson: * Reported [JACKSON-851]: State corruption with ObjectWriter, DefaultPrettyPrinter (2.1.0) Mark Wolfe: * Suggested #45: Add `@JsonNaming()` for per-class naming strategy overrides (2.1.0) Dmitry Katsubo: * Contributed patch for #65: Add getters to `ObjectMapper`, DeserializationContext, DeserializationFactory. (2.1.0) Francis Galiegue: * Reported #93 (and suggested fix): bug in `ObjectMapper.setAll(...)' implementation (2.1.1) * Reported #433: `ObjectMapper`'s `.valueToTree()` wraps `JsonSerializable` objects into a POJONode (2.3.3) * Contributed #434: Ensure that DecimalNodes with mathematically equal values are equal (2.4.0) kelaneren@github: * Reported #157, contributed unit test: NPE when registering same module twice. (2.1.4) Eric Tschetter (cheddar@github): * Reported issues #166, #167, #170 (regressions from 1.9.x to 2.x) (2.1.4) Thierry D (thierryd@github) * Reported #214: Problem with LICENSE, NOTICE, Android packaging (2.2.2) Luke G-H (lukegh@github) * Reported #223: Duplicated nulls with @JsonFormat(shape=Shape.ARRAY) (2.2.2) Karl Moore (karldmoore@github) * Reported #217: JsonProcessingExceptions not all wrapped as expected (2.2.2) David Phillips: * Requested #308: Improve serialization and deserialization speed of `java.util.UUID` (2.3.0) Seth Pellegrino (jivesoft): * Contributed #317: Fix `JsonNode` support for nulls bound to `ObjectNode`, `ArrayNode` (2.3.0) Florian Schoppmann (fschopp@github) * Reported #357: StackOverflowError with contentConverter that returns array type (2.7.0) * Reported #358: `IterableSerializer` ignoring annotated content serializer (2.3.1) * Reported #359: Converted object not using explicitly annotated serializer (2.4.0) Martin Traverso: * Reported #406: Cannot use external type id + @JsonTypeIdResolver (2.3.2) Matthew Morrissette: * Contributed #381: Allow inlining/unwrapping of value from single-component JSON array (2.4.0) Will Palmeri: (wpalmeri@github) * Contributed #407: Make array and Collection serializers use configured value null handler (2.4.0) Cemalettin Koc: (cemo@github) * Reported #353: Problems with polymorphic types, `JsonNode` (related to #88) (2.4.0) Ben Fagin: (UnquietCode@github) * Suggested #442: Make `@JsonUnwrapped` indicate property inclusion (2.4.0) * Contributed #81/#455: Allow use of @JsonUnwrapped with typed (@JsonTypeInfo) classes, provided that (new) feature `SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS` is disabled (2.4.0) Chris Cleveland: * Suggested #463: Add 'JsonNode.asText(String defaultValue)` (2.4.0) Benson Margulies: * Reported #467: Unwanted POJO's embedded in tree via serialization to tree (2.4.0) * Reported #601: ClassCastException for a custom serializer for enum key in `EnumMap` (2.4.4) * Contributed 944: Failure to use custom deserializer for key deserializer (2.6.3) * Reported #1120: String value omitted from weirdStringException (2.6.6) * Reported, fixed #1235: `java.nio.file.Path` support incomplete (2.8.0) * Reported #1270: Generic type returned from type id resolver seems to be ignored (2.8.0) Steve Sanbeg: (sanbeg@github) * Contributed #482: Make date parsing error behavior consistent with JDK (2.4.1) Ian Barfield: (tea-dragon@github) * Reported #580: delegate deserializers choke on a (single) abstract/polymorphic parameter (2.4.4) * Reported #844: Using JsonCreator still causes invalid path references in JsonMappingException (2.5.5) Eugene Lukash * Reported #592: Wrong `TokenBuffer` delegate deserialization using `@JsonCreator` (2.4.4) Fernando Otero (zeitos@github) * Contributed fix for #610: Problem with forward reference in hierarchies (2.4.4) Lovro Pandžić (lpandzic@github) * Reported #421: @JsonCreator not used in case of multiple creators with parameter names (2.5.0) Adam Stroud (adstro@github) * Contributed #576: Add fluent API for adding mixins (2.5.0) David Fleeman (fleebytes@github) * Contributed #528 implementation: Add support for `JsonType.As.EXISTING_PROPERTY` (2.5.0) Aurélien Leboulanger (herau@github) * Contributed improvement for #597: Improve error messaging for cases where JSON Creator returns null (which is illegal) (2.5.0) Michael Spiegel (mspiegel@githib) * Contributed #636: `ClassNotFoundException` for classes not (yet) needed during serialization (2.5.0) Michael Ressler (mressler@github) * Contributed #566: Add support for case-insensitive deserialization (`MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES`) (2.5.0) Konstantin Labun (kulabun@github) * Reported #647: Deserialization fails when @JsonUnwrapped property contains an object with same property name (2.5.0) Christopher Smith (chrylis@github) * Reported #594: `@JsonValue` on enum not used when enum value is a Map key (2.5.0) Alexandre Santana Campelo (alexqi200@github): * Contributed #671: Adding `java.util.Currency` deserialization support for maps (2.5.1) Zoltan Farkas (zolyfarkas@github) * Reported #674: Spring CGLIB proxies not handled as intended (2.5.1) Ludevik@github: * Reported #682: Class-valued Map keys not serialized properly (2.5.1) Antibrumm@github: * Reported #691: Jackson 2.5.0. NullSerializer for MapProperty failing (2.5.2) * Reported #984: JsonStreamContexts are not build the same way for write.. and convert methods (2.6.4) Shumpei Akai (flexfrank@github) * Reported #703: Multiple calls to ObjectMapper#canSerialize(Object.class) returns different values (2.5.2) Francisco A. Lozano (flozano@github) * Contributed fix for #703 (see above) (2.5.2) Dylan Scott (dylanscott@github) * Reported #738: #738: @JsonTypeInfo non-deterministically ignored in 2.5.1 (concurrency issue) (2.5.2) Alain Gilbert (agilbert314@github) * Reporter, contributed #766: Fix Infinite recursion (StackOverflowError) when serializing a SOAP object (2.5.3) Alexey Gavrilov (Alexey1Gavrilov@github) * Reported, contributed fix for #761: Builder deserializer: in-compatible type exception when return type is super type (2.5.3) Dmitry Spikhalskiy (Spikhalskiy@github) * Reported #731, suggested the way to fix it: XmlAdapter result marshaling error in case of ValueType=Object (2.5.3) * Reported #1456: `TypeFactory` type resolution broken in 2.7 for generic types when using `constructType` with context (2.7.9 / 2.8.6) John Meyer (jpmeyer@github) * Reported, contributed fix for #745: EnumDeserializer.deserializerForCreator() fails when used to deserialize a Map key (2.5.3) Andrew Duckett (andrewduckett@github) * Reported #771: Annotation bundles ignored when added to Mixin (2.5.4) Charles Allen: * Contributed #785: Add handlings for classes which are available in `Thread.currentThread().getContextClassLoader()` (2.5.4) Andrew Goodale (newyankeecodeshop@github) * Contributed #816: Allow date-only ISO strings to have no time zone (2.5.4) Kamil Benedykciński (Kamil-Benedykcinski@github) * Contributed #801: Using `@JsonCreator` cause generating invalid path reference in `JsonMappingException` (2.5.4) Chi Kim (chikim79@github) * Reported #878: serializeWithType on BeanSerializer does not setCurrentValue (2.5.5 / 2.6.1) Charles Allen (drcrallen@github): * Reported #696: Copy constructor does not preserve `_injectableValues` (2.6.0) Chris Pimlott (pimlottc@github): * Suggested #348: ObjectMapper.valueToTree does not work with @JsonRawValue (2.6.0) Laird Nelson (ljnelson@github) * Suggested #688: Provide a means for an ObjectMapper to discover mixin annotation classes on demand (2.6.0) * Reported #1088: NPE possibility in SimpleMixinResolver (2.6.6) Derk Norton (derknorton@github) * Suggested #689: Add `ObjectMapper.setDefaultPrettyPrinter(PrettyPrinter)` (2.6.0) Michal Letynski (mletynski@github) * Suggested #296: Serialization of transient fields with public getters (add MapperFeature.PROPAGATE_TRANSIENT_MARKER) (2.6.0) Jeff Schnitzer (stickfigure@github) * Suggested #504: Add `DeserializationFeature.USE_LONG_FOR_INTS` (2.6.0) Jerry Yang (islanderman@github) * Contributed #820: Add new method for `ObjectReader`, to bind from JSON Pointer position (2.6.0) Lars Pfannenschmidt (larsp@github) * Contributed #826: Replaced synchronized HashMap with ConcurrentHashMap in TypeDeserializerBase._findDeserializer (2.6.0) Stephen A. Goss (thezerobit@github) * Contributed #828: Respect DeserializationFeatures.WRAP_EXCEPTIONS in CollectionDeserializer (2.6.0) Andy Wilkinson (wilkinsona@github) * Reported #889: Configuring an ObjectMapper's DateFormat changes time zone (2.6.1) lufe66@github: * Reported 894: When using withFactory on ObjectMapper, the created Factory has a TypeParser which still has the original Factory (2.6.2) Daniel Walker (dsw2127@github) * Reported, contributed fix for #913: `ObjectMapper.copy()` does not preserve `MappingJsonFactory` features (2.6.2) Sadayuki Furuhashi (frsyuki@github) * Reported #941: Deserialization from "{}" to ObjectNode field causes "out of END_OBJECT token" error (2.6.3) David Haraburda (dharaburda@github) * Contributed #918: Add `MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING` (2.7.0) Sergio Mira (Sergio-Mira@github) * Contributed #940: Add missing `hashCode()` implementations for `JsonNode` types that did not have them (2.6.3) Andreas Pieber (anpieber@github) * Reported #939: Regression: DateConversionError in 2.6.x (2.6.3) Jesse Wilson (swankjesse@github) * Contributed #948: Support leap seconds, any number of millisecond digits for ISO-8601 Dates. (2.6.3) * Contributed #949: Report the offending substring when number parsing fails (2.6.3) Warren Bloomer (stormboy@github) * Reported #942: Handle null type id for polymorphic values that use external type id (2.6.3) Ievgen Pianov (pyanoveugen@github) * Reported #989: Deserialization from "{}" to java.lang.Object causes "out of END_OBJECT token" error (2.6.3) Jayson Minard (apatrida@github) * Reported #1005: Synthetic constructors confusing Jackson data binding (2.6.4) * Reported #1438: `ACCEPT_CASE_INSENSITIVE_PROPERTIES` is not respected for creator properties (2.8.5) David Bakin (david-bakin@github) * Reported #1013: `@JsonUnwrapped` is not treated as assuming `@JsonProperty("")` (2.6.4) * Suggested #1011: Change ObjectWriter::withAttributes() to take a Map with some kind of wildcard types (2.7.0) Dmitry Romantsov (DmRomantsov@github) * Reported #1036: Problem with case-insensitive deserialization (2.6.4) Daniel Norberg (danielnorberg@github) * Contributed #1099: Fix custom comparator container node traversal (2.6.6) Miles Kaufmann (milesk-amzn@github) * Reported #432: `StdValueInstantiator` unwraps exceptions, losing context (2.7.0) Thomas Mortagne (tmortagne@github) * Suggested #857: Add support for java.beans.Transient (2.7.0) Jonas Konrad (yawkat@github) * Suggested #905: Add support for `@ConstructorProperties` (2.7.0) Jirka Kremser (Jiri-Kremser@github) * Suggested #924: SequenceWriter.writeAll() could accept Iterable (2.7.0) Daniel Mischler (danielmischler@github) * Requested #963: Add PropertyNameStrategy `KEBAB_CASE` (2.7.0) Shumpei Akai (flexfrank@github) * Reported #978: ObjectMapper#canSerialize(Object.class) returns false even though FAIL_ON_EMPTY_BEANS is disabled (2.7.0) Hugo Wood (hgwood@github) * Contributed #1010: Support for array delegator (2.7.0) Julian Hyde (julianhyde@github) * Reported #1083: Field in base class is not recognized, when using `@JsonType.defaultImpl` (2.7.1) Thibault Kruse (tkruse@github) * Reported #1102: Handling of deprecated `SimpleType.construct()` too minimalistic (2.7.1) Aleks Seovic (aseovic@github) * Reported #1109: @JsonFormat is ignored by the DateSerializer unless either a custom pattern or a timezone are specified (2.7.1) Timur Shakurov (saladinkzn@github) * Reported #1134: Jackson 2.7 doesn't work with jdk6 due to use of `Collections.emptyIterator()` (2.7.2) Jiri Mikulasek (pirkogdc@github) * Reported #1124: JsonAnyGetter ignores JsonSerialize(contentUsing=...) (2.7.2) Xavi Torrens (xavitorrens@github) * Reported #1150: Problem with Object id handling, explicit `null` token (2.7.3) Yoann Rodière (fenrhil@github) * Reported #1154: @JsonFormat.pattern on dates is now ignored if shape is not explicitely provided (2.7.3) Mark Woon (markwoon@github) * Reported #1178: `@JsonSerialize(contentAs=superType)` behavior disallowed in 2.7 (2.7.4) * Reported #1231: `@JsonSerialize(as=superType)` behavior disallowed in 2.7.4 (2.7.5) * Suggested #507: Support for default `@JsonView` for a class (2.9.0) Tom Mack (tommack@github) * Reported #1208: treeToValue doesn't handle POJONodes that contain exactly the requested value type (2.7.4) William Headrick (headw01@github) * Reported#1223: `BasicClassIntrospector.forSerialization(...).findProperties` should respect MapperFeature.AUTO_DETECT_GETTERS/SETTERS? (2.7.5) Nick Babcock (nickbabcock) * Reported #1225: `JsonMappingException` should override getProcessor() (2.7.5) * Suggested #1356: Differentiate between input and code exceptions on deserialization (2.9.0) Andrew Joseph (apjoseph@github) * Reported #1248: `Annotated` returns raw type in place of Generic Type in 2.7.x (2.7.5) Erich Schubert (kno10@github) * Reported #1260: `NullPointerException` in `JsonNodeDeserializer`, provided fix (2.7.5) Brian Pontarelli (voidmain@github) * Reported #1301: Problem with `JavaType.toString()` for recursive (self-referential) types (2.7.6) Max Drobotov (fizmax@github) * Reported, contributed fix for #1332: `ArrayIndexOutOfBoundException` for enum by index deser (2.7.7) Stuart Douglas (stuartwdouglas@github) * Reported #1363: The static field ClassUtil.sCached can cause a class loader leak (2.7.8) Josh Caplan (jecaplan@github) * Reported, suggested fix for #1368: Problem serializing `JsonMappingException` due to addition of non-ignored `processor` property (added in 2.7) (2.7.8) Diego de Estrada (diegode@github) * Contributed fix for #1367: No Object Id found for an instance when using `@ConstructorProperties` (2.7.9) Kevin Hogeland (khogeland@github) * Reported #1501: `ArrayIndexOutOfBoundsException` on non-static inner class constructor (2.7.9) Artur Jonkisz (ajonkisz@github) * Reported #960: `@JsonCreator` not working on a factory with no arguments for ae enum type (2.8.0) Mikhail Kokho (mkokho@github) * Contributed impl for #990: Allow failing on `null` values for creator (add `DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES`) (2.8.0) Aleksandr Oksenenko (oleksandr-oksenenko@github) * Reported #999: External property is not deserialized (2.8.0) Lokesh Kumar (LokeshN@github) * Contributed impl for #1082: Can not use static Creator factory methods for `Enum`s, with JsonCreator.Mode.PROPERTIES (2.8.0) * Reported #1217: `@JsonIgnoreProperties` on Pojo fields not working for deserialization (2.8.0) Ross Goldberg * Reported #1165, provided fix for: `CoreXMLDeserializers` does not handle time-only `XMLGregorianCalendar`s (2.8.0) Maarten Billemont (lhunath@github) * Suggested #1184: Allow overriding of `transient` with explicit inclusion with `@JsonProperty` (2.8.0) Vladimir Kulev (lightoze@github) * Reported #1028: Ignore USE_BIG_DECIMAL_FOR_FLOATS for NaN/Infinity (2.8.0) Ari Fogel (arifogel@github) * Reported #1261, contributed fix for: `@JsonIdentityInfo` deserialization fails with combination of forward references, `@JsonCreator` (2.8.0) Andriy Plokhotnyuk (plokhotnyuk@github) * Requested #1277: Add caching of resolved generic types for `TypeFactory` (2.8.0) Arek Gabiga (arekgabiga@github) * Reported #1297: Deserialization of generic type with Map.class (2.8.1) Chris Jester-Young (cky@github) * Contributed #1335: Unconditionally call `TypeIdResolver.getDescForKnownTypeIds` (2.8.2) Andrew Snare (asnare@github) * Reported #1315: Binding numeric values can BigDecimal lose precision (2.8.2) Gili Tzabari (cowwoc@github) * Reported #1351: `@JsonInclude(NON_DEFAULT)` doesn't omit null fields (2.8.3) Oleg Zhukov (OlegZhukov@github) * Reported #1384: `@JsonDeserialize(keyUsing = ...)` does not work correctly together with `DefaultTyping.NON_FINAL` (2.8.4) Pavel Popov (tolkonepiu@github) * Contributed fix #1389: Problem with handling of multi-argument creator with Enums (2.8.4) Josh Gruenberg (joshng@github) * Reported #1403: Reference-chain hints use incorrect class-name for inner classes (2.8.4) Kevin Donnelly (kpdonn@github) * Reported #1432: Off by 1 bug in PropertyValueBuffer (2.8.5) Nathanial Ofiesh (ofiesh@github) * Reported #1441: Failure with custom Enum key deserializer, polymorphic types (2.8.5) Frédéric Camblor (fcamblor@github) * Reported #1451: Type parameter not passed by `ObjectWriter` if serializer pre-fetch disabled (2.8.6) Stephan Schroevers (Stephan202@github) * Reported #1505: @JsonEnumDefaultValue should take precedence over FAIL_ON_NUMBERS_FOR_ENUMS (2.8.7) Alex Panchenko (panchenko@github) * Reported #1543: JsonFormat.Shape.NUMBER_INT does not work when defined on enum type in 2.8 (2.8.8) Joshua Jones * Reported #1573, contributed fix: Missing properties when deserializing using a builder class with a non-default constructor and a mutator annotated with `@JsonUnwrapped` (2.8.8) Ivo Studens (istudens@redhat.com) * Contributed #1585: Invoke ServiceLoader.load() inside of a privileged block when loading modules using `ObjectMapper.findModules()` (2.8.9) Javy Luo (AnywnYu@github) * Reported #1595: `JsonIgnoreProperties.allowSetters` is not working in Jackson 2.8 (2.8.9) Marco Catania (catanm@github.com) * Contributed #1597: Escape JSONP breaking characters (2.8.9) Andrew Joseph (apjoseph@github) * Reported #1629 `FromStringDeserializer` ignores registered `DeserializationProblemHandler` for `java.util.UUID` (2.8.9) Joe Littlejohn (joelittlejohn@github) * Contributed #1642: Support `READ_UNKNOWN_ENUM_VALUES_AS_NULL` with `@JsonCreator` (2.8.9) Slobodan Pejic (slobo-showbie@github) * Reported #1647, contributed fix: Missing properties from base class when recursive types are involved (2.8.9) Bertrand Renuart (brenuart@github) * Reported #1648: `DateTimeSerializerBase` ignores configured date format when creating contextual (2.8.9) * Reported #1651: `StdDateFormat` fails to parse 'zulu' date when TimeZone other than UTC (2.8.9) * Suggested #1745: StdDateFormat: accept and truncate millis larger than 3 digits (2.9.1) * Contributed #1749: StdDateFormat: performance improvement of '_format(..)' method (2.9.1) * Contributed #1759: Reuse `Calendar` instance during parsing by `StdDateFormat` (2.9.1) Kevin Gallardo (newkek@github) * Reported #1658: Infinite recursion when deserializing a class extending a Map, with a recursive value type (2.8.10) * Reported #1729: Integer bounds verification when calling `TokenBuffer.getIntValue()` (2.9.4) Lukas Euler * Reported #1735: Missing type checks when using polymorphic type ids Connor Kuhn (ckuhn@github) * Contributed #1341: FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY (2.9.0) Jan Lolling (jlolling@github) * Contributed #1319: Add `ObjectNode.put(String, BigInteger)` (2.9.0) Michael R Fairhurst (MichaelRFairhurst@github) * Reported #1035: `@JsonAnySetter` assumes key of `String`, does not consider declared type. (2.9.0) Fabrizio Cucci (fabriziocucci@github) * Reported #1406: `ObjectMapper.readTree()` methods do not return `null` on end-of-input (2.9.0) Emiliano Clariá (emilianogc@github) * Contributed #1434: Explicitly pass null on invoke calls with no arguments (2.9.0) Ana Eliza Barbosa (AnaEliza@github) * Contributed #1520: Case insensitive enum deserialization feature. (2.9.0) Lyor Goldstein (lgoldstein@github) * Reported #1544: `EnumMapDeserializer` assumes a pure `EnumMap` and does not support derived classes (2.9.0) Harleen Sahni (harleensahni@github) * Reported #403: Make FAIL_ON_NULL_FOR_PRIMITIVES apply to primitive arrays and other types that wrap primitives (2.9.0) Jared Jacobs (2is10@github) * Requested #1605: Allow serialization of `InetAddress` as simple numeric host address (2.9.0) Patrick Gunia (pgunia@github) * Reported #1440: Wrong `JsonStreamContext` in `DeserializationProblemHandler` when reading `TokenBuffer` content (2.9.0) Carsten Wickner (CarstenWickner@github) * Contributed #1522: Global `@JsonInclude(Include.NON_NULL)` for all properties with a specific type (2.9.0) Chris Plummer (strmer15@github) * Reported #1637: `ObjectReader.at()` with `JsonPointer` stops after first collection (2.9.0) Christian Basler (Dissem@github) * Reported #1688: Deserialization fails for `java.nio.file.Path` implementations when default typing enabled (2.9.0) Tim Bartley (tbartley@github) * Reported, suggested fix for #1705: Non-generic interface method hides type resolution info from generic base class (2.9.1) Luís Cleto (luiscleto@github) * Suggested 1768: Improve `TypeFactory.constructFromCanonical()` to work with `java.lang.reflect.Type.getTypeName()` format (2.9.2) Vincent Demay (vdemay@github) * Reported #1793: `java.lang.NullPointerException` in `ObjectArraySerializer.acceptJsonFormatVisitor()` for array value with `@JsonValue` (2.9.2) Peter Jurkovic (peterjurkovic@github) * Reported #1823: ClassNameIdResolver doesn't handle resolve Collections$SingletonMap, Collections$SingletonSet (2.9.3) alinakovalenko@github: * Reported #1844: Map "deep" merge only adds new items, but not override existing values (2.9.3) Pier-Luc Whissell (pwhissell@github): * Reported #1673: Serialising generic value classes via Reference Types (like Optional) fails to include type information (2.9.4) Alexander Skvortcov (askvortcov@github) * Reported #1853: Deserialise from Object (using Creator methods) returns field name instead of value (2.9.4) Joe Schafer (jschaf@github) * Reported #1906: Add string format specifier for error message in `PropertyValueBuffer` (2.9.4) * Reported #1907: Remove `getClass()` from `_valueType` argument for error reporting (2.9.4) Deblock Thomas (deblockt@github) * Reported, contributed fix for #1912: `BeanDeserializerModifier.updateBuilder()` does not work to set custom deserializer on a property (since 2.9.0) (contributed by Deblock T) lilei@venusgroup.com.cn: * Reported #1931: Two more `c3p0` gadgets to exploit default typing issue (2.9.5) Aniruddha Maru (maroux@github) * Reported #1940: `Float` values with integer value beyond `int` lose precision if bound to `long` (2.9.5) Timur Shakurov (saladinkzn@github) * Reported #1947: `MapperFeature.AUTO_DETECT_XXX` do not work if all disabled (2.9.5) roeltje25@github * Reported #1978: Using @JsonUnwrapped annotation in builderdeserializer hangs in infinite loop (2.9.5) jackson-databind-jackson-databind-2.9.5/release-notes/VERSION-2.x000066400000000000000000002317061325620701100243460ustar00rootroot00000000000000Project: jackson-databind ------------------------------------------------------------------------ === Releases === ------------------------------------------------------------------------ 2.9.5 (26-Mar-2018) #1911: Allow serialization of `BigDecimal` as String, using `@JsonFormat(shape=Shape.String)`, config overrides (suggested by cen1@github) #1912: `BeanDeserializerModifier.updateBuilder()` not work to set custom deserializer on a property (since 2.9.0) (contributed by Deblock T) #1931: Two more `c3p0` gadgets to exploit default typing issue (reported by lilei@venusgroup.com.cn) #1932: `EnumMap` cannot deserialize with type inclusion as property #1940: `Float` values with integer value beyond `int` lose precision if bound to `long` (reported by Aniruddha M) #1941: `TypeFactory.constructFromCanonical()` throws NPE for Unparameterized generic canonical strings (reported by ayushgp@github) #1947: `MapperFeature.AUTO_DETECT_XXX` do not work if all disabled (reported by Timur S) #1977: Serializing an Iterator with multiple sub-types fails after upgrading to 2.9.x (reported by ssivanand@github) #1978: Using @JsonUnwrapped annotation in builderdeserializer hangs in infinite loop (reported by roeltje25@github) 2.9.4 (24-Jan-2018) #1382: `@JsonProperty(access=READ_ONLY)` unxepected behaviour with `Collections` (reported by hexfaker@github) #1673: Serialising generic value classes via Reference Types (like Optional) fails to include type information (reported by Pier-Luc W) #1729: Integer bounds verification when calling `TokenBuffer.getIntValue()` (reported by Kevin G) #1853: Deserialise from Object (using Creator methods) returns field name instead of value (reported by Alexander S) #1854: NPE deserializing collection with `@JsonCreator` and `ACCEPT_CASE_INSENSITIVE_PROPERTIES` (reported by rue-jw@github) #1855: Blacklist for more serialization gadgets (dbcp/tomcat, spring) #1859: Issue handling unknown/unmapped Enum keys (reported by remya11@github) #1868: Class name handling for JDK unmodifiable Collection types changed (reported by Rob W) #1870: Remove `final` on inherited methods in `BuilderBasedDeserializer` to allow overriding by subclasses (requested by Ville K) #1878: `@JsonBackReference` property is always ignored when deserializing since 2.9.0 (reported by reda-alaoui@github) #1895: Per-type config override "JsonFormat.Shape.OBJECT" for Map.Entry not working (reported by mcortella@github) #1899: Another two gadgets to exploit default typing issue in jackson-databind (reported by OneSourceCat@github) #1906: Add string format specifier for error message in `PropertyValueBuffer` (reported by Joe S) #1907: Remove `getClass()` from `_valueType` argument for error reporting (reported by Joe S) 2.9.3 (09-Dec-2017) #1604: Nested type arguments doesn't work with polymorphic types #1794: `StackTraceElementDeserializer` not working if field visibility changed (reported by dsingley@github) #1799: Allow creation of custom sub-types of `NullNode`, `BooleanNode`, `MissingNode` #1804: `ValueInstantiator.canInstantiate()` ignores `canCreateUsingArrayDelegate()` (reported byb henryptung@github) #1807: Jackson-databind caches plain map deserializer and use it even map has `@JsonDeserializer` (reported by lexas2509@github) #1823: ClassNameIdResolver doesn't handle resolve Collections$SingletonMap & Collections$SingletonSet (reported by Peter J) #1831: `ObjectReader.readValue(JsonNode)` does not work correctly with polymorphic types, value to update (reported by basmastr@github) #1835: ValueInjector break from 2.8.x to 2.9.x (repoted by kinigitbyday@github) #1842: `null` String for `Exception`s deserialized as String "null" instead of `null` (reported by ZeleniJure@github) #1843: Include name of unsettable property in exception from `SetterlessProperty.set()` (suggested by andreh7@github) #1844: Map "deep" merge only adds new items, but not override existing values (reported by alinakovalenko@github) 2.9.2 (14-Oct-2017) (possibly) #1756: Deserialization error with custom `AnnotationIntrospector` (reported by Daniel N) #1705: Non-generic interface method hides type resolution info from generic base class (reported by Tim B) NOTE: was originally reported fixed in 2.9.1 -- turns out it wasn't. #1767: Allow `DeserializationProblemHandler` to respond to primitive types (reported by nhtzr@github) #1768: Improve `TypeFactory.constructFromCanonical()` to work with `java.lang.reflect.Type.getTypeName()' format (suggested by Luís C) #1771: Pass missing argument for string formatting in `ObjectMapper` (reported by Nils B) #1788: `StdDateFormat._parseAsISO8601()` does not parse "fractional" timezone correctly #1793: `java.lang.NullPointerException` in `ObjectArraySerializer.acceptJsonFormatVisitor()` for array value with `@JsonValue` (reported by Vincent D) 2.9.1 (07-Sep-2017) #1725: `NPE` In `TypeFactory. constructParametricType(...)` (reported by ctytgat@github) #1730: InvalidFormatException` for `JsonToken.VALUE_EMBEDDED_OBJECT` (reported by zigzago@github) #1744: StdDateFormat: add option to serialize timezone offset with a colon (contributed by Bertrand R) #1745: StdDateFormat: accept and truncate millis larger than 3 digits (suggested by Bertrand R) #1749: StdDateFormat: performance improvement of '_format(..)' method (contributed by Bertrand R) #1759: Reuse `Calendar` instance during parsing by `StdDateFormat` (contributed by Bertrand R) - Fix `DelegatingDeserializer` constructor to pass `handledType()` (and not type of deserializer being delegated to!) - Add `Automatic-Module-Name` ("com.fasterxml.jackson.databind") for JDK 9 module system 2.9.0 (30-Jul-2017) #219: SqlDateSerializer does not obey SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS (reported by BrentDouglas@github) #265: Add descriptive exception for attempts to use `@JsonWrapped` via Creator parameter #291: @JsonTypeInfo with As.EXTERNAL_PROPERTY doesn't work if external type property is referenced more than once (reported by Starkom@github) #357: StackOverflowError with contentConverter that returns array type (reported by Florian S) #383: Recursive `@JsonUnwrapped` (`child` with same type) fail: "No _valueDeserializer assigned" (reported by tdavis@github) #403: Make FAIL_ON_NULL_FOR_PRIMITIVES apply to primitive arrays and other types that wrap primitives (reported by Harleen S) #476: Allow "Serialize as POJO" using `@JsonFormat(shape=Shape.OBJECT)` class annotation #507: Support for default `@JsonView` for a class (suggested by Mark W) #687: Exception deserializing a collection @JsonIdentityInfo and a property based creator #865: `JsonFormat.Shape.OBJECT` ignored when class implements `Map.Entry` #888: Allow specifying custom exclusion comparator via `@JsonInclude`, using `JsonInclude.Include.CUSTOM` #994: `DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS` only works for POJOs, Maps #1029: Add a way to define property name aliases #1035: `@JsonAnySetter` assumes key of `String`, does not consider declared type. (reported by Michael F) #1106: Add `MapperFeature.ALLOW_COERCION_OF_SCALARS` for enabling/disabling coercions #1284: Make `StdKeySerializers` use new `JsonGenerator.writeFieldId()` for `int`/`long` keys #1320: Add `ObjectNode.put(String, BigInteger)` (proposed by Jan L) #1341: `DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY` (contributed by Connor K) #1347: Extend `ObjectMapper.configOverrides()` to allow changing visibility rules #1356: Differentiate between input and code exceptions on deserialization (suggested by Nick B) #1369: Improve `@JsonCreator` detection via `AnnotationIntrospector` by passing `MappingConfig` #1371: Add `MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES` to allow disabling use of `@CreatorProperties` as explicit `@JsonCreator` equivalent #1376: Add ability to disable JsonAnySetter/JsonAnyGetter via mixin (suggested by brentryan@github) #1399: Add support for `@JsonMerge` to allow "deep update" #1402: Use `@JsonSetter(nulls=...)` to specify handling of `null` values during deserialization #1406: `ObjectMapper.readTree()` methods do not return `null` on end-of-input (reported by Fabrizio C) #1407: `@JsonFormat.pattern` is ignored for `java.sql.Date` valued properties (reported by sangpire@github) #1415: Creating CollectionType for non generic collection class broken #1428: Allow `@JsonValue` on a field, not just getter #1434: Explicitly pass null on invoke calls with no arguments (contributed by Emiliano C) #1433: `ObjectMapper.convertValue()` with null does not consider null conversions (`JsonDeserializer.getNullValue()`) (contributed by jdmichal@github) #1440: Wrong `JsonStreamContext` in `DeserializationProblemHandler` when reading `TokenBuffer` content (reported by Patrick G) #1444: Change `ObjectMapper.setSerializationInclusion()` to apply to content inclusion too #1450: `SimpleModule.addKeyDeserializer()' should throw `IllegalArgumentException` if `null` reference of `KeyDeserializer` passed (suggested by PawelJagus@github) #1454: Support `@JsonFormat.lenient` for `java.util.Date`, `java.util.Calendar` #1474: Replace use of `Class.newInstance()` (deprecated in Java 9) with call via Constructor #1480: Add support for serializing `boolean`/`Boolean` as number (0 or 1) (suggested by jwilmoth@github) #1520: Case insensitive enum deserialization with `MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS` (contributed by Ana-Eliza B) #1522: Global `@JsonInclude(Include.NON_NULL)` for all properties with a specific type (contributed by Carsten W) #1544: EnumMapDeserializer assumes a pure EnumMap and does not support EnumMap derived classes (reported by Lyor G) #1550: Unexpected behavior with `@JsonInclude(JsonInclude.Include.NON_EMPTY)` and `java.util.Date` serialization #1551: `JsonMappingException` with polymorphic type and `JsonIdentityInfo` when basic type is abstract (reported by acm073@github) #1552: Map key converted to byte array is not serialized as base64 string (reported by nmatt@github) #1554: Support deserialization of `Shape.OBJECT` ("as POJO") for `Map`s (and map-like types) #1556: Add `ObjectMapper.updateValue()` method to update instance with given overrides (suggested by syncer@github) #1583: Add a `DeserializationFeature.FAIL_ON_TRAILING_TOKENS` to force reading of the whole input as single value #1592: Add support for handling primitive/discrepancy problem with type refinements #1605: Allow serialization of `InetAddress` as simple numeric host address (requested by Jared J) #1616: Extraneous type id mapping added for base type itself #1619: By-pass annotation introspection for array types #1637: `ObjectReader.at()` with `JsonPointer` stops after first collection (reported by Chris P) #1653: Convenience overload(s) for ObjectMapper#registerSubtypes #1655: `@JsonAnyGetter` uses different `bean` parameter in `SimpleBeanPropertyFilter` (reported by georgeflugq@github) #1678: Rewrite `StdDateFormat` ISO-8601 handling functionality #1684: Rewrite handling of type ids to let `JsonGenerator` handle (more of) details #1688: Deserialization fails for `java.nio.file.Path` implementations when default typing enabled (reported by Christian B) #1690: Prevent use of quoted number (index) for Enum deserialization via `MapperFeature.ALLOW_COERCION_OF_SCALARS` (requested by magdel@github) 2.8.11.1 (11-Feb-2018) #1872: `NullPointerException` in `SubTypeValidator.validateSubType` when validating Spring interface (reported by Rob W) #1899: Another two gadgets to exploit default typing issue in jackson-databind (reported by OneSourceCat@github) #1931: Two more `c3p0` gadgets to exploit default typing issue 2.8.11 (24-Dec-2017) #1604: Nested type arguments doesn't work with polymorphic types #1680: Blacklist couple more types for deserialization #1767: Allow `DeserializationProblemHandler` to respond to primitive types (reported by nhtzr@github) #1768: Improve `TypeFactory.constructFromCanonical()` to work with `java.lang.reflect.Type.getTypeName()` format #1804: `ValueInstantiator.canInstantiate()` ignores `canCreateUsingArrayDelegate()` (reported by henryptung@github) #1807: Jackson-databind caches plain map deserializer and use it even map has `@JsonDeserializer` (reported by lexas2509@github) #1855: Blacklist for more serialization gadgets (dbcp/tomcat, spring) 2.8.10 (24-Aug-2017) #1657: `StdDateFormat` deserializes dates with no tz/offset as UTC instead of configured timezone (reported by Bertrand R) #1680: Blacklist couple more types for deserialization #1658: Infinite recursion when deserializing a class extending a Map, with a recursive value type (reported by Kevin G) #1679: `StackOverflowError` in Dynamic `StdKeySerializer` #1711: Delegating creator fails to work for binary data (`byte[]`) with binary formats (CBOR, Smile) #1735: Missing type checks when using polymorphic type ids (reported by Lukas Euler) #1737: Block more JDK types from polymorphic deserialization 2.8.9 (12-Jun-2017) #1595: `JsonIgnoreProperties.allowSetters` is not working in Jackson 2.8 (reported by Javy L) #1597: Escape JSONP breaking characters (contributed by Marco C) #1629: `FromStringDeserializer` ignores registered `DeserializationProblemHandler` for `java.util.UUID` (reported by Andrew J) #1642: Support `READ_UNKNOWN_ENUM_VALUES_AS_NULL` with `@JsonCreator` (contributed by Joe L) #1647: Missing properties from base class when recursive types are involved (reported by Slobodan P) #1648: `DateTimeSerializerBase` ignores configured date format when creating contextual (reported by Bertrand R) #1651: `StdDateFormat` fails to parse 'zulu' date when TimeZone other than UTC (reported by Bertrand R) 2.8.8.1 (19-Apr-2017) #1585: Invoke ServiceLoader.load() inside of a privileged block when loading modules using `ObjectMapper.findModules()` (contributed by Ivo S) #1599: Jackson Deserializer security vulnerability (reported by ayound@github) #1607: @JsonIdentityReference not used when setup on class only (reported by vboulaye@github) 2.8.8 (05-Apr-2017) (partial) #994: `DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS` only works for POJOs, Maps #1345: `@JsonProperty(access = READ_ONLY)` together with generated constructor (Lombok) causes exception: "Could not find creator property with name ..." (reported by Raniz85@github) #1533: `AsPropertyTypeDeserializer` ignores `DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT` #1543: JsonFormat.Shape.NUMBER_INT does not work when defined on enum type in 2.8 (reported by Alex P) #1570: `Enum` key for `Map` ignores `SerializationFeature.WRITE_ENUMS_USING_INDEX` (reported by SolaKun@github) #1573: Missing properties when deserializing using a builder class with a non-default constructor and a mutator annotated with `@JsonUnwrapped` (reported by Joshua J) #1575: Problem with `@JsonIgnoreProperties` on recursive property (regression in 2.8) (reported by anujkumar04@github) - Minor fix to creation of `PropertyMetadata`, had one path that could lead to NPE 2.8.7 (21-Feb-2017) #935: `@JsonProperty(access = Access.READ_ONLY)` - unexpected behaviour #1317: '@JsonIgnore' annotation not working with creator properties, serialization 2.8.6 (12-Jan-2017) #349: @JsonAnySetter with @JsonUnwrapped: deserialization fails with arrays (reported by hdave@github) #1388: `@JsonIdentityInfo`: id has to be the first key in deserialization when deserializing with `@JsonCreator` (reported by moodysalem@github) #1425: `JsonNode.binaryValue()` ignores illegal character if it's the last one (reported by binoternary@github) #1453: `UntypedObjectDeserializer` does not retain `float` type (over `double`) #1456: `TypeFactory` type resolution broken in 2.7 for generic types when using `constructType` with context #1473: Add explicit deserializer for `StringBuilder` due to Java 9 changes #1493: `ACCEPT_CASE_INSENSITIVE_PROPERTIES` fails with `@JsonUnwrapped` 2.8.5 (14-Nov-2016) #1417: Further issues with `@JsonInclude` with `NON_DEFAULT` #1421: ACCEPT_SINGLE_VALUE_AS_ARRAY partially broken in 2.7.x, 2.8.x #1429: `StdKeyDeserializer` can erroneously use a static factory method with more than one argument #1432: Off by 1 bug in PropertyValueBuffer (reported by Kevin D) #1438: `ACCEPT_CASE_INSENSITIVE_PROPERTIES` is not respected for creator properties (reported by Jayson M) #1439: NPE when using with filter id, serializing `java.util.Map` types #1441: Failure with custom Enum key deserializer, polymorphic types (reported by Nathanial O) #1445: Map key deserializerModifiers ignored (reported by alfonsobonso@github) - Improvements to #1411 fix to ensure consistent `null` key handling 2.8.4 (14-Oct-2016) #466: Jackson ignores Type information when raw return type is BigDecimal or BigInteger #1001: Parameter names module gets confused with delegate creator which is a static method #1324: Boolean parsing with `StdDeserializer` is too slow with huge integer value (reported by pavankumar-parankusam@github) #1383: Problem with `@JsonCreator` with 1-arg factory-method, implicit param names #1384: `@JsonDeserialize(keyUsing = ...)` does not work correctly together with DefaultTyping.NON_FINAL (reported by Oleg Z) #1385: Polymorphic type lost when using `@JsonValue` (reported by TomMarkuske@github) #1389 Problem with handling of multi-argument creator with Enums (fix contributed by Pavel P) #1392: Custom UnmodifiableSetMixin Fails in Jackson 2.7+ but works in Jackson 2.6 (reported by Rob W) #1395: Problems deserializing primitive `long` field while using `TypeResolverBuilder` (reported by UghZan3@github) #1403: Reference-chain hints use incorrect class-name for inner classes (reported by Josh G) #1411: MapSerializer._orderEntries should check for null keys (reported by Jörn H) 2.8.3 (17-Sep-2016) #1351: `@JsonInclude(NON_DEFAULT)` doesn't omit null fields (reported by Gili T) #1353: Improve error-handling for `java.net.URL` deserialization #1361: Change `TokenBuffer` to use new `writeEmbeddedObject()` if possible 2.8.2 (30-Aug-2016) #1315: Binding numeric values can BigDecimal lose precision (reported by Andrew S) #1327: Class level `@JsonInclude(JsonInclude.Include.NON_EMPTY)` is ignored (reported by elruwen@github) #1335: Unconditionally call `TypeIdResolver.getDescForKnownTypeIds` (contributed by Chris J-Y) 2.8.1 (20-Jul-2016) #1256: `Optional.empty()` not excluded if property declared with type `Object` #1288: Type id not exposed for `JsonTypeInfo.As.EXTERNAL_PROPERTY` even when `visible` set to `true` (reported by libetl@github) #1289: Optimize construction of `ArrayList`, `LinkedHashMap` instances #1291: Backward-incompatible behaviour of 2.8: deserializing enum types with two static factory methods fail by default #1297: Deserialization of generic type with Map.class (reported by Arek G) #1302: NPE for `ResolvedRecursiveType` in 2.8.0 due to caching 2.8.0 (04-Jul-2016) #621: Allow definition of "ignorable types" without annotation (using `Mapper.configOverride(type).setIsIgnoredType(true)` #867: Support `SerializationFeature.WRITE_EMPTY_JSON_ARRAYS ` for `JsonNode` #903: Add `JsonGenerator` reference to `SerializerProvider` #931: Add new method in `Deserializers.Base` to support `ReferenceType` #960: `@JsonCreator` not working on a factory with no arguments for an enum type (reported by Artur J) #990: Allow failing on `null` values for creator (add `DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES`) (contributed by mkokho@github) #999: External property is not deserialized (reported by Aleksandr O) #1017: Add new mapping exception type ('InvalidTypeIdException') for subtype resolution errors (suggested by natnan@github) #1028: Ignore USE_BIG_DECIMAL_FOR_FLOATS for NaN/Infinity (reported by Vladimir K, lightoze@github) #1047: Allow use of `@JsonAnySetter` on a Map-valued field, no need for setter #1082: Can not use static Creator factory methods for `Enum`s, with JsonCreator.Mode.PROPERTIES (contributed by Lokesh K) #1084: Change `TypeDeserializerBase` to take `JavaType` for `defaultImpl`, NOT `Class` #1126: Allow deserialization of unknown Enums using a predefined value (contributed by Alejandro R) #1136: Implement `TokenBuffer.writeEmbeddedObject(Object)` (suggested by Gregoire C, gcxRun@github) #1165: CoreXMLDeserializers does not handle time-only XMLGregorianCalendars (reported, contributed fix by Ross G) #1181: Add the ability to specify the initial capacity of the ArrayNode (suggested by Matt V, mveitas@github) #1184: Allow overriding of `transient` with explicit inclusion with `@JsonProperty` (suggested by Maarten B) #1187: Refactor `AtomicReferenceDeserializer` into `ReferenceTypeDeserializer` #1204: Add a convenience accessor `JavaType.hasContentType()` (true for container or reference type) #1206: Add "anchor type" member for `ReferenceType` #1211: Change `JsonValueSerializer` to get `AnnotatedMethod`, not "raw" method #1217: `@JsonIgnoreProperties` on Pojo fields not working for deserialization (reported by Lokesh K) #1221: Use `Throwable.addSuppressed()` directly and/or via try-with-resources #1232: Add support for `JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES` #1233: Add support for `JsonFormat.Feature.WRITE_SORTED_MAP_ENTRIES` #1235: `java.nio.file.Path` support incomplete (reported by, fix contributed by Benson M) #1261: JsonIdentityInfo broken deserialization involving forward references and/or cycles (reported by, fix contributed by Ari F) #1270: Generic type returned from type id resolver seems to be ignored (reported by Benson M) #1277: Add caching of resolved generic types for `TypeFactory` (requested by Andriy P) 2.7.10 (not yet released) #1628: Don't print to error stream about failure to load JDK 7 types (reported by Villane@github) 2.7.9 (04-Feb-2017) #1367: No Object Id found for an instance when using `@ConstructorProperties` #1505: @JsonEnumDefaultValue should take precedence over FAIL_ON_NUMBERS_FOR_ENUMS (suggested by Stephan S) #1506: Missing `KeyDeserializer` for `CharSequence` #1513: `MapSerializer._orderEntries()` throws NPE when operating on `ConcurrentHashMap` (reported by Sovietaced@github) - Simplified processing of class annotations (for `AnnotatedClass`) to try to solve rare concurrency problems with "root name" annotations. 2.7.8 (26-Sep-2016) #877: @JsonIgnoreProperties`: ignoring the "cause" property of `Throwable` on GAE #1359: Improve `JsonNode` deserializer to create `FloatNode` if parser supports #1362: ObjectReader.readValues()` ignores offset and length when reading an array (reported by wastevenson@github) #1363: The static field ClassUtil.sCached can cause a class loader leak (reported by Stuart D) #1368: Problem serializing `JsonMappingException` due to addition of non-ignored `processor` property (added in 2.7) (reported, suggesed fix by Josh C) #1383: Problem with `@JsonCreator` with 1-arg factory-method, implicit param names 2.7.7 (27-Aug-2016) #1322: EnumMap keys not using enum's `@JsonProperty` values unlike Enum values (reported by MichaelChambers@github) #1332: Fixed ArrayIndexOutOfBoundException for enum by index deser (reported by Max D) #1344: Deserializing locale assumes JDK separator (underscore), does not accept RFC specified (hyphen) (reported by Jim M) 2.7.6 (23-Jul-2016) #1215: Problem with type specialization for Maps with `@JsonDeserialize(as=subtype)` (reported by brentryan@github) #1279: Ensure DOM parsing defaults to not expanding external entities #1288: Type id not exposed for `JsonTypeInfo.As.EXTERNAL_PROPERTY` even when `visible` set to `true` #1299: Timestamp deserialization error (reported by liyuj@github) #1301: Problem with `JavaType.toString()` for recursive (self-referential) types (reported by Brian P) #1307: `TypeWrappedDeserializer` doesn't delegate the `getNullValue()` method to `_deserializer` (reported by vfries@github) 2.7.5 (11-Jun-2016) #1098: DeserializationFeature.FAIL_ON_INVALID_SUBTYPE does not work with `JsonTypeInfo.Id.CLASS` (reported by szaccaria@github) #1223: `BasicClassIntrospector.forSerialization(...).findProperties` should respect MapperFeature.AUTO_DETECT_GETTERS/SETTERS? (reported by William H) #1225: `JsonMappingException` should override getProcessor() (reported by Nick B) 2.6.8 (if ever released) #1383: Problem with `@JsonCreator` with 1-arg factory-method, implicit param names 2.6.7 (05-Jun-2016) #1194: Incorrect signature for generic type via `JavaType.getGenericSignature #1228: @JsonAnySetter does not deserialize null to Deserializer's NullValue (contributed by Eric S) #1231: `@JsonSerialize(as=superType)` behavior disallowed in 2.7.4 (reported by Mark W) #1248: `Annotated` returns raw type in place of Generic Type in 2.7.x (reported by Andrew J, apjoseph@github) #1253: Problem with context handling for `TokenBuffer`, field name #1260: `NullPointerException` in `JsonNodeDeserializer` (reported by Eric S) 2.7.4 (29-Apr-2016) #1122: Jackson 2.7 and Lombok: 'Conflicting/ambiguous property name definitions' #1178: `@JsonSerialize(contentAs=superType)` behavior disallowed in 2.7 #1186: SimpleAbstractTypeResolver breaks generic parameters (reported by tobiash@github) #1189: Converter called twice results in ClassCastException (reported by carrino@github) #1191: Non-matching quotes used in error message for date parsing #1194: Incorrect signature for generic type via `JavaType.getGenericSignature #1195: `JsonMappingException` not Serializable due to 2.7 reference to source (parser) (reported by mjustin@github) #1197: `SNAKE_CASE` doesn't work when using Lombok's `@AllArgsConstructor` #1198: Problem with `@JsonTypeInfo.As.EXTERNAL_PROPERTY`, `defaultImpl`, missing type id, NPE #1203: `@JsonTypeInfo` does not work correctly for ReferenceTypes like `AtomicReference` #1208: treeToValue doesn't handle POJONodes that contain exactly the requested value type (reported by Tom M) - Improve handling of custom content (de)serializers for `AtomicReference` 2.7.3 (16-Mar-2016) #1125: Problem with polymorphic types, losing properties from base type(s) #1150: Problem with Object id handling, explicit `null` token (reported by Xavi T) #1154: @JsonFormat.pattern on dates is now ignored if shape is not explicitely provided (reported by Yoann R) #1161: `DeserializationFeature.READ_ENUMS_USING_TO_STRING` not dynamically changeable with 2.7 (reported by asa-git@github) - Minor fixes to `AnnotationIntrospector.findEnumValues()` to correct problems with merging of explicit enum value names. 2.7.2 (26-Feb-2016) #1124: JsonAnyGetter ignores JsonSerialize(contentUsing=...) (reported by Jiri M) #1128: UnrecognizedPropertyException in 2.7.1 for properties that work with version 2.6.5 (reported by Roleek@github) #1129: When applying type modifiers, don't ignore container types. #1130: NPE in `StdDateFormat` hashCode and equals (reported by Kazuki S, kazuki43zoo@github) #1134: Jackson 2.7 doesn't work with jdk6 due to use of `Collections.emptyIterator()` (reported by Timur S, saladinkzn@github) 2.7.1-1 (03-Feb-2016) Special one-off "micro patch" for: #1115: Problems with deprecated `TypeFactory.constructType(type, ctxt)` methods if `ctxt` is `null` 2.7.1 (02-Feb-2016) #1079: Add back `TypeFactory.constructType(Type, Class)` as "deprecated" in 2.7.1 #1083: Field in base class is not recognized, when using `@JsonType.defaultImpl` (reported by Julian H) #1095: Prevent coercion of `int` from empty String to `null` if `DeserializationFeature .FAIL_ON_NULL_FOR_PRIMITIVES` is `true` (reported by yzmyyff@github) #1102: Handling of deprecated `SimpleType.construct()` too minimalistic (reported by Thibault K) #1109: @JsonFormat is ignored by the DateSerializer unless either a custom pattern or a timezone are specified (contributed by Aleks S) 2.7.0 (10-Jan-2016) #76: Problem handling datatypes Recursive type parameters (reported by Aram K) #357: StackOverflowError with contentConverter that returns array type (reported by Florian S) #432: `StdValueInstantiator` unwraps exceptions, losing context (reported by Miles K) #497: Add new JsonInclude.Include feature to exclude maps after exclusion removes all elements #803: Allow use of `StdDateFormat.setLenient()` (suggested by raj-ghodke@github) #819: Add support for setting `FormatFeature` via `ObjectReader`, `ObjectWriter` #857: Add support for java.beans.Transient (requires Java 7) (suggested by Thomas M) #898: Add `ObjectMapper.getSerializerProviderInstance()` #905: Add support for `@ConstructorProperties` (requires Java 7) (requested by Jonas K) #909: Rename PropertyNamingStrategy CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES as SNAKE_CASE, PASCAL_CASE_TO_CAMEL_CASE as UPPER_CAMEL_CASE (suggested by marcottedan@github) #915: ObjectMapper default timezone is GMT, should be UTC (suggested by Infrag@github) #918: Add `MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING` (contributed by David H) #924: `SequenceWriter.writeAll()` could accept `Iterable` (suggested by Jiri-Kremser@github( #932: Rewrite ser/deser for `AtomicReference`, based on "optional" ser/desers #933: Close some gaps to allow using the `tryToResolveUnresolved` flows #936: Deserialization into List subtype with JsonCreator no longer works (reported by adamjoeldavis@github) #948: Support leap seconds, any number of millisecond digits for ISO-8601 Dates. (contributed by Jesse W) #952: Revert non-empty handling of primitive numbers wrt `NON_EMPTY`; make `NON_DEFAULT` use extended criteria #957: Merge `datatype-jdk7` stuff in (java.nio.file.Path handling) #959: Schema generation: consider active view, discard non-included properties #963: Add PropertyNameStrategy `KEBAB_CASE` (requested by Daniel M) #978: ObjectMapper#canSerialize(Object.class) returns false even though FAIL_ON_EMPTY_BEANS is disabled (reported by Shumpei A) #997: Add `MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS` #998: Allow use of `NON_DEFAULT` for POJOs without default constructor #1000: Add new mapping exception type for enums and UUIDs (suggesed by natnan@github) #1010: Support for array delegator (contributed by Hugo W) #1011: Change ObjectWriter::withAttributes() to take a Map with some kind of wildcard types (suggested by David B) #1043: @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) does not work on fields (reported by fabiolaa@github) #1044: Add `AnnotationIntrospector.resolveSetterConflict(...)` to allow custom setter conflict resolution (suggested by clydebarrow@github) - Make `JsonValueFormat` (self-)serializable, deserializable, to/from valid external value (as per JSON Schema spec) INCOMPATIBILITIES: - While unlikely to be problematic, #959 above required an addition of `SerializerProvider` argument for `depositSchemaProperty()` method `BeanProperty` and `PropertyWriter` interfaces - JDK baseline now Java 7 (JDK 1.7), from Java 6/JDK 1.6 2.6.6 (05-Apr-2016) #1088: NPE possibility in SimpleMixinResolver (reported by Laird N) #1099: Fix custom comparator container node traversal (contributed by Daniel N) #1108: Jackson not continue to parse after DeserializationFeature.FAIL_ON_INVALID_SUBTYPE error (reported by jefferyyuan@github) #1112: Detailed error message from custom key deserializer is discarded (contributed by Benson M) #1120: String value omitted from weirdStringException (reported by Benson M) #1123: Serializing and Deserializing Locale.ROOT (reported by hookumsnivy@github) 2.6.5 (19-Jan-2016) #1052: Don't generate a spurious NullNode after parsing an embedded object (reported by philipa@github) #1061: Problem with Object Id and Type Id as Wrapper Object (regression in 2.5.1) #1073: Add try-catch around `java.sql` type serializers (suggested by claudemt@github) #1078: ObjectMapper.copy() still does not preserve _registeredModuleTypes (reported by ajonkisz@github) 2.6.4 (07-Dec-2015) #984: JsonStreamContexts are not build the same way for write.. and convert methods (reported by Antibrumm@github) #989: Deserialization from "{}" to java.lang.Object causes "out of END_OBJECT token" error (reported by Ievgen P) #1003: JsonTypeInfo.As.EXTERNAL_PROPERTY does not work with a Delegate (reported by alexwen@github) #1005: Synthetic constructors confusing Jackson data binding (reported by Jayson M) #1013: `@JsonUnwrapped` is not treated as assuming `@JsonProperty("")` (reported by David B) #1036: Problem with case-insensitive deserialization (repoted by Dmitry R) - Fix a minor problem with `@JsonNaming` not recognizing default value 2.6.3 (12-Oct-2015) #749: `EnumMap` serialization ignores `SerializationFeature.WRITE_ENUMS_USING_TO_STRING` (reported by scubasau@github) #938: Regression: `StackOverflowError` with recursive types that contain `Map.Entry` (reported by jloisel@github) #939: Regression: DateConversionError in 2.6.x (reported by Andreas P, anpieber@github) #940: Add missing `hashCode()` implementations for `JsonNode` types that did not have them (contributed by Sergio M) #941: Deserialization from "{}" to ObjectNode field causes "out of END_OBJECT token" error (reported by Sadayuki F) #942: Handle null type id for polymorphic values that use external type id (reported by Warren B, stormboy@github) #943: Incorrect serialization of enum map key (reported by Benson M) #944: Failure to use custom deserializer for key deserializer (contributed by Benson M) #949: Report the offending substring when number parsing fails (contributed by Jesse W) #965: BigDecimal values via @JsonTypeInfo/@JsonSubTypes get rounded (reported by gmjabs@github) 2.6.2 (14-Sep-2015) #894: When using withFactory on ObjectMapper, the created Factory has a TypeParser which still has the original Factory (reported by lufe66@github) #899: Problem serializing `ObjectReader` (and possibly `ObjectMapper`) #913: ObjectMapper.copy does not preserve MappingJsonFactory features (reported, fixed by Daniel W) #922: ObjectMapper.copy() does not preserve _registeredModuleTypes #928: Problem deserializing External Type Id if type id comes before POJO 2.6.1 (09-Aug-2015) #873: Add missing OSGi import #881: BeanDeserializerBase having issues with non-CreatorProperty properties. (reported by dharaburda@github) #884: ArrayIndexOutOfBoundException for `BeanPropertyMap` (with ObjectId) (reported by alterGauner@github) #889: Configuring an ObjectMapper's DateFormat changes time zone (reported by Andy W, wilkinsona@github) #890: Exception deserializing a byte[] when the target type comes from an annotation (reported by gmjabs@github) 2.6.0 (19-Jul-2015) #77: Allow injection of 'transient' fields #95: Allow read-only properties with `@JsonIgnoreProperties(allowGetters=true)` #222: EXTERNAL_PROPERTY adds property multiple times and in multiple places (reported by Rob E, thatsnotright@github) #296: Serialization of transient fields with public getters (add MapperFeature.PROPAGATE_TRANSIENT_MARKER) (suggested by Michal L) #312: Support Type Id mappings where two ids map to same Class #348: ObjectMapper.valueToTree does not work with @JsonRawValue (reported by Chris P, pimlottc@github) #504: Add `DeserializationFeature.USE_LONG_FOR_INTS` (suggested by Jeff S) #624: Allow setting external `ClassLoader` to use, via `TypeFactory` #649: Make `BeanDeserializer` use new `parser.nextFieldName()` and `.hasTokenId()` methods #664: Add `DeserializationFeature.ACCEPT_FLOAT_AS_INT` to prevent coercion of floating point numbers int `int`/`long`/`Integer`/`Long` (requested by wenzis@github) #677: Specifying `Enum` value serialization using `@JsonProperty` (requested by Allen C, allenchen1154@github) #679: Add `isEmpty()` implementation for `JsonNode` serializers #688: Provide a means for an ObjectMapper to discover mixin annotation classes on demand (requested by Laird N) #689: Add `ObjectMapper.setDefaultPrettyPrinter(PrettyPrinter)` (requested by derknorton@github) #696: Copy constructor does not preserve `_injectableValues` (reported by Charles A) #698: Add support for referential types (ReferenceType) #700: Cannot Change Default Abstract Type Mapper from LinkedHashMap (reported by wealdtech@github) #725: Auto-detect multi-argument constructor with implicit names if it is the only visible creator #727: Improve `ObjectWriter.forType()` to avoid forcing base type for container types #734: Add basic error-recovery for `ObjectReader.readValues()` #737: Add support for writing raw values in TokenBuffer (suggested by Guillaume S, gsmet@github) #740: Ensure proper `null` (as empty) handling for `AtomicReference` #741: Pass `DeserializationContext' argument for `JsonDeserializer` methods "getNullValue()" and "getEmptyValue()" #743: Add `RawValue` helper type, for piping raw values through `TokenBuffer` #756: Disabling SerializationFeature.FAIL_ON_EMPTY_BEANS does not affect `canSerialize()` (reported by nickwongdev@github) #762: Add `ObjectWriter.withoutRootName()`, `ObjectReader.withoutRootName()` #765: `SimpleType.withStaticTyping()` impl incorrect #769: Fix `JacksonAnnotationIntrospector.findDeserializer` to return `Object` (as per `AnnotationIntrospector`); similarly for other `findXxx(De)Serializer(...)` methods #777: Allow missing build method if its name is empty ("") (suggested by galdosd@github) #781: Support handling of `@JsonProperty.required` for Creator methods #787: Add `ObjectMapper setFilterProvider(FilterProvider)` to allow chaining (suggested by rgoldberg@githin) #790: Add `JsonNode.equals(Comparator, JsonNode)` to support configurable/external equality comparison #794: Add `SerializationFeature.WRITE_DATES_WITH_ZONE_ID` to allow inclusion/exclusion of timezone id for date/time values (as opposed to timezone offset) #795: Converter annotation not honored for abstract types (reported by myrosia@github) #797: `JsonNodeFactory` method `numberNode(long)` produces `IntNode` for small numbers #810: Force value coercion for `java.util.Properties`, so that values are `String`s #811: Add new option, `JsonInclude.Include.NON_ABSENT` (to support exclusion of JDK8/Guava Optionals) #812: Java 8 breaks Class-value annotation properties, wrt generics: need to work around #813: Add support for new property of `@JsonProperty.access` to support read-only/write-only use cases #820: Add new method for `ObjectReader`, to bind from JSON Pointer position (contributed by Jerry Y, islanderman@github) #824: Contextual `TimeZone` changes don't take effect wrt `java.util.Date`, `java.util.Calendar` serialization #826: Replaced synchronized HashMap with ConcurrentHashMap in TypeDeserializerBase._findDeserializer (contributed by Lars P) #827: Fix for polymorphic custom map key serializer (reported by mjr6140@gitgub) #828: Respect DeserializationFeatures.WRAP_EXCEPTIONS in CollectionDeserializer (contributed by Steve G, thezerobit@github) #840: Change semantics of `@JsonPropertyOrder(alphabetic)` to only count `true` value #848: Custom serializer not used if POJO has `@JsonValue` #849: Possible problem with `NON_EMPTY` exclusion, `int`s, `Strings` #868: Annotations are lost in the case of duplicate methods - Remove old cglib compatibility tests; cause problems in Eclipse - Add `withFilterId()` method in `JsonSerializer` (demote from `BeanSerializer`) 2.5.5 (07-Dec-2015) #844: Using JsonCreator still causes invalid path references in JsonMappingException (reported by Ian B) #852: Accept scientific number notation for quoted numbers too #878: serializeWithType on BeanSerializer does not setCurrentValue (reported by Chi K, chikim79@github) 2.5.4 (09-Jun-2015) #676: Deserialization of class with generic collection inside depends on how is was deserialized first time (reported by lunaticare@github) #771: Annotation bundles ignored when added to Mixin (reported by Andrew D) #774: NPE from SqlDateSerializer as _useTimestamp is not checked for being null (reported by mrowkow@github) #785: Add handlings for classes which are available in `Thread.currentThread().getContextClassLoader()` (contributed by Charles A) #792: Ensure Constructor Parameter annotations are linked with those of Field, Getter, or Setter #793: `ObjectMapper.readTree()` does not work with defaultTyping enabled (reported by gracefulgopher@github) #801: Using `@JsonCreator` cause generating invalid path reference in `JsonMappingException` (contributed by Kamil B) #815: Presence of PropertyNamingStrategy Makes Deserialization fail #816: Allow date-only ISO strings to have no time zone (contributed by Andrew G) - Fix handling of Enums wrt JSON Schema, when 'toString()' used for serialization 2.5.3 (24-Apr-2015) #731: XmlAdapter result marshaling error in case of ValueType=Object (reported, debugged by Dmitry S) #742: Allow deserialization of `null` Object Id (missing already allowed) #744: Custom deserializer with parent object update failing (reported by migel@github) #745: EnumDeserializer.deserializerForCreator fails when used to deserialize a Map key (contributed by John M) #761: Builder deserializer: in-compatible type exception when return type is super type (contributed by Alexey G) #766: Fix Infinite recursion (StackOverflowError) when serializing a SOAP object (contributed by Alain G) 2.5.2 (29-Mar-2015) #609: Problem resolving locally declared generic type (repoted by Hal H) #691: NullSerializer for MapProperty failing when using polymorphic handling (reported by Antibrumm@github) #703: Multiple calls to ObjectMapper#canSerialize(Object.class) returns different values (reported by flexfrank@github) #705: JsonAnyGetter doesn't work with JsonSerialize (except with keyUsing) (reported by natnan@github) #728: TypeFactory#_fromVariable returns unknownType() even though it has enough information to provide a more specific type (reported by jkochaniak@github) #733: MappingIterator should move past errors or not return hasNext() == true (reported by Lorrin N, lorrin@github) #738: @JsonTypeInfo non-deterministically ignored in 2.5.1 (concurrency issue) (reported by Dylan S, dylanscott@github) - Improvement to handling of custom `ValueInstantiator` for delegating mode; no more NPE if `getDelegateCreator()` returns null - Refactor `TypedKey` into separate util class 2.5.1 (06-Feb-2015) #667: Problem with bogus conflict between single-arg-String vs `CharSequence` constructor #669: JSOG usage of @JsonTypeInfo and @JsonIdentityInfo(generator=JSOGGenerator.class) fails (reported by ericali78@github) #671: Adding `java.util.Currency` deserialization support for maps (contributed by Alexandre S-C) #674: Spring CGLIB proxies not handled as intended (reported by Zoltan F) #682: Class-valued Map keys not serialized properly (reported by Ludevik@github) #684: FAIL_ON_NUMBERS_FOR_ENUMS does not fail when integer value is quoted (reported by kllp@github) #696: Copy constructor does not preserve `_injectableValues` (reported by Charles A) - Add a work-around in `ISO8601DateFormat` to allow omission of ':' from timezone - Bit more work to complete #633 2.5.0 (01-Jan-2015) #47: Support `@JsonValue` for (Map) key serialization #113: Problem deserializing polymorphic types with @JsonCreator #165: Add `DeserializationContext.getContextualType()` to let deserializer known the expected type. #299: Add `DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS` to allow missing Object Ids (as global default) #408: External type id does not allow use of 'visible=true' #421: @JsonCreator not used in case of multiple creators with parameter names (reported by Lovro P, lpandzic@github) #427: Make array and Collection serializers call `JsonGenerator.writeStartArray(int)` #521: Keep bundle annotations, prevent problems with recursive annotation types (reported by tea-dragon@github) #527: Add support for `@JsonInclude(content=Include.NON_NULL)` (and others) for Maps #528: Add support for `JsonType.As.EXISTING_PROPERTY` (reported by heapifyman@github; implemented by fleebytes@github) #539: Problem with post-procesing of "empty bean" serializer; was not calling 'BeanSerializerModifier.modifySerializer()` for empty beans (reported by Fabien R, fabienrenaud@github) #540: Support deserializing `[]` as null or empty collection when the java type is a not an object, `DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT` (requested by Fabien R, fabienrenaud@github) #543: Problem resolving self-referential recursive types (reported by ahgittin@github) #550: Minor optimization: prune introspection of "well-known" JDK types #552: Improved handling for ISO-8601 (date) format (contributed by Jerome G, geronimo-iia@github) #559: Add `getDateFormat()`, `getPropertyNamingStrategy()` in `ObjectMapper` #560: @JsonCreator to deserialize BigInteger to Enum (requested by gisupp@github) #565: Add support for handling `Map.Entry` #566: Add support for case-insensitive deserialization (`MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES`) (contributed by Michael R) #571: Add support in ObjectMapper for custom `ObjectReader`, `ObjectWriter` (sub-classes) #572: Override default serialization of Enums (requested by herau@github) #576: Add fluent API for adding mixins (contributed by Adam S, adstro@github) #594: `@JsonValue` on enum not used when enum value is a Map key (reported by chrylis@github) #596: Add support for `@JsonProperty.defaultValue`, exposed via `BeanProperty.getMetadata().getDefaultValue()` #597: Improve error messaging for cases where JSON Creator returns null (which is illegal) (contributed by Aurelien L) #599: Add a simple mechanism for avoiding multiple registrations of the same module #607: Allow (re)config of `JsonParser.Feature`s via `ObjectReader` #608: Allow (re)config of `JsonGenerator.Feature`s via `ObjectWriter` #614: Add a mechanism for using `@JsonCreator.mode` for resolving possible ambiguity between delegating- and property-based creators #616: Add `SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS` #622: Support for non-scalar ObjectId Reference deserialiazation (like JSOG) #623: Add `StdNodeBasedDeserializer` #630: Add `KeyDeserializer` for `Class` #631: Update `current value` of `JsonParser`, `JsonGenerator` from standard serializers, deserializers (suggested by Antibrumm@github) #633: Allow returning null value from IdResolver to make type information optional (requested by Antibrumm@github) #634: Add `typeFromId(DatabindContext,String)` in `TypeIdDeserializer` #636: `ClassNotFoundException` for classes not (yet) needed during serialization (contributed by mspiegel@github) #638: Add annotation-based method(s) for injecting properties during serialization (using @JsonAppend, VirtualBeanPropertyWriter) #647: Deserialization fails when @JsonUnwrapped property contains an object with same property name (reported by Konstantin L) #653: Jackson doesn't follow JavaBean naming convention (added `MapperFeature.USE_STD_BEAN_NAMING`) #654: Add support for (re)configuring `JsonGenerator.setRootValueSeparator()` via `ObjectWriter` #655: Add `ObjectWriter.writeValues()` for writing value sequences #660: `@JsonCreator`-annotated factory method is ignored if constructor exists - Allow use of `Shape.ARRAY` for Enums, as an alias to 'use index' - Start using `JsonGenerator.writeStartArray(int)` to help data formats that benefit from knowing number of elements in arrays (and would otherwise need to buffer values to know length) - Added new overload for `JsonSerializer.isEmpty()`, to eventually solve #588 - Improve error messaging (related to [jaxb-annotations#38]) to include known subtype ids. 2.4.6 (23-Apr-2015) #735: (complete fix) @JsonDeserialize on Map with contentUsing custom deserializer overwrites default behavior (reported by blackfyre512@github) (regression due to #604) $744: Custom deserializer with parent object update fails 2.4.5.1 (26-Mar-2015) Special one-off "micro patch" for: #706: Add support for `@JsonUnwrapped` via JSON Schema module #707: Error in getting string representation of an ObjectNode with a float number value (reported by @navidqar) #735: (partial) @JsonDeserialize on Map with contentUsing custom deserializer overwrites default behavior 2.4.5 (13-Jan-2015) #635: Reduce cachability of `Map` deserializers, to avoid problems with per-property config changes (regression due to #604) #656: `defaultImpl` configuration is ignored for `WRAPPER_OBJECT` - Solve potential cyclic-resolution problem for `UntypedObjectDeserializer` 2.4.4 (24-Nov-2014) (jackson-core)#158: Setter confusion on assignable types (reported by tsquared2763@github) #245: Calls to ObjectMapper.addMixInAnnotations() on an instance returned by ObjectMapper.copy() don't work (reported by Erik D) #580: delegate deserializers choke on a (single) abstract/polymorphic parameter (reported by Ian B, tea-dragon@github) #590: Binding invalid Currency gives nonsense at end of the message (reported by Jerbell@github) #592: Wrong `TokenBuffer` delegate deserialization using `@JsonCreator` (reported by Eugene L) #601: ClassCastException for a custom serializer for enum key in `EnumMap` (reported by Benson M) #604: `Map` deserializers not being cached, causing performance problems #610: Fix forward reference in hierarchies (contributed by zeito@github) #619: Off by one error in AnnotatedWithParams (reported by stevetodd@github) - Minor fix to `EnumSerializer` regarding detection "serialize using index" - Minor fix to number serializers, to call proper callback for schema generation 2.4.3 (02-Oct-2014) #496: Wrong result with `new TextNode("false").asBoolean(true)` (reported by Ivar R, ivarru@github) #511: DeserializationFeature.FAIL_ON_INVALID_SUBTYPE does not work (reported by sbelikov@github) #523: MapDeserializer and friends do not report the field/key name for mapping exceptions (reported by Ian B, tea-dragon@github) #524: @JsonIdentityReference(alwaysAsId = true) Custom resolver is reset to SimpleObjectIdResolver (reported by pkokorev@github) #541: @JsonProperty in @JsonCreator is conflicting with POJOs getters/attributes (reported by fabienrenaud@github) #543: Problem resolving self-referential generic types #570: Add Support for Parsing All Compliant ISO-8601 Date Formats (requested by pfconrey@github) - Fixed a problem with `acceptJsonFormatVisitor` with Collection/array types that are marked with `@JsonValue`; could cause NPE in JSON Schema generator module. 2.4.2 (14-Aug-2014) #515: Mixin annotations lost when using a mixin class hierarchy with non-mixin interfaces (reported by 'stevebread@github') - Fixed a problem related to [jackson-dataformat-smile#19]. 2.4.1.2 (12-Jul-2014) Special one-off "micro patch" for: #503: Concurrency issue inside com.fasterxml.jackson.databind.util.LRUMap.get(Object) (reported by fjtc@github) 2.4.1.1 (18-Jun-2014) Special one-off "micro patch" for: #491: Temporary work-around for issue #490 (full fix for 2.5 needs to be in `jackson-annotations`) #506: Index is never set for Collection and Array in InvalidFormatException.Reference (reported by Fabrice D, fabdouglas@github) - Fixed a problem related to [jackson-dataformat-smile#19]. 2.4.1 (17-Jun-2014) #479: NPE on trying to deserialize a `String[]` that contains null (reported by huxi@github) #482: Make date parsing error behavior consistent with JDK (suggested by Steve S, sanbeg@github) #489 (partial): TypeFactory cache prevents garbage collection of custom ClassLoader (reported by sftwrengnr@github) 2.4.0 (02-Jun-2014) #81: Allow use of @JsonUnwrapped with typed (@JsonTypeInfo) classes, provided that (new) feature `SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS` is disabled (constributed by Ben F, UnquietCode@github) #88: Prevent use of type information for `JsonNode` via default typing (reported by electricmonk@github) #149: Allow use of "stringified" indexes for Enum values (requested by chenboxiang@github) #176: Allow use external Object Id resolver (to use with @JsonIdentityInfo etc) (implemented by Pascal G) #193: Conflicting property name definitions (reported by Stuart J, sgjohnston@github) #323: Serialization of the field with deserialization config (reported by metanet@github) #327: Should not consider explicitly differing renames a fail, as long as all are explicit #335: Allow use of `@JsonPropertyOrder(alphabetic=true)` for Map properties #351: ObjectId does not properly handle forward references during deserialization (contributed by pgelinas) #352 Add `ObjectMapper.setConfig()` for overriding `SerializationConfig`/`DeserializationConfig` #353: Problems with polymorphic types, `JsonNode` (related to #88) (reported by cemo@github) #359: Converted object not using explicitly annotated serializer (reported by Florian S [fschopp@github]) #369: Incorrect comparison for renaming in `POJOPropertyBuilder` #375: Add `readValue()`/`readPropertyValue()` methods in `DeserializationContext` #376: Add support for `@JsonFormat(shape=STRING)` for number serializers #381: Allow inlining/unwrapping of value from single-component JSON array (contributed by yinzara@github) #390: Change order in which managed/back references are resolved (now back-ref first, then forward) (requested by zAlbee@github) #407: Properly use null handlers for value types when serializer Collection and array types (contributed by Will P) #425: Add support for using `Void.class` as "no class", instead of `NoClass.class` #428: `PropertyNamingStrategy` will rename even explicit name from `@JsonProperty` (reported by turskip@github) #435: Performance bottleneck in TypeFactory._fromClass (reported by Sean D, sdonovanuk@github) #434: Ensure that DecimalNodes with mathematically equal values are equal (contributed by Francis G) #435: Performance bottleneck in TypeFactory._fromClass (reported by sdonovanuk@github) #438: Add support for accessing `@JsonProperty(index=N)` annotations #442: Make `@JsonUnwrapped` indicate property inclusion (suggested by Ben F) #447: ArrayNode#addAll should accept Collection (suggested by alias@github) #461: Add new standard naming strategy, `PropertyNamingStrategy.LowerCaseStrategy` #463: Add 'JsonNode.asText(String defaultValue)` (suggested by Chris C) #464: Include `JsonLocation` in more mapping exceptions (contributed by Andy C (q3aiml@github)) #465: Make it easier to support serialization of custom subtypes of `Number` #467: Unwanted POJO's embedded in tree via serialization to tree (reported by Benson M) - Slightly improve `SqlDateSerializer` to support `@JsonFormat` - Improve handling of native type ids (YAML, CBOR) to use non-native type ids as fallback 2.3.5 (13-Jan-2015) #496: Wrong result for TextNode("false").asBoolean(true) (reported by Ivar R, ivarru@github) #543: Problems resolving self-referential generic types. #656: defaultImpl configuration is ignored for WRAPPER_OBJECT 2.3.4 (17-Jul-2014) #459: BeanDeserializerBuilder copy constructor not copying `_injectables` #462: Annotation-provided Deserializers are not contextualized inside CreatorProperties (reported by aarondav@github) 2.3.3 (10-Apr-2014) #420: Remove 'final' modifier from `BeanDeserializerBase.deserializeWithType` (requested by Ghoughpteighbteau@github) #422: Allow use of "True" and "False" as aliases for booleans when coercing from JSON String #423: Fix `CalendarSerializer` to work with custom format (reported by sergeymetallic@github) #433: `ObjectMapper`'s `.valueToTree()` wraps `JsonSerializable` objects into a POJONode (reported by Francis G) - Fix null-handling for `CollectionSerializer` 2.3.2 (01-Mar-2014) #378: Fix a problem with custom enum deserializer construction (reported by BokoEnos@github) #379: Fix a problem with (re)naming of Creator properties; needed to make Paranamer module work with NamingStrategy. (reported by Chris P, cpilsworth@github) #398: Should deserialize empty (not null) URI from empty String (reported by pgieser@github) #406: @JsonTypeIdResolver not working with external type ids (reported by Martin T) #411: NumberDeserializers throws exception with NaN and +/- Infinity (reported by clarkbreyman@github) #412: ObjectMapper.writerWithType() does not change root name being used (repoted by jhalterman@github) - Added `BeanSerializerBase._serializeObjectId()` needed by modules that override standard BeanSerializer; specifically, XML module. 2.3.1 (28-Dec-2013) #346: Fix problem deserializing `ObjectNode`, with @JsonCreator, empty JSON Object (reported by gaff78@github) #358: `IterableSerializer` ignoring annotated content serializer (reported by Florian S) #361: Reduce sync overhead for SerializerCache by using volatile, double-locking (contributed by stuartwdouglas@github) #362: UUID output as Base64 String with ObjectMapper.convertValue() (reported by jknack@github) #367: Make `TypeNameIdResolver` call `TypeResolver` for resolving base type (suggested by Ben F) #370: Fail to add Object Id for POJO with no properties (reported by jh3141@github) - Fix for [jackson-module-afterburner#38]: need to remove @JacksonStdImpl from `RawSerializer`, to avoid accidental removal of proper handling. 2.3.0 (13-Nov-2013) #48: Add support for `InetSocketAddress` (contributed by Nick T) #152: Add support for traversing `JsonNode` with (new!) `JsonPointer` implementation (suggested by fge@github) #208: Accept "fromString()" as an implicit Creator (factory) method (alias for "valueOf()") (requested by David P) #215: Allow registering custom `CharacterEscapes` to use for serialization, via `ObjectWriter.with(CharacterEscapes)` (and `ObjectMapper.writer(CharacterEscapes)`) #227: Allow "generic" Enum serializers, deserializers, via `SimpleModule` #234: Incorrect type information for deeply nested Maps (reported by Andrei P) #237: Add `DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY` to optionally throw `JsonMappingException` on duplicate keys, tree model (`JsonNode`) #238: Allow existence of overlapping getter, is-getter (choose 'regular' getter) #239: Support `ByteBuffer` (suggested by mckamey@github) #240: Make sure `@JsonSerialize.include` does not accidentally override class inclusion settings (requested by thierryhenrio@github) #253: `DelegatingDeserializer` causes problems for Managed/BackReferences (reported by bfelaco@github) #257: Make `UntypedObjectDeserializer` support overides for `List`, `Map` etc #268: Add new variant of `ObjectMapper.canSerialize()` that can return `Throwable` that caused false to be returned (if any) #269: Add support for new `@JsonPropertyDescription` via `AnnotationIntrospector` as well as `BeanProperty.getMedata().getDescription()` #270: Add `SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID` to allow use of equality (instead of identity) for figuring out when to use Object Id (requested by beku8@github) #271: Support handling of `@JsonUnwrapped` for in-built JSON Schema generation #277: Make `TokenBuffer` support new native type and object ids #302: Add `setNamingStrategy` in `Module.SetupContext` (suggested by Miguel C) #305: Add support for accessing `TypeFactory` via `TypeIdResolverBase` (not yet via `TypeIdResolver` interface), other configuration #306: Allow use of `@JsonFilter` for properties, not just classes #307: Allow use of `@JsonFilter` for Maps in addition to POJOs #308: Improve serialization and deserialization speed of `java.util.UUID` by 4x (suggested by David P) #310: Improve `java.util.UUID` serialization with binary codecs, to use "raw" form. #311: Make sure that "creator properties" are alphabetically ordered too, if so requested. #315: Allow per-property definition of null serializer to use, using new `@JsonSerialize(nullsUsing=xxx)` annotation property #317: Fix `JsonNode` support for nulls bound to `ObjectNode`, `ArrayNode` (contributed by Seth P) #318: Problems with `ObjectMapper.updateValue()`, creator property-backed accessors #319: Add support for per-call ("contextual") attributes, with defaulting, to allow keeping track of state during (de)serialization #324: Make sure to throw `JsonMappingException` from `EnumDeserializer` creator, not `IllegalArgumentException` (reported by beverku@github) #326: Support `@JsonFilter` for "any getter" properties #334: Make `ArrayNode`, `ObjectNode` non-final again #337: `AnySetter` does not support polymorphic types (reported by askvortsov@github) #340: AtomicReference not working with polymorphic types #342: Add `DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES` to make `ObjectMapper` throw exception when encountering explicitly ignored properties (requested by Ruslan M) [JACKSON-890]: Support managed/back-references for polymorphic (abstract) types - Add 'BeanPropertyWriter.isUnwrapping()' for future needs (by Afterburner) - Add coercions from String "null" (as if null token was parsed) for primitives/Wrappers. - Add `JsonDeserializer.handledType()` 2.2.4 (10-Jun-2014) #292: Problems with abstract `Map`s, `Collection`s, polymorphic deserialization #324: EnumDeserializer should throw JsonMappingException, not IllegalArgumentException #346: Problems deserializing `ObjectNode` from empty JSON Object, with @JsonCreator 2.2.3 (22-Aug-2013) #234: Problems with serializing types for deeply nested generic Maps, default typing #251: SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN ignored with JsonNode serialization (reported by fge@github) #259: Fix a problem with JSON Schema generation for `@JsonValue` (reported by Lior L) #267: Handle negative, stringified timestamps (reported by Drecth@github) #281: Make `NullNode` use configured null-value serializer #287: Fix problems with converters, Maps with Object values (reported by antubis@github) #288: Fix problem with serialization converters assigned with annotations (reported by cemo@github) 2.2.2 (26-May-2013) #216: Problems with Android, 1.6-only types #217: JsonProcessingExceptions not all wrapped as expected (reported by karldmoore@github) #220: ContainerNode missing 'createNumber(BigInteger)' (reported by Pascal G) #223: Duplicated nulls with @JsonFormat(shape=Shape.ARRAY) (reported by lukegh@github) #226: Field mapping fail on deserialization to common referenced object when @JsonUnwrapped is used (reported by ikvia@github) #232: Converting bound BigDecimal value to tree fails with WRITE_BIGDECIMAL_AS_PLAIN (reported by celkings@github) - Minor fix to handle primitive types for key deserializer lookups - Add convenience method `MappingIterator.getCurrentLocation()` (suggested by Tomdz@github) 2.2.1 (03-May-2013) #214: Problem with LICENSE, NOTICE, Android packaging (reported by thierryd@github) 2.2.0 (22-Apr-2013) Fixes: #23: Fixing typing of root-level collections #118: JsonTypeInfo.as.EXTERNAL_PROPERTY not working correctly with missing type id, scalar types #130: TimeZone not set for GregorianCalendar, even if configured #144: MissingNode.isValueNode() should return 'false' (reported by 'fge@github') #146: Creator properties were not being renamed as expected (contributed by Christoper C) #188: Problem with ObjectId serialization, 'alwaysAsId' references Improvements: #116: JavaType implements `java.lang.reflect.Type` (as does `TypeReference`) #147: Defer reporting of problems with missing creator parameters (contributed by Christoper C) #155: Make `ObjectNode` and `ArrayNode` final (other node types already were) (requested by fge@github) #161: Add deserializer for java.util.concurrent.ArrayBlockingQueue #173: Add 'JsonNode.traverse(ObjectCodec)' for convenience #181: Improve error reporting for missing '_valueDeserializer' #194: Add `FloatNode` type in tree model (JsonNode) (requested by msteiger@github) #199: Allow deserializing `Iterable` instances (as basic `Collection`s) (requested by electrum@github) #206: Make 'ObjectMapper.createDeserializationContext()' overridable (requested by noter@github) #207: Add explicit support for `short` datatypes, for tree model (contributed by msteiger@github) New features: #120: Extend BeanDeserializerModifier to work with non-POJO deserializers #121: Extend BeanSerializerModifier to work with non-POJO serializers #124: Add support for serialization converters (@JsonSerializer(converter=...)) #124: Add support for deserialization converters (@JsonDeserializer(converter=...)) #140: Add 'SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN' to allow forcing of non-scientific notation when serializing BigDecimals. (suggested by phedny@github) #148: Add 'DeserializationFeature.FAIL_ON_INVALID_SUBTYPE`, which allows mapping entries with missing or invalid type id into null references (instead of failing). Also allows use of '@JsonTypeInfo.defaultImpl = NoClass.class' as alternative. #159: Add more accessors in 'MappingIterator': getParser(), getParserSchema(), readAll() (suggested by Tom D) #190: Add 'MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS' (default: true) for pruning out final fields (to avoid using as mutators) (requested by Eric T) #195: Add 'MapperFeature.INFER_PROPERTY_MUTATORS' (default: enabled) for finer control of what mutators are auto-detected. (requested by Dain S) #198: Add SPI metadata, handling in ObjectMapper (findModules()), for automatic registration of auto-detected extension modules (suggested by 'beamerblvd@github') #203: Added new features to support advanced date/time handling: - SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS - DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS - DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE Other: #126: Update JDK baseline to 1.6 * API under 'com.fasterxml.jackson.databind.jsonFormatVisitors' changed significantly based on experiences with external JSON Schema generator. * Version information accessed via code-generated access class, instead of reading VERSION.txt * Added 2 methods in Converter interface: getInputType(), getOutputType(), to allow programmatic overrides (needed by JAXB annotation module) 2.1.4 (26-Feb-2013) * [JACKSON-887]: StackOverflow with parameterized sub-class field (reported by Alexander M) * [#130]: TimeZone not set for GregorianCalendar, when deserializing * [#157]: NPE when registering module twice * [#162]: JsonNodeFactory: work around an old bug with BigDecimal and zero (submitted by fge@github) * [#166]: Incorrect optimization for `ObjectMapper.convertValue(Class)` (reported by Eric T) * [#167]: Problems with @JsonValue, polymorphic types (regression from 1.x) (reported by Eric T) * [#170]: Problems deserializing `java.io.File` if creator auto-discovery disabled (reported by Eric T) * [#175]: NPE for JsonMappingException, if no path is specified (reported by bramp@github) 2.1.3 (19-Jan-2013) * [Issue#141]: ACCEPT_EMPTY_STRING_AS_NULL_OBJECT not working for enums * [Issue#142]: Serialization of class containing EnumMap with polymorphic enum fails to generate class type data (reported by kidavis4@github) 2.1.2 (04-Dec-2012) * [Issue#106]: NPE in ObjectArraySerializer.createContextual(...) * [Issue#117]: HandlerInstantiator defaulting not working (reported by Alexander B) * [Issue#118]: Problems with JsonTypeInfo.As.EXTERNAL_PROPERTY, scalar values (reported by Adva11@github) * [Issue#119]: Problems with @JsonValue, JsonTypeInfo.As.EXTERNAL_PROPERTY (reported by Adva11@github) * [Issue#122]: ObjectMapper.copy() was not copying underlying mix-in map (reported by rzlo@github) 2.1.1 (11-Nov-2012) Fixes: * [JACKSON-875]: Enum values not found if Feature.USE_ANNOTATIONS disabled (reported by Laurent P) * [Issue#93]: ObjectNode.setAll() broken; would not add anything for empty ObjectNodes. (reported by Francis G) * Making things implement java.io.Serializable: - Issues: #94, #99, #100, #102 (reported by Sean B) * [Issue#96]: Problem with JsonTypeInfo.As.EXTERNAL_PROPERTY, defaultImpl (reported by Adva11@github) 2.1.0 (08-Oct-2012) New minor version for 2.x series. Major improvements in multiple areas, including: - Dataformat auto-detection - More `@JsonFormat.shape` variant to serialize Collections as JSON Objects, POJOs as JSON Arrays (csv-like). - Much more configuration accessible via ObjectReader, ObjectWriter - New mechanism for JSON Schema generation, other uses (in future) Fixes: * [JACKSON-830]/[Issue#19]: Change OSGi bundle name to be fully-qualified * ]JACKSON-847]: Make @JsonIdentityInfo work with property-based creator * [JACKSON-851]: State corruption with ObjectWriter, DefaultPrettyPrinter (reported by Duncan A) * [Issue#75]: Too aggressive KeySerializer caching * Minor fix wrt [Issue#11], coercion needed extra checks Improvements: * [JACKSON-758]: Remove 'IOException' from throws clauses of "writeValueAsString" and "writeValueAsBytes" of ObjectMapper/ObjectWriter (suggested by G-T Chen) * [JACKSON-839]: Allow "upgrade" of integer number types for UntypedObjectDeserializer, even with default typing enabled. * [JACKSON-850]: Allow use of zero-arg factory methods as "default creator" (suggested by Razvan D) * [Issue#9]: Implement 'required' JSON Schema attribute for bean properties * [Issue#20]: Add new exception type, InvalidFormatException (sub-type of JsonMappingException) to indicate data format problems (suggested by HolySamosa@github) * [Issue#30]: ObjectReader and ObjectWriter now try to pre-fetch root (de)serializer if possible; minor performance improvement (2% for small POJOs). * [Issue#33]: Simplified/clarified definition of 'ObjectReader.readValues()'; minor change in behavior for JSON Array "wrapped" sequences * [Issue#60]: Add 'JsonNode.hasNonNull(...)' method(s) (suggested by Jeff S on mailing list) * [Issue#64]: Add new "standard" PropertyNamingStrategy, PascalCaseStrategy (PropertyNamingStrategy.PASCAL_CASE_TO_CAMEL_CASE) (contributed by Sean B) * [Issue#65]: Add getters to `ObjectMapper`, DeserializationContext/-Factory. (contributed by Dmitry K) * [Issue#69]: Add `PropertyName` abstraction, new methods in AnnotationIntrospector * [Issue#80]: Make `DecimalNode` normalize input, to make "1.0" and "1.00"equal (reported by fge@github) New features: * [Issue#15]: Support data format auto-detection via ObjectReader (added 'withFormatDetection(...)' fluent factories) * [Issue#21]: Add 'ObjectNode.set(...)' method (and related) to improve chaining, semantic consistency of Tree Model API (suggested by fge@Github) * [Issue#22]: Add 'ObjectMapper.setAnnotationIntrospectors()' which allows defining different introspectors for serialization, deserialization * [Issue#24]: Allow serialization of Enums as JSON Objects (suggested by rveloso@github) * [Issue#28]: Add 'ObjectMapper.copy()', to create non-linked copy of mapper, with same configuration settings * [Issue#29]: Allow serializing, deserializing POJOs as JSON Arrays by using `@JsonFormat(shape=Shape.ARRAY)` * [Issue#40]: Allow serialization of Collections as JSON Objects (and deserialization from) (suggested by 'rveloso@github') * [Issue#42]: Allow specifying Base64 variant to use for Base64-encoded data using ObjectReader.with(Base64Variant), ObjectWriter.with(Base64Variant). (suggested by 'mpfau@github') * [Issue#45]: Add '@JsonNaming' annotation to define per-class PropertyNamingStrategy (suggested by Mark W) * [Pull#58]: Make 'MappingIterator' implement 'Closable' (contributed by Pascal G) * [Issue#72]: Add 'MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME' to use wrapper name annotations for renaming properties * [Issue#87]: Add 'StdDelegatingSerializer', 'StdDelegatingDeserializer' to simplify writing of two-step handlers * (issue #4 of jackson-annotations): Add `@JsonIdentityReference(alwaysAsId=true)` to force ALL references to an object written as Object Id, even the first one. * Added 'ObjectReader#withHandler' to allow for reconfiguring deserialization problem handler (suggested by 'electricmonk') Other changes: * New variant of AnnotationIntrospector.getFormat(), to support class annotations * It is now possible to serialize instances of plain old Object, iff 'FAIL_ON_EMPTY_BEANS' is disabled. * Trying to remove reference to "JSON" in datatype conversion errors (since databinding is format-agnostic) INCOMPATIBILITIES: (rats!) * Note that [Issue#33] (see above) is, technically speaking, backwards imcompatible change. It is estimated that it should NOT affect most users, as changes are to edge cases (and undocumented ones at that). However, it can potentially cause problems with upgrade. * Implementation of `JsonFormatVisitable` resulting in 2 new methods being added in `BeanPropertyFilter` interface -- this is unfortunate, but was required to support full traversability. 2.0.4 (26-Jun-2012) * [Issue#6]: element count for PrettyPrinter, endObject wrong (reported by "thebluemountain") * [JACKSON-838]: Utf8StreamParser._reportInvalidToken() skips letters from reported token name (reported by Lóránt Pintér) * [JACKSON-841] Data is doubled in SegmentedStringWriter output (reported by Scott S) * [JACKSON-842] ArrayIndexOutOfBoundsException when skipping C-style comments (reported by Sebastien R) 2.0.3: no version 2.0.3 released -- only used for extension modules 2.0.2 [14-May-2012] Fixes: * [Issue#14]: Annotations were not included from parent classes of mix-in classes (reported by @guillaup) * [JACKSON-824]: Combination of JSON Views, ObjectMapper.readerForUpdating() was not working (reported by Nir S) (and all fixes from 1.9.7) Improvements: * [Issue#11]: Improve ObjectMapper.convertValue()/.treeToValue() to use cast if possible 2.0.1 [23-Apr-2012] Fixes: * [JACKSON-827] Ensure core packages work on JDK 1.5 (reported by Pascal g) * [JACKSON-829] Custom serializers not working for List properties, @JsonSerialize(contentUsing) (reported by James R) Improvements: * [Issue#5]: Add support for maps with java.util.Locale keys to the set of StdKeyDeserializers (contributed by Ryan G) 2.0.0 [25-Mar-2012] Fixes: * [JACKSON-368]: Problems with managed references, abstract types * [JACKSON-711]: Delegating @JsonCreator did not work with Injectable values * [JACKSON-798]: Problem with external type id, creators (reported by Casey L) (and all fixes up until and including 1.9.6) Improvements: * [JACKSON-546]: Indicate end-of-input with JsonMappingException instead of EOFException, when there is no parsing exception * [JACKSON-664]: Reduce overhead of type resolution by adding caching in TypeFactory * [JACKSON-690]: Pass DeserializationContext through ValueInstantiator * [JACKSON-695]: Add 'isEmpty(value)' in JsonSerializer to allow customizing handling of serialization of empty values * [JACKSON-710]: 'ObjectMapper.convertValue()' should ignore root value wrapping/unwrapping settings * [JACKSON-730] Split various features (JsonParser, JsonGenerator, SerializationConfig, DeserializationConfig) into per-factory features (MapperFeature, JsonFactory.Feature) an per instance features (existing ones) * [JACKSON-732]: Allow 'AnnotationIntrospector.findContentDeserializer()' (and similar) to return instance, not just Class for instance (requested by James R) * [JACKSON-736]: Add (more) access to array, container and map serializers * [JACKSON-737]: Allow accessing of "creator properties" for BeanDeserializer * [JACKSON-748]: Add 'registerSubtypes' to 'Module.setupContext' (and SimpleModule) * [JACKSON-749]: Make @JsonValue work for Enum deserialization * [JACKSON-769]: ObjectNode/ArrayNode: change 'put', 'insert', 'add' to return 'this node' (unless already returning something) * [JACKSON-770]: Simplify method naming for JsonNode, drop unnecessary 'get' prefix from methods like 'getTextValue()' (becomes 'textValue()') * [JACKSON-777]: Rename 'SerializationConfig.Feature' as 'SerializationFeature', 'DeserializationConfig.Feature' as 'DeserializationFeature' * [JACKSON-780]: MissingNode, NullNode should return 'defaultValue' from 'asXxx' methods, (not 0 for numbers), as they are not numeric types * [JACKSON-787]: Allow use of @JsonIgnoreProperties for properties (fields, getters, setters) * [JACKSON-795]: @JsonValue was not working for Maps, Collections * [JACKSON-800]: Add 'Module.SetupContext#addDeserializationProblemHandler' (suggested by James R) New features: * [JACKSON-107]: Add support for Object Identity (to handled cycles, shared refs), with @JsonIdentityInfo * [JACKSON-435]: Allow per-property Date formatting using @JsonFormat. * [JACKSON-437]: Allow injecting of type id as POJO property, by setting new '@JsonTypeInfo.visible' property to true. * [JACKSON-469]: Support "Builder pattern" for deserialiation; that is, allow use of separate Builder object for data binding, creating actual value * [JACKSON-608]: Allow use of JSON Views for deserialization * [JACKSON-636]: Add 'SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS' to allow forced sorting of Maps during serialization (suggested by Joern H) * [JACKSON-669]: Allow prefix/suffix for @JsonUnwrapped properties (requested by Aner P) * [JACKSON-707]: Add 'JsonNode.deepCopy()', to create safe deep copies of ObjectNodes, ArrayNodes. * [JACKSON-714]: Add general-purpose @JsonFormat annotation * [JACKSON-718]: Added 'JsonNode.canConvertToInt()', 'JsonNode.canConvertToLong()' * [JACKSON-747]: Allow changing of 'SerializationFeature' for ObjectWriter, 'DeserializationFeature' for ObjectReader. * [JACKSON-752]: Add @JsonInclude (replacement of @JsonSerialize.include) * [JACKSON-754]: Add @JacksonAnnotationsInside for creating "annotation bundles" (also: AnnotationIntrospector.isAnnotationBundle()) * [JACKSON-762]: Allow using @JsonTypeId to specify property to use as type id, instead of using separate type id resolver. * [JACKSON-764]: Allow specifying "root name" to use for root wrapping via ObjectReader, ObjectWriter. * [JACKSON-772]: Add 'JsonNode.withArray()' to use for traversing Array nodes. * [JACKSON-793]: Add support for configurable Locale, TimeZone to use (via SerializationConfig, DeserializationConfig) * [JACKSON-805]: Add 'SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED' to improve interoperability with BadgerFish/Jettison * [JACKSON-810]: Deserialization Feature: Allow unknown Enum values via 'DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL' (suggested by Raymond R) * [JACKSON-813]: Add '@JsonSerializableSchema.id' attribute, to indicate 'id' value to add to generated JSON Schemas. [entries for versions 1.x and earlier not retained; refer to earlier releases) jackson-databind-jackson-databind-2.9.5/run.sh000077500000000000000000000001231325620701100212510ustar00rootroot00000000000000#!/bin/sh java -Xmx256m -server -cp lib/\*:target/classes:target/test-classes $* jackson-databind-jackson-databind-2.9.5/src/000077500000000000000000000000001325620701100207015ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/000077500000000000000000000000001325620701100216255ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/000077500000000000000000000000001325620701100225465ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/000077500000000000000000000000001325620701100233245ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/000077500000000000000000000000001325620701100253315ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/000077500000000000000000000000001325620701100267615ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/000077500000000000000000000000001325620701100305275ustar00rootroot00000000000000AbstractTypeResolver.java000066400000000000000000000050251325620701100354440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; /** * Defines interface for resolvers that can resolve abstract types into concrete * ones; either by using static mappings, or possibly by materializing * implementations dynamically. */ public abstract class AbstractTypeResolver { /** * Try to locate a subtype for given abstract type, to either resolve * to a concrete type, or at least to a more-specific (and hopefully supported) * abstract type, one which may have registered deserializers. * Method is called before trying to locate registered deserializers * (as well as standard abstract type defaulting that core Jackson does), * so it is typically implemented to add custom mappings of common abstract * types (like specify which concrete implementation to use for binding * {@link java.util.List}s). *

* Note that this method does not necessarily have to do full resolution * of bindings; that is, it is legal to return type that could be further * resolved: caller is expected to keep calling this method on registered * resolvers, until a concrete type is located. * * @param config Configuration in use; should always be of type * DeserializationConfig */ public JavaType findTypeMapping(DeserializationConfig config, JavaType type) { return null; } /** * Older variant of {@link #resolveAbstractType(DeserializationConfig, BeanDescription)}; * obsoleted in 2.7 * * @deprecated since 2.8 (may be removed from 2.9 or later) */ @Deprecated public JavaType resolveAbstractType(DeserializationConfig config, JavaType type) { return null; } /** * Method called to try to resolve an abstract type into * concrete type (usually for purposes of deserializing), * when no concrete implementation was found. * It will be called after checking all other possibilities, * including defaulting. * * @param config Configuration in use; should always be of type * DeserializationConfig * @param typeDesc Description of the POJO type to resolve * * @return Resolved concrete type (which should retain generic * type parameters of input type, if any), if resolution succeeds; * null if resolver does not know how to resolve given type * * @since 2.7 */ public JavaType resolveAbstractType(DeserializationConfig config, BeanDescription typeDesc) { return null; } } AnnotationIntrospector.java000066400000000000000000001435711325620701100360540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.lang.annotation.Annotation; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.Versioned; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.util.Converter; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Abstract class that defines API used for introspecting annotation-based * configuration for serialization and deserialization. Separated * so that different sets of annotations can be supported, and support * plugged-in dynamically. *

* Although default implementations are based on using annotations as the only * (or at least main) information source, custom implementations are not limited * in such a way, and in fact there is no expectation they should be. So the name * is bit of misnomer; this is a general configuration introspection facility. *

* NOTE: due to rapid addition of new methods (and changes to existing methods), * it is strongly recommended that custom implementations should not directly * extend this class, but rather extend {@link NopAnnotationIntrospector}. * This way added methods will not break backwards compatibility of custom annotation * introspectors. */ @SuppressWarnings("serial") public abstract class AnnotationIntrospector implements Versioned, java.io.Serializable { /* /********************************************************** /* Helper types /********************************************************** */ /** * Value type used with managed and back references; contains type and * logic name, used to link related references */ public static class ReferenceProperty { public enum Type { /** * Reference property that Jackson manages and that is serialized normally (by serializing * reference object), but is used for resolving back references during * deserialization. * Usually this can be defined by using * {@link com.fasterxml.jackson.annotation.JsonManagedReference} */ MANAGED_REFERENCE /** * Reference property that Jackson manages by suppressing it during serialization, * and reconstructing during deserialization. * Usually this can be defined by using * {@link com.fasterxml.jackson.annotation.JsonBackReference} */ ,BACK_REFERENCE ; } private final Type _type; private final String _name; public ReferenceProperty(Type t, String n) { _type = t; _name = n; } public static ReferenceProperty managed(String name) { return new ReferenceProperty(Type.MANAGED_REFERENCE, name); } public static ReferenceProperty back(String name) { return new ReferenceProperty(Type.BACK_REFERENCE, name); } public Type getType() { return _type; } public String getName() { return _name; } public boolean isManagedReference() { return _type == Type.MANAGED_REFERENCE; } public boolean isBackReference() { return _type == Type.BACK_REFERENCE; } } /* /********************************************************** /* Factory methods /********************************************************** */ /** * Factory method for accessing "no operation" implementation * of introspector: instance that will never find any annotation-based * configuration. */ public static AnnotationIntrospector nopInstance() { return NopAnnotationIntrospector.instance; } public static AnnotationIntrospector pair(AnnotationIntrospector a1, AnnotationIntrospector a2) { return new AnnotationIntrospectorPair(a1, a2); } /* /********************************************************** /* Access to possibly chained introspectors /********************************************************** */ /** * Method that can be used to collect all "real" introspectors that * this introspector contains, if any; or this introspector * if it is not a container. Used to get access to all container * introspectors in their priority order. *

* Default implementation returns a Singleton list with this introspector * as contents. * This usually works for sub-classes, except for proxy or delegating "container * introspectors" which need to override implementation. */ public Collection allIntrospectors() { return Collections.singletonList(this); } /** * Method that can be used to collect all "real" introspectors that * this introspector contains, if any; or this introspector * if it is not a container. Used to get access to all container * introspectors in their priority order. *

* Default implementation adds this introspector in result; this usually * works for sub-classes, except for proxy or delegating "container * introspectors" which need to override implementation. */ public Collection allIntrospectors(Collection result) { result.add(this); return result; } /* /********************************************************** /* Default Versioned impl /********************************************************** */ @Override public abstract Version version(); /* /********************************************************** /* Meta-annotations (annotations for annotation types) /********************************************************** */ /** * Method for checking whether given annotation is considered an * annotation bundle: if so, all meta-annotations it has will * be used instead of annotation ("bundle") itself. * * @since 2.0 */ public boolean isAnnotationBundle(Annotation ann) { return false; } /* /********************************************************** /* Annotations for Object Id handling /********************************************************** */ /** * Method for checking whether given annotated thing * (type, or accessor) indicates that values * referenced (values of type of annotated class, or * values referenced by annotated property; latter * having precedence) should include Object Identifier, * and if so, specify details of Object Identity used. * * @since 2.0 */ public ObjectIdInfo findObjectIdInfo(Annotated ann) { return null; } /** * Method for figuring out additional properties of an Object Identity reference * * @since 2.1 */ public ObjectIdInfo findObjectReferenceInfo(Annotated ann, ObjectIdInfo objectIdInfo) { return objectIdInfo; } /* /********************************************************** /* General class annotations /********************************************************** */ /** * Method for locating name used as "root name" (for use by * some serializers when outputting root-level object -- mostly * for XML compatibility purposes) for given class, if one * is defined. Returns null if no declaration found; can return * explicit empty String, which is usually ignored as well as null. *

* NOTE: method signature changed in 2.1, to return {@link PropertyName} * instead of String. */ public PropertyName findRootName(AnnotatedClass ac) { return null; } /** * Method for finding information about properties to ignore either by * name, or by more general specification ("ignore all unknown"). * This method combines multiple aspects of ignorals and deprecates * earlier methods such as * {@link #findPropertiesToIgnore(Annotated, boolean)} and * {@link #findIgnoreUnknownProperties(AnnotatedClass)}. * * @since 2.8 */ public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated ac) { // 18-Oct-2016, tatu: Used to call deprecated methods for backwards // compatibility in 2.8, but not any more in 2.9 return JsonIgnoreProperties.Value.empty(); } /** * Method for checking whether properties that have specified type * (class, not generics aware) should be completely ignored for * serialization and deserialization purposes. * * @param ac Type to check * * @return Boolean.TRUE if properties of type should be ignored; * Boolean.FALSE if they are not to be ignored, null for default * handling (which is 'do not ignore') */ public Boolean isIgnorableType(AnnotatedClass ac) { return null; } /** * Method for finding if annotated class has associated filter; and if so, * to return id that is used to locate filter. * * @return Id of the filter to use for filtering properties of annotated * class, if any; or null if none found. */ public Object findFilterId(Annotated ann) { return null; } /** * Method for finding {@link PropertyNamingStrategy} for given * class, if any specified by annotations; and if so, either return * a {@link PropertyNamingStrategy} instance, or Class to use for * creating instance * * @return Sub-class or instance of {@link PropertyNamingStrategy}, if one * is specified for given class; null if not. * * @since 2.1 */ public Object findNamingStrategy(AnnotatedClass ac) { return null; } /** * Method used to check whether specified class defines a human-readable * description to use for documentation. * There are no further definitions for contents; for example, whether * these may be marked up using HTML (or something like wiki format like Markup) * is not defined. * * @return Human-readable description, if any. * * @since 2.7 */ public String findClassDescription(AnnotatedClass ac) { return null; } /** * @param forSerialization True if requesting properties to ignore for serialization; * false if for deserialization * * @since 2.6 * * @deprecated Since 2.8, use {@link #findPropertyIgnorals} instead */ @Deprecated // since 2.8 public String[] findPropertiesToIgnore(Annotated ac, boolean forSerialization) { return null; } /** * @deprecated Since 2.6, use variant that takes second argument. */ @Deprecated // since 2.6 public String[] findPropertiesToIgnore(Annotated ac) { return null; } /** * Method for checking whether an annotation indicates that all unknown properties * * @deprecated Since 2.8, use {@link #findPropertyIgnorals} instead */ @Deprecated // since 2.8 public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) { return null; } /* /********************************************************** /* Property auto-detection /********************************************************** */ /** * Method for checking if annotations indicate changes to minimum visibility levels * needed for auto-detecting property elements (fields, methods, constructors). * A baseline checker is given, and introspector is to either return it as is * (if no annotations are found), or build and return a derived instance (using * checker's build methods). */ public VisibilityChecker findAutoDetectVisibility(AnnotatedClass ac, VisibilityChecker checker) { return checker; } /* /********************************************************** /* Annotations for Polymorphic type handling /********************************************************** */ /** * Method for checking if given class has annotations that indicate * that specific type resolver is to be used for handling instances. * This includes not only * instantiating resolver builder, but also configuring it based on * relevant annotations (not including ones checked with a call to * {@link #findSubtypes} * * @param config Configuration settings in effect (for serialization or deserialization) * @param ac Annotated class to check for annotations * @param baseType Base java type of value for which resolver is to be found * * @return Type resolver builder for given type, if one found; null if none */ public TypeResolverBuilder findTypeResolver(MapperConfig config, AnnotatedClass ac, JavaType baseType) { return null; } /** * Method for checking if given property entity (field or method) has annotations * that indicate that specific type resolver is to be used for handling instances. * This includes not only * instantiating resolver builder, but also configuring it based on * relevant annotations (not including ones checked with a call to * {@link #findSubtypes} * * @param config Configuration settings in effect (for serialization or deserialization) * @param am Annotated member (field or method) to check for annotations * @param baseType Base java type of property for which resolver is to be found * * @return Type resolver builder for properties of given entity, if one found; * null if none */ public TypeResolverBuilder findPropertyTypeResolver(MapperConfig config, AnnotatedMember am, JavaType baseType) { return null; } /** * Method for checking if given structured property entity (field or method that * has nominal value of Map, Collection or array type) has annotations * that indicate that specific type resolver is to be used for handling type * information of contained values. * This includes not only * instantiating resolver builder, but also configuring it based on * relevant annotations (not including ones checked with a call to * {@link #findSubtypes} * * @param config Configuration settings in effect (for serialization or deserialization) * @param am Annotated member (field or method) to check for annotations * @param containerType Type of property for which resolver is to be found (must be a container type) * * @return Type resolver builder for values contained in properties of given entity, * if one found; null if none */ public TypeResolverBuilder findPropertyContentTypeResolver(MapperConfig config, AnnotatedMember am, JavaType containerType) { return null; } /** * Method for locating annotation-specified subtypes related to annotated * entity (class, method, field). Note that this is only guaranteed to be * a list of directly * declared subtypes, no recursive processing is guarantees (i.e. caller * has to do it if/as necessary) * * @param a Annotated entity (class, field/method) to check for annotations */ public List findSubtypes(Annotated a) { return null; } /** * Method for checking if specified type has explicit name. * * @param ac Class to check for type name annotations */ public String findTypeName(AnnotatedClass ac) { return null; } /** * Method for checking whether given accessor claims to represent * type id: if so, its value may be used as an override, * instead of generated type id. */ public Boolean isTypeId(AnnotatedMember member) { return null; } /* /********************************************************** /* General member (field, method/constructor) annotations /********************************************************** */ /** * Method for checking if given member indicates that it is part * of a reference (parent/child). */ public ReferenceProperty findReferenceType(AnnotatedMember member) { return null; } /** * Method called to check whether given property is marked to be "unwrapped" * when being serialized (and appropriately handled in reverse direction, * i.e. expect unwrapped representation during deserialization). * Return value is the name transformation to use, if wrapping/unwrapping * should be done, or null if not -- note that transformation may simply * be identity transformation (no changes). */ public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member) { return null; } /** * Method called to check whether given property is marked to * be ignored. This is used to determine whether to ignore * properties, on per-property basis, usually combining * annotations from multiple accessors (getters, setters, fields, * constructor parameters). */ public boolean hasIgnoreMarker(AnnotatedMember m) { return false; } /** * Method called to find out whether given member expectes a value * to be injected, and if so, what is the identifier of the value * to use during injection. * Type if identifier needs to be compatible with provider of * values (of type {@link InjectableValues}); often a simple String * id is used. * * @param m Member to check * * @return Identifier of value to inject, if any; null if no injection * indicator is found * * @since 2.9 */ public JacksonInject.Value findInjectableValue(AnnotatedMember m) { // 05-Apr-2017, tatu: Just for 2.9, call deprecated method to help // with some cases of overrides for legacy code Object id = findInjectableValueId(m); if (id != null) { return JacksonInject.Value.forId(id); } return null; } /** * Method that can be called to check whether this member has * an annotation that suggests whether value for matching property * is required or not. */ public Boolean hasRequiredMarker(AnnotatedMember m) { return null; } /** * Method for checking if annotated property (represented by a field or * getter/setter method) has definitions for views it is to be included in. * If null is returned, no view definitions exist and property is always * included (or always excluded as per default view inclusion configuration); * otherwise it will only be included for views included in returned * array. View matches are checked using class inheritance rules (sub-classes * inherit inclusions of super-classes) *

* Since 2.9 this method may also be called to find "default view(s)" for * {@link AnnotatedClass} * * @param a Annotated property (represented by a method, field or ctor parameter) * @return Array of views (represented by classes) that the property is included in; * if null, always included (same as returning array containing Object.class) */ public Class[] findViews(Annotated a) { return null; } /** * Method for finding format annotations for property or class. * Return value is typically used by serializers and/or * deserializers to customize presentation aspects of the * serialized value. * * @since 2.1 */ public JsonFormat.Value findFormat(Annotated memberOrClass) { return JsonFormat.Value.empty(); } /** * Method used to check if specified property has annotation that indicates * that it should be wrapped in an element; and if so, name to use. * Note that not all serializers and deserializers support use this method: * currently (2.1) it is only used by XML-backed handlers. * * @return Wrapper name to use, if any, or {@link PropertyName#USE_DEFAULT} * to indicate that no wrapper element should be used. * * @since 2.1 */ public PropertyName findWrapperName(Annotated ann) { return null; } /** * Method for finding suggested default value (as simple textual serialization) * for the property. While core databind does not make any use of it, it is exposed * for extension modules to use: an expected use is generation of schema representations * and documentation. * * @since 2.5 */ public String findPropertyDefaultValue(Annotated ann) { return null; } /** * Method used to check whether specified property member (accessor * or mutator) defines human-readable description to use for documentation. * There are no further definitions for contents; for example, whether * these may be marked up using HTML is not defined. * * @return Human-readable description, if any. * * @since 2.3 */ public String findPropertyDescription(Annotated ann) { return null; } /** * Method used to check whether specified property member (accessor * or mutator) defines numeric index, and if so, what is the index value. * Possible use cases for index values included use by underlying data format * (some binary formats mandate use of index instead of name) and ordering * of properties (for documentation, or during serialization). * * @since 2.4 * * @return Explicitly specified index for the property, if any */ public Integer findPropertyIndex(Annotated ann) { return null; } /** * Method for finding implicit name for a property that given annotated * member (field, method, creator parameter) may represent. * This is different from explicit, annotation-based property name, in that * it is "weak" and does not either proof that a property exists (for example, * if visibility is not high enough), or override explicit names. * In practice this method is used to introspect optional names for creator * parameters (which may or may not be available and cannot be detected * by standard databind); or to provide alternate name mangling for * fields, getters and/or setters. * * @since 2.4 */ public String findImplicitPropertyName(AnnotatedMember member) { return null; } /** * Method called to find if given property has alias(es) defined. * * @return `null` if member has no information; otherwise a `List` (possibly * empty) of aliases to use. * * @since 2.9 */ public List findPropertyAliases(Annotated ann) { return null; } /** * Method for finding optional access definition for a property, annotated * on one of its accessors. If a definition for read-only, write-only * or read-write cases, visibility rules may be modified. Note, however, * that even more specific annotations (like one for ignoring specific accessor) * may further override behavior of the access definition. * * @since 2.6 */ public JsonProperty.Access findPropertyAccess(Annotated ann) { return null; } /** * Method called in cases where a class has two methods eligible to be used * for the same logical property, and default logic is not enough to figure * out clear precedence. Introspector may try to choose one to use; or, if * unable, return `null` to indicate it cannot resolve the problem. * * @since 2.7 */ public AnnotatedMethod resolveSetterConflict(MapperConfig config, AnnotatedMethod setter1, AnnotatedMethod setter2) { return null; } /** * @deprecated Since 2.9 Use {@link #findInjectableValue} instead */ @Deprecated // since 2.9 public Object findInjectableValueId(AnnotatedMember m) { return null; } /* /********************************************************** /* Serialization: general annotations /********************************************************** */ /** * Method for getting a serializer definition on specified method * or field. Type of definition is either instance (of type * {@link JsonSerializer}) or Class (of type * Class<JsonSerializer>); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findSerializer(Annotated am) { return null; } /** * Method for getting a serializer definition for keys of associated Map property. * Type of definition is either instance (of type * {@link JsonSerializer}) or Class (of type * Class<JsonSerializer>); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findKeySerializer(Annotated am) { return null; } /** * Method for getting a serializer definition for content (values) of * associated Collection, array or Map property. * Type of definition is either instance (of type * {@link JsonSerializer}) or Class (of type * Class<JsonSerializer>); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findContentSerializer(Annotated am) { return null; } /** * Method for getting a serializer definition for serializer to use * for nulls (null values) of associated property or type. * * @since 2.3 */ public Object findNullSerializer(Annotated am) { return null; } /** * Method for accessing declared typing mode annotated (if any). * This is used for type detection, unless more granular settings * (such as actual exact type; or serializer to use which means * no type information is needed) take precedence. * * @return Typing mode to use, if annotation is found; null otherwise */ public JsonSerialize.Typing findSerializationTyping(Annotated a) { return null; } /** * Method for finding {@link Converter} that annotated entity * (property or class) has indicated to be used as part of * serialization. If not null, either has to be actual * {@link Converter} instance, or class for such converter; * and resulting converter will be used first to convert property * value to converter target type, and then serializer for that * type is used for actual serialization. *

* This feature is typically used to convert internal values into types * that Jackson can convert. *

* Note also that this feature does not necessarily work well with polymorphic * type handling, or object identity handling; if such features are needed * an explicit serializer is usually better way to handle serialization. * * @param a Annotated property (field, method) or class to check for * annotations * * @since 2.2 */ public Object findSerializationConverter(Annotated a) { return null; } /** * Method for finding {@link Converter} that annotated property * has indicated needs to be used for values of container type * (this also means that method should only be called for properties * of container types, List/Map/array properties). *

* If not null, either has to be actual * {@link Converter} instance, or class for such converter; * and resulting converter will be used first to convert property * value to converter target type, and then serializer for that * type is used for actual serialization. *

* Other notes are same as those for {@link #findSerializationConverter} * * @param a Annotated property (field, method) to check. * * @since 2.2 */ public Object findSerializationContentConverter(AnnotatedMember a) { return null; } /** * Method for checking inclusion criteria for a type (Class) or property (yes, method * name is bit unfortunate -- not just for properties!). * In case of class, acts as the default for properties POJO contains; for properties * acts as override for class defaults and possible global defaults. * * @since 2.6 */ public JsonInclude.Value findPropertyInclusion(Annotated a) { return JsonInclude.Value.empty(); } /** * Method for checking whether given annotated entity (class, method, * field) defines which Bean/Map properties are to be included in * serialization. * If no annotation is found, method should return given second * argument; otherwise value indicated by the annotation. *

* Note that meaning of inclusion value depends on whether it is for * a Class or property (field/method/constructor): in former case, * it is the default for all properties; in latter case it is specific * override for annotated property. * * @return Enumerated value indicating which properties to include * in serialization * * @deprecated Since 2.7 Use {@link #findPropertyInclusion} instead */ @Deprecated // since 2.7 public JsonInclude.Include findSerializationInclusion(Annotated a, JsonInclude.Include defValue) { return defValue; } /** * Method for checking whether content (entries) of a {@link java.util.Map} property * are to be included during serialization or not. * NOTE: this is NOT called for POJO properties, or array/Collection elements. * * @since 2.5 * * @deprecated Since 2.7 Use {@link #findPropertyInclusion} instead */ @Deprecated // since 2.7 public JsonInclude.Include findSerializationInclusionForContent(Annotated a, JsonInclude.Include defValue) { return defValue; } /* /********************************************************** /* Serialization: type refinements /********************************************************** */ /** * Method called to find out possible type refinements to use * for deserialization, including not just value itself but * key and/or content type, if type has those. * * @since 2.7 */ public JavaType refineSerializationType(final MapperConfig config, final Annotated a, final JavaType baseType) throws JsonMappingException { return baseType; } /** * @deprecated Since 2.7 call {@link #refineSerializationType} instead */ @Deprecated // since 2.7 public Class findSerializationType(Annotated a) { return null; } /** * @deprecated Since 2.7 call {@link #refineSerializationType} instead */ @Deprecated // since 2.7 public Class findSerializationKeyType(Annotated am, JavaType baseType) { return null; } /** * @deprecated Since 2.7 call {@link #refineSerializationType} instead */ @Deprecated // since 2.7 public Class findSerializationContentType(Annotated am, JavaType baseType) { return null; } /* /********************************************************** /* Serialization: class annotations /********************************************************** */ /** * Method for accessing defined property serialization order (which may be * partial). May return null if no ordering is defined. */ public String[] findSerializationPropertyOrder(AnnotatedClass ac) { return null; } /** * Method for checking whether an annotation indicates that serialized properties * for which no explicit is defined should be alphabetically (lexicograpically) * ordered */ public Boolean findSerializationSortAlphabetically(Annotated ann) { return null; } /** * Method for adding possible virtual properties to be serialized along * with regular properties. * * @since 2.5 */ public void findAndAddVirtualProperties(MapperConfig config, AnnotatedClass ac, List properties) { } /* /********************************************************** /* Serialization: property annotations /********************************************************** */ /** * Method for checking whether given property accessors (method, * field) has an annotation that suggests property name to use * for serialization. * Should return null if no annotation * is found; otherwise a non-null name (possibly * {@link PropertyName#USE_DEFAULT}, which means "use default heuristics"). * * @param a Property accessor to check * * @return Name to use if found; null if not. * * @since 2.1 */ public PropertyName findNameForSerialization(Annotated a) { return null; } /** * Method for checking whether given method has an annotation * that suggests that the return value of annotated method * should be used as "the value" of the object instance; usually * serialized as a primitive value such as String or number. * * @return {@link Boolean#TRUE} if such annotation is found and is not disabled; * {@link Boolean#FALSE} if disabled annotation (block) is found (to indicate * accessor is definitely NOT to be used "as value"); or `null` if no * information found. * * @since 2.9 */ public Boolean hasAsValue(Annotated a) { // 20-Nov-2016, tatu: Delegate in 2.9; remove redirect from later versions if (a instanceof AnnotatedMethod) { if (hasAsValueAnnotation((AnnotatedMethod) a)) { return true; } } return null; } /** * Method for checking whether given method has an annotation * that suggests that the method is to serve as "any setter"; * method to be used for accessing set of miscellaneous "extra" * properties, often bound with matching "any setter" method. * * @return True if such annotation is found (and is not disabled), * false otherwise * * @since 2.9 */ public Boolean hasAnyGetter(Annotated a) { // 21-Nov-2016, tatu: Delegate in 2.9; remove redirect from later versions if (a instanceof AnnotatedMethod) { if (hasAnyGetterAnnotation((AnnotatedMethod) a)) { return true; } } return null; } /** * Method for efficiently figuring out which if given set of Enum values * have explicitly defined name. Method will overwrite entries in incoming names * array with explicit names found, if any, leaving other entries unmodified. *

* Default implementation will simply delegate to {@link #findEnumValue}, which is close * enough, although unfortunately NOT 100% equivalent (as it will also consider name() * to give explicit value). * * @since 2.7 */ public String[] findEnumValues(Class enumType, Enum[] enumValues, String[] names) { // 18-Oct-2016, tatu: In 2.8 delegated to deprecated method; not so in 2.9 and beyond return names; } /** * Finds the Enum value that should be considered the default value, if possible. * * @param enumCls The Enum class to scan for the default value. * @return null if none found or it's not possible to determine one. * * @since 2.8 */ public Enum findDefaultEnumValue(Class> enumCls) { return null; } /** * Method for determining the String value to use for serializing * given enumeration entry; used when serializing enumerations * as Strings (the standard method). * * @return Serialized enum value. * * @deprecated Since 2.8: use {@link #findEnumValues} instead because this method * does not properly handle override settings (defaults to enum.name * without indicating whether that is explicit or not), and is inefficient to * call one-by-one. */ @Deprecated public String findEnumValue(Enum value) { return value.name(); } /** * @deprecated Since 2.9 Use {@link #hasAsValue(Annotated)} instead. */ @Deprecated // since 2.9 public boolean hasAsValueAnnotation(AnnotatedMethod am) { return false; } /** * @deprecated Since 2.9 Use {@link #hasAnyGetter} instead */ @Deprecated public boolean hasAnyGetterAnnotation(AnnotatedMethod am) { return false; } /* /********************************************************** /* Deserialization: general annotations /********************************************************** */ /** * Method for getting a deserializer definition on specified method * or field. * Type of definition is either instance (of type * {@link JsonDeserializer}) or Class (of type * Class<JsonDeserializer>); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findDeserializer(Annotated am) { return null; } /** * Method for getting a deserializer definition for keys of * associated Map property. * Type of definition is either instance (of type * {@link JsonDeserializer}) or Class (of type * Class<JsonDeserializer>); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findKeyDeserializer(Annotated am) { return null; } /** * Method for getting a deserializer definition for content (values) of * associated Collection, array or * Map property. * Type of definition is either instance (of type * {@link JsonDeserializer}) or Class (of type * Class<JsonDeserializer>); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findContentDeserializer(Annotated am) { return null; } /** * Method for finding {@link Converter} that annotated entity * (property or class) has indicated to be used as part of * deserialization. * If not null, either has to be actual * {@link Converter} instance, or class for such converter; * and resulting converter will be used after Jackson has deserializer * data into intermediate type (Converter input type), and Converter * needs to convert this into its target type to be set as property value. *

* This feature is typically used to convert intermediate Jackson types * (that default deserializers can produce) into custom type instances. *

* Note also that this feature does not necessarily work well with polymorphic * type handling, or object identity handling; if such features are needed * an explicit deserializer is usually better way to handle deserialization. * * @param a Annotated property (field, method) or class to check for * annotations * * @since 2.2 */ public Object findDeserializationConverter(Annotated a) { return null; } /** * Method for finding {@link Converter} that annotated property * has indicated needs to be used for values of container type * (this also means that method should only be called for properties * of container types, List/Map/array properties). *

* If not null, either has to be actual * {@link Converter} instance, or class for such converter; * and resulting converter will be used after Jackson has deserializer * data into intermediate type (Converter input type), and Converter * needs to convert this into its target type to be set as property value. *

* Other notes are same as those for {@link #findDeserializationConverter} * * @param a Annotated property (field, method) to check. * * @since 2.2 */ public Object findDeserializationContentConverter(AnnotatedMember a) { return null; } /* /********************************************************** /* Deserialization: type refinements /********************************************************** */ /** * Method called to find out possible type refinements to use * for deserialization. * * @since 2.7 */ public JavaType refineDeserializationType(final MapperConfig config, final Annotated a, final JavaType baseType) throws JsonMappingException { return baseType; } /** * Method for accessing annotated type definition that a * property can have, to be used as the type for deserialization * instead of the static (declared) type. * Type is usually narrowing conversion (i.e.subtype of declared type). * Declared return type of the method is also considered acceptable. * * @param baseType Assumed type before considering annotations * * @return Class to use for deserialization instead of declared type * * @deprecated Since 2.7 call {@link #refineDeserializationType} instead */ @Deprecated public Class findDeserializationType(Annotated am, JavaType baseType) { return null; } /** * Method for accessing additional narrowing type definition that a * method can have, to define more specific key type to use. * It should be only be used with {@link java.util.Map} types. * * @param baseKeyType Assumed key type before considering annotations * * @return Class specifying more specific type to use instead of * declared type, if annotation found; null if not * * @deprecated Since 2.7 call {@link #refineDeserializationType} instead */ @Deprecated public Class findDeserializationKeyType(Annotated am, JavaType baseKeyType) { return null; } /** * Method for accessing additional narrowing type definition that a * method can have, to define more specific content type to use; * content refers to Map values and Collection/array elements. * It should be only be used with Map, Collection and array types. * * @param baseContentType Assumed content (value) type before considering annotations * * @return Class specifying more specific type to use instead of * declared type, if annotation found; null if not * * @deprecated Since 2.7 call {@link #refineDeserializationType} instead */ @Deprecated public Class findDeserializationContentType(Annotated am, JavaType baseContentType) { return null; } /* /********************************************************** /* Deserialization: class annotations /********************************************************** */ /** * Method getting {@link ValueInstantiator} to use for given * type (class): return value can either be an instance of * instantiator, or class of instantiator to create. */ public Object findValueInstantiator(AnnotatedClass ac) { return null; } /** * Method for finding Builder object to use for constructing * value instance and binding data (sort of combining value * instantiators that can construct, and deserializers * that can bind data). *

* Note that unlike accessors for some helper Objects, this * method does not allow returning instances: the reason is * that builders have state, and a separate instance needs * to be created for each deserialization call. * * @since 2.0 */ public Class findPOJOBuilder(AnnotatedClass ac) { return null; } /** * @since 2.0 */ public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) { return null; } /* /********************************************************** /* Deserialization: property annotations /********************************************************** */ /** * Method for checking whether given property accessors (method, * field) has an annotation that suggests property name to use * for deserialization (reading JSON into POJOs). * Should return null if no annotation * is found; otherwise a non-null name (possibly * {@link PropertyName#USE_DEFAULT}, which means "use default heuristics"). * * @param a Property accessor to check * * @return Name to use if found; null if not. * * @since 2.1 */ public PropertyName findNameForDeserialization(Annotated a) { return null; } /** * Method for checking whether given method has an annotation * that suggests that the method is to serve as "any setter"; * method to be used for setting values of any properties for * which no dedicated setter method is found. * * @return True if such annotation is found (and is not disabled), * false otherwise * * @since 2.9 */ public Boolean hasAnySetter(Annotated a) { return null; } /** * Method for finding possible settings for property, given annotations * on an accessor. * * @since 2.9 */ public JsonSetter.Value findSetterInfo(Annotated a) { return JsonSetter.Value.empty(); } /** * Method for finding merge settings for property, if any. * * @since 2.9 */ public Boolean findMergeInfo(Annotated a) { return null; } /** * Method called to check whether potential Creator (constructor or static factory * method) has explicit annotation to indicate it as actual Creator; and if so, * which {@link com.fasterxml.jackson.annotation.JsonCreator.Mode} to use. *

* NOTE: caller needs to consider possibility of both `null` (no annotation found) * and {@link com.fasterxml.jackson.annotation.JsonCreator.Mode#DISABLED} (annotation found, * but disabled); latter is necessary as marker in case multiple introspectors are chained, * as well as possibly as when using mix-in annotations. * * @param config Configuration settings in effect (for serialization or deserialization) * @param a Annotated accessor (usually constructor or static method) to check * * @since 2.9 */ public JsonCreator.Mode findCreatorAnnotation(MapperConfig config, Annotated a) { // 13-Sep-2016, tatu: for backwards compatibility, implement using delegation /// (remove from version AFTER 2.9) if (hasCreatorAnnotation(a)) { JsonCreator.Mode mode = findCreatorBinding(a); if (mode == null) { mode = JsonCreator.Mode.DEFAULT; } return mode; } return null; } /** * Method for checking whether given annotated item (method, constructor) * has an annotation * that suggests that the method is a "creator" (aka factory) * method to be used for construct new instances of deserialized * values. * * @return True if such annotation is found (and is not disabled), * false otherwise * * @deprecated Since 2.9 use {@link #findCreatorAnnotation} instead. */ @Deprecated public boolean hasCreatorAnnotation(Annotated a) { return false; } /** * Method for finding indication of creator binding mode for * a creator (something for which {@link #hasCreatorAnnotation} returns * true), for cases where there may be ambiguity (currently: single-argument * creator with implicit but no explicit name for the argument). * * @since 2.5 * @deprecated Since 2.9 use {@link #findCreatorAnnotation} instead. */ @Deprecated public JsonCreator.Mode findCreatorBinding(Annotated a) { return null; } /** * @deprecated Since 2.9 use {@link #hasAnySetter} instead. */ @Deprecated // since 2.9 public boolean hasAnySetterAnnotation(AnnotatedMethod am) { return false; } /* /********************************************************** /* Overridable methods: may be used as low-level extension /* points. /********************************************************** */ /** * Method that should be used by sub-classes for ALL * annotation access; * overridable so * that sub-classes may, if they choose to, mangle actual access to * block access ("hide" annotations) or perhaps change it. *

* Default implementation is simply: * * return annotated.getAnnotation(annoClass); * * * @since 2.5 */ protected A _findAnnotation(Annotated annotated, Class annoClass) { return annotated.getAnnotation(annoClass); } /** * Method that should be used by sub-classes for ALL * annotation existence access; * overridable so that sub-classes may, if they choose to, mangle actual access to * block access ("hide" annotations) or perhaps change value seen. *

* Default implementation is simply: * * return annotated.hasAnnotation(annoClass); * * * @since 2.5 */ protected boolean _hasAnnotation(Annotated annotated, Class annoClass) { return annotated.hasAnnotation(annoClass); } /** * Alternative lookup method that is used to see if annotation has at least one of * annotations of types listed in second argument. * * @since 2.7 */ protected boolean _hasOneOf(Annotated annotated, Class[] annoClasses) { return annotated.hasOneOf(annoClasses); } } BeanDescription.java000066400000000000000000000246061325620701100343740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.type.TypeBindings; import com.fasterxml.jackson.databind.util.Annotations; import com.fasterxml.jackson.databind.util.Converter; /** * Basic container for information gathered by {@link ClassIntrospector} to * help in constructing serializers and deserializers. * Note that the main implementation type is * {@link com.fasterxml.jackson.databind.introspect.BasicBeanDescription}, * meaning that it is safe to upcast to this type. */ public abstract class BeanDescription { /** * Bean type information, including raw class and possible * generics information */ protected final JavaType _type; /* /********************************************************** /* Life-cycle /********************************************************** */ protected BeanDescription(JavaType type) { _type = type; } /* /********************************************************** /* Simple accesors /********************************************************** */ /** * Method for accessing declared type of bean being introspected, * including full generic type information (from declaration) */ public JavaType getType() { return _type; } public Class getBeanClass() { return _type.getRawClass(); } /** * @since 2.9 */ public boolean isNonStaticInnerClass() { return getClassInfo().isNonStaticInnerClass(); } /** * Method for accessing low-level information about Class this * item describes. */ public abstract AnnotatedClass getClassInfo(); /** * Accessor for getting information about Object Id expected to * be used for this POJO type, if any. */ public abstract ObjectIdInfo getObjectIdInfo(); /** * Method for checking whether class being described has any * annotations recognized by registered annotation introspector. */ public abstract boolean hasKnownClassAnnotations(); /** * Accessor for type bindings that may be needed to fully resolve * types of member object, such as return and argument types of * methods and constructors, and types of fields. * * @deprecated Since 2.7, should not need to access bindings directly */ @Deprecated public abstract TypeBindings bindingsForBeanType(); /** * Method for resolving given JDK type, using this bean as the * generic type resolution context. * * @deprecated Since 2.8, should simply call getType of * property accessor directly. */ @Deprecated public abstract JavaType resolveType(java.lang.reflect.Type jdkType); /** * Method for accessing collection of annotations the bean * class has. */ public abstract Annotations getClassAnnotations(); /* /********************************************************** /* Basic API for finding properties /********************************************************** */ /** * @return Ordered Map with logical property name as key, and * matching getter method as value. */ public abstract List findProperties(); public abstract Set getIgnoredPropertyNames(); /** * Method for locating all back-reference properties (setters, fields) bean has * * @since 2.9 */ public abstract List findBackReferences(); /** * Method for locating all back-reference properties (setters, fields) bean has * * @deprecated Since 2.9 use {@link #findBackReferences()} instead */ @Deprecated public abstract Map findBackReferenceProperties(); /* /********************************************************** /* Basic API for finding creator members /********************************************************** */ public abstract List getConstructors(); public abstract List getFactoryMethods(); /** * Method that will locate the no-arg constructor for this class, * if it has one, and that constructor has not been marked as * ignorable. */ public abstract AnnotatedConstructor findDefaultConstructor(); /** * Method that can be called to locate a single-arg constructor that * takes specified exact type (will not accept supertype constructors) * * @param argTypes Type(s) of the argument that we are looking for */ public abstract Constructor findSingleArgConstructor(Class... argTypes); /** * Method that can be called to find if introspected class declares * a static "valueOf" factory method that returns an instance of * introspected type, given one of acceptable types. * * @param expArgTypes Types that the matching single argument factory * method can take: will also accept super types of these types * (ie. arg just has to be assignable from expArgType) */ public abstract Method findFactoryMethod(Class... expArgTypes); /* /********************************************************** /* Basic API for finding property accessors /********************************************************** */ /** * Method for locating accessor (readable field, or "getter" method) * that has * {@link com.fasterxml.jackson.annotation.JsonValue} annotation, * if any. If multiple ones are found, * an error is reported by throwing {@link IllegalArgumentException} * * @since 2.9 */ public abstract AnnotatedMember findJsonValueAccessor(); public abstract AnnotatedMember findAnyGetter(); /** * Method used to locate a mutator (settable field, or 2-argument set method) * of introspected class that * implements {@link com.fasterxml.jackson.annotation.JsonAnySetter}. * If no such mutator exists null is returned. If more than one are found, * an exception is thrown. * Additional checks are also made to see that method signature * is acceptable: needs to take 2 arguments, first one String or * Object; second any can be any type. * * @since 2.9 */ public abstract AnnotatedMember findAnySetterAccessor(); public abstract AnnotatedMethod findMethod(String name, Class[] paramTypes); @Deprecated // since 2.9 public abstract AnnotatedMethod findJsonValueMethod(); /** * @deprecated Since 2.9: use {@link #findAnySetterAccessor} instead */ @Deprecated public AnnotatedMethod findAnySetter() { AnnotatedMember m = findAnySetterAccessor(); if (m instanceof AnnotatedMethod) { return (AnnotatedMethod) m; } return null; } /** * @deprecated Since 2.9: use {@link #findAnySetterAccessor} instead */ @Deprecated public AnnotatedMember findAnySetterField() { AnnotatedMember m = findAnySetterAccessor(); if (m instanceof AnnotatedField) { return m; } return null; } /* /********************************************************** /* Basic API, class configuration /********************************************************** */ /** * Method for finding annotation-indicated inclusion definition (if any); * possibly overriding given default value. *

* NOTE: does NOT use global inclusion default settings as the base, unless * passed as `defValue`. * * @since 2.7 */ public abstract JsonInclude.Value findPropertyInclusion(JsonInclude.Value defValue); /** * Method for checking what is the expected format for POJO, as * defined by defaults and possible annotations. * Note that this may be further refined by per-property annotations. * * @since 2.1 */ public abstract JsonFormat.Value findExpectedFormat(JsonFormat.Value defValue); /** * Method for finding {@link Converter} used for serializing instances * of this class. * * @since 2.2 */ public abstract Converter findSerializationConverter(); /** * Method for finding {@link Converter} used for serializing instances * of this class. * * @since 2.2 */ public abstract Converter findDeserializationConverter(); /** * Accessor for possible description for the bean type, used for constructing * documentation. * * @since 2.7 */ public String findClassDescription() { return null; } /* /********************************************************** /* Basic API, other /********************************************************** */ public abstract Map findInjectables(); /** * Method for checking if the POJO type has annotations to * indicate that a builder is to be used for instantiating * instances and handling data binding, instead of standard * bean deserializer. */ public abstract Class findPOJOBuilder(); /** * Method for finding configuration for POJO Builder class. */ public abstract JsonPOJOBuilder.Value findPOJOBuilderConfig(); /** * Method called to create a "default instance" of the bean, currently * only needed for obtaining default field values which may be used for * suppressing serialization of fields that have "not changed". * * @param fixAccess If true, method is allowed to fix access to the * default constructor (to be able to call non-public constructor); * if false, has to use constructor as is. * * @return Instance of class represented by this descriptor, if * suitable default constructor was found; null otherwise. */ public abstract Object instantiateBean(boolean fixAccess); /** * Method for finding out if the POJO specifies default view(s) to * use for properties, considering both per-type annotations and * global default settings. * * @since 2.9 */ public abstract Class[] findDefaultViews(); } BeanProperty.java000066400000000000000000000337241325620701100337360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.List; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat.Value; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.Annotations; import com.fasterxml.jackson.databind.util.Named; /** * Bean properties are logical entities that represent data * that Java objects (POJOs (Plain Old Java Objects), sometimes also called "beans") * contain; and that are accessed using accessors (methods like getters * and setters, fields, constructor parameters). * Instances allow access to annotations directly associated * to property (via field or method), as well as contextual * annotations (annotations for class that contains properties). *

* Instances are not typically passed when constructing serializers * and deserializers, but rather only passed when context * is known when * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer} and * {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer} * resolution occurs (createContextual(...) method is called). * References may (need to) be retained by serializers and deserializers, * especially when further resolving dependent handlers like value * serializers/deserializers or structured types. */ public interface BeanProperty extends Named { public final static JsonFormat.Value EMPTY_FORMAT = new JsonFormat.Value(); public final static JsonInclude.Value EMPTY_INCLUDE = JsonInclude.Value.empty(); /** * Method to get logical name of the property */ @Override public String getName(); /** * Method for getting full name definition, including possible * format-specific additional properties (such as namespace when * using XML backend). * * @since 2.3 */ public PropertyName getFullName(); /** * Method to get declared type of the property. */ public JavaType getType(); /** * If property is indicated to be wrapped, name of * wrapper element to use. * * @since 2.2 */ public PropertyName getWrapperName(); /** * Accessor for additional optional information about property. * * @since 2.3 * * @return Metadata about property; never null. */ public PropertyMetadata getMetadata(); /** * Whether value for property is marked as required using * annotations or associated schema. * Equivalent to: * * getMetadata().isRequired() * * * @since 2.2 */ public boolean isRequired(); /** * Accessor for checking whether there is an actual physical property * behind this property abstraction or not. * * @since 2.7 */ public boolean isVirtual(); /* /********************************************************** /* Access to annotation information /********************************************************** */ /** * Method for finding annotation associated with this property; * meaning annotation associated with one of entities used to * access property. *

* Note that this method should only be called for custom annotations; * access to standard Jackson annotations (or ones supported by * alternate {@link AnnotationIntrospector}s) should be accessed * through {@link AnnotationIntrospector}. */ public A getAnnotation(Class acls); /** * Method for finding annotation associated with context of * this property; usually class in which member is declared * (or its subtype if processing subtype). *

* Note that this method should only be called for custom annotations; * access to standard Jackson annotations (or ones supported by * alternate {@link AnnotationIntrospector}s) should be accessed * through {@link AnnotationIntrospector}. */ public A getContextAnnotation(Class acls); /** * Method for accessing primary physical entity that represents the property; * annotated field, method or constructor property. */ public AnnotatedMember getMember(); /** * Convenience method that is roughly equivalent to *

     *   return intr.findFormat(getMember());
     *
* and specifically does NOT try to find per-type format defaults to merge; * use {@link #findPropertyFormat} if such defaults would be useful. * * @since 2.6 * * @deprecated since 2.8 use {@link #findPropertyFormat} instead. */ @Deprecated public JsonFormat.Value findFormatOverrides(AnnotationIntrospector intr); /** * Helper method used to look up format settings applicable to this property, * considering both possible per-type configuration settings * * @since 2.7 */ public JsonFormat.Value findPropertyFormat(MapperConfig config, Class baseType); /** * Convenience method that is roughly equivalent to *
     *   return config.getAnnotationIntrospector().findPropertyInclusion(getMember());
     *
* but also considers global default settings for inclusion * * @since 2.7 */ public JsonInclude.Value findPropertyInclusion(MapperConfig config, Class baseType); /** * Method for accessing set of possible alternate names that are accepted * during deserialization. * * @return List (possibly empty) of alternate names; never null * * @since 2.9 */ public List findAliases(MapperConfig config); /* /********************************************************** /* Schema/introspection support /********************************************************** */ /** * Method that can be called to visit the type structure that this * property is part of. * Note that not all implementations support traversal with this * method; those that do not should throw * {@link UnsupportedOperationException}. *

* NOTE: Starting with 2.7, takes explicit {@link SerializerProvider} * argument to reduce the need to rely on provider visitor may or may not * have assigned. * * @param objectVisitor Visitor to used as the callback handler * * @since 2.2 (although signature did change in 2.7) */ public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException; /* /********************************************************** /* Helper classes /********************************************************** */ /** * Simple stand-alone implementation, useful as a placeholder * or base class for more complex implementations. */ public static class Std implements BeanProperty, java.io.Serializable // 2.9 { private static final long serialVersionUID = 1L; protected final PropertyName _name; protected final JavaType _type; protected final PropertyName _wrapperName; protected final PropertyMetadata _metadata; /** * Physical entity (field, method or constructor argument) that * is used to access value of property (or in case of constructor * property, just placeholder) */ protected final AnnotatedMember _member; public Std(PropertyName name, JavaType type, PropertyName wrapperName, AnnotatedMember member, PropertyMetadata metadata) { _name = name; _type = type; _wrapperName = wrapperName; _metadata = metadata; _member = member; } /** * @deprecated Since 2.9 */ @Deprecated public Std(PropertyName name, JavaType type, PropertyName wrapperName, Annotations contextAnnotations, AnnotatedMember member, PropertyMetadata metadata) { this(name, type, wrapperName, member, metadata); } /** * @since 2.6 */ public Std(Std base, JavaType newType) { this(base._name, newType, base._wrapperName, base._member, base._metadata); } public Std withType(JavaType type) { return new Std(this, type); } @Override public A getAnnotation(Class acls) { return (_member == null) ? null : _member.getAnnotation(acls); } @Override public A getContextAnnotation(Class acls) { return null; } @Override @Deprecated public JsonFormat.Value findFormatOverrides(AnnotationIntrospector intr) { if ((_member != null) && (intr != null)) { JsonFormat.Value v = intr.findFormat(_member); if (v != null) { return v; } } return EMPTY_FORMAT; } @Override public JsonFormat.Value findPropertyFormat(MapperConfig config, Class baseType) { JsonFormat.Value v0 = config.getDefaultPropertyFormat(baseType); AnnotationIntrospector intr = config.getAnnotationIntrospector(); if ((intr == null) || (_member == null)) { return v0; } JsonFormat.Value v = intr.findFormat(_member); if (v == null) { return v0; } return v0.withOverrides(v); } @Override public JsonInclude.Value findPropertyInclusion(MapperConfig config, Class baseType) { JsonInclude.Value v0 = config.getDefaultInclusion(baseType, _type.getRawClass()); AnnotationIntrospector intr = config.getAnnotationIntrospector(); if ((intr == null) || (_member == null)) { return v0; } JsonInclude.Value v = intr.findPropertyInclusion(_member); if (v == null) { return v0; } return v0.withOverrides(v); } @Override public List findAliases(MapperConfig config) { // 26-Feb-2017, tatu: Do we really need to allow actual definition? // For now, let's not. return Collections.emptyList(); } @Override public String getName() { return _name.getSimpleName(); } @Override public PropertyName getFullName() { return _name; } @Override public JavaType getType() { return _type; } @Override public PropertyName getWrapperName() { return _wrapperName; } @Override public boolean isRequired() { return _metadata.isRequired(); } @Override public PropertyMetadata getMetadata() { return _metadata; } @Override public AnnotatedMember getMember() { return _member; } @Override public boolean isVirtual() { return false; } /** * Implementation of this method throws * {@link UnsupportedOperationException}, since instances of this * implementation should not be used as part of actual structure * visited. Rather, other implementations should handle it. */ @Override public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) { throw new UnsupportedOperationException("Instances of "+getClass().getName()+" should not get visited"); } } /** * Alternative "Null" implementation that can be used in cases where a non-null * {@link BeanProperty} is needed * * @since 2.9 */ public static class Bogus implements BeanProperty { @Override public String getName() { return ""; } @Override public PropertyName getFullName() { return PropertyName.NO_NAME; } @Override public JavaType getType() { return TypeFactory.unknownType(); } @Override public PropertyName getWrapperName() { return null; } @Override public PropertyMetadata getMetadata() { return PropertyMetadata.STD_REQUIRED_OR_OPTIONAL; } @Override public boolean isRequired() { return false; } @Override public boolean isVirtual() { return false; } @Override public A getAnnotation(Class acls) { return null; } @Override public A getContextAnnotation(Class acls) { return null; } @Override public AnnotatedMember getMember() { return null; } @Override @Deprecated public Value findFormatOverrides(AnnotationIntrospector intr) { return Value.empty(); } @Override public Value findPropertyFormat(MapperConfig config, Class baseType) { return Value.empty(); } @Override public com.fasterxml.jackson.annotation.JsonInclude.Value findPropertyInclusion( MapperConfig config, Class baseType) { return null; } @Override public List findAliases(MapperConfig config) { return Collections.emptyList(); } @Override public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException { } } } DatabindContext.java000066400000000000000000000311011325620701100343620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.lang.reflect.Type; import java.util.Locale; import java.util.TimeZone; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.ObjectIdInfo; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.Converter; /** * Shared base class for {@link DeserializationContext} and * {@link SerializerProvider}, context objects passed through data-binding * process. Designed so that some of implementations can rely on shared * aspects like access to secondary contextual objects like type factories * or handler instantiators. * * @since 2.2 */ public abstract class DatabindContext { /** * Let's limit length of error messages, for cases where underlying data * may be very large -- no point in spamming logs with megabytes of meaningless * data. * * @since 2.9 */ private final static int MAX_ERROR_STR_LEN = 500; /* /********************************************************** /* Generic config access /********************************************************** */ /** * Accessor to currently active configuration (both per-request configs * and per-mapper config). */ public abstract MapperConfig getConfig(); /** * Convenience method for accessing serialization view in use (if any); equivalent to: *

     *   getConfig().getAnnotationIntrospector();
     *
*/ public abstract AnnotationIntrospector getAnnotationIntrospector(); /* /********************************************************** /* Access to specific config settings /********************************************************** */ /** * Convenience method for checking whether specified serialization * feature is enabled or not. * Shortcut for: *
     *  getConfig().isEnabled(feature);
     *
*/ public abstract boolean isEnabled(MapperFeature feature); /** * Convenience method for accessing serialization view in use (if any); equivalent to: *
     *   getConfig().canOverrideAccessModifiers();
     *
*/ public abstract boolean canOverrideAccessModifiers(); /** * Accessor for locating currently active view, if any; * returns null if no view has been set. */ public abstract Class getActiveView(); /** * @since 2.6 */ public abstract Locale getLocale(); /** * @since 2.6 */ public abstract TimeZone getTimeZone(); /** * @since 2.7 */ public abstract JsonFormat.Value getDefaultPropertyFormat(Class baseType); /* /********************************************************** /* Generic attributes (2.3+) /********************************************************** */ /** * Method for accessing attributes available in this context. * Per-call attributes have highest precedence; attributes set * via {@link ObjectReader} or {@link ObjectWriter} have lower * precedence. * * @param key Key of the attribute to get * @return Value of the attribute, if any; null otherwise * * @since 2.3 */ public abstract Object getAttribute(Object key); /** * Method for setting per-call value of given attribute. * This will override any previously defined value for the * attribute within this context. * * @param key Key of the attribute to set * @param value Value to set attribute to * * @return This context object, to allow chaining * * @since 2.3 */ public abstract DatabindContext setAttribute(Object key, Object value); /* /********************************************************** /* Type instantiation/resolution /********************************************************** */ /** * Convenience method for constructing {@link JavaType} for given JDK * type (usually {@link java.lang.Class}) */ public JavaType constructType(Type type) { if (type == null) { return null; } return getTypeFactory().constructType(type); } /** * Convenience method for constructing subtypes, retaining generic * type parameter (if any) */ public JavaType constructSpecializedType(JavaType baseType, Class subclass) { // simple optimization to avoid costly introspection if type-erased type does NOT differ if (baseType.getRawClass() == subclass) { return baseType; } return getConfig().constructSpecializedType(baseType, subclass); } /** * Lookup method called when code needs to resolve class name from input; * usually simple lookup * * @since 2.9 */ public JavaType resolveSubType(JavaType baseType, String subClass) throws JsonMappingException { // 30-Jan-2010, tatu: Most ids are basic class names; so let's first // check if any generics info is added; and only then ask factory // to do translation when necessary if (subClass.indexOf('<') > 0) { // note: may want to try combining with specialization (esp for EnumMap)? // 17-Aug-2017, tatu: As per [databind#1735] need to ensure assignment // compatibility -- needed later anyway, and not doing so may open // security issues. JavaType t = getTypeFactory().constructFromCanonical(subClass); if (t.isTypeOrSubTypeOf(baseType.getRawClass())) { return t; } } else { Class cls; try { cls = getTypeFactory().findClass(subClass); } catch (ClassNotFoundException e) { // let caller handle this problem return null; } catch (Exception e) { throw invalidTypeIdException(baseType, subClass, String.format( "problem: (%s) %s", e.getClass().getName(), e.getMessage())); } if (baseType.isTypeOrSuperTypeOf(cls)) { return getTypeFactory().constructSpecializedType(baseType, cls); } } throw invalidTypeIdException(baseType, subClass, "Not a subtype"); } /** * Helper method for constructing exception to indicate that given type id * could not be resolved to a valid subtype of specified base type. * Most commonly called during polymorphic deserialization. *

* Note that most of the time this method should NOT be called directly: instead, * method handleUnknownTypeId() should be called which will call this method * if necessary. * * @since 2.9 */ protected abstract JsonMappingException invalidTypeIdException(JavaType baseType, String typeId, String extraDesc); public abstract TypeFactory getTypeFactory(); /* /********************************************************** /* Helper object construction /********************************************************** */ public ObjectIdGenerator objectIdGeneratorInstance(Annotated annotated, ObjectIdInfo objectIdInfo) throws JsonMappingException { Class implClass = objectIdInfo.getGeneratorType(); final MapperConfig config = getConfig(); HandlerInstantiator hi = config.getHandlerInstantiator(); ObjectIdGenerator gen = (hi == null) ? null : hi.objectIdGeneratorInstance(config, annotated, implClass); if (gen == null) { gen = (ObjectIdGenerator) ClassUtil.createInstance(implClass, config.canOverrideAccessModifiers()); } return gen.forScope(objectIdInfo.getScope()); } public ObjectIdResolver objectIdResolverInstance(Annotated annotated, ObjectIdInfo objectIdInfo) { Class implClass = objectIdInfo.getResolverType(); final MapperConfig config = getConfig(); HandlerInstantiator hi = config.getHandlerInstantiator(); ObjectIdResolver resolver = (hi == null) ? null : hi.resolverIdGeneratorInstance(config, annotated, implClass); if (resolver == null) { resolver = ClassUtil.createInstance(implClass, config.canOverrideAccessModifiers()); } return resolver; } /** * Helper method to use to construct a {@link Converter}, given a definition * that may be either actual converter instance, or Class for instantiating one. * * @since 2.2 */ @SuppressWarnings("unchecked") public Converter converterInstance(Annotated annotated, Object converterDef) throws JsonMappingException { if (converterDef == null) { return null; } if (converterDef instanceof Converter) { return (Converter) converterDef; } if (!(converterDef instanceof Class)) { throw new IllegalStateException("AnnotationIntrospector returned Converter definition of type " +converterDef.getClass().getName()+"; expected type Converter or Class instead"); } Class converterClass = (Class)converterDef; // there are some known "no class" markers to consider too: if (converterClass == Converter.None.class || ClassUtil.isBogusClass(converterClass)) { return null; } if (!Converter.class.isAssignableFrom(converterClass)) { throw new IllegalStateException("AnnotationIntrospector returned Class " +converterClass.getName()+"; expected Class"); } final MapperConfig config = getConfig(); HandlerInstantiator hi = config.getHandlerInstantiator(); Converter conv = (hi == null) ? null : hi.converterInstance(config, annotated, converterClass); if (conv == null) { conv = (Converter) ClassUtil.createInstance(converterClass, config.canOverrideAccessModifiers()); } return (Converter) conv; } /* /********************************************************** /* Error reporting /********************************************************** */ /** * Helper method called to indicate a generic problem that stems from type * definition(s), not input data, or input/output state; typically this * means throwing a {@link com.fasterxml.jackson.databind.exc.InvalidDefinitionException}. * * @since 2.9 */ public abstract T reportBadDefinition(JavaType type, String msg) throws JsonMappingException; /** * @since 2.9 */ public T reportBadDefinition(Class type, String msg) throws JsonMappingException { return reportBadDefinition(constructType(type), msg); } /* /********************************************************** /* Helper methods /********************************************************** */ /** * @since 2.9 */ protected final String _format(String msg, Object... msgArgs) { if (msgArgs.length > 0) { return String.format(msg, msgArgs); } return msg; } /** * @since 2.9 */ protected final String _truncate(String desc) { if (desc == null) { return ""; } if (desc.length() <= MAX_ERROR_STR_LEN) { return desc; } return desc.substring(0, MAX_ERROR_STR_LEN) + "]...[" + desc.substring(desc.length() - MAX_ERROR_STR_LEN); } /** * @since 2.9 */ protected String _quotedString(String desc) { if (desc == null) { return "[N/A]"; } // !!! should we quote it? (in case there are control chars, linefeeds) return String.format("\"%s\"", _truncate(desc)); } /** * @since 2.9 */ protected String _colonConcat(String msgBase, String extra) { if (extra == null) { return msgBase; } return msgBase + ": " + extra; } /** * @since 2.9 */ protected String _desc(String desc) { if (desc == null) { return "[N/A]"; } // !!! should we quote it? (in case there are control chars, linefeeds) return _truncate(desc); } } DeserializationConfig.java000066400000000000000000000702431325620701100355750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.cfg.*; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.*; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.util.LinkedNode; import com.fasterxml.jackson.databind.util.RootNameLookup; /** * Object that contains baseline configuration for deserialization * process. An instance is owned by {@link ObjectMapper}, which * passes an immutable instance to be used for deserialization process. *

* Note that instances are considered immutable and as such no copies * should need to be created for sharing; all copying is done with * "fluent factory" methods. */ public final class DeserializationConfig extends MapperConfigBase implements java.io.Serializable // since 2.1 { // since 2.9 private static final long serialVersionUID = 2; /* /********************************************************** /* Configured helper objects /********************************************************** */ /** * Linked list that contains all registered problem handlers. * Implementation as front-added linked list allows for sharing * of the list (tail) without copying the list. */ protected final LinkedNode _problemHandlers; /** * Factory used for constructing {@link com.fasterxml.jackson.databind.JsonNode} instances. */ protected final JsonNodeFactory _nodeFactory; /* /********************************************************** /* Deserialization features /********************************************************** */ /** * Set of {@link DeserializationFeature}s enabled. */ protected final int _deserFeatures; /* /********************************************************** /* Parser features: generic, format-specific /********************************************************** */ /** * States of {@link com.fasterxml.jackson.core.JsonParser.Feature}s to enable/disable. */ protected final int _parserFeatures; /** * Bitflag of {@link com.fasterxml.jackson.core.JsonParser.Feature}s to enable/disable */ protected final int _parserFeaturesToChange; /** * States of {@link com.fasterxml.jackson.core.FormatFeature}s to enable/disable. * * @since 2.7 */ protected final int _formatReadFeatures; /** * Bitflag of {@link com.fasterxml.jackson.core.FormatFeature}s to enable/disable * * @since 2.7 */ protected final int _formatReadFeaturesToChange; /* /********************************************************** /* Life-cycle, primary constructors for new instances /********************************************************** */ /** * Constructor used by ObjectMapper to create default configuration object instance. */ public DeserializationConfig(BaseSettings base, SubtypeResolver str, SimpleMixInResolver mixins, RootNameLookup rootNames, ConfigOverrides configOverrides) { super(base, str, mixins, rootNames, configOverrides); _deserFeatures = collectFeatureDefaults(DeserializationFeature.class); _nodeFactory = JsonNodeFactory.instance; _problemHandlers = null; _parserFeatures = 0; _parserFeaturesToChange = 0; _formatReadFeatures = 0; _formatReadFeaturesToChange = 0; } /** * Copy-constructor used for making a copy used by new {@link ObjectMapper}. * * @since 2.9 */ protected DeserializationConfig(DeserializationConfig src, SimpleMixInResolver mixins, RootNameLookup rootNames, ConfigOverrides configOverrides) { super(src, mixins, rootNames, configOverrides); _deserFeatures = src._deserFeatures; _problemHandlers = src._problemHandlers; _nodeFactory = src._nodeFactory; _parserFeatures = src._parserFeatures; _parserFeaturesToChange = src._parserFeaturesToChange; _formatReadFeatures = src._formatReadFeatures; _formatReadFeaturesToChange = src._formatReadFeaturesToChange; } /* /********************************************************** /* Life-cycle, secondary constructors to support /* "mutant factories", with single property changes /********************************************************** */ private DeserializationConfig(DeserializationConfig src, int mapperFeatures, int deserFeatures, int parserFeatures, int parserFeatureMask, int formatFeatures, int formatFeatureMask) { super(src, mapperFeatures); _deserFeatures = deserFeatures; _nodeFactory = src._nodeFactory; _problemHandlers = src._problemHandlers; _parserFeatures = parserFeatures; _parserFeaturesToChange = parserFeatureMask; _formatReadFeatures = formatFeatures; _formatReadFeaturesToChange = formatFeatureMask; } /** * Copy constructor used to create a non-shared instance with given mix-in * annotation definitions and subtype resolver. */ private DeserializationConfig(DeserializationConfig src, SubtypeResolver str) { super(src, str); _deserFeatures = src._deserFeatures; _nodeFactory = src._nodeFactory; _problemHandlers = src._problemHandlers; _parserFeatures = src._parserFeatures; _parserFeaturesToChange = src._parserFeaturesToChange; _formatReadFeatures = src._formatReadFeatures; _formatReadFeaturesToChange = src._formatReadFeaturesToChange; } private DeserializationConfig(DeserializationConfig src, BaseSettings base) { super(src, base); _deserFeatures = src._deserFeatures; _nodeFactory = src._nodeFactory; _problemHandlers = src._problemHandlers; _parserFeatures = src._parserFeatures; _parserFeaturesToChange = src._parserFeaturesToChange; _formatReadFeatures = src._formatReadFeatures; _formatReadFeaturesToChange = src._formatReadFeaturesToChange; } private DeserializationConfig(DeserializationConfig src, JsonNodeFactory f) { super(src); _deserFeatures = src._deserFeatures; _problemHandlers = src._problemHandlers; _nodeFactory = f; _parserFeatures = src._parserFeatures; _parserFeaturesToChange = src._parserFeaturesToChange; _formatReadFeatures = src._formatReadFeatures; _formatReadFeaturesToChange = src._formatReadFeaturesToChange; } private DeserializationConfig(DeserializationConfig src, LinkedNode problemHandlers) { super(src); _deserFeatures = src._deserFeatures; _problemHandlers = problemHandlers; _nodeFactory = src._nodeFactory; _parserFeatures = src._parserFeatures; _parserFeaturesToChange = src._parserFeaturesToChange; _formatReadFeatures = src._formatReadFeatures; _formatReadFeaturesToChange = src._formatReadFeaturesToChange; } private DeserializationConfig(DeserializationConfig src, PropertyName rootName) { super(src, rootName); _deserFeatures = src._deserFeatures; _problemHandlers = src._problemHandlers; _nodeFactory = src._nodeFactory; _parserFeatures = src._parserFeatures; _parserFeaturesToChange = src._parserFeaturesToChange; _formatReadFeatures = src._formatReadFeatures; _formatReadFeaturesToChange = src._formatReadFeaturesToChange; } private DeserializationConfig(DeserializationConfig src, Class view) { super(src, view); _deserFeatures = src._deserFeatures; _problemHandlers = src._problemHandlers; _nodeFactory = src._nodeFactory; _parserFeatures = src._parserFeatures; _parserFeaturesToChange = src._parserFeaturesToChange; _formatReadFeatures = src._formatReadFeatures; _formatReadFeaturesToChange = src._formatReadFeaturesToChange; } protected DeserializationConfig(DeserializationConfig src, ContextAttributes attrs) { super(src, attrs); _deserFeatures = src._deserFeatures; _problemHandlers = src._problemHandlers; _nodeFactory = src._nodeFactory; _parserFeatures = src._parserFeatures; _parserFeaturesToChange = src._parserFeaturesToChange; _formatReadFeatures = src._formatReadFeatures; _formatReadFeaturesToChange = src._formatReadFeaturesToChange; } protected DeserializationConfig(DeserializationConfig src, SimpleMixInResolver mixins) { super(src, mixins); _deserFeatures = src._deserFeatures; _problemHandlers = src._problemHandlers; _nodeFactory = src._nodeFactory; _parserFeatures = src._parserFeatures; _parserFeaturesToChange = src._parserFeaturesToChange; _formatReadFeatures = src._formatReadFeatures; _formatReadFeaturesToChange = src._formatReadFeaturesToChange; } // for unit tests only: protected BaseSettings getBaseSettings() { return _base; } /* /********************************************************** /* Life-cycle, general factory methods from MapperConfig(Base) /********************************************************** */ @Override // since 2.9 protected final DeserializationConfig _withBase(BaseSettings newBase) { return (_base == newBase) ? this : new DeserializationConfig(this, newBase); } @Override // since 2.9 protected final DeserializationConfig _withMapperFeatures(int mapperFeatures) { return new DeserializationConfig(this, mapperFeatures, _deserFeatures, _parserFeatures, _parserFeaturesToChange, _formatReadFeatures, _formatReadFeaturesToChange); } /* /********************************************************** /* Life-cycle, specific factory methods from MapperConfig /********************************************************** */ @Override public DeserializationConfig with(SubtypeResolver str) { return (_subtypeResolver == str) ? this : new DeserializationConfig(this, str); } @Override public DeserializationConfig withRootName(PropertyName rootName) { if (rootName == null) { if (_rootName == null) { return this; } } else if (rootName.equals(_rootName)) { return this; } return new DeserializationConfig(this, rootName); } @Override public DeserializationConfig withView(Class view) { return (_view == view) ? this : new DeserializationConfig(this, view); } @Override public DeserializationConfig with(ContextAttributes attrs) { return (attrs == _attributes) ? this : new DeserializationConfig(this, attrs); } /* /********************************************************** /* Life-cycle, DeserializationFeature-based factory methods /********************************************************** */ /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. */ public DeserializationConfig with(DeserializationFeature feature) { int newDeserFeatures = (_deserFeatures | feature.getMask()); return (newDeserFeatures == _deserFeatures) ? this : new DeserializationConfig(this, _mapperFeatures, newDeserFeatures, _parserFeatures, _parserFeaturesToChange, _formatReadFeatures, _formatReadFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. */ public DeserializationConfig with(DeserializationFeature first, DeserializationFeature... features) { int newDeserFeatures = _deserFeatures | first.getMask(); for (DeserializationFeature f : features) { newDeserFeatures |= f.getMask(); } return (newDeserFeatures == _deserFeatures) ? this : new DeserializationConfig(this, _mapperFeatures, newDeserFeatures, _parserFeatures, _parserFeaturesToChange, _formatReadFeatures, _formatReadFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. */ public DeserializationConfig withFeatures(DeserializationFeature... features) { int newDeserFeatures = _deserFeatures; for (DeserializationFeature f : features) { newDeserFeatures |= f.getMask(); } return (newDeserFeatures == _deserFeatures) ? this : new DeserializationConfig(this, _mapperFeatures, newDeserFeatures, _parserFeatures, _parserFeaturesToChange, _formatReadFeatures, _formatReadFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature disabled. */ public DeserializationConfig without(DeserializationFeature feature) { int newDeserFeatures = _deserFeatures & ~feature.getMask(); return (newDeserFeatures == _deserFeatures) ? this : new DeserializationConfig(this, _mapperFeatures, newDeserFeatures, _parserFeatures, _parserFeaturesToChange, _formatReadFeatures, _formatReadFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. */ public DeserializationConfig without(DeserializationFeature first, DeserializationFeature... features) { int newDeserFeatures = _deserFeatures & ~first.getMask(); for (DeserializationFeature f : features) { newDeserFeatures &= ~f.getMask(); } return (newDeserFeatures == _deserFeatures) ? this : new DeserializationConfig(this, _mapperFeatures, newDeserFeatures, _parserFeatures, _parserFeaturesToChange, _formatReadFeatures, _formatReadFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. */ public DeserializationConfig withoutFeatures(DeserializationFeature... features) { int newDeserFeatures = _deserFeatures; for (DeserializationFeature f : features) { newDeserFeatures &= ~f.getMask(); } return (newDeserFeatures == _deserFeatures) ? this : new DeserializationConfig(this, _mapperFeatures, newDeserFeatures, _parserFeatures, _parserFeaturesToChange, _formatReadFeatures, _formatReadFeaturesToChange); } /* /********************************************************** /* Life-cycle, JsonParser.Feature-based factory methods /********************************************************** */ /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. * * @since 2.5 */ public DeserializationConfig with(JsonParser.Feature feature) { int newSet = _parserFeatures | feature.getMask(); int newMask = _parserFeaturesToChange | feature.getMask(); return ((_parserFeatures == newSet) && (_parserFeaturesToChange == newMask)) ? this : new DeserializationConfig(this, _mapperFeatures, _deserFeatures, newSet, newMask, _formatReadFeatures, _formatReadFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. * * @since 2.5 */ public DeserializationConfig withFeatures(JsonParser.Feature... features) { int newSet = _parserFeatures; int newMask = _parserFeaturesToChange; for (JsonParser.Feature f : features) { int mask = f.getMask(); newSet |= mask; newMask |= mask; } return ((_parserFeatures == newSet) && (_parserFeaturesToChange == newMask)) ? this : new DeserializationConfig(this, _mapperFeatures, _deserFeatures, newSet, newMask, _formatReadFeatures, _formatReadFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature disabled. * * @since 2.5 */ public DeserializationConfig without(JsonParser.Feature feature) { int newSet = _parserFeatures & ~feature.getMask(); int newMask = _parserFeaturesToChange | feature.getMask(); return ((_parserFeatures == newSet) && (_parserFeaturesToChange == newMask)) ? this : new DeserializationConfig(this, _mapperFeatures, _deserFeatures, newSet, newMask, _formatReadFeatures, _formatReadFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. * * @since 2.5 */ public DeserializationConfig withoutFeatures(JsonParser.Feature... features) { int newSet = _parserFeatures; int newMask = _parserFeaturesToChange; for (JsonParser.Feature f : features) { int mask = f.getMask(); newSet &= ~mask; newMask |= mask; } return ((_parserFeatures == newSet) && (_parserFeaturesToChange == newMask)) ? this : new DeserializationConfig(this, _mapperFeatures, _deserFeatures, newSet, newMask, _formatReadFeatures, _formatReadFeaturesToChange); } /* /********************************************************** /* Life-cycle, JsonParser.FormatFeature-based factory methods /********************************************************** */ /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. * * @since 2.7 */ public DeserializationConfig with(FormatFeature feature) { int newSet = _formatReadFeatures | feature.getMask(); int newMask = _formatReadFeaturesToChange | feature.getMask(); return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this : new DeserializationConfig(this, _mapperFeatures, _deserFeatures, _parserFeatures, _parserFeaturesToChange, newSet, newMask); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. * * @since 2.7 */ public DeserializationConfig withFeatures(FormatFeature... features) { int newSet = _formatReadFeatures; int newMask = _formatReadFeaturesToChange; for (FormatFeature f : features) { int mask = f.getMask(); newSet |= mask; newMask |= mask; } return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this : new DeserializationConfig(this, _mapperFeatures, _deserFeatures, _parserFeatures, _parserFeaturesToChange, newSet, newMask); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature disabled. * * @since 2.7 */ public DeserializationConfig without(FormatFeature feature) { int newSet = _formatReadFeatures & ~feature.getMask(); int newMask = _formatReadFeaturesToChange | feature.getMask(); return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this : new DeserializationConfig(this, _mapperFeatures, _deserFeatures, _parserFeatures, _parserFeaturesToChange, newSet, newMask); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. * * @since 2.7 */ public DeserializationConfig withoutFeatures(FormatFeature... features) { int newSet = _formatReadFeatures; int newMask = _formatReadFeaturesToChange; for (FormatFeature f : features) { int mask = f.getMask(); newSet &= ~mask; newMask |= mask; } return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this : new DeserializationConfig(this, _mapperFeatures, _deserFeatures, _parserFeatures, _parserFeaturesToChange, newSet, newMask); } /* /********************************************************** /* Life-cycle, deserialization-specific factory methods /********************************************************** */ /** * Fluent factory method that will construct a new instance with * specified {@link JsonNodeFactory} */ public DeserializationConfig with(JsonNodeFactory f) { if (_nodeFactory == f) { return this; } return new DeserializationConfig(this, f); } /** * Method that can be used to add a handler that can (try to) * resolve non-fatal deserialization problems. */ public DeserializationConfig withHandler(DeserializationProblemHandler h) { // Sanity check: let's prevent adding same handler multiple times if (LinkedNode.contains(_problemHandlers, h)) { return this; } return new DeserializationConfig(this, new LinkedNode(h, _problemHandlers)); } /** * Method for removing all configured problem handlers; usually done to replace * existing handler(s) with different one(s) */ public DeserializationConfig withNoProblemHandlers() { if (_problemHandlers == null) { return this; } return new DeserializationConfig(this, (LinkedNode) null); } /* /********************************************************** /* JsonParser initialization /********************************************************** */ /** * Method called by {@link ObjectMapper} and {@link ObjectReader} * to modify those {@link com.fasterxml.jackson.core.JsonParser.Feature} settings * that have been configured via this config instance. * * @since 2.5 */ public void initialize(JsonParser p) { if (_parserFeaturesToChange != 0) { p.overrideStdFeatures(_parserFeatures, _parserFeaturesToChange); } if (_formatReadFeaturesToChange != 0) { p.overrideFormatFeatures(_formatReadFeatures, _formatReadFeaturesToChange); } } /* /********************************************************** /* MapperConfig implementation/overrides: other /********************************************************** */ @Override public boolean useRootWrapping() { if (_rootName != null) { // empty String disables wrapping; non-empty enables return !_rootName.isEmpty(); } return isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE); } public final boolean isEnabled(DeserializationFeature f) { return (_deserFeatures & f.getMask()) != 0; } public final boolean isEnabled(JsonParser.Feature f, JsonFactory factory) { int mask = f.getMask(); if ((_parserFeaturesToChange & mask) != 0) { return (_parserFeatures & f.getMask()) != 0; } return factory.isEnabled(f); } /** * Bulk access method for checking that all features specified by * mask are enabled. * * @since 2.3 */ public final boolean hasDeserializationFeatures(int featureMask) { return (_deserFeatures & featureMask) == featureMask; } /** * Bulk access method for checking that at least one of features specified by * mask is enabled. * * @since 2.6 */ public final boolean hasSomeOfFeatures(int featureMask) { return (_deserFeatures & featureMask) != 0; } /** * Bulk access method for getting the bit mask of all {@link DeserializationFeature}s * that are enabled. */ public final int getDeserializationFeatures() { return _deserFeatures; } /** * Convenience method equivalant to: * * isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS) * * * @since 2.9 */ public final boolean requiresFullValue() { return DeserializationFeature.FAIL_ON_TRAILING_TOKENS.enabledIn(_deserFeatures); } /* /********************************************************** /* Other configuration /********************************************************** */ /** * Method for getting head of the problem handler chain. May be null, * if no handlers have been added. */ public LinkedNode getProblemHandlers() { return _problemHandlers; } public final JsonNodeFactory getNodeFactory() { return _nodeFactory; } /* /********************************************************** /* Introspection methods /********************************************************** */ /** * Method that will introspect full bean properties for the purpose * of building a bean deserializer * * @param type Type of class to be introspected */ @SuppressWarnings("unchecked") public T introspect(JavaType type) { return (T) getClassIntrospector().forDeserialization(this, type, this); } /** * Method that will introspect subset of bean properties needed to * construct bean instance. */ @SuppressWarnings("unchecked") public T introspectForCreation(JavaType type) { return (T) getClassIntrospector().forCreation(this, type, this); } /** * @since 2.0 */ @SuppressWarnings("unchecked") public T introspectForBuilder(JavaType type) { return (T) getClassIntrospector().forDeserializationWithBuilder(this, type, this); } /* /********************************************************** /* Support for polymorphic type handling /********************************************************** */ /** * Helper method that is needed to properly handle polymorphic referenced * types, such as types referenced by {@link java.util.concurrent.atomic.AtomicReference}, * or various "optional" types. * * @since 2.4 */ public TypeDeserializer findTypeDeserializer(JavaType baseType) throws JsonMappingException { BeanDescription bean = introspectClassAnnotations(baseType.getRawClass()); AnnotatedClass ac = bean.getClassInfo(); TypeResolverBuilder b = getAnnotationIntrospector().findTypeResolver(this, ac, baseType); /* Ok: if there is no explicit type info handler, we may want to * use a default. If so, config object knows what to use. */ Collection subtypes = null; if (b == null) { b = getDefaultTyper(baseType); if (b == null) { return null; } } else { subtypes = getSubtypeResolver().collectAndResolveSubtypesByTypeId(this, ac); } return b.buildTypeDeserializer(this, baseType, subtypes); } } DeserializationContext.java000066400000000000000000002071621325620701100360160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdResolver; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.cfg.ContextAttributes; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader; import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId; import com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import com.fasterxml.jackson.databind.exc.InvalidTypeIdException; import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.*; /** * Context for the process of deserialization a single root-level value. * Used to allow passing in configuration settings and reusable temporary * objects (scrap arrays, containers). *

* Instance life-cycle is such that a partially configured "blueprint" object * is registered with {@link ObjectMapper} (and {@link ObjectReader}, * and when actual instance is needed for deserialization, * a fully configured instance will be created using a method in extended internal * API of sub-class * ({@link com.fasterxml.jackson.databind.deser.DefaultDeserializationContext#createInstance}). * Each instance is guaranteed to only be used from single-threaded context; * instances may be reused if (and only if) no configuration has changed. *

* Defined as abstract class so that implementations must define methods * for reconfiguring blueprints and creating instances. */ public abstract class DeserializationContext extends DatabindContext implements java.io.Serializable { private static final long serialVersionUID = 1L; // 2.6 /* /********************************************************** /* Configuration, immutable /********************************************************** */ /** * Object that handle details of {@link JsonDeserializer} caching. */ protected final DeserializerCache _cache; /* /********************************************************** /* Configuration, changeable via fluent factories /********************************************************** */ /** * Read-only factory instance; exposed to let * owners (ObjectMapper, ObjectReader) * access it. */ protected final DeserializerFactory _factory; /* /********************************************************** /* Configuration that gets set for instances (not blueprints) /* (partly denormalized for performance) /********************************************************** */ /** * Generic deserialization processing configuration */ protected final DeserializationConfig _config; /** * Bitmap of {@link DeserializationFeature}s that are enabled */ protected final int _featureFlags; /** * Currently active view, if any. */ protected final Class _view; /** * Currently active parser used for deserialization. * May be different from the outermost parser * when content is buffered. */ protected transient JsonParser _parser; /** * Object used for resolving references to injectable * values. */ protected final InjectableValues _injectableValues; /* /********************************************************** /* Per-operation reusable helper objects (not for blueprints) /********************************************************** */ protected transient ArrayBuilders _arrayBuilders; protected transient ObjectBuffer _objectBuffer; protected transient DateFormat _dateFormat; /** * Lazily-constructed holder for per-call attributes. * * @since 2.3 */ protected transient ContextAttributes _attributes; /** * Type of {@link JsonDeserializer} (or, more specifically, * {@link ContextualDeserializer}) that is being * contextualized currently. * * @since 2.5 */ protected LinkedNode _currentType; /* /********************************************************** /* Life-cycle /********************************************************** */ protected DeserializationContext(DeserializerFactory df) { this(df, null); } protected DeserializationContext(DeserializerFactory df, DeserializerCache cache) { if (df == null) { throw new IllegalArgumentException("Cannot pass null DeserializerFactory"); } _factory = df; if (cache == null) { cache = new DeserializerCache(); } _cache = cache; _featureFlags = 0; _config = null; _injectableValues = null; _view = null; _attributes = null; } protected DeserializationContext(DeserializationContext src, DeserializerFactory factory) { _cache = src._cache; _factory = factory; _config = src._config; _featureFlags = src._featureFlags; _view = src._view; _parser = src._parser; _injectableValues = src._injectableValues; _attributes = src._attributes; } /** * Constructor used for creating actual per-call instances. */ protected DeserializationContext(DeserializationContext src, DeserializationConfig config, JsonParser p, InjectableValues injectableValues) { _cache = src._cache; _factory = src._factory; _config = config; _featureFlags = config.getDeserializationFeatures(); _view = config.getActiveView(); _parser = p; _injectableValues = injectableValues; _attributes = config.getAttributes(); } /** * Copy-constructor for use with copy() by {@link ObjectMapper#copy()} */ protected DeserializationContext(DeserializationContext src) { _cache = new DeserializerCache(); _factory = src._factory; _config = src._config; _featureFlags = src._featureFlags; _view = src._view; _injectableValues = null; } /* /********************************************************** /* DatabindContext implementation /********************************************************** */ @Override public DeserializationConfig getConfig() { return _config; } @Override public final Class getActiveView() { return _view; } @Override public final boolean canOverrideAccessModifiers() { return _config.canOverrideAccessModifiers(); } @Override public final boolean isEnabled(MapperFeature feature) { return _config.isEnabled(feature); } @Override public final JsonFormat.Value getDefaultPropertyFormat(Class baseType) { return _config.getDefaultPropertyFormat(baseType); } @Override public final AnnotationIntrospector getAnnotationIntrospector() { return _config.getAnnotationIntrospector(); } @Override public final TypeFactory getTypeFactory() { return _config.getTypeFactory(); } /** * Method for accessing default Locale to use: convenience method for *

     *   getConfig().getLocale();
     *
*/ @Override public Locale getLocale() { return _config.getLocale(); } /** * Method for accessing default TimeZone to use: convenience method for *
     *   getConfig().getTimeZone();
     *
*/ @Override public TimeZone getTimeZone() { return _config.getTimeZone(); } /* /********************************************************** /* Access to per-call state, like generic attributes (2.3+) /********************************************************** */ @Override public Object getAttribute(Object key) { return _attributes.getAttribute(key); } @Override public DeserializationContext setAttribute(Object key, Object value) { _attributes = _attributes.withPerCallAttribute(key, value); return this; } /** * Accessor to {@link JavaType} of currently contextualized * {@link ContextualDeserializer}, if any. * This is sometimes useful for generic {@link JsonDeserializer}s that * do not get passed (or do not retain) type information when being * constructed: happens for example for deserializers constructed * from annotations. * * @since 2.5 * * @return Type of {@link ContextualDeserializer} being contextualized, * if process is on-going; null if not. */ public JavaType getContextualType() { return (_currentType == null) ? null : _currentType.value(); } /* /********************************************************** /* Public API, config setting accessors /********************************************************** */ /** * Method for getting current {@link DeserializerFactory}. */ public DeserializerFactory getFactory() { return _factory; } /** * Convenience method for checking whether specified on/off * feature is enabled */ public final boolean isEnabled(DeserializationFeature feat) { /* 03-Dec-2010, tatu: minor shortcut; since this is called quite often, * let's use a local copy of feature settings: */ return (_featureFlags & feat.getMask()) != 0; } /** * Bulk access method for getting the bit mask of all {@link DeserializationFeature}s * that are enabled. * * @since 2.6 */ public final int getDeserializationFeatures() { return _featureFlags; } /** * Bulk access method for checking that all features specified by * mask are enabled. * * @since 2.3 */ public final boolean hasDeserializationFeatures(int featureMask) { return (_featureFlags & featureMask) == featureMask; } /** * Bulk access method for checking that at least one of features specified by * mask is enabled. * * @since 2.6 */ public final boolean hasSomeOfFeatures(int featureMask) { return (_featureFlags & featureMask) != 0; } /** * Method for accessing the currently active parser. * May be different from the outermost parser * when content is buffered. *

* Use of this method is discouraged: if code has direct access * to the active parser, that should be used instead. */ public final JsonParser getParser() { return _parser; } public final Object findInjectableValue(Object valueId, BeanProperty forProperty, Object beanInstance) throws JsonMappingException { if (_injectableValues == null) { reportBadDefinition(ClassUtil.classOf(valueId), String.format( "No 'injectableValues' configured, cannot inject value with id [%s]", valueId)); } return _injectableValues.findInjectableValue(valueId, this, forProperty, beanInstance); } /** * Convenience method for accessing the default Base64 encoding * used for decoding base64 encoded binary content. * Same as calling: *

     *  getConfig().getBase64Variant();
     *
*/ public final Base64Variant getBase64Variant() { return _config.getBase64Variant(); } /** * Convenience method, functionally equivalent to: *
     *  getConfig().getNodeFactory();
     * 
*/ public final JsonNodeFactory getNodeFactory() { return _config.getNodeFactory(); } /* /********************************************************** /* Public API, pass-through to DeserializerCache /********************************************************** */ /** * Method for checking whether we could find a deserializer * for given type. * * @param type * @since 2.3 */ public boolean hasValueDeserializerFor(JavaType type, AtomicReference cause) { try { return _cache.hasValueDeserializerFor(this, _factory, type); } catch (JsonMappingException e) { if (cause != null) { cause.set(e); } } catch (RuntimeException e) { if (cause == null) { // earlier behavior throw e; } cause.set(e); } return false; } /** * Method for finding a value deserializer, and creating a contextual * version if necessary, for value reached via specified property. */ @SuppressWarnings("unchecked") public final JsonDeserializer findContextualValueDeserializer(JavaType type, BeanProperty prop) throws JsonMappingException { JsonDeserializer deser = _cache.findValueDeserializer(this, _factory, type); if (deser != null) { deser = (JsonDeserializer) handleSecondaryContextualization(deser, prop, type); } return deser; } /** * Variant that will try to locate deserializer for current type, but without * performing any contextualization (unlike {@link #findContextualValueDeserializer}) * or checking for need to create a {@link TypeDeserializer} (unlike * {@link #findRootValueDeserializer(JavaType)}. * This method is usually called from within {@link ResolvableDeserializer#resolve}, * and expectation is that caller then calls either * {@link #handlePrimaryContextualization(JsonDeserializer, BeanProperty, JavaType)} or * {@link #handleSecondaryContextualization(JsonDeserializer, BeanProperty, JavaType)} at a * later point, as necessary. * * @since 2.5 */ public final JsonDeserializer findNonContextualValueDeserializer(JavaType type) throws JsonMappingException { return _cache.findValueDeserializer(this, _factory, type); } /** * Method for finding a deserializer for root-level value. */ @SuppressWarnings("unchecked") public final JsonDeserializer findRootValueDeserializer(JavaType type) throws JsonMappingException { JsonDeserializer deser = _cache.findValueDeserializer(this, _factory, type); if (deser == null) { // can this occur? return null; } deser = (JsonDeserializer) handleSecondaryContextualization(deser, null, type); TypeDeserializer typeDeser = _factory.findTypeDeserializer(_config, type); if (typeDeser != null) { // important: contextualize to indicate this is for root value typeDeser = typeDeser.forProperty(null); return new TypeWrappedDeserializer(typeDeser, deser); } return deser; } /** * Convenience method, functionally same as: *
     *  getDeserializerProvider().findKeyDeserializer(getConfig(), prop.getType(), prop);
     *
*/ public final KeyDeserializer findKeyDeserializer(JavaType keyType, BeanProperty prop) throws JsonMappingException { KeyDeserializer kd = _cache.findKeyDeserializer(this, _factory, keyType); // Second: contextualize? if (kd instanceof ContextualKeyDeserializer) { kd = ((ContextualKeyDeserializer) kd).createContextual(this, prop); } return kd; } /* /********************************************************** /* Public API, ObjectId handling /********************************************************** */ /** * Method called to find and return entry corresponding to given * Object Id: will add an entry if necessary, and never returns null */ public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator generator, ObjectIdResolver resolver); /** * Method called to ensure that every object id encounter during processing * are resolved. * * @throws UnresolvedForwardReference */ public abstract void checkUnresolvedObjectId() throws UnresolvedForwardReference; /* /********************************************************** /* Public API, type handling /********************************************************** */ /** * Convenience method, functionally equivalent to: *
     *  getConfig().constructType(cls);
     * 
*/ public final JavaType constructType(Class cls) { return (cls == null) ? null : _config.constructType(cls); } /** * Helper method that is to be used when resolving basic class name into * Class instance, the reason being that it may be necessary to work around * various ClassLoader limitations, as well as to handle primitive type * signatures. * * @since 2.6 */ public Class findClass(String className) throws ClassNotFoundException { // By default, delegate to ClassUtil: can be overridden with custom handling return getTypeFactory().findClass(className); } /* /********************************************************** /* Public API, helper object recycling /********************************************************** */ /** * Method that can be used to get access to a reusable ObjectBuffer, * useful for efficiently constructing Object arrays and Lists. * Note that leased buffers should be returned once deserializer * is done, to allow for reuse during same round of deserialization. */ public final ObjectBuffer leaseObjectBuffer() { ObjectBuffer buf = _objectBuffer; if (buf == null) { buf = new ObjectBuffer(); } else { _objectBuffer = null; } return buf; } /** * Method to call to return object buffer previously leased with * {@link #leaseObjectBuffer}. * * @param buf Returned object buffer */ public final void returnObjectBuffer(ObjectBuffer buf) { /* Already have a reusable buffer? Let's retain bigger one * (or if equal, favor newer one, shorter life-cycle) */ if (_objectBuffer == null || buf.initialCapacity() >= _objectBuffer.initialCapacity()) { _objectBuffer = buf; } } /** * Method for accessing object useful for building arrays of * primitive types (such as int[]). */ public final ArrayBuilders getArrayBuilders() { if (_arrayBuilders == null) { _arrayBuilders = new ArrayBuilders(); } return _arrayBuilders; } /* /********************************************************** /* Extended API: handler instantiation /********************************************************** */ public abstract JsonDeserializer deserializerInstance(Annotated annotated, Object deserDef) throws JsonMappingException; public abstract KeyDeserializer keyDeserializerInstance(Annotated annotated, Object deserDef) throws JsonMappingException; /* /********************************************************** /* Extended API: resolving contextual deserializers; called /* by structured deserializers for their value/component /* deserializers /********************************************************** */ /** * Method called for primary property deserializers (ones * directly created to deserialize values of a POJO property), * to handle details of resolving * {@link ContextualDeserializer} with given property context. * * @param prop Property for which the given primary deserializer is used; never null. * * @since 2.5 */ public JsonDeserializer handlePrimaryContextualization(JsonDeserializer deser, BeanProperty prop, JavaType type) throws JsonMappingException { if (deser instanceof ContextualDeserializer) { _currentType = new LinkedNode(type, _currentType); try { deser = ((ContextualDeserializer) deser).createContextual(this, prop); } finally { _currentType = _currentType.next(); } } return deser; } /** * Method called for secondary property deserializers (ones * NOT directly created to deal with an annotatable POJO property, * but instead created as a component -- such as value deserializers * for structured types, or deserializers for root values) * to handle details of resolving * {@link ContextualDeserializer} with given property context. * Given that these deserializers are not directly related to given property * (or, in case of root value property, to any property), annotations * accessible may or may not be relevant. * * @param prop Property for which deserializer is used, if any; null * when deserializing root values * * @since 2.5 */ public JsonDeserializer handleSecondaryContextualization(JsonDeserializer deser, BeanProperty prop, JavaType type) throws JsonMappingException { if (deser instanceof ContextualDeserializer) { _currentType = new LinkedNode(type, _currentType); try { deser = ((ContextualDeserializer) deser).createContextual(this, prop); } finally { _currentType = _currentType.next(); } } return deser; } /* /********************************************************** /* Parsing methods that may use reusable/-cyclable objects /********************************************************** */ /** * Convenience method for parsing a Date from given String, using * currently configured date format (accessed using * {@link DeserializationConfig#getDateFormat()}). *

* Implementation will handle thread-safety issues related to * date formats such that first time this method is called, * date format is cloned, and cloned instance will be retained * for use during this deserialization round. */ public Date parseDate(String dateStr) throws IllegalArgumentException { try { DateFormat df = getDateFormat(); return df.parse(dateStr); } catch (ParseException e) { throw new IllegalArgumentException(String.format( "Failed to parse Date value '%s': %s", dateStr, e.getMessage())); } } /** * Convenience method for constructing Calendar instance set * to specified time, to be modified and used by caller. */ public Calendar constructCalendar(Date d) { // 08-Jan-2008, tatu: not optimal, but should work for the most part; let's revise as needed. Calendar c = Calendar.getInstance(getTimeZone()); c.setTime(d); return c; } /* /********************************************************** /* Convenience methods for reading parsed values /********************************************************** */ /** * Convenience method that may be used by composite or container deserializers, * for reading one-off values contained (for sequences, it is more efficient * to actually fetch deserializer once for the whole collection). *

* NOTE: when deserializing values of properties contained in composite types, * rather use {@link #readPropertyValue(JsonParser, BeanProperty, Class)}; * this method does not allow use of contextual annotations. * * @since 2.4 */ public T readValue(JsonParser p, Class type) throws IOException { return readValue(p, getTypeFactory().constructType(type)); } /** * @since 2.4 */ @SuppressWarnings("unchecked") public T readValue(JsonParser p, JavaType type) throws IOException { JsonDeserializer deser = findRootValueDeserializer(type); if (deser == null) { reportBadDefinition(type, "Could not find JsonDeserializer for type "+type); } return (T) deser.deserialize(p, this); } /** * Convenience method that may be used by composite or container deserializers, * for reading one-off values for the composite type, taking into account * annotations that the property (passed to this method -- usually property that * has custom serializer that called this method) has. * * @since 2.4 */ public T readPropertyValue(JsonParser p, BeanProperty prop, Class type) throws IOException { return readPropertyValue(p, prop, getTypeFactory().constructType(type)); } /** * @since 2.4 */ @SuppressWarnings("unchecked") public T readPropertyValue(JsonParser p, BeanProperty prop, JavaType type) throws IOException { JsonDeserializer deser = findContextualValueDeserializer(type, prop); if (deser == null) { return reportBadDefinition(type, String.format( "Could not find JsonDeserializer for type %s (via property %s)", type, ClassUtil.nameOf(prop))); } return (T) deser.deserialize(p, this); } /* /********************************************************** /* Methods for problem handling /********************************************************** */ /** * Method that deserializers should call if they encounter an unrecognized * property (and once that is not explicitly designed as ignorable), to * inform possibly configured {@link DeserializationProblemHandler}s and * let it handle the problem. * * @return True if there was a configured problem handler that was able to handle the * problem */ public boolean handleUnknownProperty(JsonParser p, JsonDeserializer deser, Object instanceOrClass, String propName) throws IOException { LinkedNode h = _config.getProblemHandlers(); while (h != null) { // Can bail out if it's handled if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) { return true; } h = h.next(); } // Nope, not handled. Potentially that's a problem... if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) { p.skipChildren(); return true; } // Do we know properties that are expected instead? Collection propIds = (deser == null) ? null : deser.getKnownPropertyNames(); throw UnrecognizedPropertyException.from(_parser, instanceOrClass, propName, propIds); } /** * Method that deserializers should call if they encounter a String value * that cannot be converted to expected key of a {@link java.util.Map} * valued property. * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue} * on configured handlers, if any, to allow for recovery; if recovery does not * succeed, will throw {@link InvalidFormatException} with given message. * * @param keyClass Expected type for key * @param keyValue String value from which to deserialize key * @param msg Error message template caller wants to use if exception is to be thrown * @param msgArgs Optional arguments to use for message, if any * * @return Key value to use * * @throws IOException To indicate unrecoverable problem, usually based on msg * * @since 2.8 */ public Object handleWeirdKey(Class keyClass, String keyValue, String msg, Object... msgArgs) throws IOException { // but if not handled, just throw exception msg = _format(msg, msgArgs); LinkedNode h = _config.getProblemHandlers(); while (h != null) { // Can bail out if it's handled Object key = h.value().handleWeirdKey(this, keyClass, keyValue, msg); if (key != DeserializationProblemHandler.NOT_HANDLED) { // Sanity check for broken handlers, otherwise nasty to debug: if ((key == null) || keyClass.isInstance(key)) { return key; } throw weirdStringException(keyValue, keyClass, String.format( "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s", keyClass, key.getClass())); } h = h.next(); } throw weirdKeyException(keyClass, keyValue, msg); } /** * Method that deserializers should call if they encounter a String value * that cannot be converted to target property type, in cases where some * String values could be acceptable (either with different settings, * or different value). * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdStringValue} * on configured handlers, if any, to allow for recovery; if recovery does not * succeed, will throw {@link InvalidFormatException} with given message. * * @param targetClass Type of property into which incoming number should be converted * @param value String value from which to deserialize property value * @param msg Error message template caller wants to use if exception is to be thrown * @param msgArgs Optional arguments to use for message, if any * * @return Property value to use * * @throws IOException To indicate unrecoverable problem, usually based on msg * * @since 2.8 */ public Object handleWeirdStringValue(Class targetClass, String value, String msg, Object... msgArgs) throws IOException { // but if not handled, just throw exception msg = _format(msg, msgArgs); LinkedNode h = _config.getProblemHandlers(); while (h != null) { // Can bail out if it's handled Object instance = h.value().handleWeirdStringValue(this, targetClass, value, msg); if (instance != DeserializationProblemHandler.NOT_HANDLED) { // Sanity check for broken handlers, otherwise nasty to debug: if (_isCompatible(targetClass, instance)) { return instance; } throw weirdStringException(value, targetClass, String.format( "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s", targetClass, instance.getClass())); } h = h.next(); } throw weirdStringException(value, targetClass, msg); } /** * Method that deserializers should call if they encounter a numeric value * that cannot be converted to target property type, in cases where some * numeric values could be acceptable (either with different settings, * or different numeric value). * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue} * on configured handlers, if any, to allow for recovery; if recovery does not * succeed, will throw {@link InvalidFormatException} with given message. * * @param targetClass Type of property into which incoming number should be converted * @param value Number value from which to deserialize property value * @param msg Error message template caller wants to use if exception is to be thrown * @param msgArgs Optional arguments to use for message, if any * * @return Property value to use * * @throws IOException To indicate unrecoverable problem, usually based on msg * * @since 2.8 */ public Object handleWeirdNumberValue(Class targetClass, Number value, String msg, Object... msgArgs) throws IOException { msg = _format(msg, msgArgs); LinkedNode h = _config.getProblemHandlers(); while (h != null) { // Can bail out if it's handled Object key = h.value().handleWeirdNumberValue(this, targetClass, value, msg); if (key != DeserializationProblemHandler.NOT_HANDLED) { // Sanity check for broken handlers, otherwise nasty to debug: if (_isCompatible(targetClass, key)) { return key; } throw weirdNumberException(value, targetClass, _format( "DeserializationProblemHandler.handleWeirdNumberValue() for type %s returned value of type %s", targetClass, key.getClass())); } h = h.next(); } throw weirdNumberException(value, targetClass, msg); } public Object handleWeirdNativeValue(JavaType targetType, Object badValue, JsonParser p) throws IOException { LinkedNode h = _config.getProblemHandlers(); final Class raw = targetType.getRawClass(); for (; h != null; h = h.next()) { // Can bail out if it's handled Object goodValue = h.value().handleWeirdNativeValue(this, targetType, badValue, p); if (goodValue != DeserializationProblemHandler.NOT_HANDLED) { // Sanity check for broken handlers, otherwise nasty to debug: if ((goodValue == null) || raw.isInstance(goodValue)) { return goodValue; } throw JsonMappingException.from(p, _format( "DeserializationProblemHandler.handleWeirdNativeValue() for type %s returned value of type %s", targetType, goodValue.getClass())); } } throw weirdNativeValueException(badValue, raw); } /** * Method that deserializers should call if they fail to instantiate value * due to lack of viable instantiator (usually creator, that is, constructor * or static factory method). Method should be called at point where value * has not been decoded, so that handler has a chance to handle decoding * using alternate mechanism, and handle underlying content (possibly by * just skipping it) to keep input state valid * * @param instClass Type that was to be instantiated * @param valueInst (optional) Value instantiator to be used, if any; null if type does not * use one for instantiation (custom deserialiers don't; standard POJO deserializer does) * @param p Parser that points to the JSON value to decode * * @return Object that should be constructed, if any; has to be of type instClass * * @since 2.9 (2.8 had alternate that did not take ValueInstantiator) */ @SuppressWarnings("resource") public Object handleMissingInstantiator(Class instClass, ValueInstantiator valueInst, JsonParser p, String msg, Object... msgArgs) throws IOException { if (p == null) { p = getParser(); } msg = _format(msg, msgArgs); LinkedNode h = _config.getProblemHandlers(); while (h != null) { // Can bail out if it's handled Object instance = h.value().handleMissingInstantiator(this, instClass, valueInst, p, msg); if (instance != DeserializationProblemHandler.NOT_HANDLED) { // Sanity check for broken handlers, otherwise nasty to debug: if (_isCompatible(instClass, instance)) { return instance; } reportBadDefinition(constructType(instClass), String.format( "DeserializationProblemHandler.handleMissingInstantiator() for type %s returned value of type %s", instClass, ClassUtil.classNameOf(instance))); } h = h.next(); } // 16-Oct-2016, tatu: This is either a definition problem (if no applicable creator // exists), or input mismatch problem (otherwise) since none of existing creators // match with token. if ((valueInst != null) && !valueInst.canInstantiate()) { msg = String.format("Cannot construct instance of %s (no Creators, like default construct, exist): %s", ClassUtil.nameOf(instClass), msg); return reportBadDefinition(constructType(instClass), msg); } msg = String.format("Cannot construct instance of %s (although at least one Creator exists): %s", ClassUtil.nameOf(instClass), msg); return reportInputMismatch(instClass, msg); } /** * Method that deserializers should call if they fail to instantiate value * due to an exception that was thrown by constructor (or other mechanism used * to create instances). * Default implementation will try to call {@link DeserializationProblemHandler#handleInstantiationProblem} * on configured handlers, if any, to allow for recovery; if recovery does not * succeed, will throw exception constructed with {@link #instantiationException}. * * @param instClass Type that was to be instantiated * @param argument (optional) Argument that was passed to constructor or equivalent * instantiator; often a {@link java.lang.String}. * @param t Exception that caused failure * * @return Object that should be constructed, if any; has to be of type instClass * * @since 2.8 */ public Object handleInstantiationProblem(Class instClass, Object argument, Throwable t) throws IOException { LinkedNode h = _config.getProblemHandlers(); while (h != null) { // Can bail out if it's handled Object instance = h.value().handleInstantiationProblem(this, instClass, argument, t); if (instance != DeserializationProblemHandler.NOT_HANDLED) { // Sanity check for broken handlers, otherwise nasty to debug: if (_isCompatible(instClass, instance)) { return instance; } reportBadDefinition(constructType(instClass), String.format( "DeserializationProblemHandler.handleInstantiationProblem() for type %s returned value of type %s", instClass, ClassUtil.classNameOf(instance))); } h = h.next(); } // 18-May-2016, tatu: Only wrap if not already a valid type to throw ClassUtil.throwIfIOE(t); throw instantiationException(instClass, t); } /** * Method that deserializers should call if the first token of the value to * deserialize is of unexpected type (that is, type of token that deserializer * cannot handle). This could occur, for example, if a Number deserializer * encounter {@link JsonToken#START_ARRAY} instead of * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}. * * @param instClass Type that was to be instantiated * @param p Parser that points to the JSON value to decode * * @return Object that should be constructed, if any; has to be of type instClass * * @since 2.8 */ public Object handleUnexpectedToken(Class instClass, JsonParser p) throws IOException { return handleUnexpectedToken(instClass, p.getCurrentToken(), p, null); } /** * Method that deserializers should call if the first token of the value to * deserialize is of unexpected type (that is, type of token that deserializer * cannot handle). This could occur, for example, if a Number deserializer * encounter {@link JsonToken#START_ARRAY} instead of * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}. * * @param instClass Type that was to be instantiated * @param t Token encountered that does match expected * @param p Parser that points to the JSON value to decode * * @return Object that should be constructed, if any; has to be of type instClass * * @since 2.8 */ public Object handleUnexpectedToken(Class instClass, JsonToken t, JsonParser p, String msg, Object... msgArgs) throws IOException { msg = _format(msg, msgArgs); LinkedNode h = _config.getProblemHandlers(); while (h != null) { Object instance = h.value().handleUnexpectedToken(this, instClass, t, p, msg); if (instance != DeserializationProblemHandler.NOT_HANDLED) { if (_isCompatible(instClass, instance)) { return instance; } reportBadDefinition(constructType(instClass), String.format( "DeserializationProblemHandler.handleUnexpectedToken() for type %s returned value of type %s", ClassUtil.nameOf(instClass), ClassUtil.classNameOf(instance))); } h = h.next(); } if (msg == null) { if (t == null) { msg = String.format("Unexpected end-of-input when binding data into %s", ClassUtil.nameOf(instClass)); } else { msg = String.format("Cannot deserialize instance of %s out of %s token", ClassUtil.nameOf(instClass), t); } } reportInputMismatch(instClass, msg); return null; // never gets here } /** * Method that deserializers should call if they encounter a type id * (for polymorphic deserialization) that cannot be resolved to an * actual type; usually since there is no mapping defined. * Default implementation will try to call {@link DeserializationProblemHandler#handleUnknownTypeId} * on configured handlers, if any, to allow for recovery; if recovery does not * succeed, will throw exception constructed with {@link #invalidTypeIdException}. * * @param baseType Base type from which resolution starts * @param id Type id that could not be converted * @param extraDesc Additional problem description to add to default exception message, * if resolution fails. * * @return {@link JavaType} that id resolves to * * @throws IOException To indicate unrecoverable problem, if resolution cannot * be made to work * * @since 2.8 */ public JavaType handleUnknownTypeId(JavaType baseType, String id, TypeIdResolver idResolver, String extraDesc) throws IOException { LinkedNode h = _config.getProblemHandlers(); while (h != null) { // Can bail out if it's handled JavaType type = h.value().handleUnknownTypeId(this, baseType, id, idResolver, extraDesc); if (type != null) { if (type.hasRawClass(Void.class)) { return null; } // But ensure there's type compatibility if (type.isTypeOrSubTypeOf(baseType.getRawClass())) { return type; } throw invalidTypeIdException(baseType, id, "problem handler tried to resolve into non-subtype: "+type); } h = h.next(); } // 24-May-2016, tatu: Actually we may still not want to fail quite yet if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) { return null; } throw invalidTypeIdException(baseType, id, extraDesc); } /** * @since 2.9 */ public JavaType handleMissingTypeId(JavaType baseType, TypeIdResolver idResolver, String extraDesc) throws IOException { LinkedNode h = _config.getProblemHandlers(); while (h != null) { // Can bail out if it's handled JavaType type = h.value().handleMissingTypeId(this, baseType, idResolver, extraDesc); if (type != null) { if (type.hasRawClass(Void.class)) { return null; } // But ensure there's type compatibility if (type.isTypeOrSubTypeOf(baseType.getRawClass())) { return type; } throw invalidTypeIdException(baseType, null, "problem handler tried to resolve into non-subtype: "+type); } h = h.next(); } // 09-Mar-2017, tatu: We may want to consider yet another feature at some // point to allow returning `null`... but that seems bit risky for now // if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) { // return null; // } throw missingTypeIdException(baseType, extraDesc); } /** * @since 2.9.2 */ protected boolean _isCompatible(Class target, Object value) { if ((value == null) || target.isInstance(value)) { return true; } // [databind#1767]: Make sure to allow wrappers for primitive fields return target.isPrimitive() && ClassUtil.wrapperType(target).isInstance(value); } /* /********************************************************** /* Methods for problem reporting, in cases where recovery /* is not considered possible: input problem /********************************************************** */ /** * Method for deserializers to call * when the token encountered was of type different than what should * be seen at that position, usually within a sequence of expected tokens. * Note that this method will throw a {@link JsonMappingException} and no * recovery is attempted (via {@link DeserializationProblemHandler}, as * problem is considered to be difficult to recover from, in general. * * @since 2.9 */ public void reportWrongTokenException(JsonDeserializer deser, JsonToken expToken, String msg, Object... msgArgs) throws JsonMappingException { msg = _format(msg, msgArgs); throw wrongTokenException(getParser(), deser.handledType(), expToken, msg); } /** * Method for deserializers to call * when the token encountered was of type different than what should * be seen at that position, usually within a sequence of expected tokens. * Note that this method will throw a {@link JsonMappingException} and no * recovery is attempted (via {@link DeserializationProblemHandler}, as * problem is considered to be difficult to recover from, in general. * * @since 2.9 */ public void reportWrongTokenException(JavaType targetType, JsonToken expToken, String msg, Object... msgArgs) throws JsonMappingException { msg = _format(msg, msgArgs); throw wrongTokenException(getParser(), targetType, expToken, msg); } /** * Method for deserializers to call * when the token encountered was of type different than what should * be seen at that position, usually within a sequence of expected tokens. * Note that this method will throw a {@link JsonMappingException} and no * recovery is attempted (via {@link DeserializationProblemHandler}, as * problem is considered to be difficult to recover from, in general. * * @since 2.9 */ public void reportWrongTokenException(Class targetType, JsonToken expToken, String msg, Object... msgArgs) throws JsonMappingException { msg = _format(msg, msgArgs); throw wrongTokenException(getParser(), targetType, expToken, msg); } /** * @since 2.8 */ public T reportUnresolvedObjectId(ObjectIdReader oidReader, Object bean) throws JsonMappingException { String msg = String.format("No Object Id found for an instance of %s, to assign to property '%s'", ClassUtil.classNameOf(bean), oidReader.propertyName); return reportInputMismatch(oidReader.idProperty, msg); } /** * Helper method used to indicate a problem with input in cases where more * specific reportXxx() method was not available. * * @since 2.9 */ public T reportInputMismatch(BeanProperty prop, String msg, Object... msgArgs) throws JsonMappingException { msg = _format(msg, msgArgs); JavaType type = (prop == null) ? null : prop.getType(); throw MismatchedInputException.from(getParser(), type, msg); } /** * Helper method used to indicate a problem with input in cases where more * specific reportXxx() method was not available. * * @since 2.9 */ public T reportInputMismatch(JsonDeserializer src, String msg, Object... msgArgs) throws JsonMappingException { msg = _format(msg, msgArgs); throw MismatchedInputException.from(getParser(), src.handledType(), msg); } /** * Helper method used to indicate a problem with input in cases where more * specific reportXxx() method was not available. * * @since 2.9 */ public T reportInputMismatch(Class targetType, String msg, Object... msgArgs) throws JsonMappingException { msg = _format(msg, msgArgs); throw MismatchedInputException.from(getParser(), targetType, msg); } /** * Helper method used to indicate a problem with input in cases where more * specific reportXxx() method was not available. * * @since 2.9 */ public T reportInputMismatch(JavaType targetType, String msg, Object... msgArgs) throws JsonMappingException { msg = _format(msg, msgArgs); throw MismatchedInputException.from(getParser(), targetType, msg); } public T reportTrailingTokens(Class targetType, JsonParser p, JsonToken trailingToken) throws JsonMappingException { throw MismatchedInputException.from(p, targetType, String.format( "Trailing token (of type %s) found after value (bound as %s): not allowed as per `DeserializationFeature.FAIL_ON_TRAILING_TOKENS`", trailingToken, ClassUtil.nameOf(targetType) )); } @Deprecated // since 2.9 public void reportWrongTokenException(JsonParser p, JsonToken expToken, String msg, Object... msgArgs) throws JsonMappingException { msg = _format(msg, msgArgs); throw wrongTokenException(p, expToken, msg); } /** * Helper method for reporting a problem with unhandled unknown property. * * @param instanceOrClass Either value being populated (if one has been * instantiated), or Class that indicates type that would be (or * have been) instantiated * @param deser Deserializer that had the problem, if called by deserializer * (or on behalf of one) * * @deprecated Since 2.8 call {@link #handleUnknownProperty} instead */ @Deprecated public void reportUnknownProperty(Object instanceOrClass, String fieldName, JsonDeserializer deser) throws JsonMappingException { if (isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) { // Do we know properties that are expected instead? Collection propIds = (deser == null) ? null : deser.getKnownPropertyNames(); throw UnrecognizedPropertyException.from(_parser, instanceOrClass, fieldName, propIds); } } /** * @since 2.8 * * @deprecated Since 2.9: not clear this ever occurs */ @Deprecated // since 2.9 public void reportMissingContent(String msg, Object... msgArgs) throws JsonMappingException { throw MismatchedInputException.from(getParser(), (JavaType) null, "No content to map due to end-of-input"); } /* /********************************************************** /* Methods for problem reporting, in cases where recovery /* is not considered possible: POJO definition problems /********************************************************** */ /** * Helper method called to indicate problem in POJO (serialization) definitions or settings * regarding specific Java type, unrelated to actual JSON content to map. * Default behavior is to construct and throw a {@link JsonMappingException}. * * @since 2.9 */ public T reportBadTypeDefinition(BeanDescription bean, String msg, Object... msgArgs) throws JsonMappingException { msg = _format(msg, msgArgs); String beanDesc = ClassUtil.nameOf(bean.getBeanClass()); msg = String.format("Invalid type definition for type %s: %s", beanDesc, msg); throw InvalidDefinitionException.from(_parser, msg, bean, null); } /** * Helper method called to indicate problem in POJO (serialization) definitions or settings * regarding specific property (of a type), unrelated to actual JSON content to map. * Default behavior is to construct and throw a {@link JsonMappingException}. * * @since 2.9 */ public T reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop, String msg, Object... msgArgs) throws JsonMappingException { msg = _format(msg, msgArgs); String propName = ClassUtil.nameOf(prop); String beanDesc = ClassUtil.nameOf(bean.getBeanClass()); msg = String.format("Invalid definition for property %s (of type %s): %s", propName, beanDesc, msg); throw InvalidDefinitionException.from(_parser, msg, bean, prop); } @Override public T reportBadDefinition(JavaType type, String msg) throws JsonMappingException { throw InvalidDefinitionException.from(_parser, msg, type); } /** * Method that deserializer may call if it is called to do an update ("merge") * but deserializer operates on a non-mergeable type. Although this should * usually be caught earlier, sometimes it may only be caught during operation * and if so this is the method to call. * Note that if {@link MapperFeature#IGNORE_MERGE_FOR_UNMERGEABLE} is enabled, * this method will simply return null; otherwise {@link InvalidDefinitionException} * will be thrown. * * @since 2.9 */ public T reportBadMerge(JsonDeserializer deser) throws JsonMappingException { if (isEnabled(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)) { return null; } JavaType type = constructType(deser.handledType()); String msg = String.format("Invalid configuration: values of type %s cannot be merged", type); throw InvalidDefinitionException.from(getParser(), msg, type); } /* /********************************************************** /* Methods for constructing semantic exceptions; usually not /* to be called directly, call `handleXxx()` instead /********************************************************** */ /** * Helper method for constructing {@link JsonMappingException} to indicate * that the token encountered was of type different than what should * be seen at that position, usually within a sequence of expected tokens. * Note that most of the time this method should NOT be directly called; * instead, {@link #reportWrongTokenException} should be called and will * call this method as necessary. * * @since 2.9 */ public JsonMappingException wrongTokenException(JsonParser p, JavaType targetType, JsonToken expToken, String extra) { String msg = String.format("Unexpected token (%s), expected %s", p.getCurrentToken(), expToken); msg = _colonConcat(msg, extra); return MismatchedInputException.from(p, targetType, msg); } public JsonMappingException wrongTokenException(JsonParser p, Class targetType, JsonToken expToken, String extra) { String msg = String.format("Unexpected token (%s), expected %s", p.getCurrentToken(), expToken); msg = _colonConcat(msg, extra); return MismatchedInputException.from(p, targetType, msg); } @Deprecated // since 2.9 public JsonMappingException wrongTokenException(JsonParser p, JsonToken expToken, String msg) { return wrongTokenException(p, (JavaType) null, expToken, msg); } /** * Helper method for constructing exception to indicate that given JSON * Object field name was not in format to be able to deserialize specified * key type. * Note that most of the time this method should NOT be called; instead, * {@link #handleWeirdKey} should be called which will call this method * if necessary. */ public JsonMappingException weirdKeyException(Class keyClass, String keyValue, String msg) { return InvalidFormatException.from(_parser, String.format("Cannot deserialize Map key of type %s from String %s: %s", ClassUtil.nameOf(keyClass), _quotedString(keyValue), msg), keyValue, keyClass); } /** * Helper method for constructing exception to indicate that input JSON * String was not suitable for deserializing into given target type. * Note that most of the time this method should NOT be called; instead, * {@link #handleWeirdStringValue} should be called which will call this method * if necessary. * * @param value String value from input being deserialized * @param instClass Type that String should be deserialized into * @param msg Message that describes specific problem * * @since 2.1 */ public JsonMappingException weirdStringException(String value, Class instClass, String msg) { return InvalidFormatException.from(_parser, String.format("Cannot deserialize value of type %s from String %s: %s", ClassUtil.nameOf(instClass), _quotedString(value), msg), value, instClass); } /** * Helper method for constructing exception to indicate that input JSON * Number was not suitable for deserializing into given target type. * Note that most of the time this method should NOT be called; instead, * {@link #handleWeirdNumberValue} should be called which will call this method * if necessary. */ public JsonMappingException weirdNumberException(Number value, Class instClass, String msg) { return InvalidFormatException.from(_parser, String.format("Cannot deserialize value of type %s from number %s: %s", ClassUtil.nameOf(instClass), String.valueOf(value), msg), value, instClass); } /** * Helper method for constructing exception to indicate that input JSON * token of type "native value" (see {@link JsonToken#VALUE_EMBEDDED_OBJECT}) * is of incompatible type (and there is no delegating creator or such to use) * and can not be used to construct value of specified type (usually POJO). * Note that most of the time this method should NOT be called; instead, * {@link #handleWeirdNativeValue} should be called which will call this method * * @since 2.9 */ public JsonMappingException weirdNativeValueException(Object value, Class instClass) { return InvalidFormatException.from(_parser, String.format( "Cannot deserialize value of type %s from native value (`JsonToken.VALUE_EMBEDDED_OBJECT`) of type %s: incompatible types", ClassUtil.nameOf(instClass), ClassUtil.classNameOf(value)), value, instClass); } /** * Helper method for constructing instantiation exception for specified type, * to indicate problem with physically constructing instance of * specified class (missing constructor, exception from constructor) *

* Note that most of the time this method should NOT be called; instead, * {@link #handleInstantiationProblem} should be called which will call this method * if necessary. */ public JsonMappingException instantiationException(Class instClass, Throwable cause) { // Most likely problem with Creator definition, right? JavaType type = constructType(instClass); String msg = String.format("Cannot construct instance of %s, problem: %s", ClassUtil.nameOf(instClass), cause.getMessage()); InvalidDefinitionException e = InvalidDefinitionException.from(_parser, msg, type); e.initCause(cause); return e; } /** * Helper method for constructing instantiation exception for specified type, * to indicate that instantiation failed due to missing instantiator * (creator; constructor or factory method). *

* Note that most of the time this method should NOT be called; instead, * {@link #handleMissingInstantiator} should be called which will call this method * if necessary. */ public JsonMappingException instantiationException(Class instClass, String msg0) { // Most likely problem with Creator definition, right? JavaType type = constructType(instClass); String msg = String.format("Cannot construct instance of %s: %s", ClassUtil.nameOf(instClass), msg0); return InvalidDefinitionException.from(_parser, msg, type); } @Override public JsonMappingException invalidTypeIdException(JavaType baseType, String typeId, String extraDesc) { String msg = String.format("Could not resolve type id '%s' as a subtype of %s", typeId, baseType); return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, typeId); } /** * @since 2.9 */ public JsonMappingException missingTypeIdException(JavaType baseType, String extraDesc) { String msg = String.format("Missing type id when trying to resolve subtype of %s", baseType); return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, null); } /* /********************************************************** /* Deprecated exception factory methods /********************************************************** */ /** * @since 2.5 * * @deprecated Since 2.8 use {@link #handleUnknownTypeId} instead */ @Deprecated public JsonMappingException unknownTypeException(JavaType type, String id, String extraDesc) { String msg = String.format("Could not resolve type id '%s' into a subtype of %s", id, type); msg = _colonConcat(msg, extraDesc); return MismatchedInputException.from(_parser, type, msg); } /** * Helper method for constructing exception to indicate that end-of-input was * reached while still expecting more tokens to deserialize value of specified type. * * @deprecated Since 2.8; currently no way to catch EOF at databind level */ @Deprecated public JsonMappingException endOfInputException(Class instClass) { return MismatchedInputException.from(_parser, instClass, "Unexpected end-of-input when trying to deserialize a "+instClass.getName()); } /* /********************************************************** /* Deprecated methods for constructing, throwing non-specific /* JsonMappingExceptions: as of 2.9, should use more specific /* ones. /********************************************************** */ /** * Fallback method that may be called if no other reportXxx * is applicable -- but only in that case. * * @since 2.8 * * @deprecated Since 2.9: use a more specific method, or {@link #reportBadDefinition(JavaType, String)}, * or {@link #reportInputMismatch} instead */ @Deprecated // since 2.9 public void reportMappingException(String msg, Object... msgArgs) throws JsonMappingException { throw JsonMappingException.from(getParser(), _format(msg, msgArgs)); } /** * Helper method for constructing generic mapping exception with specified * message and current location information. * Note that application code should almost always call * one of handleXxx methods, or {@link #reportMappingException(String, Object...)} * instead. * * @since 2.6 * * @deprecated Since 2.9 use more specific error reporting methods instead */ @Deprecated public JsonMappingException mappingException(String message) { return JsonMappingException.from(getParser(), message); } /** * Helper method for constructing generic mapping exception with specified * message and current location information * Note that application code should almost always call * one of handleXxx methods, or {@link #reportMappingException(String, Object...)} * instead. * * @since 2.6 * * @deprecated Since 2.9 use more specific error reporting methods instead */ @Deprecated public JsonMappingException mappingException(String msg, Object... msgArgs) { return JsonMappingException.from(getParser(), _format(msg, msgArgs)); } /** * Helper method for constructing generic mapping exception for specified type * * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead */ @Deprecated public JsonMappingException mappingException(Class targetClass) { return mappingException(targetClass, _parser.getCurrentToken()); } /** * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead */ @Deprecated public JsonMappingException mappingException(Class targetClass, JsonToken token) { return JsonMappingException.from(_parser, String.format("Cannot deserialize instance of %s out of %s token", ClassUtil.nameOf(targetClass), token)); } /* /********************************************************** /* Other internal methods /********************************************************** */ protected DateFormat getDateFormat() { if (_dateFormat != null) { return _dateFormat; } /* 24-Feb-2012, tatu: At this point, all timezone configuration * should have occurred, with respect to default dateformat * and timezone configuration. But we still better clone * an instance as formatters may be stateful. */ DateFormat df = _config.getDateFormat(); _dateFormat = df = (DateFormat) df.clone(); return df; } } DeserializationFeature.java000066400000000000000000000520131325620701100357560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import com.fasterxml.jackson.databind.cfg.ConfigFeature; /** * Enumeration that defines simple on/off features that affect * the way Java objects are deserialized from JSON *

* Note that features can be set both through * {@link ObjectMapper} (as sort of defaults) and through * {@link ObjectReader}. * In first case these defaults must follow "config-then-use" patterns * (i.e. defined once, not changed afterwards); all per-call * changes must be done using {@link ObjectReader}. *

* Note that features that do not indicate version of inclusion * were available in Jackson 2.0 (or earlier); only later additions * indicate version of inclusion. */ public enum DeserializationFeature implements ConfigFeature { /* /****************************************************** /* Value (mostly scalar) conversion features /****************************************************** */ /** * Feature that determines whether JSON floating point numbers * are to be deserialized into {@link java.math.BigDecimal}s * if only generic type description (either {@link Object} or * {@link Number}, or within untyped {@link java.util.Map} * or {@link java.util.Collection} context) is available. * If enabled such values will be deserialized as {@link java.math.BigDecimal}s; * if disabled, will be deserialized as {@link Double}s. *

* Feature is disabled by default, meaning that "untyped" floating * point numbers will by default be deserialized as {@link Double}s * (choice is for performance reason -- BigDecimals are slower than * Doubles). */ USE_BIG_DECIMAL_FOR_FLOATS(false), /** * Feature that determines whether JSON integral (non-floating-point) * numbers are to be deserialized into {@link java.math.BigInteger}s * if only generic type description (either {@link Object} or * {@link Number}, or within untyped {@link java.util.Map} * or {@link java.util.Collection} context) is available. * If enabled such values will be deserialized as * {@link java.math.BigInteger}s; * if disabled, will be deserialized as "smallest" available type, * which is either {@link Integer}, {@link Long} or * {@link java.math.BigInteger}, depending on number of digits. *

* Feature is disabled by default, meaning that "untyped" integral * numbers will by default be deserialized using whatever * is the most compact integral type, to optimize efficiency. */ USE_BIG_INTEGER_FOR_INTS(false), /** * Feature that determines how "small" JSON integral (non-floating-point) * numbers -- ones that fit in 32-bit signed integer (`int`) -- are bound * when target type is loosely typed as {@link Object} or {@link Number} * (or within untyped {@link java.util.Map} or {@link java.util.Collection} context). * If enabled, such values will be deserialized as {@link java.lang.Long}; * if disabled, they will be deserialized as "smallest" available type, * {@link Integer}. * In addition, if enabled, trying to bind values that do not fit in {@link java.lang.Long} * will throw a {@link com.fasterxml.jackson.core.JsonProcessingException}. *

* Note: if {@link #USE_BIG_INTEGER_FOR_INTS} is enabled, it has precedence * over this setting, forcing use of {@link java.math.BigInteger} for all * integral values. *

* Feature is disabled by default, meaning that "untyped" integral * numbers will by default be deserialized using {@link java.lang.Integer} * if value fits. * * @since 2.6 */ USE_LONG_FOR_INTS(false), /** * Feature that determines whether JSON Array is mapped to * Object[] or List<Object> when binding * "untyped" objects (ones with nominal type of java.lang.Object). * If true, binds as Object[]; if false, as List<Object>. *

* Feature is disabled by default, meaning that JSON arrays are bound as * {@link java.util.List}s. */ USE_JAVA_ARRAY_FOR_JSON_ARRAY(false), /* /****************************************************** /* Error handling features /****************************************************** */ /** * Feature that determines whether encountering of unknown * properties (ones that do not map to a property, and there is * no "any setter" or handler that can handle it) * should result in a failure (by throwing a * {@link JsonMappingException}) or not. * This setting only takes effect after all other handling * methods for unknown properties have been tried, and * property remains unhandled. *

* Feature is enabled by default (meaning that a * {@link JsonMappingException} will be thrown if an unknown property * is encountered). */ FAIL_ON_UNKNOWN_PROPERTIES(true), /** * Feature that determines whether encountering of JSON null * is an error when deserializing into Java primitive types * (like 'int' or 'double'). If it is, a JsonProcessingException * is thrown to indicate this; if not, default value is used * (0 for 'int', 0.0 for double, same defaulting as what JVM uses). *

* Feature is disabled by default. */ FAIL_ON_NULL_FOR_PRIMITIVES(false), /** * Feature that determines whether JSON integer numbers are valid * values to be used for deserializing Java enum values. * If set to 'false' numbers are acceptable and are used to map to * ordinal() of matching enumeration value; if 'true', numbers are * not allowed and a {@link JsonMappingException} will be thrown. * Latter behavior makes sense if there is concern that accidental * mapping from integer values to enums might happen (and when enums * are always serialized as JSON Strings) *

* Feature is disabled by default. */ FAIL_ON_NUMBERS_FOR_ENUMS(false), /** * Feature that determines what happens when type of a polymorphic * value (indicated for example by {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) * cannot be found (missing) or resolved (invalid class name, unmappable id); * if enabled, an exception ir thrown; if false, null value is used instead. *

* Feature is enabled by default so that exception is thrown for missing or invalid * type information. * * @since 2.2 */ FAIL_ON_INVALID_SUBTYPE(true), /** * Feature that determines what happens when reading JSON content into tree * ({@link com.fasterxml.jackson.core.TreeNode}) and a duplicate key * is encountered (property name that was already seen for the JSON Object). * If enabled, {@link JsonMappingException} will be thrown; if disabled, no exception * is thrown and the new (later) value overwrites the earlier value. *

* Note that this property does NOT affect other aspects of data-binding; that is, * no detection is done with respect to POJO properties or {@link java.util.Map} * keys. New features may be added to control additional cases. *

* Feature is disabled by default so that no exception is thrown. * * @since 2.3 */ FAIL_ON_READING_DUP_TREE_KEY(false), /** * Feature that determines what happens when a property that has been explicitly * marked as ignorable is encountered in input: if feature is enabled, * {@link JsonMappingException} is thrown; if false, property is quietly skipped. *

* Feature is disabled by default so that no exception is thrown. * * @since 2.3 */ FAIL_ON_IGNORED_PROPERTIES(false), /** * Feature that determines what happens if an Object Id reference is encountered * that does not refer to an actual Object with that id ("unresolved Object Id"): * either an exception is thrown (true), or a null object is used * instead (false). * Note that if this is set to false, no further processing is done; * specifically, if reference is defined via setter method, that method will NOT * be called. *

* Feature is enabled by default, so that unknown Object Ids will result in an * exception being thrown, at the end of deserialization. * * @since 2.5 */ FAIL_ON_UNRESOLVED_OBJECT_IDS(true), /** * Feature that determines what happens if one or more Creator properties (properties * bound to parameters of Creator method (constructor or static factory method)) * are missing value to bind to from content. * If enabled, such missing values result in a {@link JsonMappingException} being * thrown with information on the first one (by index) of missing properties. * If disabled, and if property is NOT marked as required, * missing Creator properties are filled * with null values provided by deserializer for the type of parameter * (usually null for Object types, and default value for primitives; but redefinable * via custom deserializers). *

* Note that having an injectable value counts as "not missing". *

* Feature is disabled by default, so that no exception is thrown for missing creator * property values, unless they are explicitly marked as `required`. * * @since 2.6 */ FAIL_ON_MISSING_CREATOR_PROPERTIES(false), /** * Feature that determines what happens if one or more Creator properties (properties * bound to parameters of Creator method (constructor or static factory method)) * are bound to null values - either from the JSON or as a default value. This * is useful if you want to avoid nulls in your codebase, and particularly useful * if you are using Java or Scala optionals for non-mandatory fields. * Feature is disabled by default, so that no exception is thrown for missing creator * property values, unless they are explicitly marked as `required`. * * @since 2.8 */ FAIL_ON_NULL_CREATOR_PROPERTIES(false), /** * Feature that determines what happens when a property annotated with * {@link com.fasterxml.jackson.annotation.JsonTypeInfo.As#EXTERNAL_PROPERTY} is missing, * but associated type id is available. If enabled, {@link JsonMappingException} is always * thrown when property value is missing (if type id does exist); * if disabled, exception is only thrown if property is marked as `required`. *

* Feature is enabled by default, so that exception is thrown when a subtype property is * missing. * * @since 2.9 */ FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY(true), /** * Feature that determines behaviour for data-binding after binding the root value. * If feature is enabled, one more call to * {@link com.fasterxml.jackson.core.JsonParser#nextToken} is made to ensure that * no more tokens are found (and if any is found, * {@link com.fasterxml.jackson.databind.exc.MismatchedInputException} is thrown); if * disabled, no further checks are made. *

* Feature could alternatively be called READ_FULL_STREAM, since it * effectively verifies that input stream contains only as much data as is needed * for binding the full value, and nothing more (except for possible ignorable * white space or comments, if supported by data format). *

* Feature is disabled by default (so that no check is made for possible trailing * token(s)) for backwards compatibility reasons. * * @since 2.9 */ FAIL_ON_TRAILING_TOKENS(false), /** * Feature that determines whether Jackson code should catch * and wrap {@link Exception}s (but never {@link Error}s!) * to add additional information about * location (within input) of problem or not. If enabled, * most exceptions will be caught and re-thrown (exception * specifically being that {@link java.io.IOException}s may be passed * as is, since they are declared as throwable); this can be * convenient both in that all exceptions will be checked and * declared, and so there is more contextual information. * However, sometimes calling application may just want "raw" * unchecked exceptions passed as is. *

* Feature is enabled by default. */ WRAP_EXCEPTIONS(true), /* /****************************************************** /* Structural conversion features /****************************************************** */ /** * Feature that determines whether it is acceptable to coerce non-array * (in JSON) values to work with Java collection (arrays, java.util.Collection) * types. If enabled, collection deserializers will try to handle non-array * values as if they had "implicit" surrounding JSON array. * This feature is meant to be used for compatibility/interoperability reasons, * to work with packages (such as XML-to-JSON converters) that leave out JSON * array in cases where there is just a single element in array. *

* Feature is disabled by default. */ ACCEPT_SINGLE_VALUE_AS_ARRAY(false), /** * Feature that determines whether it is acceptable to coerce single value array (in JSON) * values to the corresponding value type. This is basically the opposite of the {@link #ACCEPT_SINGLE_VALUE_AS_ARRAY} * feature. If more than one value is found in the array, a JsonMappingException is thrown. *

* * Feature is disabled by default * @since 2.4 */ UNWRAP_SINGLE_VALUE_ARRAYS(false), /** * Feature to allow "unwrapping" root-level JSON value, to match setting of * {@link SerializationFeature#WRAP_ROOT_VALUE} used for serialization. * Will verify that the root JSON value is a JSON Object, and that it has * a single property with expected root name. If not, a * {@link JsonMappingException} is thrown; otherwise value of the wrapped property * will be deserialized as if it was the root value. *

* Feature is disabled by default. */ UNWRAP_ROOT_VALUE(false), /* /****************************************************** /* Value conversion features /****************************************************** */ /** * Feature that can be enabled to allow JSON empty String * value ("") to be bound as `null` for POJOs and other structured * values ({@link java.util.Map}s, {@link java.util.Collection}s). * If disabled, standard POJOs can only be bound from JSON `null` or * JSON Object (standard meaning that no custom deserializers or * constructors are defined; both of which can add support for other * kinds of JSON values); if enabled, empty JSON String can be taken * to be equivalent of JSON null. *

* NOTE: this does NOT apply to scalar values such as booleans and numbers; * whether they can be coerced depends on * {@link MapperFeature#ALLOW_COERCION_OF_SCALARS}. *

* Feature is disabled by default. */ ACCEPT_EMPTY_STRING_AS_NULL_OBJECT(false), /** * Feature that can be enabled to allow empty JSON Array * value (that is, [ ]) to be bound to POJOs (and * with 2.9, other values too) as `null`. * If disabled, standard POJOs can only be bound from JSON `null` or * JSON Object (standard meaning that no custom deserializers or * constructors are defined; both of which can add support for other * kinds of JSON values); if enabled, empty JSON Array will be taken * to be equivalent of JSON null. *

* Feature is disabled by default. * * @since 2.5 */ ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT(false), /** * Feature that determines whether coercion from JSON floating point * number (anything with command (`.`) or exponent portion (`e` / `E')) * to an expected integral number (`int`, `long`, `java.lang.Integer`, `java.lang.Long`, * `java.math.BigDecimal`) is allowed or not. * If enabled, coercion truncates value; if disabled, a {@link JsonMappingException} * will be thrown. *

* Feature is enabled by default. * * @since 2.6 */ ACCEPT_FLOAT_AS_INT(true), /** * Feature that determines standard deserialization mechanism used for * Enum values: if enabled, Enums are assumed to have been serialized using * return value of Enum.toString(); * if disabled, return value of Enum.name() is assumed to have been used. *

* Note: this feature should usually have same value * as {@link SerializationFeature#WRITE_ENUMS_USING_TO_STRING}. *

* Feature is disabled by default. */ READ_ENUMS_USING_TO_STRING(false), /** * Feature that allows unknown Enum values to be parsed as null values. * If disabled, unknown Enum values will throw exceptions. *

* Note that in some cases this will basically ignore unknown Enum values; * this is the keys for keys of {@link java.util.EnumMap} and values * of {@link java.util.EnumSet} (because nulls are not accepted in these * cases). *

* Feature is disabled by default. * * @since 2.0 */ READ_UNKNOWN_ENUM_VALUES_AS_NULL(false), /** * Feature that allows unknown Enum values to be ignored and a predefined value specified through * {@link com.fasterxml.jackson.annotation.JsonEnumDefaultValue @JsonEnumDefaultValue} annotation. * If disabled, unknown Enum values will throw exceptions. * If enabled, but no predefined default Enum value is specified, an exception will be thrown as well. *

* Feature is disabled by default. * * @since 2.8 */ READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE(false), /** * Feature that controls whether numeric timestamp values are expected * to be written using nanosecond timestamps (enabled) or not (disabled), * if and only if datatype supports such resolution. * Only newer datatypes (such as Java8 Date/Time) support such resolution -- * older types (pre-Java8 java.util.Date etc) and Joda do not -- * and this setting has no effect on such types. *

* If disabled, standard millisecond timestamps are assumed. * This is the counterpart to {@link SerializationFeature#WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS}. *

* Feature is enabled by default, to support most accurate time values possible. * * @since 2.2 */ READ_DATE_TIMESTAMPS_AS_NANOSECONDS(true), /** * Feature that specifies whether context provided {@link java.util.TimeZone} * ({@link DeserializationContext#getTimeZone()} should be used to adjust Date/Time * values on deserialization, even if value itself contains timezone information. * If enabled, contextual TimeZone will essentially override any other * TimeZone information; if disabled, it will only be used if value itself does not * contain any TimeZone information. *

* Note that exact behavior depends on date/time types in question; and specifically * JDK type of {@link java.util.Date} does NOT have in-built timezone information * so this setting has no effect. * Further, while {@link java.util.Calendar} does have this information basic * JDK {@link java.text.SimpleDateFormat} is unable to retain parsed zone information, * and as a result, {@link java.util.Calendar} will always get context timezone * adjustment regardless of this setting. *

*

* Taking above into account, this feature is supported only by extension modules for * Joda and Java 8 date/tyime datatypes. * * @since 2.2 */ ADJUST_DATES_TO_CONTEXT_TIME_ZONE(true), /* /****************************************************** /* Other /****************************************************** */ /** * Feature that determines whether {@link ObjectReader} should * try to eagerly fetch necessary {@link JsonDeserializer} when * possible. This improves performance in cases where similarly * configured {@link ObjectReader} instance is used multiple * times; and should not significantly affect single-use cases. *

* Note that there should not be any need to normally disable this * feature: only consider that if there are actual perceived problems. *

* Feature is enabled by default. * * @since 2.1 */ EAGER_DESERIALIZER_FETCH(true) ; private final boolean _defaultState; private final int _mask; private DeserializationFeature(boolean defaultState) { _defaultState = defaultState; _mask = (1 << ordinal()); } @Override public boolean enabledByDefault() { return _defaultState; } @Override public int getMask() { return _mask; } @Override public boolean enabledIn(int flags) { return (flags & _mask) != 0; } } InjectableValues.java000066400000000000000000000061071325620701100345370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.util.*; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Abstract class that defines API for objects that provide value to * "inject" during deserialization. An instance of this object */ public abstract class InjectableValues { /** * Method called to find value identified by id valueId to * inject as value of specified property during deserialization, passing * POJO instance in which value will be injected if it is available * (will be available when injected via field or setter; not available * when injected via constructor or factory method argument). * * @param valueId Object that identifies value to inject; may be a simple * name or more complex identifier object, whatever provider needs * @param ctxt Deserialization context * @param forProperty Bean property in which value is to be injected * @param beanInstance Bean instance that contains property to inject, * if available; null if bean has not yet been constructed. */ public abstract Object findInjectableValue(Object valueId, DeserializationContext ctxt, BeanProperty forProperty, Object beanInstance) throws JsonMappingException; /* /********************************************************** /* Standard implementation /********************************************************** */ /** * Simple standard implementation which uses a simple Map to * store values to inject, identified by simple String keys. */ public static class Std extends InjectableValues implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final Map _values; public Std() { this(new HashMap()); } public Std(Map values) { _values = values; } public Std addValue(String key, Object value) { _values.put(key, value); return this; } public Std addValue(Class classKey, Object value) { _values.put(classKey.getName(), value); return this; } @Override public Object findInjectableValue(Object valueId, DeserializationContext ctxt, BeanProperty forProperty, Object beanInstance) throws JsonMappingException { if (!(valueId instanceof String)) { ctxt.reportBadDefinition(ClassUtil.classOf(valueId), String.format( "Unrecognized inject value id type (%s), expecting String", ClassUtil.classNameOf(valueId))); } String key = (String) valueId; Object ob = _values.get(key); if (ob == null && !_values.containsKey(key)) { throw new IllegalArgumentException("No injectable id with value '"+key+"' found (for property '"+forProperty.getName()+"')"); } return ob; } } } jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/JavaType.java000066400000000000000000000430321325620701100331170ustar00rootroot00000000000000package com.fasterxml.jackson.databind; import java.lang.reflect.Modifier; import java.util.List; import com.fasterxml.jackson.core.type.ResolvedType; import com.fasterxml.jackson.databind.type.TypeBindings; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Base class for type token classes used both to contain information * and as keys for deserializers. *

* Instances can (only) be constructed by * com.fasterxml.jackson.databind.type.TypeFactory. *

* Since 2.2 this implements {@link java.lang.reflect.Type} to allow * it to be pushed through interfaces that only expose that type. */ public abstract class JavaType extends ResolvedType implements java.io.Serializable, // 2.1 java.lang.reflect.Type // 2.2 { private static final long serialVersionUID = 1; /** * This is the nominal type-erased Class that would be close to the * type represented (but not exactly type, due to type erasure: type * instance may have more information on this). * May be an interface or abstract class, so instantiation * may not be possible. */ protected final Class _class; protected final int _hash; /** * Optional handler (codec) that can be attached to indicate * what to use for handling (serializing, deserializing) values of * this specific type. *

* Note: untyped (i.e. caller has to cast) because it is used for * different kinds of handlers, with unrelated types. */ protected final Object _valueHandler; /** * Optional handler that can be attached to indicate how to handle * additional type metadata associated with this type. *

* Note: untyped (i.e. caller has to cast) because it is used for * different kinds of handlers, with unrelated types. */ protected final Object _typeHandler; /** * Whether entities defined with this type should be handled using * static typing (as opposed to dynamic runtime type) or not. * * @since 2.2 */ protected final boolean _asStatic; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @param raw "Raw" (type-erased) class for this type * @param additionalHash Additional hash code to use, in addition * to hash code of the class name */ protected JavaType(Class raw, int additionalHash, Object valueHandler, Object typeHandler, boolean asStatic) { _class = raw; _hash = raw.getName().hashCode() + additionalHash; _valueHandler = valueHandler; _typeHandler = typeHandler; _asStatic = asStatic; } /** * Copy-constructor used when refining/upgrading type instances. * * @since 2.7 */ protected JavaType(JavaType base) { _class = base._class; _hash = base._hash; _valueHandler = base._valueHandler; _typeHandler = base._typeHandler; _asStatic = base._asStatic; } /** * "Copy method" that will construct a new instance that is identical to * this instance, except that it will have specified type handler assigned. * * @return Newly created type instance */ public abstract JavaType withTypeHandler(Object h); /** * Mutant factory method that will construct a new instance that is identical to * this instance, except that it will have specified content type (element type * for arrays, value type for Maps and so forth) handler assigned. * * @return Newly created type instance, with given */ public abstract JavaType withContentTypeHandler(Object h); /** * Mutant factory method that will construct a new instance that is identical to * this instance, except that it will have specified value handler assigned. * * @return Newly created type instance */ public abstract JavaType withValueHandler(Object h); /** * Mutant factory method that will construct a new instance that is identical to * this instance, except that it will have specified content value handler assigned. * * @return Newly created type instance */ public abstract JavaType withContentValueHandler(Object h); /** * Mutant factory method that will try to copy handlers that the specified * source type instance had, if any; this must be done recursively where * necessary (as content types may be structured). * * @since 2.8.4 */ public JavaType withHandlersFrom(JavaType src) { JavaType type = this; Object h = src.getTypeHandler(); if (h != _typeHandler) { type = type.withTypeHandler(h); } h = src.getValueHandler(); if (h != _valueHandler) { type = type.withValueHandler(h); } return type; } /** * Mutant factory method that may be called on structured types * that have a so-called content type (element of arrays, value type * of Maps, referenced type of referential types), * and will construct a new instance that is identical to * this instance, except that it has specified content type, instead of current * one. If content type is already set to given type, this is returned. * If type does not have a content type (which is the case with * SimpleType), {@link IllegalArgumentException} * will be thrown. * * @return Newly created type instance * * @since 2.7 */ public abstract JavaType withContentType(JavaType contentType); /** * Method that can be called to get a type instance that indicates * that values of the type should be handled using "static typing" for purposes * of serialization (as opposed to "dynamic" aka runtime typing): * meaning that no runtime information is needed for determining serializers to use. * The main use case is to allow forcing of specific root value serialization type, * and specifically in resolving serializers for contained types (element types * for arrays, Collections and Maps). * * @since 2.2 */ public abstract JavaType withStaticTyping(); /* /********************************************************** /* Type coercion fluent factory methods /********************************************************** */ /** * Mutant factory method that will try to create and return a sub-type instance * for known parameterized types; for other types will return `null` to indicate * that no just refinement makes necessary sense, without trying to detect * special status through implemented interfaces. * * @since 2.7 */ public abstract JavaType refine(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces); /** * Legacy method used for forcing sub-typing of this type into * type specified by specific type erasure. * Deprecated as of 2.7 as such specializations really ought to * go through {@link TypeFactory}, not directly via {@link JavaType}. * * @since 2.7 */ @Deprecated public JavaType forcedNarrowBy(Class subclass) { if (subclass == _class) { // can still optimize for simple case return this; } return _narrow(subclass); } @Deprecated // since 2.7 protected abstract JavaType _narrow(Class subclass); /* /********************************************************** /* Implementation of ResolvedType API /********************************************************** */ @Override public final Class getRawClass() { return _class; } /** * Method that can be used to check whether this type has * specified Class as its type erasure. Put another way, returns * true if instantiation of this Type is given (type-erased) Class. */ @Override public final boolean hasRawClass(Class clz) { return _class == clz; } /** * Accessor that allows determining whether {@link #getContentType()} should * return a non-null value (that is, there is a "content type") or not. * True if {@link #isContainerType()} or {@link #isReferenceType()} return true. * * @since 2.8 */ public boolean hasContentType() { return true; } /** * @since 2.6 */ public final boolean isTypeOrSubTypeOf(Class clz) { return (_class == clz) || clz.isAssignableFrom(_class); } /** * @since 2.9 */ public final boolean isTypeOrSuperTypeOf(Class clz) { return (_class == clz) || _class.isAssignableFrom(clz); } @Override public boolean isAbstract() { return Modifier.isAbstract(_class.getModifiers()); } /** * Convenience method for checking whether underlying Java type * is a concrete class or not: abstract classes and interfaces * are not. */ @Override public boolean isConcrete() { int mod = _class.getModifiers(); if ((mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0) { return true; } /* 19-Feb-2010, tatus: Holy mackarel; primitive types * have 'abstract' flag set... */ return _class.isPrimitive(); } @Override public boolean isThrowable() { return Throwable.class.isAssignableFrom(_class); } @Override public boolean isArrayType() { return false; } @Override public final boolean isEnumType() { return _class.isEnum(); } @Override public final boolean isInterface() { return _class.isInterface(); } @Override public final boolean isPrimitive() { return _class.isPrimitive(); } @Override public final boolean isFinal() { return Modifier.isFinal(_class.getModifiers()); } /** * @return True if type represented is a container type; this includes * array, Map and Collection types. */ @Override public abstract boolean isContainerType(); /** * @return True if type is either true {@link java.util.Collection} type, * or something similar (meaning it has at least one type parameter, * which describes type of contents) */ @Override public boolean isCollectionLikeType() { return false; } /** * @return True if type is either true {@link java.util.Map} type, * or something similar (meaning it has at least two type parameter; * first one describing key type, second value type) */ @Override public boolean isMapLikeType() { return false; } /** * Convenience method, short-hand for * * getRawClass() == Object.class * * and used to figure if we basically have "untyped" type object. * * @since 2.5 */ public final boolean isJavaLangObject() { return _class == Object.class; } /** * Accessor for checking whether handlers for dealing with values of * this type should use static typing (as opposed to dynamic typing). * Note that while value of 'true' does mean that static typing is to * be used, value of 'false' may still be overridden by other settings. * * @since 2.2 */ public final boolean useStaticType() { return _asStatic; } /* /********************************************************** /* Public API, type parameter access; pass-through /********************************************************** */ @Override public boolean hasGenericTypes() { return containedTypeCount() > 0; } @Override public JavaType getKeyType() { return null; } @Override public JavaType getContentType() { return null; } @Override // since 2.6 public JavaType getReferencedType() { return null; } @Override public abstract int containedTypeCount(); @Override public abstract JavaType containedType(int index); @Deprecated // since 2.7 @Override public abstract String containedTypeName(int index); @Deprecated // since 2.7 @Override public Class getParameterSource() { return null; } /* /********************************************************** /* Extended API beyond ResolvedType /********************************************************** */ // NOTE: not defined in Resolved type /** * Convenience method that is functionally same as: * * JavaType t = containedType(index); * if (t == null) { * t = TypeFactory.unknownType(); * } * * and typically used to eliminate need for null checks for common case * where we just want to check if containedType is available first; and * if not, use "unknown type" (which translates to java.lang.Object * basically). * * @since 2.5 */ public JavaType containedTypeOrUnknown(int index) { JavaType t = containedType(index); return (t == null) ? TypeFactory.unknownType() : t; } /** * @since 2.7 */ public abstract TypeBindings getBindings(); /** * Method that may be called to find representation of given type * within type hierarchy of this type: either this type (if this * type has given erased type), one of its supertypes that has the * erased types, or null if target is neither this type or any of its * supertypes. * * @since 2.7 */ public abstract JavaType findSuperType(Class erasedTarget); /** * Accessor for finding fully resolved parent class of this type, * if it has one; null if not. * * @since 2.7 */ public abstract JavaType getSuperClass(); /** * Accessor for finding fully resolved interfaces this type implements, * if any; empty array if none. * * @since 2.7 */ public abstract List getInterfaces(); /** * Method that may be used to find paramaterization this type has for * given type-erased generic target type. * * @since 2.7 */ public abstract JavaType[] findTypeParameters(Class expType); /* /********************************************************** /* Semi-public API, accessing handlers /********************************************************** */ /** * Method for accessing value handler associated with this type, if any */ @SuppressWarnings("unchecked") public T getValueHandler() { return (T) _valueHandler; } /** * Method for accessing type handler associated with this type, if any */ @SuppressWarnings("unchecked") public T getTypeHandler() { return (T) _typeHandler; } /** * @since 2.7 */ public Object getContentValueHandler() { return null; } /** * @since 2.7 */ public Object getContentTypeHandler() { return null; } /** * @since 2.6 */ public boolean hasValueHandler() { return _valueHandler != null; } /** * Helper method that checks whether this type, or its (optional) key * or content type has {@link #getValueHandler} or {@link #getTypeHandler()}; * that is, are there any non-standard handlers associated with this * type object. * * @since 2.8 */ public boolean hasHandlers() { return (_typeHandler != null) || (_valueHandler != null); } /* /********************************************************** /* Support for producing signatures /********************************************************** */ //public abstract String toCanonical(); /** * Method for accessing signature that contains generic * type information, in form compatible with JVM 1.5 * as per JLS. It is a superset of {@link #getErasedSignature}, * in that generic information can be automatically removed * if necessary (just remove outermost * angle brackets along with content inside) */ public String getGenericSignature() { StringBuilder sb = new StringBuilder(40); getGenericSignature(sb); return sb.toString(); } /** * * @param sb StringBuilder to append signature to * * @return StringBuilder that was passed in; returned to allow * call chaining */ public abstract StringBuilder getGenericSignature(StringBuilder sb); /** * Method for accessing signature without generic * type information, in form compatible with all versions * of JVM, and specifically used for type descriptions * when generating byte code. */ public String getErasedSignature() { StringBuilder sb = new StringBuilder(40); getErasedSignature(sb); return sb.toString(); } /** * Method for accessing signature without generic * type information, in form compatible with all versions * of JVM, and specifically used for type descriptions * when generating byte code. * * @param sb StringBuilder to append signature to * * @return StringBuilder that was passed in; returned to allow * call chaining */ public abstract StringBuilder getErasedSignature(StringBuilder sb); /* /********************************************************** /* Standard methods; let's make them abstract to force override /********************************************************** */ @Override public abstract String toString(); @Override public abstract boolean equals(Object o); @Override public final int hashCode() { return _hash; } } JsonDeserializer.java000066400000000000000000000425471325620701100346030ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.IOException; import java.util.Collection; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.AccessPattern; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Abstract class that defines API used by {@link ObjectMapper} (and * other chained {@link JsonDeserializer}s too) to deserialize Objects of * arbitrary types from JSON, using provided {@link JsonParser}. *

* Custom deserializers should usually not directly extend this class, * but instead extend {@link com.fasterxml.jackson.databind.deser.std.StdDeserializer} * (or its subtypes like {@link com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer}). *

* If deserializer is an aggregate one -- meaning it delegates handling of some * of its contents by using other deserializer(s) -- it typically also needs * to implement {@link com.fasterxml.jackson.databind.deser.ResolvableDeserializer}, * which can locate dependant deserializers. This is important to allow dynamic * overrides of deserializers; separate call interface is needed to separate * resolution of dependant deserializers (which may have cyclic link back * to deserializer itself, directly or indirectly). *

* In addition, to support per-property annotations (to configure aspects * of deserialization on per-property basis), deserializers may want * to implement * {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer}, * which allows specialization of deserializers: call to * {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer#createContextual} * is passed information on property, and can create a newly configured * deserializer for handling that particular property. *

* If both * {@link com.fasterxml.jackson.databind.deser.ResolvableDeserializer} and * {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer} * are implemented, resolution of deserializers occurs before * contextualization. */ public abstract class JsonDeserializer implements NullValueProvider // since 2.9 { /* /********************************************************** /* Main deserialization methods /********************************************************** */ /** * Method that can be called to ask implementation to deserialize * JSON content into the value type this serializer handles. * Returned instance is to be constructed by method itself. *

* Pre-condition for this method is that the parser points to the * first event that is part of value to deserializer (and which * is never JSON 'null' literal, more on this below): for simple * types it may be the only value; and for structured types the * Object start marker or a FIELD_NAME. *

*

* The two possible input conditions for structured types result * from polymorphism via fields. In the ordinary case, Jackson * calls this method when it has encountered an OBJECT_START, * and the method implementation must advance to the next token to * see the first field name. If the application configures * polymorphism via a field, then the object looks like the following. *

     *      {
     *          "@class": "class name",
     *          ...
     *      }
     *  
* Jackson consumes the two tokens (the @class field name * and its value) in order to learn the class and select the deserializer. * Thus, the stream is pointing to the FIELD_NAME for the first field * after the @class. Thus, if you want your method to work correctly * both with and without polymorphism, you must begin your method with: *
     *       if (p.getCurrentToken() == JsonToken.START_OBJECT) {
     *         p.nextToken();
     *       }
     *  
* This results in the stream pointing to the field name, so that * the two conditions align. *

* Post-condition is that the parser will point to the last * event that is part of deserialized value (or in case deserialization * fails, event that was not recognized or usable, which may be * the same event as the one it pointed to upon call). *

* Note that this method is never called for JSON null literal, * and thus deserializers need (and should) not check for it. * * @param p Parsed used for reading JSON content * @param ctxt Context that can be used to access information about * this deserialization activity. * * @return Deserialized value */ public abstract T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException; /** * Alternate deserialization method (compared to the most commonly * used, {@link #deserialize(JsonParser, DeserializationContext)}), * which takes in initialized value instance, to be * configured and/or populated by deserializer. * Method is not necessarily used (or supported) by all types * (it will not work for immutable types, for obvious reasons): * most commonly it is used for Collections and Maps. * It may be used both with "updating readers" (for POJOs) and * when Collections and Maps use "getter as setter". *

* Default implementation just throws * {@link UnsupportedOperationException}, to indicate that types * that do not explicitly add support do not necessarily support * update-existing-value operation (esp. immutable types) */ public T deserialize(JsonParser p, DeserializationContext ctxt, T intoValue) throws IOException { if (ctxt.isEnabled(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)) { return deserialize(p, ctxt); } throw new UnsupportedOperationException("Cannot update object of type " +intoValue.getClass().getName()+" (by deserializer of type "+getClass().getName()+")"); } /** * Deserialization called when type being deserialized is defined to * contain additional type identifier, to allow for correctly * instantiating correct subtype. This can be due to annotation on * type (or its supertype), or due to global settings without * annotations. *

* Default implementation may work for some types, but ideally subclasses * should not rely on current default implementation. * Implementation is mostly provided to avoid compilation errors with older * code. * * @param typeDeserializer Deserializer to use for handling type information */ public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // We could try calling return typeDeserializer.deserializeTypedFromAny(p, ctxt); } /* /********************************************************** /* Fluent factory methods for constructing decorated versions /********************************************************** */ /** * Method that will return deserializer instance that is able * to handle "unwrapped" value instances * If no unwrapped instance can be constructed, will simply * return this object as-is. *

* Default implementation just returns 'this' * indicating that no unwrapped variant exists */ public JsonDeserializer unwrappingDeserializer(NameTransformer unwrapper) { return this; } /** * Method that can be called to try to replace deserializer this deserializer * delegates calls to. If not supported (either this deserializer does not * delegate anything; or it does not want any changes), should either * throw {@link UnsupportedOperationException} (if operation does not * make sense or is not allowed); or return this deserializer as is. * * @since 2.1 */ public JsonDeserializer replaceDelegatee(JsonDeserializer delegatee) { throw new UnsupportedOperationException(); } /* /********************************************************** /* Introspection methods for figuring out configuration/setup /* of this deserializer instance and/or type it handles /********************************************************** */ /** * Method for accessing type of values this deserializer produces. * Note that this information is not guaranteed to be exact -- it * may be a more generic (super-type) -- but it should not be * incorrect (return a non-related type). *

* Default implementation will return null, which means almost same * same as returning Object.class would; that is, that * nothing is known about handled type. *

* @since 2.3 */ public Class handledType() { return null; } /** * Method called to see if deserializer instance is cachable and * usable for other properties of same type (type for which instance * was created). *

* Note that cached instances are still resolved on per-property basis, * if instance implements {@link com.fasterxml.jackson.databind.deser.ResolvableDeserializer}: * cached instance is just as the base. This means that in most cases it is safe to * cache instances; however, it only makes sense to cache instances * if instantiation is expensive, or if instances are heavy-weight. *

* Default implementation returns false, to indicate that no caching * is done. */ public boolean isCachable() { return false; } /** * Accessor that can be used to determine if this deserializer uses * another deserializer for actual deserialization, by delegating * calls. If so, will return immediate delegate (which itself may * delegate to further deserializers); otherwise will return null. * * @return Deserializer this deserializer delegates calls to, if null; * null otherwise. * * @since 2.1 */ public JsonDeserializer getDelegatee() { return null; } /** * Method that will * either return null to indicate that type being deserializers * has no concept of properties; or a collection of identifiers * for which toString will give external property * name. * This is only to be used for error reporting and diagnostics * purposes (most commonly, to accompany "unknown property" * exception). * * @since 2.0 */ public Collection getKnownPropertyNames() { return null; } /* /********************************************************** /* Default NullValueProvider implementation /********************************************************** */ /** * Method that can be called to determine value to be used for * representing null values (values deserialized when JSON token * is {@link JsonToken#VALUE_NULL}). Usually this is simply * Java null, but for some types (especially primitives) it may be * necessary to use non-null values. *

* Since version 2.6 (in which the context argument was added), call is * expected to be made each and every time a null token needs to * be handled. *

* Default implementation simply returns null. * * @since 2.6 Added to replace earlier no-arguments variant */ @Override public T getNullValue(DeserializationContext ctxt) throws JsonMappingException { // Change the direction in 2.7 return getNullValue(); } /** * Default implementation indicates that "null value" to use for input null * is simply Java `null` for all deserializers, unless overridden by sub-classes. * This information may be used as optimization. */ @Override public AccessPattern getNullAccessPattern() { // Default implementation assumes that the null value does not vary, which // is usually the case for most implementations. But it is not necessarily // `null`; so sub-classes may want to refine further. return AccessPattern.CONSTANT; } /** * This method may be called in conjunction with calls to * {@link #getEmptyValue(DeserializationContext)}, to check whether it needs * to be called just once (static values), or each time empty value is * needed. * * @since 2.9 */ public AccessPattern getEmptyAccessPattern() { return AccessPattern.DYNAMIC; } /* /********************************************************** /* Other accessors /********************************************************** */ /** * Method called to determine value to be used for "empty" values * (most commonly when deserializing from empty JSON Strings). * Usually this is same as {@link #getNullValue} (which in turn * is usually simply Java null), but it can be overridden * for types. Or, if type should never be converted from empty * String, method can also throw an exception. *

* Since version 2.6 (in which the context argument was added), call is * expected to be made each and every time an empty value is needed. *

* Since version 2.9 does not require return of `T` any more. *

* Default implementation simply calls {@link #getNullValue} and * returns value. * * @since 2.6 Added to replace earlier no-arguments variant */ public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { return getNullValue(ctxt); } /** * Accessor that can be used to check whether this deserializer * is expecting to possibly get an Object Identifier value instead of full value * serialization, and if so, should be able to resolve it to actual * Object instance to return as deserialized value. *

* Default implementation returns null, as support cannot be implemented * generically. Some standard deserializers (most notably * {@link com.fasterxml.jackson.databind.deser.BeanDeserializer}) * do implement this feature, and may return reader instance, depending on exact * configuration of instance (which is based on type, and referring property). * * @return ObjectIdReader used for resolving possible Object Identifier * value, instead of full value serialization, if deserializer can do that; * null if no Object Id is expected. * * @since 2.0 */ public ObjectIdReader getObjectIdReader() { return null; } /** * Method needed by {@link BeanDeserializerFactory} to properly link * managed- and back-reference pairs. * * @since 2.2 (was moved out of BeanDeserializerBase) */ public SettableBeanProperty findBackReference(String refName) { throw new IllegalArgumentException("Cannot handle managed/back reference '"+refName +"': type: value deserializer of type "+getClass().getName()+" does not support them"); } /** * Introspection method that may be called to see whether deserializer supports * update of an existing value (aka "merging") or not. Return value should either * be {@link Boolean#FALSE} if update is not supported at all (immutable values); * {@link Boolean#TRUE} if update should usually work (regular POJOs, for example), * or null if this is either not known, or may sometimes work. *

* Information gathered is typically used to either prevent merging update for * property (either by skipping, if based on global defaults; or by exception during * deserialization construction if explicit attempt made) if {@link Boolean#FALSE} * returned, or inclusion if {@link Boolean#TRUE} is specified. If "unknown" case * (null returned) behavior is to exclude property if global defaults * used; or to allow if explicit per-type or property merging is defined. *

* Default implementation returns null to allow explicit per-type * or per-property attempts. * * @since 2.9 */ public Boolean supportsUpdate(DeserializationConfig config) { return null; } /* /********************************************************** /* Deprecated methods /********************************************************** */ /** * @deprecated Since 2.6 Use overloaded variant that takes context argument */ @Deprecated public T getNullValue() { return null; } /** * @deprecated Since 2.6 Use overloaded variant that takes context argument */ @Deprecated public Object getEmptyValue() { return getNullValue(); } /* /********************************************************** /* Helper classes /********************************************************** */ /** * This marker class is only to be used with annotations, to * indicate that no deserializer is configured. *

* Specifically, this class is to be used as the marker for * annotation {@link com.fasterxml.jackson.databind.annotation.JsonDeserialize} */ public abstract static class None extends JsonDeserializer { private None() { } // not to be instantiated } } JsonMappingException.java000066400000000000000000000422441325620701100354250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.Closeable; import java.io.IOException; import java.io.Serializable; import java.util.*; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.core.*; /** * Checked exception used to signal fatal problems with mapping of * content, distinct from low-level I/O problems (signaled using * simple {@link java.io.IOException}s) or data encoding/decoding * problems (signaled with {@link com.fasterxml.jackson.core.JsonParseException}, * {@link com.fasterxml.jackson.core.JsonGenerationException}). *

* One additional feature is the ability to denote relevant path * of references (during serialization/deserialization) to help in * troubleshooting. */ public class JsonMappingException 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 = 1000; /* /********************************************************** /* 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 = 2L; // changes between 2.7 and 2.8 // transient since 2.8 protected transient 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" (or not relevant). */ protected int _index = -1; /** * Lazily-constructed description of this instance; needed mostly to * allow JDK serialization to work in case where {@link #_from} is * non-serializable (and has to be dropped) but we still want to pass * actual description along. * * @since 2.8 */ protected String _desc; /** * 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("Cannot pass null fieldName"); } _fieldName = fieldName; } public Reference(Object from, int index) { _from = from; _index = index; } // Setters to let Jackson deserialize instances, but not to be called from outside void setFieldName(String n) { _fieldName = n; } void setIndex(int ix) { _index = ix; } void setDescription(String d) { _desc = d; } /** * Object through which reference was resolved. Can be either * actual instance (usually the case for serialization), or * Class (usually the case for deserialization). *

* Note that this value must be `transient` to allow serializability (as * often such Object is NOT serializable; or, in case of `Class`, may * not available at the point of deserialization). As such will return * `null` if instance has been passed using JDK serialization. */ @JsonIgnore public Object getFrom() { return _from; } public String getFieldName() { return _fieldName; } public int getIndex() { return _index; } public String getDescription() { if (_desc == null) { StringBuilder sb = new StringBuilder(); if (_from == null) { // can this ever occur? sb.append("UNKNOWN"); } else { Class cls = (_from instanceof Class) ? (Class)_from : _from.getClass(); // Hmmh. Although Class.getName() is mostly ok, it does look // butt-ugly for arrays. // 06-Oct-2016, tatu: as per [databind#1403], `getSimpleName()` not so good // as it drops enclosing class. So let's try bit different approach int arrays = 0; while (cls.isArray()) { cls = cls.getComponentType(); ++arrays; } sb.append(cls.getName()); while (--arrays >= 0) { sb.append("[]"); } /* was: String pkgName = ClassUtil.getPackageName(cls); if (pkgName != null) { sb.append(pkgName); sb.append('.'); } */ } sb.append('['); if (_fieldName != null) { sb.append('"'); sb.append(_fieldName); sb.append('"'); } else if (_index >= 0) { sb.append(_index); } else { sb.append('?'); } sb.append(']'); _desc = sb.toString(); } return _desc; } @Override public String toString() { return getDescription(); } /** * May need some cleaning here, given that `from` may or may not be serializable. * * since 2.8 */ Object writeReplace() { // as per [databind#1195], need to ensure description is not null, since // `_from` is transient getDescription(); return this; } } /* /********************************************************** /* State/configuration /********************************************************** */ /** * Path through which problem that triggering throwing of * this exception was reached. */ protected LinkedList _path; /** * Underlying processor ({@link JsonParser} or {@link JsonGenerator}), * if known. *

* NOTE: typically not serializable hence transient * * @since 2.7 */ protected transient Closeable _processor; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @deprecated Since 2.7 Use variant that takes {@link JsonParser} instead */ @Deprecated // since 2.7 public JsonMappingException(String msg) { super(msg); } /** * @deprecated Since 2.7 Use variant that takes {@link JsonParser} instead */ @Deprecated // since 2.7 public JsonMappingException(String msg, Throwable rootCause) { super(msg, rootCause); } /** * @deprecated Since 2.7 Use variant that takes {@link JsonParser} instead */ @Deprecated // since 2.7 public JsonMappingException(String msg, JsonLocation loc) { super(msg, loc); } /** * @deprecated Since 2.7 Use variant that takes {@link JsonParser} instead */ @Deprecated // since 2.7 public JsonMappingException(String msg, JsonLocation loc, Throwable rootCause) { super(msg, loc, rootCause); } /** * @since 2.7 */ public JsonMappingException(Closeable processor, String msg) { super(msg); _processor = processor; if (processor instanceof JsonParser) { // 17-Aug-2015, tatu: Use of token location makes some sense from databinding, // since actual parsing (current) location is typically only needed for low-level // parsing exceptions. _location = ((JsonParser) processor).getTokenLocation(); } } /** * @since 2.7 */ public JsonMappingException(Closeable processor, String msg, Throwable problem) { super(msg, problem); _processor = processor; if (processor instanceof JsonParser) { _location = ((JsonParser) processor).getTokenLocation(); } } /** * @since 2.7 */ public JsonMappingException(Closeable processor, String msg, JsonLocation loc) { super(msg, loc); _processor = processor; } /** * @since 2.7 */ public static JsonMappingException from(JsonParser p, String msg) { return new JsonMappingException(p, msg); } /** * @since 2.7 */ public static JsonMappingException from(JsonParser p, String msg, Throwable problem) { return new JsonMappingException(p, msg, problem); } /** * @since 2.7 */ public static JsonMappingException from(JsonGenerator g, String msg) { return new JsonMappingException(g, msg, (Throwable) null); } /** * @since 2.7 */ public static JsonMappingException from(JsonGenerator g, String msg, Throwable problem) { return new JsonMappingException(g, msg, problem); } /** * @since 2.7 */ public static JsonMappingException from(DeserializationContext ctxt, String msg) { return new JsonMappingException(ctxt.getParser(), msg); } /** * @since 2.7 */ public static JsonMappingException from(DeserializationContext ctxt, String msg, Throwable t) { return new JsonMappingException(ctxt.getParser(), msg, t); } /** * @since 2.7 */ public static JsonMappingException from(SerializerProvider ctxt, String msg) { return new JsonMappingException(ctxt.getGenerator(), msg); } /** * @since 2.7 */ public static JsonMappingException from(SerializerProvider ctxt, String msg, Throwable problem) { /* 17-Aug-2015, tatu: As per [databind#903] this is bit problematic as * SerializerProvider instance does not currently hold on to generator... */ return new JsonMappingException(ctxt.getGenerator(), msg, problem); } /** * Factory method used when "upgrading" an {@link IOException} into * {@link JsonMappingException}: usually only needed to comply with * a signature. *

* NOTE: since 2.9 should usually NOT be used on input-side (deserialization) * exceptions; instead use method(s) of InputMismatchException * * @since 2.1 */ public static JsonMappingException fromUnexpectedIOE(IOException src) { return new JsonMappingException(null, String.format("Unexpected IOException (of type %s): %s", src.getClass().getName(), src.getMessage())); } /** * 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 JsonMappingException 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 JsonMappingException 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. */ @SuppressWarnings("resource") public static JsonMappingException wrapWithPath(Throwable src, Reference ref) { JsonMappingException jme; if (src instanceof JsonMappingException) { jme = (JsonMappingException) src; } else { String msg = src.getMessage(); // Let's use a more meaningful placeholder if all we have is null if (msg == null || msg.length() == 0) { msg = "(was "+src.getClass().getName()+")"; } // 17-Aug-2015, tatu: Let's also pass the processor (parser/generator) along Closeable proc = null; if (src instanceof JsonProcessingException) { Object proc0 = ((JsonProcessingException) src).getProcessor(); if (proc0 instanceof Closeable) { proc = (Closeable) proc0; } } jme = new JsonMappingException(proc, msg, 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 accessing 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 // since 2.7.5 @JsonIgnore // as per [databind#1368] public Object getProcessor() { return _processor; } @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() { /* First: if we have no path info, let's just use parent's * definition as is */ String msg = super.getMessage(); if (_path == null) { return msg; } StringBuilder sb = (msg == null) ? new StringBuilder() : new StringBuilder(msg); /* 18-Feb-2009, tatu: initially there was a linefeed between * message and path reference; but unfortunately many systems * (loggers, junit) seem to assume linefeeds are only added to * separate stack trace. */ 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("->"); } } } } jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/JsonNode.java000066400000000000000000001056031325620701100331160ustar00rootroot00000000000000package com.fasterxml.jackson.databind; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.node.JsonNodeType; import com.fasterxml.jackson.databind.node.MissingNode; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Base class for all JSON nodes, which form the basis of JSON * Tree Model that Jackson implements. * One way to think of these nodes is to consider them * similar to DOM nodes in XML DOM trees. *

* As a general design rule, most accessors ("getters") are included * in this base class, to allow for traversing structure without * type casts. Most mutators, however, need to be accessed through * specific sub-classes (such as ObjectNode * and ArrayNode). * This seems sensible because proper type * information is generally available when building or modifying * trees, but less often when reading a tree (newly built from * parsed JSON content). *

* Actual concrete sub-classes can be found from package * {@link com.fasterxml.jackson.databind.node}. *

* Note that it is possible to "read" from nodes, using * method {@link TreeNode#traverse(ObjectCodec)}, which will result in * a {@link JsonParser} being constructed. This can be used for (relatively) * efficient conversations between different representations; and it is what * core databind uses for methods like {@link ObjectMapper#treeToValue(TreeNode, Class)} * and {@link ObjectMapper#treeAsTokens(TreeNode)} */ public abstract class JsonNode extends JsonSerializable.Base // i.e. implements JsonSerializable implements TreeNode, Iterable { /* /********************************************************** /* Construction, related /********************************************************** */ protected JsonNode() { } /** * Method that can be called to get a node that is guaranteed * not to allow changing of this node through mutators on * this node or any of its children. * This means it can either make a copy of this node (and all * mutable children and grand children nodes), or node itself * if it is immutable. *

* Note: return type is guaranteed to have same type as the * node method is called on; which is why method is declared * with local generic type. * * @since 2.0 * * @return Node that is either a copy of this node (and all non-leaf * children); or, for immutable leaf nodes, node itself. */ public abstract T deepCopy(); /* /********************************************************** /* TreeNode implementation /********************************************************** */ // public abstract JsonToken asToken(); // public abstract JsonToken traverse(); // public abstract JsonToken traverse(ObjectCodec codec); // public abstract JsonParser.NumberType numberType(); @Override public int size() { return 0; } @Override public final boolean isValueNode() { switch (getNodeType()) { case ARRAY: case OBJECT: case MISSING: return false; default: return true; } } @Override public final boolean isContainerNode() { final JsonNodeType type = getNodeType(); return type == JsonNodeType.OBJECT || type == JsonNodeType.ARRAY; } @Override public boolean isMissingNode() { return false; } @Override public boolean isArray() { return false; } @Override public boolean isObject() { return false; } /** * Method for accessing value of the specified element of * an array node. For other nodes, null is always returned. *

* For array nodes, index specifies * exact location within array and allows for efficient iteration * over child elements (underlying storage is guaranteed to * be efficiently indexable, i.e. has random-access to elements). * If index is less than 0, or equal-or-greater than * node.size(), null is returned; no exception is * thrown for any index. *

* NOTE: if the element value has been explicitly set as null * (which is different from removal!), * a {@link com.fasterxml.jackson.databind.node.NullNode} will be returned, * not null. * * @return Node that represent value of the specified element, * if this node is an array and has specified element. * Null otherwise. */ @Override public abstract JsonNode get(int index); /** * Method for accessing value of the specified field of * an object node. If this node is not an object (or it * does not have a value for specified field name), or * if there is no field with such name, null is returned. *

* NOTE: if the property value has been explicitly set as null * (which is different from removal!), * a {@link com.fasterxml.jackson.databind.node.NullNode} will be returned, * not null. * * @return Node that represent value of the specified field, * if this node is an object and has value for the specified * field. Null otherwise. */ @Override public JsonNode get(String fieldName) { return null; } /** * This method is similar to {@link #get(String)}, except * that instead of returning null if no such value exists (due * to this node not being an object, or object not having value * for the specified field), * a "missing node" (node that returns true for * {@link #isMissingNode}) will be returned. This allows for * convenient and safe chained access via path calls. */ @Override public abstract JsonNode path(String fieldName); /** * This method is similar to {@link #get(int)}, except * that instead of returning null if no such element exists (due * to index being out of range, or this node not being an array), * a "missing node" (node that returns true for * {@link #isMissingNode}) will be returned. This allows for * convenient and safe chained access via path calls. */ @Override public abstract JsonNode path(int index); @Override public Iterator fieldNames() { return ClassUtil.emptyIterator(); } /** * Method for locating node specified by given JSON pointer instances. * Method will never return null; if no matching node exists, * will return a node for which {@link #isMissingNode()} returns true. * * @return Node that matches given JSON Pointer: if no match exists, * will return a node for which {@link #isMissingNode()} returns true. * * @since 2.3 */ @Override public final JsonNode at(JsonPointer ptr) { // Basically: value nodes only match if we have "empty" path left if (ptr.matches()) { return this; } JsonNode n = _at(ptr); if (n == null) { return MissingNode.getInstance(); } return n.at(ptr.tail()); } /** * Convenience method that is functionally equivalent to: *

     *   return at(JsonPointer.valueOf(jsonPointerExpression));
     *
*

* Note that if the same expression is used often, it is preferable to construct * {@link JsonPointer} instance once and reuse it: this method will not perform * any caching of compiled expressions. * * @param jsonPtrExpr Expression to compile as a {@link JsonPointer} * instance * * @return Node that matches given JSON Pointer: if no match exists, * will return a node for which {@link TreeNode#isMissingNode()} returns true. * * @since 2.3 */ @Override public final JsonNode at(String jsonPtrExpr) { return at(JsonPointer.compile(jsonPtrExpr)); } protected abstract JsonNode _at(JsonPointer ptr); /* /********************************************************** /* Public API, type introspection /********************************************************** */ // // First high-level division between values, containers and "missing" /** * Return the type of this node * * @return the node type as a {@link JsonNodeType} enum value * * @since 2.2 */ public abstract JsonNodeType getNodeType(); /** * Method that can be used to check if the node is a wrapper * for a POJO ("Plain Old Java Object" aka "bean". * Returns true only for * instances of POJONode. * * @return True if this node wraps a POJO */ public final boolean isPojo() { return getNodeType() == JsonNodeType.POJO; } /** * @return True if this node represents a numeric JSON value */ public final boolean isNumber() { return getNodeType() == JsonNodeType.NUMBER; } /** * * @return True if this node represents an integral (integer) * numeric JSON value */ public boolean isIntegralNumber() { return false; } /** * @return True if this node represents a non-integral * numeric JSON value */ public boolean isFloatingPointNumber() { return false; } /** * Method that can be used to check whether contained value * is a number represented as Java short. * Note, however, that even if this method returns false, it * is possible that conversion would be possible from other numeric * types -- to check if this is possible, use * {@link #canConvertToInt()} instead. * * @return True if the value contained by this node is stored as Java short */ public boolean isShort() { return false; } /** * Method that can be used to check whether contained value * is a number represented as Java int. * Note, however, that even if this method returns false, it * is possible that conversion would be possible from other numeric * types -- to check if this is possible, use * {@link #canConvertToInt()} instead. * * @return True if the value contained by this node is stored as Java int */ public boolean isInt() { return false; } /** * Method that can be used to check whether contained value * is a number represented as Java long. * Note, however, that even if this method returns false, it * is possible that conversion would be possible from other numeric * types -- to check if this is possible, use * {@link #canConvertToInt()} instead. * * @return True if the value contained by this node is stored as Java long */ public boolean isLong() { return false; } /** * @since 2.2 */ public boolean isFloat() { return false; } public boolean isDouble() { return false; } public boolean isBigDecimal() { return false; } public boolean isBigInteger() { return false; } /** * Method that checks whether this node represents basic JSON String * value. */ public final boolean isTextual() { return getNodeType() == JsonNodeType.STRING; } /** * Method that can be used to check if this node was created from * JSON boolean value (literals "true" and "false"). */ public final boolean isBoolean() { return getNodeType() == JsonNodeType.BOOLEAN; } /** * Method that can be used to check if this node was created from * JSON literal null value. */ public final boolean isNull() { return getNodeType() == JsonNodeType.NULL; } /** * Method that can be used to check if this node represents * binary data (Base64 encoded). Although this will be externally * written as JSON String value, {@link #isTextual} will * return false if this method returns true. * * @return True if this node represents base64 encoded binary data */ public final boolean isBinary() { return getNodeType() == JsonNodeType.BINARY; } /** * Method that can be used to check whether this node is a numeric * node ({@link #isNumber} would return true) AND its value fits * within Java's 32-bit signed integer type, int. * Note that floating-point numbers are convertible if the integral * part fits without overflow (as per standard Java coercion rules) *

* NOTE: this method does not consider possible value type conversion * from JSON String into Number; so even if this method returns false, * it is possible that {@link #asInt} could still succeed * if node is a JSON String representing integral number, or boolean. * * @since 2.0 */ public boolean canConvertToInt() { return false; } /** * Method that can be used to check whether this node is a numeric * node ({@link #isNumber} would return true) AND its value fits * within Java's 64-bit signed integer type, long. * Note that floating-point numbers are convertible if the integral * part fits without overflow (as per standard Java coercion rules) *

* NOTE: this method does not consider possible value type conversion * from JSON String into Number; so even if this method returns false, * it is possible that {@link #asLong} could still succeed * if node is a JSON String representing integral number, or boolean. * * @since 2.0 */ public boolean canConvertToLong() { return false; } /* /********************************************************** /* Public API, straight value access /********************************************************** */ /** * Method to use for accessing String values. * Does NOT do any conversions for non-String value nodes; * for non-String values (ones for which {@link #isTextual} returns * false) null will be returned. * For String values, null is never returned (but empty Strings may be) * * @return Textual value this node contains, iff it is a textual * JSON node (comes from JSON String value entry) */ public String textValue() { return null; } /** * Method to use for accessing binary content of binary nodes (nodes * for which {@link #isBinary} returns true); or for Text Nodes * (ones for which {@link #textValue} returns non-null value), * to read decoded base64 data. * For other types of nodes, returns null. * * @return Binary data this node contains, iff it is a binary * node; null otherwise */ public byte[] binaryValue() throws IOException { return null; } /** * Method to use for accessing JSON boolean values (value * literals 'true' and 'false'). * For other types, always returns false. * * @return Textual value this node contains, iff it is a textual * json node (comes from JSON String value entry) */ public boolean booleanValue() { return false; } /** * Returns numeric value for this node, if and only if * this node is numeric ({@link #isNumber} returns true); otherwise * returns null * * @return Number value this node contains, if any (null for non-number * nodes). */ public Number numberValue() { return null; } /** * Returns 16-bit short value for this node, if and only if * this node is numeric ({@link #isNumber} returns true). For other * types returns 0. * For floating-point numbers, value is truncated using default * Java coercion, similar to how cast from double to short operates. * * @return Short value this node contains, if any; 0 for non-number * nodes. */ public short shortValue() { return 0; } /** * Returns integer value for this node, if and only if * this node is numeric ({@link #isNumber} returns true). For other * types returns 0. * For floating-point numbers, value is truncated using default * Java coercion, similar to how cast from double to int operates. * * @return Integer value this node contains, if any; 0 for non-number * nodes. */ public int intValue() { return 0; } /** * Returns 64-bit long value for this node, if and only if * this node is numeric ({@link #isNumber} returns true). For other * types returns 0. * For floating-point numbers, value is truncated using default * Java coercion, similar to how cast from double to long operates. * * @return Long value this node contains, if any; 0 for non-number * nodes. */ public long longValue() { return 0L; } /** * Returns 32-bit floating value for this node, if and only if * this node is numeric ({@link #isNumber} returns true). For other * types returns 0.0. * For integer values, conversion is done using coercion; this means * that an overflow is possible for `long` values * * @return 32-bit float value this node contains, if any; 0.0 for non-number nodes. * * @since 2.2 */ public float floatValue() { return 0.0f; } /** * Returns 64-bit floating point (double) value for this node, if and only if * this node is numeric ({@link #isNumber} returns true). For other * types returns 0.0. * For integer values, conversion is done using coercion; this may result * in overflows with {@link BigInteger} values. * * @return 64-bit double value this node contains, if any; 0.0 for non-number nodes. * * @since 2.2 */ public double doubleValue() { return 0.0; } /** * Returns floating point value for this node (as {@link BigDecimal}), if and only if * this node is numeric ({@link #isNumber} returns true). For other * types returns BigDecimal.ZERO. * * @return {@link BigDecimal} value this node contains, if numeric node; BigDecimal.ZERO for non-number nodes. */ public BigDecimal decimalValue() { return BigDecimal.ZERO; } /** * Returns integer value for this node (as {@link BigDecimal}), if and only if * this node is numeric ({@link #isNumber} returns true). For other * types returns BigInteger.ZERO. * * @return {@link BigInteger} value this node contains, if numeric node; BigInteger.ZERO for non-number nodes. */ public BigInteger bigIntegerValue() { return BigInteger.ZERO; } /* /********************************************************** /* Public API, value access with conversion(s)/coercion(s) /********************************************************** */ /** * Method that will return a valid String representation of * the container value, if the node is a value node * (method {@link #isValueNode} returns true), * otherwise empty String. */ public abstract String asText(); /** * Method similar to {@link #asText()}, except that it will return * defaultValue in cases where null value would be returned; * either for missing nodes (trying to access missing property, or element * at invalid item for array) or explicit nulls. * * @since 2.4 */ public String asText(String defaultValue) { String str = asText(); return (str == null) ? defaultValue : str; } /** * Method that will try to convert value of this node to a Java int. * Numbers are coerced using default Java rules; booleans convert to 0 (false) * and 1 (true), and Strings are parsed using default Java language integer * parsing rules. *

* If representation cannot be converted to an int (including structured types * like Objects and Arrays), * default value of 0 will be returned; no exceptions are thrown. */ public int asInt() { return asInt(0); } /** * Method that will try to convert value of this node to a Java int. * Numbers are coerced using default Java rules; booleans convert to 0 (false) * and 1 (true), and Strings are parsed using default Java language integer * parsing rules. *

* If representation cannot be converted to an int (including structured types * like Objects and Arrays), * specified defaultValue will be returned; no exceptions are thrown. */ public int asInt(int defaultValue) { return defaultValue; } /** * Method that will try to convert value of this node to a Java long. * Numbers are coerced using default Java rules; booleans convert to 0 (false) * and 1 (true), and Strings are parsed using default Java language integer * parsing rules. *

* If representation cannot be converted to an long (including structured types * like Objects and Arrays), * default value of 0 will be returned; no exceptions are thrown. */ public long asLong() { return asLong(0L); } /** * Method that will try to convert value of this node to a Java long. * Numbers are coerced using default Java rules; booleans convert to 0 (false) * and 1 (true), and Strings are parsed using default Java language integer * parsing rules. *

* If representation cannot be converted to an long (including structured types * like Objects and Arrays), * specified defaultValue will be returned; no exceptions are thrown. */ public long asLong(long defaultValue) { return defaultValue; } /** * Method that will try to convert value of this node to a Java double. * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) * and 1.0 (true), and Strings are parsed using default Java language integer * parsing rules. *

* If representation cannot be converted to an int (including structured types * like Objects and Arrays), * default value of 0.0 will be returned; no exceptions are thrown. */ public double asDouble() { return asDouble(0.0); } /** * Method that will try to convert value of this node to a Java double. * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) * and 1.0 (true), and Strings are parsed using default Java language integer * parsing rules. *

* If representation cannot be converted to an int (including structured types * like Objects and Arrays), * specified defaultValue will be returned; no exceptions are thrown. */ public double asDouble(double defaultValue) { return defaultValue; } /** * Method that will try to convert value of this node to a Java boolean. * JSON booleans map naturally; integer numbers other than 0 map to true, and * 0 maps to false * and Strings 'true' and 'false' map to corresponding values. *

* If representation cannot be converted to a boolean value (including structured types * like Objects and Arrays), * default value of false will be returned; no exceptions are thrown. */ public boolean asBoolean() { return asBoolean(false); } /** * Method that will try to convert value of this node to a Java boolean. * JSON booleans map naturally; integer numbers other than 0 map to true, and * 0 maps to false * and Strings 'true' and 'false' map to corresponding values. *

* If representation cannot be converted to a boolean value (including structured types * like Objects and Arrays), * specified defaultValue will be returned; no exceptions are thrown. */ public boolean asBoolean(boolean defaultValue) { return defaultValue; } /* /********************************************************** /* Public API, value find / existence check methods /********************************************************** */ /** * Method that allows checking whether this node is JSON Object node * and contains value for specified property. If this is the case * (including properties with explicit null values), returns true; * otherwise returns false. *

* This method is equivalent to: *

     *   node.get(fieldName) != null
     *
* (since return value of get() is node, not value node contains) *

* NOTE: when explicit null values are added, this * method will return true for such properties. * * @param fieldName Name of element to check * * @return True if this node is a JSON Object node, and has a property * entry with specified name (with any value, including null value) */ public boolean has(String fieldName) { return get(fieldName) != null; } /** * Method that allows checking whether this node is JSON Array node * and contains a value for specified index * If this is the case * (including case of specified indexing having null as value), returns true; * otherwise returns false. *

* Note: array element indexes are 0-based. *

* This method is equivalent to: *

     *   node.get(index) != null
     *
*

* NOTE: this method will return true for explicitly added * null values. * * @param index Index to check * * @return True if this node is a JSON Object node, and has a property * entry with specified name (with any value, including null value) */ public boolean has(int index) { return get(index) != null; } /** * Method that is similar to {@link #has(String)}, but that will * return false for explicitly added nulls. *

* This method is functionally equivalent to: *

     *   node.get(fieldName) != null << !node.get(fieldName).isNull()
     *
* * @since 2.1 */ public boolean hasNonNull(String fieldName) { JsonNode n = get(fieldName); return (n != null) && !n.isNull(); } /** * Method that is similar to {@link #has(int)}, but that will * return false for explicitly added nulls. *

* This method is equivalent to: *

     *   node.get(index) != null << !node.get(index).isNull()
     *
* * @since 2.1 */ public boolean hasNonNull(int index) { JsonNode n = get(index); return (n != null) && !n.isNull(); } /* /********************************************************** /* Public API, container access /********************************************************** */ /** * Same as calling {@link #elements}; implemented so that * convenience "for-each" loop can be used for looping over elements * of JSON Array constructs. */ @Override public final Iterator iterator() { return elements(); } /** * Method for accessing all value nodes of this Node, iff * this node is a JSON Array or Object node. In case of Object node, * field names (keys) are not included, only values. * For other types of nodes, returns empty iterator. */ public Iterator elements() { return ClassUtil.emptyIterator(); } /** * @return Iterator that can be used to traverse all key/value pairs for * object nodes; empty iterator (no contents) for other types */ public Iterator> fields() { return ClassUtil.emptyIterator(); } /* /********************************************************** /* Public API, find methods /********************************************************** */ /** * Method for finding a JSON Object field with specified name in this * node or its child nodes, and returning value it has. * If no matching field is found in this node or its descendants, returns null. * * @param fieldName Name of field to look for * * @return Value of first matching node found, if any; null if none */ public abstract JsonNode findValue(String fieldName); /** * Method for finding JSON Object fields with specified name, and returning * found ones as a List. Note that sub-tree search ends if a field is found, * so possible children of result nodes are not included. * If no matching fields are found in this node or its descendants, returns * an empty List. * * @param fieldName Name of field to look for */ public final List findValues(String fieldName) { List result = findValues(fieldName, null); if (result == null) { return Collections.emptyList(); } return result; } /** * Similar to {@link #findValues}, but will additionally convert * values into Strings, calling {@link #asText}. */ public final List findValuesAsText(String fieldName) { List result = findValuesAsText(fieldName, null); if (result == null) { return Collections.emptyList(); } return result; } /** * Method similar to {@link #findValue}, but that will return a * "missing node" instead of null if no field is found. Missing node * is a specific kind of node for which {@link #isMissingNode} * returns true; and all value access methods return empty or * missing value. * * @param fieldName Name of field to look for * * @return Value of first matching node found; or if not found, a * "missing node" (non-null instance that has no value) */ public abstract JsonNode findPath(String fieldName); /** * Method for finding a JSON Object that contains specified field, * within this node or its descendants. * If no matching field is found in this node or its descendants, returns null. * * @param fieldName Name of field to look for * * @return Value of first matching node found, if any; null if none */ public abstract JsonNode findParent(String fieldName); /** * Method for finding a JSON Object that contains specified field, * within this node or its descendants. * If no matching field is found in this node or its descendants, returns null. * * @param fieldName Name of field to look for * * @return Value of first matching node found, if any; null if none */ public final List findParents(String fieldName) { List result = findParents(fieldName, null); if (result == null) { return Collections.emptyList(); } return result; } public abstract List findValues(String fieldName, List foundSoFar); public abstract List findValuesAsText(String fieldName, List foundSoFar); public abstract List findParents(String fieldName, List foundSoFar); /* /********************************************************** /* Public API, path handling /********************************************************** */ /** * Method that can be called on Object nodes, to access a property * that has Object value; or if no such property exists, to create, * add and return such Object node. * If the node method is called on is not Object node, * or if property exists and has value that is not Object node, * {@link UnsupportedOperationException} is thrown */ public JsonNode with(String propertyName) { throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but " +getClass().getName()+"), cannot call with() on it"); } /** * Method that can be called on Object nodes, to access a property * that has Array value; or if no such property exists, to create, * add and return such Array node. * If the node method is called on is not Object node, * or if property exists and has value that is not Array node, * {@link UnsupportedOperationException} is thrown */ public JsonNode withArray(String propertyName) { throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but " +getClass().getName()+"), cannot call withArray() on it"); } /* /********************************************************** /* Public API, comparison /********************************************************** */ /** * Entry method for invoking customizable comparison, using passed-in * {@link Comparator} object. Nodes will handle traversal of structured * types (arrays, objects), but defer to comparator for scalar value * comparisons. If a "natural" {@link Comparator} is passed -- one that * simply calls equals() on one of arguments, passing the other * -- implementation is the same as directly calling equals() * on node. *

* Default implementation simply delegates to passed in comparator, * with this as the first argument, and other as * the second argument. * * @param comparator Object called to compare two scalar {@link JsonNode} * instances, and return either 0 (are equals) or non-zero (not equal) * * @since 2.6 */ public boolean equals(Comparator comparator, JsonNode other) { return comparator.compare(this, other) == 0; } /* /********************************************************** /* Overridden standard methods /********************************************************** */ /** * Method that will produce developer-readable representation of the * node; which may or may not be as valid JSON. * If you want valid JSON output (or output formatted using one of * other Jackson supported data formats) make sure to use * {@link ObjectMapper} or {@link ObjectWriter} to serialize an * instance, for example: *

     *   String json = objectMapper.writeValueAsString(rootNode);
     *
*

* Note: method defined as abstract to ensure all implementation * classes explicitly implement method, instead of relying * on {@link Object#toString()} definition. */ @Override public abstract String toString(); /** * Equality for node objects is defined as full (deep) value * equality. This means that it is possible to compare complete * JSON trees for equality by comparing equality of root nodes. *

* Note: marked as abstract to ensure all implementation * classes define it properly and not rely on definition * from {@link java.lang.Object}. */ @Override public abstract boolean equals(Object o); } JsonSerializable.java000066400000000000000000000047111325620701100345560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * Interface that can be implemented by objects that know how to * serialize themselves to JSON, using {@link JsonGenerator} * (and {@link SerializerProvider} if necessary). *

* Note that implementing this interface binds implementing object * closely to Jackson API, and that it is often not necessary to do * so -- if class is a bean, it can be serialized without * implementing this interface. *

* Note that while it is possible to just directly implement {@link JsonSerializable}, * actual implementations are strongly recommended to instead extend * {@link JsonSerializable.Base}. */ public interface JsonSerializable { /** * Serialization method called when no additional type information is * to be included in serialization. */ public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException; /** * Serialization method called when additional type information is * expected to be included in serialization, for deserialization to use. *

* Usually implementation consists of a call to {@link TypeSerializer#writeTypePrefix} * followed by serialization of contents, * followed by a call to {@link TypeSerializer#writeTypeSuffix}). * Details of the type id argument to pass depend on shape of JSON Object used * (Array, Object or scalar like String/Number/Boolean). *

* Note that some types (most notably, "natural" types: String, Integer, * Double and Boolean) never include type information. */ public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException; /** * Base class with minimal implementation, as well as couple of extension methods * that core Jackson databinding makes use of. * Use of this base class is strongly recommended over directly implementing * {@link JsonSerializable}. * * @since 2.6 */ public abstract static class Base implements JsonSerializable { /** * Method that may be called on instance to determine if it is considered * "empty" for purposes of serialization filtering or not. */ public boolean isEmpty(SerializerProvider serializers) { return false; } } } JsonSerializer.java000066400000000000000000000263431325620701100342660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.IOException; import java.util.Iterator; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.PropertyWriter; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Abstract class that defines API used by {@link ObjectMapper} (and * other chained {@link JsonSerializer}s too) to serialize Objects of * arbitrary types into JSON, using provided {@link JsonGenerator}. * {@link com.fasterxml.jackson.databind.ser.std.StdSerializer} instead * of this class, since it will implement many of optional * methods of this class. *

* NOTE: various serialize methods are never (to be) called * with null values -- caller must handle null values, usually * by calling {@link SerializerProvider#findNullValueSerializer} to obtain * serializer to use. * This also means that custom serializers cannot be directly used to change * the output to produce when serializing null values. *

* If serializer is an aggregate one -- meaning it delegates handling of some * of its contents by using other serializer(s) -- it typically also needs * to implement {@link com.fasterxml.jackson.databind.ser.ResolvableSerializer}, * which can locate secondary serializers needed. This is important to allow dynamic * overrides of serializers; separate call interface is needed to separate * resolution of secondary serializers (which may have cyclic link back * to serializer itself, directly or indirectly). *

* In addition, to support per-property annotations (to configure aspects * of serialization on per-property basis), serializers may want * to implement * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer}, * which allows specialization of serializers: call to * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer#createContextual} * is passed information on property, and can create a newly configured * serializer for handling that particular property. *

* If both * {@link com.fasterxml.jackson.databind.ser.ResolvableSerializer} and * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer} * are implemented, resolution of serializers occurs before * contextualization. */ public abstract class JsonSerializer implements JsonFormatVisitable // since 2.1 { /* /********************************************************** /* Fluent factory methods for constructing decorated versions /********************************************************** */ /** * Method that will return serializer instance that produces * "unwrapped" serialization, if applicable for type being * serialized (which is the case for some serializers * that produce JSON Objects as output). * If no unwrapped serializer can be constructed, will simply * return serializer as-is. *

* Default implementation just returns serializer as-is, * indicating that no unwrapped variant exists * * @param unwrapper Name transformation to use to convert between names * of unwrapper properties */ public JsonSerializer unwrappingSerializer(NameTransformer unwrapper) { return this; } /** * Method that can be called to try to replace serializer this serializer * delegates calls to. If not supported (either this serializer does not * delegate anything; or it does not want any changes), should either * throw {@link UnsupportedOperationException} (if operation does not * make sense or is not allowed); or return this serializer as is. * * @since 2.1 */ public JsonSerializer replaceDelegatee(JsonSerializer delegatee) { throw new UnsupportedOperationException(); } /** * Mutant factory method that is called if contextual configuration indicates that * a specific filter (as specified by filterId) is to be used for * serialization. *

* Default implementation simply returns this; sub-classes that do support * filtering will need to create and return new instance if filter changes. * * @since 2.6 */ public JsonSerializer withFilterId(Object filterId) { return this; } /* /********************************************************** /* Serialization methods /********************************************************** */ /** * Method that can be called to ask implementation to serialize * values of type this serializer handles. * * @param value Value to serialize; can not be null. * @param gen Generator used to output resulting Json content * @param serializers Provider that can be used to get serializers for * serializing Objects value contains, if any. */ public abstract void serialize(T value, JsonGenerator gen, SerializerProvider serializers) throws IOException; /** * Method that can be called to ask implementation to serialize * values of type this serializer handles, using specified type serializer * for embedding necessary type information. *

* Default implementation will throw {@link UnsupportedOperationException} * to indicate that proper type handling needs to be implemented. *

* For simple datatypes written as a single scalar value (JSON String, Number, Boolean), * implementation would look like: *

     *  // note: method to call depends on whether this type is serialized as JSON scalar, object or Array!
     *  typeSer.writeTypePrefixForScalar(value, gen);
     *  serialize(value, gen, provider);
     *  typeSer.writeTypeSuffixForScalar(value, gen);
     *
* and implementations for type serialized as JSON Arrays or Objects would differ slightly, * as START-ARRAY/END-ARRAY and * START-OBJECT/END-OBJECT pairs * need to be properly handled with respect to serializing of contents. * * @param value Value to serialize; can not be null. * @param gen Generator used to output resulting Json content * @param serializers Provider that can be used to get serializers for * serializing Objects value contains, if any. * @param typeSer Type serializer to use for including type information */ public void serializeWithType(T value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException { Class clz = handledType(); if (clz == null) { clz = value.getClass(); } serializers.reportBadDefinition(clz, String.format( "Type id handling not implemented for type %s (by serializer of type %s)", clz.getName(), getClass().getName())); } /* /********************************************************** /* Other accessors /********************************************************** */ /** * Method for accessing type of Objects this serializer can handle. * Note that this information is not guaranteed to be exact -- it * may be a more generic (super-type) -- but it should not be * incorrect (return a non-related type). *

* Default implementation will return null, which essentially means * same as returning Object.class would; that is, that * nothing is known about handled type. *

*/ public Class handledType() { return null; } /** * Method called to check whether given serializable value is * considered "empty" value (for purposes of suppressing serialization * of empty values). *

* Default implementation will consider only null values to be empty. * * @deprecated Since 2.5 Use {@link #isEmpty(SerializerProvider, Object)} instead; * will be removed from 3.0 */ @Deprecated public boolean isEmpty(T value) { return isEmpty(null, value); } /** * Method called to check whether given serializable value is * considered "empty" value (for purposes of suppressing serialization * of empty values). *

* Default implementation will consider only null values to be empty. *

* NOTE: replaces {@link #isEmpty(Object)}, which was deprecated in 2.5 * * @since 2.5 */ public boolean isEmpty(SerializerProvider provider, T value) { return (value == null); } /** * Method that can be called to see whether this serializer instance * will use Object Id to handle cyclic references. */ public boolean usesObjectId() { return false; } /** * Accessor for checking whether this serializer is an * "unwrapping" serializer; this is necessary to know since * it may also require caller to suppress writing of the * leading property name. */ public boolean isUnwrappingSerializer() { return false; } /** * Accessor that can be used to determine if this serializer uses * another serializer for actual serialization, by delegating * calls. If so, will return immediate delegate (which itself may * delegate to further serializers); otherwise will return null. * * @return Serializer this serializer delegates calls to, if null; * null otherwise. * * @since 2.1 */ public JsonSerializer getDelegatee() { return null; } /** * Accessor for iterating over logical properties that the type * handled by this serializer has, from serialization perspective. * Actual type of properties, if any, will be * {@link com.fasterxml.jackson.databind.ser.BeanPropertyWriter}. * Of standard Jackson serializers, only {@link com.fasterxml.jackson.databind.ser.BeanSerializer} * exposes properties. * * @since 2.6 */ public Iterator properties() { return ClassUtil.emptyIterator(); } /* /********************************************************** /* Default JsonFormatVisitable implementation /********************************************************** */ /** * Default implementation simply calls {@link JsonFormatVisitorWrapper#expectAnyFormat(JavaType)}. * * @since 2.1 */ @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType type) throws JsonMappingException { visitor.expectAnyFormat(type); } /* /********************************************************** /* Helper class(es) /********************************************************** */ /** * This marker class is only to be used with annotations, to * indicate that no serializer is configured. *

* Specifically, this class is to be used as the marker for * annotation {@link com.fasterxml.jackson.databind.annotation.JsonSerialize}. */ public abstract static class None extends JsonSerializer { } } KeyDeserializer.java000066400000000000000000000016351325620701100344130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.IOException; /** * Abstract class that defines API used for deserializing JSON content * field names into Java Map keys. These deserializers are only used * if the Map key class is not String or Object. */ public abstract class KeyDeserializer { /** * Method called to deserialize a {@link java.util.Map} key from JSON property name. */ public abstract Object deserializeKey(String key, DeserializationContext ctxt) throws IOException; /** * This marker class is only to be used with annotations, to * indicate that no deserializer is configured. *

* Specifically, this class is to be used as the marker for * annotation {@link com.fasterxml.jackson.databind.annotation.JsonDeserialize}. */ public abstract static class None extends KeyDeserializer { } } MapperFeature.java000066400000000000000000000467101325620701100340630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.cfg.ConfigFeature; /** * Enumeration that defines simple on/off features to set * for {@link ObjectMapper}, and accessible (but not changeable) * via {@link ObjectReader} and {@link ObjectWriter} (as well as * through various convenience methods through context objects). *

* Note that in addition to being only mutable via {@link ObjectMapper}, * changes only take effect when done before any serialization or * deserialization calls -- that is, caller must follow * "configure-then-use" pattern. */ public enum MapperFeature implements ConfigFeature { /* /****************************************************** /* General introspection features /****************************************************** */ /** * Feature that determines whether annotation introspection * is used for configuration; if enabled, configured * {@link AnnotationIntrospector} will be used: if disabled, * no annotations are considered. *

* Feature is enabled by default. */ USE_ANNOTATIONS(true), /** * Feature that determines whether otherwise regular "getter" * methods (but only ones that handle Collections and Maps, * not getters of other type) * can be used for purpose of getting a reference to a Collection * and Map to modify the property, without requiring a setter * method. * This is similar to how JAXB framework sets Collections and * Maps: no setter is involved, just setter. *

* Note that such getters-as-setters methods have lower * precedence than setters, so they are only used if no * setter is found for the Map/Collection property. *

* Feature is enabled by default. */ USE_GETTERS_AS_SETTERS(true), /** * Feature that determines how transient modifier for fields * is handled: if disabled, it is only taken to mean exclusion of the field * as accessor; if true, it is taken to imply removal of the whole property. *

* Feature is disabled by default, meaning that existence of `transient` * for a field does not necessarily lead to ignoral of getters or setters * but just ignoring the use of field for access. * * @since 2.6 */ PROPAGATE_TRANSIENT_MARKER(false), /* /****************************************************** /* Introspection-based property auto-detection /****************************************************** */ /** * Feature that determines whether "creator" methods are * automatically detected by consider public constructors, * and static single argument methods with name "valueOf". * If disabled, only methods explicitly annotated are considered * creator methods (except for the no-arg default constructor which * is always considered a factory method). *

* Note that this feature has lower precedence than per-class * annotations, and is only used if there isn't more granular * configuration available. *

* Feature is enabled by default. */ AUTO_DETECT_CREATORS(true), /** * Feature that determines whether non-static fields are recognized as * properties. * If yes, then all public member fields * are considered as properties. If disabled, only fields explicitly * annotated are considered property fields. *

* Note that this feature has lower precedence than per-class * annotations, and is only used if there isn't more granular * configuration available. *

* Feature is enabled by default. */ AUTO_DETECT_FIELDS(true), /** * Feature that determines whether regular "getter" methods are * automatically detected based on standard Bean naming convention * or not. If yes, then all public zero-argument methods that * start with prefix "get" * are considered as getters. * If disabled, only methods explicitly annotated are considered getters. *

* Note that since version 1.3, this does NOT include * "is getters" (see {@link #AUTO_DETECT_IS_GETTERS} for details) *

* Note that this feature has lower precedence than per-class * annotations, and is only used if there isn't more granular * configuration available. *

* Feature is enabled by default. */ AUTO_DETECT_GETTERS(true), /** * Feature that determines whether "is getter" methods are * automatically detected based on standard Bean naming convention * or not. If yes, then all public zero-argument methods that * start with prefix "is", and whose return type is boolean * are considered as "is getters". * If disabled, only methods explicitly annotated are considered getters. *

* Note that this feature has lower precedence than per-class * annotations, and is only used if there isn't more granular * configuration available. *

* Feature is enabled by default. */ AUTO_DETECT_IS_GETTERS(true), /** * Feature that determines whether "setter" methods are * automatically detected based on standard Bean naming convention * or not. If yes, then all public one-argument methods that * start with prefix "set" * are considered setters. If disabled, only methods explicitly * annotated are considered setters. *

* Note that this feature has lower precedence than per-class * annotations, and is only used if there isn't more granular * configuration available. *

* Feature is enabled by default. */ AUTO_DETECT_SETTERS(true), /** * Feature that determines whether getters (getter methods) * can be auto-detected if there is no matching mutator (setter, * constructor parameter or field) or not: if set to true, * only getters that match a mutator are auto-discovered; if * false, all auto-detectable getters can be discovered. *

* Feature is disabled by default. */ REQUIRE_SETTERS_FOR_GETTERS(false), /** * Feature that determines whether member fields declared as 'final' may * be auto-detected to be used mutators (used to change value of the logical * property) or not. If enabled, 'final' access modifier has no effect, and * such fields may be detected according to usual visibility and inference * rules; if disabled, such fields are NOT used as mutators except if * explicitly annotated for such use. *

* Feature is enabled by default, for backwards compatibility reasons. * * @since 2.2 */ ALLOW_FINAL_FIELDS_AS_MUTATORS(true), /** * Feature that determines whether member mutators (fields and * setters) may be "pulled in" even if they are not visible, * as long as there is a visible accessor (getter or field) with same name. * For example: field "value" may be inferred as mutator, * if there is visible or explicitly marked getter "getValue()". * If enabled, inferring is enabled; otherwise (disabled) only visible and * explicitly annotated accessors are ever used. *

* Note that 'getters' are never inferred and need to be either visible (including * bean-style naming) or explicitly annotated. *

* Feature is enabled by default. * * @since 2.2 */ INFER_PROPERTY_MUTATORS(true), /** * Feature that determines handling of java.beans.ConstructorProperties * annotation: when enabled, it is considered as alias of * {@link com.fasterxml.jackson.annotation.JsonCreator}, to mean that constructor * should be considered a property-based Creator; when disabled, only constructor * parameter name information is used, but constructor is NOT considered an explicit * Creator (although may be discovered as one using other annotations or heuristics). *

* Feature is mostly used to help interoperability with frameworks like Lombok * that may automatically generate ConstructorProperties annotation * but without necessarily meaning that constructor should be used as Creator * for deserialization. *

* Feature is enabled by default. * * @since 2.9 */ INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES(true), /* /****************************************************** /* Access modifier handling /****************************************************** */ /** * Feature that determines whether method and field access * modifier settings can be overridden when accessing * properties. If enabled, method * {@link java.lang.reflect.AccessibleObject#setAccessible} * may be called to enable access to otherwise unaccessible objects. *

* Note that this setting may have significant performance implications, * since access override helps remove costly access checks on each * and every Reflection access. If you are considering disabling * this feature, be sure to verify performance consequences if usage * is performance sensitive. * Also note that performance effects vary between Java platforms * (JavaSE vs Android, for example), as well as JDK versions: older * versions seemed to have more significant performance difference. *

* Conversely, on some platforms, it may be necessary to disable this feature * as platform does not allow such calls. For example, when developing * Applets (or other Java code that runs on tightly restricted sandbox), * it may be necessary to disable the feature regardless of performance effects. *

* Feature is enabled by default. */ CAN_OVERRIDE_ACCESS_MODIFIERS(true), /** * Feature that determines that forces call to * {@link java.lang.reflect.AccessibleObject#setAccessible} even for * public accessors -- that is, even if no such call is * needed from functionality perspective -- if call is allowed * (that is, {@link #CAN_OVERRIDE_ACCESS_MODIFIERS} is set to true). * The main reason to enable this feature is possible performance * improvement as JDK does not have to perform access checks; these * checks are otherwise made for all accessors, including public ones, * and may result in slower Reflection calls. Exact impact (if any) * depends on Java platform (Java SE, Android) as well as JDK version. *

* Feature is enabled by default, for legacy reasons (it was the behavior * until 2.6) * * @since 2.7 */ OVERRIDE_PUBLIC_ACCESS_MODIFIERS(true), /* /****************************************************** /* Type-handling features /****************************************************** */ /** * Feature that determines whether the type detection for * serialization should be using actual dynamic runtime type, * or declared static type. * Note that deserialization always uses declared static types * since no runtime types are available (as we are creating * instances after using type information). *

* This global default value can be overridden at class, method * or field level by using {@link JsonSerialize#typing} annotation * property. *

* Feature is disabled by default which means that dynamic runtime types * are used (instead of declared static types) for serialization. */ USE_STATIC_TYPING(false), /* /****************************************************** /* View-related features /****************************************************** */ /** * Feature that determines whether properties that have no view * annotations are included in JSON serialization views (see * {@link com.fasterxml.jackson.annotation.JsonView} for more * details on JSON Views). * If enabled, non-annotated properties will be included; * when disabled, they will be excluded. So this feature * changes between "opt-in" (feature disabled) and * "opt-out" (feature enabled) modes. *

* Default value is enabled, meaning that non-annotated * properties are included in all views if there is no * {@link com.fasterxml.jackson.annotation.JsonView} annotation. *

* Feature is enabled by default. */ DEFAULT_VIEW_INCLUSION(true), /* /****************************************************** /* Generic output features /****************************************************** */ /** * Feature that defines default property serialization order used * for POJO fields (note: does not apply to {@link java.util.Map} * serialization!): * if enabled, default ordering is alphabetic (similar to * how {@link com.fasterxml.jackson.annotation.JsonPropertyOrder#alphabetic()} * works); if disabled, order is unspecified (based on what JDK gives * us, which may be declaration order, but is not guaranteed). *

* Note that this is just the default behavior, and can be overridden by * explicit overrides in classes (for example with * {@link com.fasterxml.jackson.annotation.JsonPropertyOrder} annotation) *

* Feature is disabled by default. */ SORT_PROPERTIES_ALPHABETICALLY(false), /* /****************************************************** /* Name-related features /****************************************************** */ /** * Feature that will allow for more forgiving deserialization of incoming JSON. * If enabled, the bean properties will be matched using their lower-case equivalents, * meaning that any case-combination (incoming and matching names are canonicalized * by lower-casing) should work. *

* Note that there is additional performance overhead since incoming property * names need to be lower-cased before comparison, for cases where there are upper-case * letters. Overhead for names that are already lower-case should be negligible however. *

* Feature is disabled by default. * * @since 2.5 */ ACCEPT_CASE_INSENSITIVE_PROPERTIES(false), /** * Feature that determines if Enum deserialization should be case sensitive or not. * If enabled, Enum deserialization will ignore case, that is, case of incoming String * value and enum id (dependant on other settings, either `name()`, `toString()`, or * explicit override) do not need to match. *

* Feature is disabled by default. * * @since 2.9 */ ACCEPT_CASE_INSENSITIVE_ENUMS(false), /** * Feature that can be enabled to make property names be * overridden by wrapper name (usually detected with annotations * as defined by {@link AnnotationIntrospector#findWrapperName}. * If enabled, all properties that have associated non-empty Wrapper * name will use that wrapper name instead of property name. * If disabled, wrapper name is only used for wrapping (if anything). *

* Feature is disabled by default. * * @since 2.1 */ USE_WRAPPER_NAME_AS_PROPERTY_NAME(false), /** * Feature that may be enabled to enforce strict compatibility with * Bean name introspection, instead of slightly different mechanism * Jackson defaults to. * Specific difference is that Jackson always lower cases leading upper-case * letters, so "getURL()" becomes "url" property; whereas standard Bean * naming only lower-cases the first letter if it is NOT followed by * another upper-case letter (so "getURL()" would result in "URL" property). *

* Feature is disabled by default for backwards compatibility purposes: earlier * Jackson versions used Jackson's own mechanism. * * @since 2.5 */ USE_STD_BEAN_NAMING(false), /** * Feature that when enabled will allow explicitly named properties (i.e., fields or methods * annotated with {@link com.fasterxml.jackson.annotation.JsonProperty}("explicitName")) to * be re-named by a {@link PropertyNamingStrategy}, if one is configured. *

* Feature is disabled by default. * * @since 2.7 */ ALLOW_EXPLICIT_PROPERTY_RENAMING(false), /* /****************************************************** /* Coercion features /****************************************************** */ /** * Feature that determines whether coercions from secondary representations are allowed * for simple non-textual scalar types: numbers and booleans. This includes `primitive` * types and their wrappers, but excludes `java.lang.String` and date/time types. *

* When feature is disabled, only strictly compatible input may be bound: numbers for * numbers, boolean values for booleans. When feature is enabled, conversions from * JSON String are allowed, as long as textual value matches (for example, String * "true" is allowed as equivalent of JSON boolean token `true`; or String "1.0" * for `double`). *

* Note that it is possible that other configurability options can override this * in closer scope (like on per-type or per-property basis); this is just the global * default. *

* Feature is enabled by default (for backwards compatibility since this was the * default behavior) * * @since 2.9 */ ALLOW_COERCION_OF_SCALARS(true), /* /****************************************************** /* Other features /****************************************************** */ /** * Feature that determines whether multiple registrations of same module * should be ignored or not; if enabled, only the first registration call * results in module being called, and possible duplicate calls are silently * ignored; if disabled, no checking is done and all registration calls are * dispatched to module. *

* Definition of "same module" is based on using {@link Module#getTypeId()}; * modules with same non-null type id are considered same for * purposes of duplicate registration. This also avoids having to keep track * of actual module instances; only ids will be kept track of (and only if * this feature is enabled). *

* Feature is enabled by default. * * @since 2.5 */ IGNORE_DUPLICATE_MODULE_REGISTRATIONS(true), /** * Setting that determines what happens if an attempt is made to explicitly * "merge" value of a property, where value does not support merging; either * merging is skipped and new value is created (true) or * an exception is thrown (false). *

* Feature is disabled by default since non-mergeable property types are ignored * even if defaults call for merging, and usually explicit per-type or per-property * settings for such types should result in an exception. * * @since 2.9 */ IGNORE_MERGE_FOR_UNMERGEABLE(true) ; private final boolean _defaultState; private final int _mask; private MapperFeature(boolean defaultState) { _defaultState = defaultState; _mask = (1 << ordinal()); } @Override public boolean enabledByDefault() { return _defaultState; } @Override public int getMask() { return _mask; } @Override public boolean enabledIn(int flags) { return (flags & _mask) != 0; } } MappingIterator.java000066400000000000000000000305001325620701100344160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.Closeable; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; /** * Iterator exposed by {@link ObjectMapper} when binding sequence of * objects. Extension is done to allow more convenient exposing of * {@link IOException} (which basic {@link Iterator} does not expose) */ public class MappingIterator implements Iterator, Closeable { protected final static MappingIterator EMPTY_ITERATOR = new MappingIterator(null, null, null, null, false, null); /* /********************************************************** /* State constants /********************************************************** */ /** * State in which iterator is closed */ protected final static int STATE_CLOSED = 0; /** * State in which value read failed */ protected final static int STATE_NEED_RESYNC = 1; /** * State in which no recovery is needed, but "hasNextValue()" needs * to be called first */ protected final static int STATE_MAY_HAVE_VALUE = 2; /** * State in which "hasNextValue()" has been succesfully called * and deserializer can be called to fetch value */ protected final static int STATE_HAS_VALUE = 3; /* /********************************************************** /* Configuration /********************************************************** */ /** * Type to bind individual elements to. */ protected final JavaType _type; /** * Context for deserialization, needed to pass through to deserializer */ protected final DeserializationContext _context; /** * Deserializer for individual element values. */ protected final JsonDeserializer _deserializer; /** * Underlying parser used for reading content to bind. Initialized * as not null but set as null when * iterator is closed, to denote closing. */ protected final JsonParser _parser; /** * Context to resynchronize to, in case an exception is encountered * but caller wants to try to read more elements. */ protected final JsonStreamContext _seqContext; /** * If not null, "value to update" instead of creating a new instance * for each call. */ protected final T _updatedValue; /** * Flag that indicates whether input {@link JsonParser} should be closed * when we are done or not; generally only called when caller did not * pass JsonParser. */ protected final boolean _closeParser; /* /********************************************************** /* Parsing state /********************************************************** */ /** * State of the iterator */ protected int _state; /* /********************************************************** /* Construction /********************************************************** */ /** * @param managedParser Whether we "own" the {@link JsonParser} passed or not: * if true, it was created by {@link ObjectReader} and code here needs to * close it; if false, it was passed by calling code and should not be * closed by iterator. */ @SuppressWarnings("unchecked") protected MappingIterator(JavaType type, JsonParser p, DeserializationContext ctxt, JsonDeserializer deser, boolean managedParser, Object valueToUpdate) { _type = type; _parser = p; _context = ctxt; _deserializer = (JsonDeserializer) deser; _closeParser = managedParser; if (valueToUpdate == null) { _updatedValue = null; } else { _updatedValue = (T) valueToUpdate; } /* Ok: one more thing; we may have to skip START_ARRAY, assuming * "wrapped" sequence; but this is ONLY done for 'managed' parsers * and never if JsonParser was directly passed by caller (if it * was, caller must have either positioned it over first token of * the first element, or cleared the START_ARRAY token explicitly). * Note, however, that we do not try to guess whether this could be * an unwrapped sequence of arrays/Lists: we just assume it is wrapped; * and if not, caller needs to hand us JsonParser instead, pointing to * the first token of the first element. */ if (p == null) { // can this occur? _seqContext = null; _state = STATE_CLOSED; } else { JsonStreamContext sctxt = p.getParsingContext(); if (managedParser && p.isExpectedStartArrayToken()) { // If pointing to START_ARRAY, context should be that ARRAY p.clearCurrentToken(); } else { // regardless, recovery context should be whatever context we have now, // with sole exception of pointing to a start marker, in which case it's // the parent JsonToken t = p.getCurrentToken(); if ((t == JsonToken.START_OBJECT) || (t == JsonToken.START_ARRAY)) { sctxt = sctxt.getParent(); } } _seqContext = sctxt; _state = STATE_MAY_HAVE_VALUE; } } @SuppressWarnings("unchecked") protected static MappingIterator emptyIterator() { return (MappingIterator) EMPTY_ITERATOR; } /* /********************************************************** /* Basic iterator impl /********************************************************** */ @Override public boolean hasNext() { try { return hasNextValue(); } catch (JsonMappingException e) { return (Boolean) _handleMappingException(e); } catch (IOException e) { return (Boolean) _handleIOException(e); } } @Override public T next() { try { return nextValue(); } catch (JsonMappingException e) { throw new RuntimeJsonMappingException(e.getMessage(), e); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public void close() throws IOException { if (_state != STATE_CLOSED) { _state = STATE_CLOSED; if (_parser != null) { _parser.close(); } } } /* /********************************************************** /* Extended API, iteration /********************************************************** */ /* */ /** * Equivalent of {@link #next} but one that may throw checked * exceptions from Jackson due to invalid input. */ public boolean hasNextValue() throws IOException { switch (_state) { case STATE_CLOSED: return false; case STATE_NEED_RESYNC: _resync(); // fall-through case STATE_MAY_HAVE_VALUE: JsonToken t = _parser.getCurrentToken(); if (t == null) { // un-initialized or cleared; find next t = _parser.nextToken(); // If EOF, no more, or if we hit END_ARRAY (although we don't clear the token). if (t == null || t == JsonToken.END_ARRAY) { _state = STATE_CLOSED; if (_closeParser && (_parser != null)) { _parser.close(); } return false; } } _state = STATE_HAS_VALUE; return true; case STATE_HAS_VALUE: // fall through } return true; } public T nextValue() throws IOException { switch (_state) { case STATE_CLOSED: return _throwNoSuchElement(); case STATE_NEED_RESYNC: // fall-through, will do re-sync case STATE_MAY_HAVE_VALUE: if (!hasNextValue()) { return _throwNoSuchElement(); } break; case STATE_HAS_VALUE: break; } int nextState = STATE_NEED_RESYNC; try { T value; if (_updatedValue == null) { value = _deserializer.deserialize(_parser, _context); } else{ _deserializer.deserialize(_parser, _context, _updatedValue); value = _updatedValue; } nextState = STATE_MAY_HAVE_VALUE; return value; } finally { _state = nextState; /* 24-Mar-2015, tatu: As per [#733], need to mark token consumed no * matter what, to avoid infinite loop for certain failure cases. * For 2.6 need to improve further. */ _parser.clearCurrentToken(); } } /** * Convenience method for reading all entries accessible via * this iterator; resulting container will be a {@link java.util.ArrayList}. * * @return List of entries read * * @since 2.2 */ public List readAll() throws IOException { return readAll(new ArrayList()); } /** * Convenience method for reading all entries accessible via * this iterator * * @return List of entries read (same as passed-in argument) * * @since 2.2 */ public > L readAll(L resultList) throws IOException { while (hasNextValue()) { resultList.add(nextValue()); } return resultList; } /** * Convenience method for reading all entries accessible via * this iterator * * @since 2.5 */ public > C readAll(C results) throws IOException { while (hasNextValue()) { results.add(nextValue()); } return results; } /* /********************************************************** /* Extended API, accessors /********************************************************** */ /** * Accessor for getting underlying parser this iterator uses. * * @since 2.2 */ public JsonParser getParser() { return _parser; } /** * Accessor for accessing {@link FormatSchema} that the underlying parser * (as per {@link #getParser}) is using, if any; only parser of schema-aware * formats use schemas. * * @since 2.2 */ public FormatSchema getParserSchema() { return _parser.getSchema(); } /** * Convenience method, functionally equivalent to: * * iterator.getParser().getCurrentLocation() * * * @return Location of the input stream of the underlying parser * * @since 2.2.1 */ public JsonLocation getCurrentLocation() { return _parser.getCurrentLocation(); } /* /********************************************************** /* Helper methods /********************************************************** */ protected void _resync() throws IOException { final JsonParser p = _parser; // First, a quick check to see if we might have been lucky and no re-sync needed if (p.getParsingContext() == _seqContext) { return; } while (true) { JsonToken t = p.nextToken(); if ((t == JsonToken.END_ARRAY) || (t == JsonToken.END_OBJECT)) { if (p.getParsingContext() == _seqContext) { p.clearCurrentToken(); return; } } else if ((t == JsonToken.START_ARRAY) || (t == JsonToken.START_OBJECT)) { p.skipChildren(); } else if (t == null) { return; } } } protected R _throwNoSuchElement() { throw new NoSuchElementException(); } protected R _handleMappingException(JsonMappingException e) { throw new RuntimeJsonMappingException(e.getMessage(), e); } protected R _handleIOException(IOException e) { throw new RuntimeException(e.getMessage(), e); } } MappingJsonFactory.java000066400000000000000000000044371325620701100351000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.format.InputAccessor; import com.fasterxml.jackson.core.format.MatchStrength; /** * Sub-class of {@link JsonFactory} that will create a proper * {@link ObjectCodec} to allow seam-less conversions between * JSON content and Java objects (POJOs). * The only addition to regular {@link JsonFactory} currently * is that {@link ObjectMapper} is constructed and passed as * the codec to use. */ public class MappingJsonFactory extends JsonFactory { private static final long serialVersionUID = -1; // since 2.7 public MappingJsonFactory() { this(null); } public MappingJsonFactory(ObjectMapper mapper) { super(mapper); if (mapper == null) { setCodec(new ObjectMapper(this)); } } public MappingJsonFactory(JsonFactory src, ObjectMapper mapper) { super(src, mapper); if (mapper == null) { setCodec(new ObjectMapper(this)); } } /** * We'll override the method to return more specific type; co-variance * helps here */ @Override public final ObjectMapper getCodec() { return (ObjectMapper) _objectCodec; } // @since 2.1 @Override public JsonFactory copy() { _checkInvalidCopy(MappingJsonFactory.class); // note: as with base class, must NOT copy mapper reference return new MappingJsonFactory(this, null); } /* /********************************************************** /* Format detection functionality (since 1.8) /********************************************************** */ /** * Sub-classes need to override this method */ @Override public String getFormatName() { /* since non-JSON factories typically should not extend this class, * let's just always return JSON as name. */ return FORMAT_NAME_JSON; } /** * Sub-classes need to override this method */ @Override public MatchStrength hasFormat(InputAccessor acc) throws IOException { if (getClass() == MappingJsonFactory.class) { return hasJSONFormat(acc); } return null; } } jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/Module.java000066400000000000000000000331531325620701100326240ustar00rootroot00000000000000package com.fasterxml.jackson.databind; import java.util.Collection; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.cfg.MutableConfigOverride; import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; import com.fasterxml.jackson.databind.deser.Deserializers; import com.fasterxml.jackson.databind.deser.KeyDeserializers; import com.fasterxml.jackson.databind.deser.ValueInstantiators; import com.fasterxml.jackson.databind.introspect.ClassIntrospector; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; import com.fasterxml.jackson.databind.ser.Serializers; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.type.TypeModifier; /** * Simple interface for extensions that can be registered with {@link ObjectMapper} * to provide a well-defined set of extensions to default functionality; such as * support for new data types. */ public abstract class Module implements Versioned { /* /********************************************************** /* Simple accessors /********************************************************** */ /** * Method that returns a display that can be used by Jackson * for informational purposes, as well as in associating extensions with * module that provides them. */ public abstract String getModuleName(); /** * Method that returns version of this module. Can be used by Jackson for * informational purposes. */ @Override public abstract Version version(); /** * Method that returns an id that may be used to determine if two {@link Module} * instances are considered to be of same type, for purpose of preventing * multiple registrations of "same type of" module * (see {@link com.fasterxml.jackson.databind.MapperFeature#IGNORE_DUPLICATE_MODULE_REGISTRATIONS}) * If `null` is returned, every instance is considered unique. * If non-null value is returned, equality of id Objects is used to check whether * modules should be considered to be "of same type" *

* Default implementation returns value of class name ({@link Class#getName}). * * @since 2.5 */ public Object getTypeId() { return getClass().getName(); } /* /********************************************************** /* Life-cycle: registration /********************************************************** */ /** * Method called by {@link ObjectMapper} when module is registered. * It is called to let module register functionality it provides, * using callback methods passed-in context object exposes. */ public abstract void setupModule(SetupContext context); /* /********************************************************** /* Helper types /********************************************************** */ /** * Interface Jackson exposes to modules for purpose of registering * extended functionality. * Usually implemented by {@link ObjectMapper}, but modules should * NOT rely on this -- if they do require access to mapper instance, * they need to call {@link SetupContext#getOwner} method. */ public static interface SetupContext { /* /********************************************************** /* Simple accessors /********************************************************** */ /** * Method that returns version information about {@link ObjectMapper} * that implements this context. Modules can use this to choose * different settings or initialization order; or even decide to fail * set up completely if version is compatible with module. */ public Version getMapperVersion(); /** * Fallback access method that allows modules to refer to the * {@link ObjectMapper} that provided this context. * It should NOT be needed by most modules; and ideally should * not be used -- however, there may be cases where this may * be necessary due to various design constraints. *

* NOTE: use of this method is discouraged, as it allows access to * things Modules typically should not modify. It is included, however, * to allow access to new features in cases where Module API * has not yet been extended, or there are oversights. *

* Return value is chosen to not leak dependency to {@link ObjectMapper}; * however, instance will always be of that type. * This is why return value is declared generic, to allow caller to * specify context to often avoid casting. * * @since 2.0 */ public C getOwner(); /** * Accessor for finding {@link TypeFactory} that is currently configured * by the context. *

* NOTE: since it is possible that other modules might change or replace * TypeFactory, use of this method adds order-dependency for registrations. * * @since 2.0 */ public TypeFactory getTypeFactory(); public boolean isEnabled(MapperFeature f); public boolean isEnabled(DeserializationFeature f); public boolean isEnabled(SerializationFeature f); public boolean isEnabled(JsonFactory.Feature f); public boolean isEnabled(JsonParser.Feature f); public boolean isEnabled(JsonGenerator.Feature f); /* /********************************************************** /* Mutant accessors /********************************************************** */ /** * "Mutant accessor" for getting a mutable configuration override object for * given type, needed to add or change per-type overrides applied * to properties of given type. * Usage is through returned object by colling "setter" methods, which * directly modify override object and take effect directly. * For example you can do *

         *   mapper.configOverride(java.util.Date.class)
         *       .setFormat(JsonFormat.Value.forPattern("yyyy-MM-dd"));
         *
         * to change the default format to use for properties of type
         * {@link java.util.Date} (possibly further overridden by per-property
         * annotations)
         *
         * @since 2.8
         */
        public MutableConfigOverride configOverride(Class type);
        
        /*
        /**********************************************************
        /* Handler registration; serializers/deserializers
        /**********************************************************
         */
        
        /**
         * Method that module can use to register additional deserializers to use for
         * handling types.
         * 
         * @param d Object that can be called to find deserializer for types supported
         *   by module (null returned for non-supported types)
         */
        public void addDeserializers(Deserializers d);

        /**
         * Method that module can use to register additional deserializers to use for
         * handling Map key values (which are separate from value deserializers because
         * they are always serialized from String values)
         */
        public void addKeyDeserializers(KeyDeserializers s);
        
        /**
         * Method that module can use to register additional serializers to use for
         * handling types.
         * 
         * @param s Object that can be called to find serializer for types supported
         *   by module (null returned for non-supported types)
         */
        public void addSerializers(Serializers s);

        /**
         * Method that module can use to register additional serializers to use for
         * handling Map key values (which are separate from value serializers because
         * they must write JsonToken.FIELD_NAME instead of String value).
         */
        public void addKeySerializers(Serializers s);

        /*
        /**********************************************************
        /* Handler registration; other
        /**********************************************************
         */
        
        /**
         * Method that module can use to register additional modifier objects to
         * customize configuration and construction of bean deserializers.
         * 
         * @param mod Modifier to register
         */
        public void addBeanDeserializerModifier(BeanDeserializerModifier mod);

        /**
         * Method that module can use to register additional modifier objects to
         * customize configuration and construction of bean serializers.
         * 
         * @param mod Modifier to register
         */
        public void addBeanSerializerModifier(BeanSerializerModifier mod);

        /**
         * Method that module can use to register additional
         * {@link AbstractTypeResolver} instance, to handle resolution of
         * abstract to concrete types (either by defaulting, or by materializing).
         * 
         * @param resolver Resolver to add.
         */
        public void addAbstractTypeResolver(AbstractTypeResolver resolver);

        /**
         * Method that module can use to register additional
         * {@link TypeModifier} instance, which can augment {@link com.fasterxml.jackson.databind.JavaType}
         * instances constructed by {@link com.fasterxml.jackson.databind.type.TypeFactory}.
         * 
         * @param modifier to add
         */
        public void addTypeModifier(TypeModifier modifier);

        /**
         * Method that module can use to register additional {@link com.fasterxml.jackson.databind.deser.ValueInstantiator}s,
         * by adding {@link ValueInstantiators} object that gets called when 
         * instantatiator is needed by a deserializer.
         * 
         * @param instantiators Object that can provide {@link com.fasterxml.jackson.databind.deser.ValueInstantiator}s for
         *    constructing POJO values during deserialization
         */
        public void addValueInstantiators(ValueInstantiators instantiators);

        /**
         * Method for replacing the default class introspector with a derived class that
         * overrides specific behavior.
         *
         * @param ci Derived class of ClassIntrospector with overriden behavior
         *
         * @since 2.2
         */
        public void setClassIntrospector(ClassIntrospector ci);

        /**
         * Method for registering specified {@link AnnotationIntrospector} as the highest
         * priority introspector (will be chained with existing introspector(s) which
         * will be used as fallbacks for cases this introspector does not handle)
         * 
         * @param ai Annotation introspector to register.
         */
        public void insertAnnotationIntrospector(AnnotationIntrospector ai);

        /**
         * Method for registering specified {@link AnnotationIntrospector} as the lowest
         * priority introspector, chained with existing introspector(s) and called
         * as fallback for cases not otherwise handled.
         * 
         * @param ai Annotation introspector to register.
         */
        public void appendAnnotationIntrospector(AnnotationIntrospector ai);

        /**
         * Method for registering specified classes as subtypes (of supertype(s)
         * they have)
         */
        public void registerSubtypes(Class... subtypes);

        /**
         * Method for registering specified classes as subtypes (of supertype(s)
         * they have), using specified type names.
         */
        public void registerSubtypes(NamedType... subtypes);

        /**
         * Method for registering specified classes as subtypes (of supertype(s)
         * they have)
         *
         * @since 2.9
         */
        public void registerSubtypes(Collection> subtypes);
        
        /**
         * Method used for defining mix-in annotations to use for augmenting
         * specified class or interface.
         * All annotations from
         * mixinSource are taken to override annotations
         * that target (or its supertypes) has.
         *

* Note: mix-ins are registered both for serialization and deserialization * (which can be different internally). *

* Note: currently only one set of mix-in annotations can be defined for * a single class; so if multiple modules register mix-ins, highest * priority one (last one registered) will have priority over other modules. * * @param target Class (or interface) whose annotations to effectively override * @param mixinSource Class (or interface) whose annotations are to * be "added" to target's annotations, overriding as necessary */ public void setMixInAnnotations(Class target, Class mixinSource); /** * Add a deserialization problem handler * * @param handler The deserialization problem handler */ public void addDeserializationProblemHandler(DeserializationProblemHandler handler); /** * Method that may be used to override naming strategy that is used * by {@link ObjectMapper}. * * @since 2.3 */ public void setNamingStrategy(PropertyNamingStrategy naming); } } ObjectMapper.java000066400000000000000000005060771325620701100337050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.*; import java.lang.reflect.Type; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; import java.text.DateFormat; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.CharacterEscapes; import com.fasterxml.jackson.core.io.SegmentedStringWriter; import com.fasterxml.jackson.core.type.ResolvedType; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.util.*; import com.fasterxml.jackson.databind.cfg.*; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.*; import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver; import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder; import com.fasterxml.jackson.databind.node.*; import com.fasterxml.jackson.databind.ser.*; import com.fasterxml.jackson.databind.type.*; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.RootNameLookup; import com.fasterxml.jackson.databind.util.StdDateFormat; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * ObjectMapper provides functionality for reading and writing JSON, * either to and from basic POJOs (Plain Old Java Objects), or to and from * a general-purpose JSON Tree Model ({@link JsonNode}), as well as * related functionality for performing conversions. * It is also highly customizable to work both with different styles of JSON * content, and to support more advanced Object concepts such as * polymorphism and Object identity. * ObjectMapper also acts as a factory for more advanced {@link ObjectReader} * and {@link ObjectWriter} classes. * Mapper (and {@link ObjectReader}s, {@link ObjectWriter}s it constructs) will * use instances of {@link JsonParser} and {@link JsonGenerator} * for implementing actual reading/writing of JSON. * Note that although most read and write methods are exposed through this class, * some of the functionality is only exposed via {@link ObjectReader} and * {@link ObjectWriter}: specifically, reading/writing of longer sequences of * values is only available through {@link ObjectReader#readValues(InputStream)} * and {@link ObjectWriter#writeValues(OutputStream)}. *

Simplest usage is of form:

  final ObjectMapper mapper = new ObjectMapper(); // can use static singleton, inject: just make sure to reuse!
  MyValue value = new MyValue();
  // ... and configure
  File newState = new File("my-stuff.json");
  mapper.writeValue(newState, value); // writes JSON serialization of MyValue instance
  // or, read
  MyValue older = mapper.readValue(new File("my-older-stuff.json"), MyValue.class);

  // Or if you prefer JSON Tree representation:
  JsonNode root = mapper.readTree(newState);
  // and find values by, for example, using a {@link com.fasterxml.jackson.core.JsonPointer} expression:
  int age = root.at("/personal/age").getValueAsInt(); 
*

* The main conversion API is defined in {@link ObjectCodec}, so that * implementation details of this class need not be exposed to * streaming parser and generator classes. Usage via {@link ObjectCodec} is, * however, usually only for cases where dependency to {@link ObjectMapper} is * either not possible (from Streaming API), or undesireable (when only relying * on Streaming API). *

* Mapper instances are fully thread-safe provided that ALL configuration of the * instance occurs before ANY read or write calls. If configuration of a mapper instance * is modified after first usage, changes may or may not take effect, and configuration * calls themselves may fail. * If you need to use different configuration, you have two main possibilities: *

    *
  • Construct and use {@link ObjectReader} for reading, {@link ObjectWriter} for writing. * Both types are fully immutable and you can freely create new instances with different * configuration using either factory methods of {@link ObjectMapper}, or readers/writers * themselves. Construction of new {@link ObjectReader}s and {@link ObjectWriter}s is * a very light-weight operation so it is usually appropriate to create these on per-call * basis, as needed, for configuring things like optional indentation of JSON. *
  • *
  • If the specific kind of configurability is not available via {@link ObjectReader} and * {@link ObjectWriter}, you may need to use multiple {@link ObjectMapper} instead (for example: * you cannot change mix-in annotations on-the-fly; or, set of custom (de)serializers). * To help with this usage, you may want to use method {@link #copy()} which creates a clone * of the mapper with specific configuration, and allows configuration of the copied instance * before it gets used. Note that {@link #copy} operation is as expensive as constructing * a new {@link ObjectMapper} instance: if possible, you should still pool and reuse mappers * if you intend to use them for multiple operations. *
  • *
*

* Note on caching: root-level deserializers are always cached, and accessed * using full (generics-aware) type information. This is different from * caching of referenced types, which is more limited and is done only * for a subset of all deserializer types. The main reason for difference * is that at root-level there is no incoming reference (and hence no * referencing property, no referral information or annotations to * produce differing deserializers), and that the performance impact * greatest at root level (since it'll essentially cache the full * graph of deserializers involved). *

* Notes on security: use "default typing" feature (see {@link #enableDefaultTyping()}) * is a potential security risk, if used with untrusted content (content generated by * untrusted external parties). If so, you may want to construct a custom * {@link TypeResolverBuilder} implementation to limit possible types to instantiate, * (using {@link #setDefaultTyping}). */ public class ObjectMapper extends ObjectCodec implements Versioned, java.io.Serializable // as of 2.1 { private static final long serialVersionUID = 2L; // as of 2.9 /* /********************************************************** /* Helper classes, enums /********************************************************** */ /** * Enumeration used with {@link ObjectMapper#enableDefaultTyping()} * to specify what kind of types (classes) default typing should * be used for. It will only be used if no explicit type information * is found, but this enumeration further limits subset of those types. *

* Since 2.4 there are special exceptions for JSON Tree model * types (sub-types of {@link TreeNode}: default typing is never * applied to them. * Since 2.8(.4) additional checks are made to avoid attempts at default * typing primitive-valued properties. *

* NOTE: use of Default Typing can be a potential security risk if incoming * content comes from untrusted sources, and it is recommended that this * is either not done, or, if enabled, use {@link #setDefaultTyping} * passing a custom {@link TypeResolverBuilder} implementation that white-lists * legal types to use. */ public enum DefaultTyping { /** * This value means that only properties that have * {@link java.lang.Object} as declared type (including * generic types without explicit type) will use default * typing. */ JAVA_LANG_OBJECT, /** * Value that means that default typing will be used for * properties with declared type of {@link java.lang.Object} * or an abstract type (abstract class or interface). * Note that this does not include array types. *

* Since 2.4, this does NOT apply to {@link TreeNode} and its subtypes. */ OBJECT_AND_NON_CONCRETE, /** * Value that means that default typing will be used for * all types covered by {@link #OBJECT_AND_NON_CONCRETE} * plus all array types for them. *

* Since 2.4, this does NOT apply to {@link TreeNode} and its subtypes. */ NON_CONCRETE_AND_ARRAYS, /** * Value that means that default typing will be used for * all non-final types, with exception of small number of * "natural" types (String, Boolean, Integer, Double), which * can be correctly inferred from JSON; as well as for * all arrays of non-final types. *

* Since 2.4, this does NOT apply to {@link TreeNode} and its subtypes. */ NON_FINAL } /** * Customized {@link TypeResolverBuilder} that provides type resolver builders * used with so-called "default typing" * (see {@link ObjectMapper#enableDefaultTyping()} for details). *

* Type resolver construction is based on configuration: implementation takes care * of only providing builders in cases where type information should be applied. * This is important since build calls may be sent for any and all types, and * type information should NOT be applied to all of them. */ public static class DefaultTypeResolverBuilder extends StdTypeResolverBuilder implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Definition of what types is this default typer valid for. */ protected final DefaultTyping _appliesFor; public DefaultTypeResolverBuilder(DefaultTyping t) { _appliesFor = t; } @Override public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, JavaType baseType, Collection subtypes) { return useForType(baseType) ? super.buildTypeDeserializer(config, baseType, subtypes) : null; } @Override public TypeSerializer buildTypeSerializer(SerializationConfig config, JavaType baseType, Collection subtypes) { return useForType(baseType) ? super.buildTypeSerializer(config, baseType, subtypes) : null; } /** * Method called to check if the default type handler should be * used for given type. * Note: "natural types" (String, Boolean, Integer, Double) will never * use typing; that is both due to them being concrete and final, * and since actual serializers and deserializers will also ignore any * attempts to enforce typing. */ public boolean useForType(JavaType t) { // 03-Oct-2016, tatu: As per [databind#1395], need to skip // primitive types too, regardless if (t.isPrimitive()) { return false; } switch (_appliesFor) { case NON_CONCRETE_AND_ARRAYS: while (t.isArrayType()) { t = t.getContentType(); } // fall through case OBJECT_AND_NON_CONCRETE: // 19-Apr-2016, tatu: ReferenceType like Optional also requires similar handling: while (t.isReferenceType()) { t = t.getReferencedType(); } return t.isJavaLangObject() || (!t.isConcrete() // [databind#88] Should not apply to JSON tree models: && !TreeNode.class.isAssignableFrom(t.getRawClass())); case NON_FINAL: while (t.isArrayType()) { t = t.getContentType(); } // 19-Apr-2016, tatu: ReferenceType like Optional also requires similar handling: while (t.isReferenceType()) { t = t.getReferencedType(); } // [databind#88] Should not apply to JSON tree models: return !t.isFinal() && !TreeNode.class.isAssignableFrom(t.getRawClass()); default: //case JAVA_LANG_OBJECT: return t.isJavaLangObject(); } } } /* /********************************************************** /* Internal constants, singletons /********************************************************** */ // Quick little shortcut, to avoid having to use global TypeFactory instance... // 19-Oct-2015, tatu: Not sure if this is really safe to do; let's at least allow // some amount of introspection private final static JavaType JSON_NODE_TYPE = SimpleType.constructUnsafe(JsonNode.class); // TypeFactory.defaultInstance().constructType(JsonNode.class); // 16-May-2009, tatu: Ditto ^^^ protected final static AnnotationIntrospector DEFAULT_ANNOTATION_INTROSPECTOR = new JacksonAnnotationIntrospector(); /** * Base settings contain defaults used for all {@link ObjectMapper} * instances. */ protected final static BaseSettings DEFAULT_BASE = new BaseSettings( null, // cannot share global ClassIntrospector any more (2.5+) DEFAULT_ANNOTATION_INTROSPECTOR, null, TypeFactory.defaultInstance(), null, StdDateFormat.instance, null, Locale.getDefault(), null, // to indicate "use Jackson default TimeZone" (UTC since Jackson 2.7) Base64Variants.getDefaultVariant() // 2.1 ); /* /********************************************************** /* Configuration settings, shared /********************************************************** */ /** * Factory used to create {@link JsonParser} and {@link JsonGenerator} * instances as necessary. */ protected final JsonFactory _jsonFactory; /** * Specific factory used for creating {@link JavaType} instances; * needed to allow modules to add more custom type handling * (mostly to support types of non-Java JVM languages) */ protected TypeFactory _typeFactory; /** * Provider for values to inject in deserialized POJOs. */ protected InjectableValues _injectableValues; /** * Thing used for registering sub-types, resolving them to * super/sub-types as needed. */ protected SubtypeResolver _subtypeResolver; /** * Currently active per-type configuration overrides, accessed by * declared type of property. * * @since 2.9 */ protected final ConfigOverrides _configOverrides; /* /********************************************************** /* Configuration settings: mix-in annotations /********************************************************** */ /** * Mapping that defines how to apply mix-in annotations: key is * the type to received additional annotations, and value is the * type that has annotations to "mix in". *

* Annotations associated with the value classes will be used to * override annotations of the key class, associated with the * same field or method. They can be further masked by sub-classes: * you can think of it as injecting annotations between the target * class and its sub-classes (or interfaces) * * @since 2.6 (earlier was a simple {@link java.util.Map} */ protected SimpleMixInResolver _mixIns; /* /********************************************************** /* Configuration settings, serialization /********************************************************** */ /** * Configuration object that defines basic global * settings for the serialization process */ protected SerializationConfig _serializationConfig; /** * Object that manages access to serializers used for serialization, * including caching. * It is configured with {@link #_serializerFactory} to allow * for constructing custom serializers. *

* Note: while serializers are only exposed {@link SerializerProvider}, * mappers and readers need to access additional API defined by * {@link DefaultSerializerProvider} */ protected DefaultSerializerProvider _serializerProvider; /** * Serializer factory used for constructing serializers. */ protected SerializerFactory _serializerFactory; /* /********************************************************** /* Configuration settings, deserialization /********************************************************** */ /** * Configuration object that defines basic global * settings for the serialization process */ protected DeserializationConfig _deserializationConfig; /** * Blueprint context object; stored here to allow custom * sub-classes. Contains references to objects needed for * deserialization construction (cache, factory). */ protected DefaultDeserializationContext _deserializationContext; /* /********************************************************** /* Module-related /********************************************************** */ /** * Set of module types (as per {@link Module#getTypeId()} that have been * registered; kept track of iff {@link MapperFeature#IGNORE_DUPLICATE_MODULE_REGISTRATIONS} * is enabled, so that duplicate registration calls can be ignored * (to avoid adding same handlers multiple times, mostly). * * @since 2.5 */ protected Set _registeredModuleTypes; /* /********************************************************** /* Caching /********************************************************** */ /* Note: handling of serializers and deserializers is not symmetric; * and as a result, only root-level deserializers can be cached here. * This is mostly because typing and resolution for deserializers is * fully static; whereas it is quite dynamic for serialization. */ /** * We will use a separate main-level Map for keeping track * of root-level deserializers. This is where most successful * cache lookups get resolved. * Map will contain resolvers for all kinds of types, including * container types: this is different from the component cache * which will only cache bean deserializers. *

* Given that we don't expect much concurrency for additions * (should very quickly converge to zero after startup), let's * explicitly define a low concurrency setting. *

* Since version 1.5, these may are either "raw" deserializers (when * no type information is needed for base type), or type-wrapped * deserializers (if it is needed) */ final protected ConcurrentHashMap> _rootDeserializers = new ConcurrentHashMap>(64, 0.6f, 2); /* /********************************************************** /* Life-cycle: constructing instance /********************************************************** */ /** * Default constructor, which will construct the default * {@link JsonFactory} as necessary, use * {@link SerializerProvider} as its * {@link SerializerProvider}, and * {@link BeanSerializerFactory} as its * {@link SerializerFactory}. * This means that it * can serialize all standard JDK types, as well as regular * Java Beans (based on method names and Jackson-specific annotations), * but does not support JAXB annotations. */ public ObjectMapper() { this(null, null, null); } /** * Constructs instance that uses specified {@link JsonFactory} * for constructing necessary {@link JsonParser}s and/or * {@link JsonGenerator}s. */ public ObjectMapper(JsonFactory jf) { this(jf, null, null); } /** * Copy-constructor, mostly used to support {@link #copy}. * * @since 2.1 */ protected ObjectMapper(ObjectMapper src) { _jsonFactory = src._jsonFactory.copy(); _jsonFactory.setCodec(this); _subtypeResolver = src._subtypeResolver; _typeFactory = src._typeFactory; _injectableValues = src._injectableValues; _configOverrides = src._configOverrides.copy(); _mixIns = src._mixIns.copy(); RootNameLookup rootNames = new RootNameLookup(); _serializationConfig = new SerializationConfig(src._serializationConfig, _mixIns, rootNames, _configOverrides); _deserializationConfig = new DeserializationConfig(src._deserializationConfig, _mixIns, rootNames, _configOverrides); _serializerProvider = src._serializerProvider.copy(); _deserializationContext = src._deserializationContext.copy(); // Default serializer factory is stateless, can just assign _serializerFactory = src._serializerFactory; // as per [databind#922], [databind#1078] make sure to copy registered modules as appropriate Set reg = src._registeredModuleTypes; if (reg == null) { _registeredModuleTypes = null; } else { _registeredModuleTypes = new LinkedHashSet(reg); } } /** * Constructs instance that uses specified {@link JsonFactory} * for constructing necessary {@link JsonParser}s and/or * {@link JsonGenerator}s, and uses given providers for accessing * serializers and deserializers. * * @param jf JsonFactory to use: if null, a new {@link MappingJsonFactory} will be constructed * @param sp SerializerProvider to use: if null, a {@link SerializerProvider} will be constructed * @param dc Blueprint deserialization context instance to use for creating * actual context objects; if null, will construct standard * {@link DeserializationContext} */ public ObjectMapper(JsonFactory jf, DefaultSerializerProvider sp, DefaultDeserializationContext dc) { /* 02-Mar-2009, tatu: Important: we MUST default to using * the mapping factory, otherwise tree serialization will * have problems with POJONodes. * 03-Jan-2010, tatu: and obviously we also must pass 'this', * to create actual linking. */ if (jf == null) { _jsonFactory = new MappingJsonFactory(this); } else { _jsonFactory = jf; if (jf.getCodec() == null) { // as per [JACKSON-741] _jsonFactory.setCodec(this); } } _subtypeResolver = new StdSubtypeResolver(); RootNameLookup rootNames = new RootNameLookup(); // and default type factory is shared one _typeFactory = TypeFactory.defaultInstance(); SimpleMixInResolver mixins = new SimpleMixInResolver(null); _mixIns = mixins; BaseSettings base = DEFAULT_BASE.withClassIntrospector(defaultClassIntrospector()); _configOverrides = new ConfigOverrides(); _serializationConfig = new SerializationConfig(base, _subtypeResolver, mixins, rootNames, _configOverrides); _deserializationConfig = new DeserializationConfig(base, _subtypeResolver, mixins, rootNames, _configOverrides); // Some overrides we may need final boolean needOrder = _jsonFactory.requiresPropertyOrdering(); if (needOrder ^ _serializationConfig.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)) { configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, needOrder); } _serializerProvider = (sp == null) ? new DefaultSerializerProvider.Impl() : sp; _deserializationContext = (dc == null) ? new DefaultDeserializationContext.Impl(BeanDeserializerFactory.instance) : dc; // Default serializer factory is stateless, can just assign _serializerFactory = BeanSerializerFactory.instance; } /** * Overridable helper method used to construct default {@link ClassIntrospector} * to use. * * @since 2.5 */ protected ClassIntrospector defaultClassIntrospector() { return new BasicClassIntrospector(); } /* /********************************************************** /* Methods sub-classes MUST override /********************************************************** */ /** * Method for creating a new {@link ObjectMapper} instance that * has same initial configuration as this instance. Note that this * also requires making a copy of the underlying {@link JsonFactory} * instance. *

* Method is typically * used when multiple, differently configured mappers are needed. * Although configuration is shared, cached serializers and deserializers * are NOT shared, which means that the new instance may be re-configured * before use; meaning that it behaves the same way as if an instance * was constructed from scratch. * * @since 2.1 */ public ObjectMapper copy() { _checkInvalidCopy(ObjectMapper.class); return new ObjectMapper(this); } /** * @since 2.1 */ protected void _checkInvalidCopy(Class exp) { if (getClass() != exp) { // 10-Nov-2016, tatu: could almost use `ClassUtil.verifyMustOverride()` but not quite throw new IllegalStateException("Failed copy(): "+getClass().getName() +" (version: "+version()+") does not override copy(); it has to"); } } /* /********************************************************** /* Methods sub-classes MUST override if providing custom /* ObjectReader/ObjectWriter implementations /********************************************************** */ /** * Factory method sub-classes must override, to produce {@link ObjectReader} * instances of proper sub-type * * @since 2.5 */ protected ObjectReader _newReader(DeserializationConfig config) { return new ObjectReader(this, config); } /** * Factory method sub-classes must override, to produce {@link ObjectReader} * instances of proper sub-type * * @since 2.5 */ protected ObjectReader _newReader(DeserializationConfig config, JavaType valueType, Object valueToUpdate, FormatSchema schema, InjectableValues injectableValues) { return new ObjectReader(this, config, valueType, valueToUpdate, schema, injectableValues); } /** * Factory method sub-classes must override, to produce {@link ObjectWriter} * instances of proper sub-type * * @since 2.5 */ protected ObjectWriter _newWriter(SerializationConfig config) { return new ObjectWriter(this, config); } /** * Factory method sub-classes must override, to produce {@link ObjectWriter} * instances of proper sub-type * * @since 2.5 */ protected ObjectWriter _newWriter(SerializationConfig config, FormatSchema schema) { return new ObjectWriter(this, config, schema); } /** * Factory method sub-classes must override, to produce {@link ObjectWriter} * instances of proper sub-type * * @since 2.5 */ protected ObjectWriter _newWriter(SerializationConfig config, JavaType rootType, PrettyPrinter pp) { return new ObjectWriter(this, config, rootType, pp); } /* /********************************************************** /* Versioned impl /********************************************************** */ /** * Method that will return version information stored in and read from jar * that contains this class. */ @Override public Version version() { return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION; } /* /********************************************************** /* Module registration, discovery /********************************************************** */ /** * Method for registering a module that can extend functionality * provided by this mapper; for example, by adding providers for * custom serializers and deserializers. * * @param module Module to register */ public ObjectMapper registerModule(Module module) { if (isEnabled(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS)) { Object typeId = module.getTypeId(); if (typeId != null) { if (_registeredModuleTypes == null) { // plus let's keep them in order too, easier to debug or expose // in registration order if that matter _registeredModuleTypes = new LinkedHashSet(); } // try adding; if already had it, should skip if (!_registeredModuleTypes.add(typeId)) { return this; } } } /* Let's ensure we have access to name and version information, * even if we do not have immediate use for either. This way we know * that they will be available from beginning */ String name = module.getModuleName(); if (name == null) { throw new IllegalArgumentException("Module without defined name"); } Version version = module.version(); if (version == null) { throw new IllegalArgumentException("Module without defined version"); } // And then call registration module.setupModule(new Module.SetupContext() { // // // Accessors @Override public Version getMapperVersion() { return version(); } @SuppressWarnings("unchecked") @Override public C getOwner() { // why do we need the cast here?!? return (C) ObjectMapper.this; } @Override public TypeFactory getTypeFactory() { return _typeFactory; } @Override public boolean isEnabled(MapperFeature f) { return ObjectMapper.this.isEnabled(f); } @Override public boolean isEnabled(DeserializationFeature f) { return ObjectMapper.this.isEnabled(f); } @Override public boolean isEnabled(SerializationFeature f) { return ObjectMapper.this.isEnabled(f); } @Override public boolean isEnabled(JsonFactory.Feature f) { return ObjectMapper.this.isEnabled(f); } @Override public boolean isEnabled(JsonParser.Feature f) { return ObjectMapper.this.isEnabled(f); } @Override public boolean isEnabled(JsonGenerator.Feature f) { return ObjectMapper.this.isEnabled(f); } // // // Mutant accessors @Override public MutableConfigOverride configOverride(Class type) { return ObjectMapper.this.configOverride(type); } // // // Methods for registering handlers: deserializers @Override public void addDeserializers(Deserializers d) { DeserializerFactory df = _deserializationContext._factory.withAdditionalDeserializers(d); _deserializationContext = _deserializationContext.with(df); } @Override public void addKeyDeserializers(KeyDeserializers d) { DeserializerFactory df = _deserializationContext._factory.withAdditionalKeyDeserializers(d); _deserializationContext = _deserializationContext.with(df); } @Override public void addBeanDeserializerModifier(BeanDeserializerModifier modifier) { DeserializerFactory df = _deserializationContext._factory.withDeserializerModifier(modifier); _deserializationContext = _deserializationContext.with(df); } // // // Methods for registering handlers: serializers @Override public void addSerializers(Serializers s) { _serializerFactory = _serializerFactory.withAdditionalSerializers(s); } @Override public void addKeySerializers(Serializers s) { _serializerFactory = _serializerFactory.withAdditionalKeySerializers(s); } @Override public void addBeanSerializerModifier(BeanSerializerModifier modifier) { _serializerFactory = _serializerFactory.withSerializerModifier(modifier); } // // // Methods for registering handlers: other @Override public void addAbstractTypeResolver(AbstractTypeResolver resolver) { DeserializerFactory df = _deserializationContext._factory.withAbstractTypeResolver(resolver); _deserializationContext = _deserializationContext.with(df); } @Override public void addTypeModifier(TypeModifier modifier) { TypeFactory f = _typeFactory; f = f.withModifier(modifier); setTypeFactory(f); } @Override public void addValueInstantiators(ValueInstantiators instantiators) { DeserializerFactory df = _deserializationContext._factory.withValueInstantiators(instantiators); _deserializationContext = _deserializationContext.with(df); } @Override public void setClassIntrospector(ClassIntrospector ci) { _deserializationConfig = _deserializationConfig.with(ci); _serializationConfig = _serializationConfig.with(ci); } @Override public void insertAnnotationIntrospector(AnnotationIntrospector ai) { _deserializationConfig = _deserializationConfig.withInsertedAnnotationIntrospector(ai); _serializationConfig = _serializationConfig.withInsertedAnnotationIntrospector(ai); } @Override public void appendAnnotationIntrospector(AnnotationIntrospector ai) { _deserializationConfig = _deserializationConfig.withAppendedAnnotationIntrospector(ai); _serializationConfig = _serializationConfig.withAppendedAnnotationIntrospector(ai); } @Override public void registerSubtypes(Class... subtypes) { ObjectMapper.this.registerSubtypes(subtypes); } @Override public void registerSubtypes(NamedType... subtypes) { ObjectMapper.this.registerSubtypes(subtypes); } @Override public void registerSubtypes(Collection> subtypes) { ObjectMapper.this.registerSubtypes(subtypes); } @Override public void setMixInAnnotations(Class target, Class mixinSource) { addMixIn(target, mixinSource); } @Override public void addDeserializationProblemHandler(DeserializationProblemHandler handler) { addHandler(handler); } @Override public void setNamingStrategy(PropertyNamingStrategy naming) { setPropertyNamingStrategy(naming); } }); return this; } /** * Convenience method for registering specified modules in order; * functionally equivalent to: *
     *   for (Module module : modules) {
     *      registerModule(module);
     *   }
     *
* * @since 2.2 */ public ObjectMapper registerModules(Module... modules) { for (Module module : modules) { registerModule(module); } return this; } /** * Convenience method for registering specified modules in order; * functionally equivalent to: *
     *   for (Module module : modules) {
     *      registerModule(module);
     *   }
     *
* * @since 2.2 */ public ObjectMapper registerModules(Iterable modules) { for (Module module : modules) { registerModule(module); } return this; } /** * Method for locating available methods, using JDK {@link ServiceLoader} * facility, along with module-provided SPI. *

* Note that method does not do any caching, so calls should be considered * potentially expensive. * * @since 2.2 */ public static List findModules() { return findModules(null); } /** * Method for locating available methods, using JDK {@link ServiceLoader} * facility, along with module-provided SPI. *

* Note that method does not do any caching, so calls should be considered * potentially expensive. * * @since 2.2 */ public static List findModules(ClassLoader classLoader) { ArrayList modules = new ArrayList(); ServiceLoader loader = secureGetServiceLoader(Module.class, classLoader); for (Module module : loader) { modules.add(module); } return modules; } private static ServiceLoader secureGetServiceLoader(final Class clazz, final ClassLoader classLoader) { final SecurityManager sm = System.getSecurityManager(); if (sm == null) { return (classLoader == null) ? ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader); } return AccessController.doPrivileged(new PrivilegedAction>() { @Override public ServiceLoader run() { return (classLoader == null) ? ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader); } }); } /** * Convenience method that is functionally equivalent to: * * mapper.registerModules(mapper.findModules()); * *

* As with {@link #findModules()}, no caching is done for modules, so care * needs to be taken to either create and share a single mapper instance; * or to cache introspected set of modules. * * @since 2.2 */ public ObjectMapper findAndRegisterModules() { return registerModules(findModules()); } /* /********************************************************** /* Configuration: main config object access /********************************************************** */ /** * Method that returns the shared default {@link SerializationConfig} * object that defines configuration settings for serialization. *

* Note that since instances are immutable, you can NOT change settings * by accessing an instance and calling methods: this will simply create * new instance of config object. */ public SerializationConfig getSerializationConfig() { return _serializationConfig; } /** * Method that returns * the shared default {@link DeserializationConfig} object * that defines configuration settings for deserialization. *

* Note that since instances are immutable, you can NOT change settings * by accessing an instance and calling methods: this will simply create * new instance of config object. */ public DeserializationConfig getDeserializationConfig() { return _deserializationConfig; } /** * Method for getting current {@link DeserializationContext}. *

* Note that since instances are immutable, you can NOT change settings * by accessing an instance and calling methods: this will simply create * new instance of context object. */ public DeserializationContext getDeserializationContext() { return _deserializationContext; } /* /********************************************************** /* Configuration: ser/deser factory, provider access /********************************************************** */ /** * Method for setting specific {@link SerializerFactory} to use * for constructing (bean) serializers. */ public ObjectMapper setSerializerFactory(SerializerFactory f) { _serializerFactory = f; return this; } /** * Method for getting current {@link SerializerFactory}. *

* Note that since instances are immutable, you can NOT change settings * by accessing an instance and calling methods: this will simply create * new instance of factory object. */ public SerializerFactory getSerializerFactory() { return _serializerFactory; } /** * Method for setting "blueprint" {@link SerializerProvider} instance * to use as the base for actual provider instances to use for handling * caching of {@link JsonSerializer} instances. */ public ObjectMapper setSerializerProvider(DefaultSerializerProvider p) { _serializerProvider = p; return this; } /** * Accessor for the "blueprint" (or, factory) instance, from which instances * are created by calling {@link DefaultSerializerProvider#createInstance}. * Note that returned instance cannot be directly used as it is not properly * configured: to get a properly configured instance to call, use * {@link #getSerializerProviderInstance()} instead. */ public SerializerProvider getSerializerProvider() { return _serializerProvider; } /** * Accessor for constructing and returning a {@link SerializerProvider} * instance that may be used for accessing serializers. This is same as * calling {@link #getSerializerProvider}, and calling createInstance * on it. * * @since 2.7 */ public SerializerProvider getSerializerProviderInstance() { return _serializerProvider(_serializationConfig); } /* /********************************************************** /* Configuration: mix-in annotations /********************************************************** */ /** * Method to use for defining mix-in annotations to use for augmenting * annotations that processable (serializable / deserializable) * classes have. * Mixing in is done when introspecting class annotations and properties. * Map passed contains keys that are target classes (ones to augment * with new annotation overrides), and values that are source classes * (have annotations to use for augmentation). * Annotations from source classes (and their supertypes) * will override * annotations that target classes (and their super-types) have. *

* Note that this method will CLEAR any previously defined mix-ins * for this mapper. * * @since 2.5 */ public ObjectMapper setMixIns(Map, Class> sourceMixins) { // NOTE: does NOT change possible externally configured resolver, just local defs _mixIns.setLocalDefinitions(sourceMixins); return this; } /** * Method to use for adding mix-in annotations to use for augmenting * specified class or interface. All annotations from * mixinSource are taken to override annotations * that target (or its supertypes) has. * * @param target Class (or interface) whose annotations to effectively override * @param mixinSource Class (or interface) whose annotations are to * be "added" to target's annotations, overriding as necessary * * @since 2.5 */ public ObjectMapper addMixIn(Class target, Class mixinSource) { _mixIns.addLocalDefinition(target, mixinSource); return this; } /** * Method that can be called to specify given resolver for locating * mix-in classes to use, overriding directly added mappings. * Note that direct mappings are not cleared, but they are only applied * if resolver does not provide mix-in matches. * * @since 2.6 */ public ObjectMapper setMixInResolver(ClassIntrospector.MixInResolver resolver) { SimpleMixInResolver r = _mixIns.withOverrides(resolver); if (r != _mixIns) { _mixIns = r; _deserializationConfig = new DeserializationConfig(_deserializationConfig, r); _serializationConfig = new SerializationConfig(_serializationConfig, r); } return this; } public Class findMixInClassFor(Class cls) { return _mixIns.findMixInClassFor(cls); } // For testing only: public int mixInCount() { return _mixIns.localSize(); } /** * @deprecated Since 2.5: replaced by a fluent form of the method; {@link #setMixIns}. */ @Deprecated public void setMixInAnnotations(Map, Class> sourceMixins) { setMixIns(sourceMixins); } /** * @deprecated Since 2.5: replaced by a fluent form of the method; {@link #addMixIn(Class, Class)}. */ @Deprecated public final void addMixInAnnotations(Class target, Class mixinSource) { addMixIn(target, mixinSource); } /* /********************************************************** /* Configuration, introspection /********************************************************** */ /** * Method for accessing currently configured visibility checker; * object used for determining whether given property element * (method, field, constructor) can be auto-detected or not. */ public VisibilityChecker getVisibilityChecker() { return _serializationConfig.getDefaultVisibilityChecker(); } /** * Method for setting currently configured default {@link VisibilityChecker}, * object used for determining whether given property element * (method, field, constructor) can be auto-detected or not. * This default checker is used as the base visibility: * per-class overrides (both via annotations and per-type config overrides) * can further change these settings. * * @since 2.6 */ public ObjectMapper setVisibility(VisibilityChecker vc) { _configOverrides.setDefaultVisibility(vc); return this; } /** * Convenience method that allows changing configuration for * underlying {@link VisibilityChecker}s, to change details of what kinds of * properties are auto-detected. * Basically short cut for doing: *

     *  mapper.setVisibilityChecker(
     *     mapper.getVisibilityChecker().withVisibility(forMethod, visibility)
     *  );
     *
* one common use case would be to do: *
     *  mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
     *
* which would make all member fields serializable without further annotations, * instead of just public fields (default setting). * * @param forMethod Type of property descriptor affected (field, getter/isGetter, * setter, creator) * @param visibility Minimum visibility to require for the property descriptors of type * * @return Modified mapper instance (that is, "this"), to allow chaining * of configuration calls */ public ObjectMapper setVisibility(PropertyAccessor forMethod, JsonAutoDetect.Visibility visibility) { VisibilityChecker vc = _configOverrides.getDefaultVisibility(); vc = vc.withVisibility(forMethod, visibility); _configOverrides.setDefaultVisibility(vc); return this; } /** * Method for accessing subtype resolver in use. */ public SubtypeResolver getSubtypeResolver() { return _subtypeResolver; } /** * Method for setting custom subtype resolver to use. */ public ObjectMapper setSubtypeResolver(SubtypeResolver str) { _subtypeResolver = str; _deserializationConfig = _deserializationConfig.with(str); _serializationConfig = _serializationConfig.with(str); return this; } /** * Method for setting {@link AnnotationIntrospector} used by this * mapper instance for both serialization and deserialization. * Note that doing this will replace the current introspector, which * may lead to unavailability of core Jackson annotations. * If you want to combine handling of multiple introspectors, * have a look at {@link com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair}. * * @see com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair */ public ObjectMapper setAnnotationIntrospector(AnnotationIntrospector ai) { _serializationConfig = _serializationConfig.with(ai); _deserializationConfig = _deserializationConfig.with(ai); return this; } /** * Method for changing {@link AnnotationIntrospector} instances used * by this mapper instance for serialization and deserialization, * specifying them separately so that different introspection can be * used for different aspects * * @since 2.1 * * @param serializerAI {@link AnnotationIntrospector} to use for configuring * serialization * @param deserializerAI {@link AnnotationIntrospector} to use for configuring * deserialization * * @see com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair */ public ObjectMapper setAnnotationIntrospectors(AnnotationIntrospector serializerAI, AnnotationIntrospector deserializerAI) { _serializationConfig = _serializationConfig.with(serializerAI); _deserializationConfig = _deserializationConfig.with(deserializerAI); return this; } /** * Method for setting custom property naming strategy to use. */ public ObjectMapper setPropertyNamingStrategy(PropertyNamingStrategy s) { _serializationConfig = _serializationConfig.with(s); _deserializationConfig = _deserializationConfig.with(s); return this; } /** * @since 2.5 */ public PropertyNamingStrategy getPropertyNamingStrategy() { // arbitrary choice but let's do: return _serializationConfig.getPropertyNamingStrategy(); } /** * Method for specifying {@link PrettyPrinter} to use when "default pretty-printing" * is enabled (by enabling {@link SerializationFeature#INDENT_OUTPUT}) * * @param pp Pretty printer to use by default. * * @return This mapper, useful for call-chaining * * @since 2.6 */ public ObjectMapper setDefaultPrettyPrinter(PrettyPrinter pp) { _serializationConfig = _serializationConfig.withDefaultPrettyPrinter(pp); return this; } /** * @deprecated Since 2.6 use {@link #setVisibility(VisibilityChecker)} instead. */ @Deprecated public void setVisibilityChecker(VisibilityChecker vc) { setVisibility(vc); } /* /********************************************************** /* Configuration: global-default/per-type override settings /********************************************************** */ /** * Convenience method, equivalent to calling: *
     *  setPropertyInclusion(JsonInclude.Value.construct(incl, incl));
     *
*

* NOTE: behavior differs slightly from 2.8, where second argument was * implied to be JsonInclude.Include.ALWAYS. */ public ObjectMapper setSerializationInclusion(JsonInclude.Include incl) { setPropertyInclusion(JsonInclude.Value.construct(incl, incl)); return this; } /** * @since 2.7 * @deprecated Since 2.9 use {@link #setDefaultPropertyInclusion} */ @Deprecated public ObjectMapper setPropertyInclusion(JsonInclude.Value incl) { return setDefaultPropertyInclusion(incl); } /** * Method for setting default POJO property inclusion strategy for serialization, * applied for all properties for which there are no per-type or per-property * overrides (via annotations or config overrides). * * @since 2.9 (basically rename of setPropertyInclusion) */ public ObjectMapper setDefaultPropertyInclusion(JsonInclude.Value incl) { _configOverrides.setDefaultInclusion(incl); return this; } /** * Short-cut for: *

     *  setDefaultPropertyInclusion(JsonInclude.Value.construct(incl, incl));
     *
* * @since 2.9 (basically rename of setPropertyInclusion) */ public ObjectMapper setDefaultPropertyInclusion(JsonInclude.Include incl) { _configOverrides.setDefaultInclusion(JsonInclude.Value.construct(incl, incl)); return this; } /** * Method for setting default Setter configuration, regarding things like * merging, null-handling; used for properties for which there are * no per-type or per-property overrides (via annotations or config overrides). * * @since 2.9 */ public ObjectMapper setDefaultSetterInfo(JsonSetter.Value v) { _configOverrides.setDefaultSetterInfo(v); return this; } /** * Method for setting auto-detection visibility definition * defaults, which are in effect unless overridden by * annotations (like JsonAutoDetect) or per-type * visibility overrides. * * @since 2.9 */ public ObjectMapper setDefaultVisibility(JsonAutoDetect.Value vis) { _configOverrides.setDefaultVisibility(VisibilityChecker.Std.construct(vis)); return this; } /** * Method for setting default Setter configuration, regarding things like * merging, null-handling; used for properties for which there are * no per-type or per-property overrides (via annotations or config overrides). * * @since 2.9 */ public ObjectMapper setDefaultMergeable(Boolean b) { _configOverrides.setDefaultMergeable(b); return this; } /* /********************************************************** /* Type information configuration /********************************************************** */ /** * Convenience method that is equivalent to calling *
     *  enableDefaultTyping(DefaultTyping.OBJECT_AND_NON_CONCRETE);
     *
*

* NOTE: use of Default Typing can be a potential security risk if incoming * content comes from untrusted sources, and it is recommended that this * is either not done, or, if enabled, use {@link #setDefaultTyping} * passing a custom {@link TypeResolverBuilder} implementation that white-lists * legal types to use. */ public ObjectMapper enableDefaultTyping() { return enableDefaultTyping(DefaultTyping.OBJECT_AND_NON_CONCRETE); } /** * Convenience method that is equivalent to calling *

     *  enableDefaultTyping(dti, JsonTypeInfo.As.WRAPPER_ARRAY);
     *
*

* NOTE: use of Default Typing can be a potential security risk if incoming * content comes from untrusted sources, and it is recommended that this * is either not done, or, if enabled, use {@link #setDefaultTyping} * passing a custom {@link TypeResolverBuilder} implementation that white-lists * legal types to use. */ public ObjectMapper enableDefaultTyping(DefaultTyping dti) { return enableDefaultTyping(dti, JsonTypeInfo.As.WRAPPER_ARRAY); } /** * Method for enabling automatic inclusion of type information, needed * for proper deserialization of polymorphic types (unless types * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}). *

* NOTE: use of JsonTypeInfo.As#EXTERNAL_PROPERTY NOT SUPPORTED; * and attempts of do so will throw an {@link IllegalArgumentException} to make * this limitation explicit. *

* NOTE: use of Default Typing can be a potential security risk if incoming * content comes from untrusted sources, and it is recommended that this * is either not done, or, if enabled, use {@link #setDefaultTyping} * passing a custom {@link TypeResolverBuilder} implementation that white-lists * legal types to use. * * @param applicability Defines kinds of types for which additional type information * is added; see {@link DefaultTyping} for more information. */ public ObjectMapper enableDefaultTyping(DefaultTyping applicability, JsonTypeInfo.As includeAs) { /* 18-Sep-2014, tatu: Let's add explicit check to ensure no one tries to * use "As.EXTERNAL_PROPERTY", since that will not work (with 2.5+) */ if (includeAs == JsonTypeInfo.As.EXTERNAL_PROPERTY) { throw new IllegalArgumentException("Cannot use includeAs of "+includeAs); } TypeResolverBuilder typer = new DefaultTypeResolverBuilder(applicability); // we'll always use full class name, when using defaulting typer = typer.init(JsonTypeInfo.Id.CLASS, null); typer = typer.inclusion(includeAs); return setDefaultTyping(typer); } /** * Method for enabling automatic inclusion of type information -- needed * for proper deserialization of polymorphic types (unless types * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) -- * using "As.PROPERTY" inclusion mechanism and specified property name * to use for inclusion (default being "@class" since default type information * always uses class name as type identifier) *

* NOTE: use of Default Typing can be a potential security risk if incoming * content comes from untrusted sources, and it is recommended that this * is either not done, or, if enabled, use {@link #setDefaultTyping} * passing a custom {@link TypeResolverBuilder} implementation that white-lists * legal types to use. */ public ObjectMapper enableDefaultTypingAsProperty(DefaultTyping applicability, String propertyName) { TypeResolverBuilder typer = new DefaultTypeResolverBuilder(applicability); // we'll always use full class name, when using defaulting typer = typer.init(JsonTypeInfo.Id.CLASS, null); typer = typer.inclusion(JsonTypeInfo.As.PROPERTY); typer = typer.typeProperty(propertyName); return setDefaultTyping(typer); } /** * Method for disabling automatic inclusion of type information; if so, only * explicitly annotated types (ones with * {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) will have * additional embedded type information. */ public ObjectMapper disableDefaultTyping() { return setDefaultTyping(null); } /** * Method for enabling automatic inclusion of type information, using * specified handler object for determining which types this affects, * as well as details of how information is embedded. *

* NOTE: use of Default Typing can be a potential security risk if incoming * content comes from untrusted sources, so care should be taken to use * a {@link TypeResolverBuilder} that can limit allowed classes to * deserialize. * * @param typer Type information inclusion handler */ public ObjectMapper setDefaultTyping(TypeResolverBuilder typer) { _deserializationConfig = _deserializationConfig.with(typer); _serializationConfig = _serializationConfig.with(typer); return this; } /** * Method for registering specified class as a subtype, so that * typename-based resolution can link supertypes to subtypes * (as an alternative to using annotations). * Type for given class is determined from appropriate annotation; * or if missing, default name (unqualified class name) */ public void registerSubtypes(Class... classes) { getSubtypeResolver().registerSubtypes(classes); } /** * Method for registering specified class as a subtype, so that * typename-based resolution can link supertypes to subtypes * (as an alternative to using annotations). * Name may be provided as part of argument, but if not will * be based on annotations or use default name (unqualified * class name). */ public void registerSubtypes(NamedType... types) { getSubtypeResolver().registerSubtypes(types); } /** * @since 2.9 */ public void registerSubtypes(Collection> subtypes) { getSubtypeResolver().registerSubtypes(subtypes); } /* /********************************************************** /* Configuration, basic type handling /********************************************************** */ /** * Accessor for getting a mutable configuration override object for * given type, needed to add or change per-type overrides applied * to properties of given type. * Usage is through returned object by colling "setter" methods, which * directly modify override object and take effect directly. * For example you can do *

     *   mapper.configOverride(java.util.Date.class)
     *       .setFormat(JsonFormat.Value.forPattern("yyyy-MM-dd"));
     *
     * to change the default format to use for properties of type
     * {@link java.util.Date} (possibly further overridden by per-property
     * annotations)
     *
     * @since 2.8
     */
    public MutableConfigOverride configOverride(Class type) {
        return _configOverrides.findOrCreateOverride(type);
    }

    /*
    /**********************************************************
    /* Configuration, basic type handling
    /**********************************************************
     */

    /**
     * Accessor for getting currently configured {@link TypeFactory} instance.
     */
    public TypeFactory getTypeFactory() {
        return _typeFactory;
    }

    /**
     * Method that can be used to override {@link TypeFactory} instance
     * used by this mapper.
     *

* Note: will also set {@link TypeFactory} that deserialization and * serialization config objects use. */ public ObjectMapper setTypeFactory(TypeFactory f) { _typeFactory = f; _deserializationConfig = _deserializationConfig.with(f); _serializationConfig = _serializationConfig.with(f); return this; } /** * Convenience method for constructing {@link JavaType} out of given * type (typically java.lang.Class), but without explicit * context. */ public JavaType constructType(Type t) { return _typeFactory.constructType(t); } /* /********************************************************** /* Configuration, deserialization /********************************************************** */ /** * Method that can be used to get hold of {@link JsonNodeFactory} * that this mapper will use when directly constructing * root {@link JsonNode} instances for Trees. *

* Note: this is just a shortcut for calling *

     *   getDeserializationConfig().getNodeFactory()
     *
*/ public JsonNodeFactory getNodeFactory() { return _deserializationConfig.getNodeFactory(); } /** * Method for specifying {@link JsonNodeFactory} to use for * constructing root level tree nodes (via method * {@link #createObjectNode} */ public ObjectMapper setNodeFactory(JsonNodeFactory f) { _deserializationConfig = _deserializationConfig.with(f); return this; } /** * Method for adding specified {@link DeserializationProblemHandler} * to be used for handling specific problems during deserialization. */ public ObjectMapper addHandler(DeserializationProblemHandler h) { _deserializationConfig = _deserializationConfig.withHandler(h); return this; } /** * Method for removing all registered {@link DeserializationProblemHandler}s * instances from this mapper. */ public ObjectMapper clearProblemHandlers() { _deserializationConfig = _deserializationConfig.withNoProblemHandlers(); return this; } /** * Method that allows overriding of the underlying {@link DeserializationConfig} * object. * It is added as a fallback method that may be used if no other configuration * modifier method works: it should not be used if there are alternatives, * and its use is generally discouraged. *

* NOTE: only use this method if you know what you are doing -- it allows * by-passing some of checks applied to other configuration methods. * Also keep in mind that as with all configuration of {@link ObjectMapper}, * this is only thread-safe if done before calling any deserialization methods. * * @since 2.4 */ public ObjectMapper setConfig(DeserializationConfig config) { _deserializationConfig = config; return this; } /* /********************************************************** /* Configuration, serialization /********************************************************** */ /** * @deprecated Since 2.6, use {@link #setFilterProvider} instead (allows chaining) */ @Deprecated public void setFilters(FilterProvider filterProvider) { _serializationConfig = _serializationConfig.withFilters(filterProvider); } /** * Method for configuring this mapper to use specified {@link FilterProvider} for * mapping Filter Ids to actual filter instances. *

* Note that usually it is better to use method {@link #writer(FilterProvider)}; * however, sometimes * this method is more convenient. For example, some frameworks only allow configuring * of ObjectMapper instances and not {@link ObjectWriter}s. * * @since 2.6 */ public ObjectMapper setFilterProvider(FilterProvider filterProvider) { _serializationConfig = _serializationConfig.withFilters(filterProvider); return this; } /** * Method that will configure default {@link Base64Variant} that * byte[] serializers and deserializers will use. * * @param v Base64 variant to use * * @return This mapper, for convenience to allow chaining * * @since 2.1 */ public ObjectMapper setBase64Variant(Base64Variant v) { _serializationConfig = _serializationConfig.with(v); _deserializationConfig = _deserializationConfig.with(v); return this; } /** * Method that allows overriding of the underlying {@link SerializationConfig} * object, which contains serialization-specific configuration settings. * It is added as a fallback method that may be used if no other configuration * modifier method works: it should not be used if there are alternatives, * and its use is generally discouraged. *

* NOTE: only use this method if you know what you are doing -- it allows * by-passing some of checks applied to other configuration methods. * Also keep in mind that as with all configuration of {@link ObjectMapper}, * this is only thread-safe if done before calling any serialization methods. * * @since 2.4 */ public ObjectMapper setConfig(SerializationConfig config) { _serializationConfig = config; return this; } /* /********************************************************** /* Configuration, other /********************************************************** */ /** * Method that can be used to get hold of {@link JsonFactory} that this * mapper uses if it needs to construct {@link JsonParser}s * and/or {@link JsonGenerator}s. *

* WARNING: note that all {@link ObjectReader} and {@link ObjectWriter} * instances created by this mapper usually share the same configured * {@link JsonFactory}, so changes to its configuration will "leak". * To avoid such observed changes you should always use "with()" and * "without()" method of {@link ObjectReader} and {@link ObjectWriter} * for changing {@link com.fasterxml.jackson.core.JsonParser.Feature} * and {@link com.fasterxml.jackson.core.JsonGenerator.Feature} * settings to use on per-call basis. * * @return {@link JsonFactory} that this mapper uses when it needs to * construct Json parser and generators */ @Override public JsonFactory getFactory() { return _jsonFactory; } /** * @deprecated Since 2.1: Use {@link #getFactory} instead */ @Deprecated @Override public JsonFactory getJsonFactory() { return getFactory(); } /** * Method for configuring the default {@link DateFormat} to use when serializing time * values as Strings, and deserializing from JSON Strings. * This is preferably to directly modifying {@link SerializationConfig} and * {@link DeserializationConfig} instances. * If you need per-request configuration, use {@link #writer(DateFormat)} to * create properly configured {@link ObjectWriter} and use that; this because * {@link ObjectWriter}s are thread-safe whereas ObjectMapper itself is only * thread-safe when configuring methods (such as this one) are NOT called. */ public ObjectMapper setDateFormat(DateFormat dateFormat) { _deserializationConfig = _deserializationConfig.with(dateFormat); _serializationConfig = _serializationConfig.with(dateFormat); return this; } /** * @since 2.5 */ public DateFormat getDateFormat() { // arbitrary choice but let's do: return _serializationConfig.getDateFormat(); } /** * Method for configuring {@link HandlerInstantiator} to use for creating * instances of handlers (such as serializers, deserializers, type and type * id resolvers), given a class. * * @param hi Instantiator to use; if null, use the default implementation */ public Object setHandlerInstantiator(HandlerInstantiator hi) { _deserializationConfig = _deserializationConfig.with(hi); _serializationConfig = _serializationConfig.with(hi); return this; } /** * Method for configuring {@link InjectableValues} which used to find * values to inject. */ public ObjectMapper setInjectableValues(InjectableValues injectableValues) { _injectableValues = injectableValues; return this; } /** * @since 2.6 */ public InjectableValues getInjectableValues() { return _injectableValues; } /** * Method for overriding default locale to use for formatting. * Default value used is {@link Locale#getDefault()}. */ public ObjectMapper setLocale(Locale l) { _deserializationConfig = _deserializationConfig.with(l); _serializationConfig = _serializationConfig.with(l); return this; } /** * Method for overriding default TimeZone to use for formatting. * Default value used is UTC (NOT default TimeZone of JVM). */ public ObjectMapper setTimeZone(TimeZone tz) { _deserializationConfig = _deserializationConfig.with(tz); _serializationConfig = _serializationConfig.with(tz); return this; } /* /********************************************************** /* Configuration, simple features: MapperFeature /********************************************************** */ /** * Method for checking whether given {@link MapperFeature} is enabled. */ public boolean isEnabled(MapperFeature f) { // ok to use either one, should be kept in sync return _serializationConfig.isEnabled(f); } /** * Method for changing state of an on/off mapper feature for * this mapper instance. */ public ObjectMapper configure(MapperFeature f, boolean state) { _serializationConfig = state ? _serializationConfig.with(f) : _serializationConfig.without(f); _deserializationConfig = state ? _deserializationConfig.with(f) : _deserializationConfig.without(f); return this; } /** * Method for enabling specified {@link MapperConfig} features. * Modifies and returns this instance; no new object is created. */ public ObjectMapper enable(MapperFeature... f) { _deserializationConfig = _deserializationConfig.with(f); _serializationConfig = _serializationConfig.with(f); return this; } /** * Method for enabling specified {@link DeserializationConfig} features. * Modifies and returns this instance; no new object is created. */ public ObjectMapper disable(MapperFeature... f) { _deserializationConfig = _deserializationConfig.without(f); _serializationConfig = _serializationConfig.without(f); return this; } /* /********************************************************** /* Configuration, simple features: SerializationFeature /********************************************************** */ /** * Method for checking whether given serialization-specific * feature is enabled. */ public boolean isEnabled(SerializationFeature f) { return _serializationConfig.isEnabled(f); } /** * Method for changing state of an on/off serialization feature for * this object mapper. */ public ObjectMapper configure(SerializationFeature f, boolean state) { _serializationConfig = state ? _serializationConfig.with(f) : _serializationConfig.without(f); return this; } /** * Method for enabling specified {@link DeserializationConfig} feature. * Modifies and returns this instance; no new object is created. */ public ObjectMapper enable(SerializationFeature f) { _serializationConfig = _serializationConfig.with(f); return this; } /** * Method for enabling specified {@link DeserializationConfig} features. * Modifies and returns this instance; no new object is created. */ public ObjectMapper enable(SerializationFeature first, SerializationFeature... f) { _serializationConfig = _serializationConfig.with(first, f); return this; } /** * Method for enabling specified {@link DeserializationConfig} features. * Modifies and returns this instance; no new object is created. */ public ObjectMapper disable(SerializationFeature f) { _serializationConfig = _serializationConfig.without(f); return this; } /** * Method for enabling specified {@link DeserializationConfig} features. * Modifies and returns this instance; no new object is created. */ public ObjectMapper disable(SerializationFeature first, SerializationFeature... f) { _serializationConfig = _serializationConfig.without(first, f); return this; } /* /********************************************************** /* Configuration, simple features: DeserializationFeature /********************************************************** */ /** * Method for checking whether given deserialization-specific * feature is enabled. */ public boolean isEnabled(DeserializationFeature f) { return _deserializationConfig.isEnabled(f); } /** * Method for changing state of an on/off deserialization feature for * this object mapper. */ public ObjectMapper configure(DeserializationFeature f, boolean state) { _deserializationConfig = state ? _deserializationConfig.with(f) : _deserializationConfig.without(f); return this; } /** * Method for enabling specified {@link DeserializationConfig} features. * Modifies and returns this instance; no new object is created. */ public ObjectMapper enable(DeserializationFeature feature) { _deserializationConfig = _deserializationConfig.with(feature); return this; } /** * Method for enabling specified {@link DeserializationConfig} features. * Modifies and returns this instance; no new object is created. */ public ObjectMapper enable(DeserializationFeature first, DeserializationFeature... f) { _deserializationConfig = _deserializationConfig.with(first, f); return this; } /** * Method for enabling specified {@link DeserializationConfig} features. * Modifies and returns this instance; no new object is created. */ public ObjectMapper disable(DeserializationFeature feature) { _deserializationConfig = _deserializationConfig.without(feature); return this; } /** * Method for enabling specified {@link DeserializationConfig} features. * Modifies and returns this instance; no new object is created. */ public ObjectMapper disable(DeserializationFeature first, DeserializationFeature... f) { _deserializationConfig = _deserializationConfig.without(first, f); return this; } /* /********************************************************** /* Configuration, simple features: JsonParser.Feature /********************************************************** */ public boolean isEnabled(JsonParser.Feature f) { return _deserializationConfig.isEnabled(f, _jsonFactory); } /** * Method for changing state of specified {@link com.fasterxml.jackson.core.JsonParser.Feature}s * for parser instances this object mapper creates. *

* Note that this is equivalent to directly calling same method * on {@link #getFactory}. *

* WARNING: since this method directly modifies state of underlying {@link JsonFactory}, * it will change observed configuration by {@link ObjectReader}s as well -- to avoid * this, use {@link ObjectReader#with(JsonParser.Feature)} instead. */ public ObjectMapper configure(JsonParser.Feature f, boolean state) { _jsonFactory.configure(f, state); return this; } /** * Method for enabling specified {@link com.fasterxml.jackson.core.JsonParser.Feature}s * for parser instances this object mapper creates. *

* Note that this is equivalent to directly calling same method on {@link #getFactory}. *

* WARNING: since this method directly modifies state of underlying {@link JsonFactory}, * it will change observed configuration by {@link ObjectReader}s as well -- to avoid * this, use {@link ObjectReader#with(JsonParser.Feature)} instead. * * @since 2.5 */ public ObjectMapper enable(JsonParser.Feature... features) { for (JsonParser.Feature f : features) { _jsonFactory.enable(f); } return this; } /** * Method for disabling specified {@link com.fasterxml.jackson.core.JsonParser.Feature}s * for parser instances this object mapper creates. *

* Note that this is equivalent to directly calling same method on {@link #getFactory}. *

* WARNING: since this method directly modifies state of underlying {@link JsonFactory}, * it will change observed configuration by {@link ObjectReader}s as well -- to avoid * this, use {@link ObjectReader#without(JsonParser.Feature)} instead. * * @since 2.5 */ public ObjectMapper disable(JsonParser.Feature... features) { for (JsonParser.Feature f : features) { _jsonFactory.disable(f); } return this; } /* /********************************************************** /* Configuration, simple features: JsonGenerator.Feature /********************************************************** */ public boolean isEnabled(JsonGenerator.Feature f) { return _serializationConfig.isEnabled(f, _jsonFactory); } /** * Method for changing state of an on/off {@link JsonGenerator} feature for * generator instances this object mapper creates. *

* Note that this is equivalent to directly calling same method * on {@link #getFactory}. *

* WARNING: since this method directly modifies state of underlying {@link JsonFactory}, * it will change observed configuration by {@link ObjectWriter}s as well -- to avoid * this, use {@link ObjectWriter#with(JsonGenerator.Feature)} instead. */ public ObjectMapper configure(JsonGenerator.Feature f, boolean state) { _jsonFactory.configure(f, state); return this; } /** * Method for enabling specified {@link com.fasterxml.jackson.core.JsonGenerator.Feature}s * for parser instances this object mapper creates. *

* Note that this is equivalent to directly calling same method on {@link #getFactory}. *

* WARNING: since this method directly modifies state of underlying {@link JsonFactory}, * it will change observed configuration by {@link ObjectWriter}s as well -- to avoid * this, use {@link ObjectWriter#with(JsonGenerator.Feature)} instead. * * @since 2.5 */ public ObjectMapper enable(JsonGenerator.Feature... features) { for (JsonGenerator.Feature f : features) { _jsonFactory.enable(f); } return this; } /** * Method for disabling specified {@link com.fasterxml.jackson.core.JsonGenerator.Feature}s * for parser instances this object mapper creates. *

* Note that this is equivalent to directly calling same method on {@link #getFactory}. *

* WARNING: since this method directly modifies state of underlying {@link JsonFactory}, * it will change observed configuration by {@link ObjectWriter}s as well -- to avoid * this, use {@link ObjectWriter#without(JsonGenerator.Feature)} instead. * * @since 2.5 */ public ObjectMapper disable(JsonGenerator.Feature... features) { for (JsonGenerator.Feature f : features) { _jsonFactory.disable(f); } return this; } /* /********************************************************** /* Configuration, simple features: JsonFactory.Feature /********************************************************** */ /** * Convenience method, equivalent to: *

     *  getJsonFactory().isEnabled(f);
     *
*/ public boolean isEnabled(JsonFactory.Feature f) { return _jsonFactory.isEnabled(f); } /* /********************************************************** /* Public API (from ObjectCodec): deserialization /* (mapping from JSON to Java types); /* main methods /********************************************************** */ /** * Method to deserialize JSON content into a non-container * type (it can be an array type, however): typically a bean, array * or a wrapper type (like {@link java.lang.Boolean}). *

* Note: this method should NOT be used if the result type is a * container ({@link java.util.Collection} or {@link java.util.Map}. * The reason is that due to type erasure, key and value types * cannot be introspected when using this method. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @Override @SuppressWarnings("unchecked") public T readValue(JsonParser p, Class valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueType)); } /** * Method to deserialize JSON content into a Java type, reference * to which is passed as argument. Type is passed using so-called * "super type token" (see ) * and specifically needs to be used if the root type is a * parameterized (generic) container type. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @Override @SuppressWarnings("unchecked") public T readValue(JsonParser p, TypeReference valueTypeRef) throws IOException, JsonParseException, JsonMappingException { return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueTypeRef)); } /** * Method to deserialize JSON content into a Java type, reference * to which is passed as argument. Type is passed using * Jackson specific type; instance of which can be constructed using * {@link TypeFactory}. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @Override @SuppressWarnings("unchecked") public final T readValue(JsonParser p, ResolvedType valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readValue(getDeserializationConfig(), p, (JavaType) valueType); } /** * Type-safe overloaded method, basically alias for {@link #readValue(JsonParser, Class)}. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @SuppressWarnings("unchecked") public T readValue(JsonParser p, JavaType valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readValue(getDeserializationConfig(), p, valueType); } /** * Method to deserialize JSON content as tree expressed * using set of {@link JsonNode} instances. Returns * root of the resulting tree (where root can consist * of just a single node if the current event is a * value event, not container). * * @return a {@link JsonNode}, if valid JSON content found; null * if input has no content to bind -- note, however, that if * JSON null token is found, it will be represented * as a non-null {@link JsonNode} (one that returns true * for {@link JsonNode#isNull()} * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) */ @Override public T readTree(JsonParser p) throws IOException, JsonProcessingException { /* 02-Mar-2009, tatu: One twist; deserialization provider * will map JSON null straight into Java null. But what * we want to return is the "null node" instead. */ /* 05-Aug-2011, tatu: Also, must check for EOF here before * calling readValue(), since that'll choke on it otherwise */ DeserializationConfig cfg = getDeserializationConfig(); JsonToken t = p.getCurrentToken(); if (t == null) { t = p.nextToken(); if (t == null) { return null; } } JsonNode n = (JsonNode) _readValue(cfg, p, JSON_NODE_TYPE); if (n == null) { n = getNodeFactory().nullNode(); } @SuppressWarnings("unchecked") T result = (T) n; return result; } /** * Convenience method, equivalent in function to: *

     *   readerFor(valueType).readValues(p);
     *
*

* Method for reading sequence of Objects from parser stream. * Sequence can be either root-level "unwrapped" sequence (without surrounding * JSON array), or a sequence contained in a JSON Array. * In either case {@link JsonParser} MUST point to the first token of * the first element, OR not point to any token (in which case it is advanced * to the next token). This means, specifically, that for wrapped sequences, * parser MUST NOT point to the surrounding START_ARRAY (one that * contains values to read) but rather to the token following it which is the first * token of the first value to read. *

* Note that {@link ObjectReader} has more complete set of variants. */ @Override public MappingIterator readValues(JsonParser p, ResolvedType valueType) throws IOException, JsonProcessingException { return readValues(p, (JavaType) valueType); } /** * Convenience method, equivalent in function to: *

     *   readerFor(valueType).readValues(p);
     *
*

* Type-safe overload of {@link #readValues(JsonParser, ResolvedType)}. */ public MappingIterator readValues(JsonParser p, JavaType valueType) throws IOException, JsonProcessingException { DeserializationConfig config = getDeserializationConfig(); DeserializationContext ctxt = createDeserializationContext(p, config); JsonDeserializer deser = _findRootDeserializer(ctxt, valueType); // false -> do NOT close JsonParser (since caller passed it) return new MappingIterator(valueType, p, ctxt, deser, false, null); } /** * Convenience method, equivalent in function to: *

     *   readerFor(valueType).readValues(p);
     *
*

* Type-safe overload of {@link #readValues(JsonParser, ResolvedType)}. */ @Override public MappingIterator readValues(JsonParser p, Class valueType) throws IOException, JsonProcessingException { return readValues(p, _typeFactory.constructType(valueType)); } /** * Method for reading sequence of Objects from parser stream. */ @Override public MappingIterator readValues(JsonParser p, TypeReference valueTypeRef) throws IOException, JsonProcessingException { return readValues(p, _typeFactory.constructType(valueTypeRef)); } /* /********************************************************** /* Public API not included in ObjectCodec: deserialization /* (mapping from JSON to Java types) /********************************************************** */ /** * Method to deserialize JSON content as tree expressed * using set of {@link JsonNode} instances. * Returns root of the resulting tree (where root can consist * of just a single node if the current event is a * value event, not container). *

* If a low-level I/O problem (missing input, network error) occurs, * a {@link IOException} will be thrown. * If a parsing problem occurs (invalid JSON), * {@link JsonParseException} will be thrown. * If no content is found from input (end-of-input), Java * null will be returned. * * @param in Input stream used to read JSON content * for building the JSON tree. * * @return a {@link JsonNode}, if valid JSON content found; null * if input has no content to bind -- note, however, that if * JSON null token is found, it will be represented * as a non-null {@link JsonNode} (one that returns true * for {@link JsonNode#isNull()} * * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) */ public JsonNode readTree(InputStream in) throws IOException { return _readTreeAndClose(_jsonFactory.createParser(in)); } /** * Method to deserialize JSON content as tree expressed * using set of {@link JsonNode} instances. * Returns root of the resulting tree (where root can consist * of just a single node if the current event is a * value event, not container). *

* If a low-level I/O problem (missing input, network error) occurs, * a {@link IOException} will be thrown. * If a parsing problem occurs (invalid JSON), * {@link JsonParseException} will be thrown. * If no content is found from input (end-of-input), Java * null will be returned. * * @param r Reader used to read JSON content * for building the JSON tree. * * @return a {@link JsonNode}, if valid JSON content found; null * if input has no content to bind -- note, however, that if * JSON null token is found, it will be represented * as a non-null {@link JsonNode} (one that returns true * for {@link JsonNode#isNull()} */ public JsonNode readTree(Reader r) throws IOException { return _readTreeAndClose(_jsonFactory.createParser(r)); } /** * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances. * Returns root of the resulting tree (where root can consist of just a single node if the current * event is a value event, not container). *

* If a low-level I/O problem (missing input, network error) occurs, * a {@link IOException} will be thrown. * If a parsing problem occurs (invalid JSON), * {@link JsonParseException} will be thrown. * If no content is found from input (end-of-input), Java * null will be returned. * * @param content JSON content to parse to build the JSON tree. * * @return a {@link JsonNode}, if valid JSON content found; null * if input has no content to bind -- note, however, that if * JSON null token is found, it will be represented * as a non-null {@link JsonNode} (one that returns true * for {@link JsonNode#isNull()} * * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) */ public JsonNode readTree(String content) throws IOException { return _readTreeAndClose(_jsonFactory.createParser(content)); } /** * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances. * Returns root of the resulting tree (where root can consist of just a single node if the current * event is a value event, not container). * * @param content JSON content to parse to build the JSON tree. * * @return a {@link JsonNode}, if valid JSON content found; null * if input has no content to bind -- note, however, that if * JSON null token is found, it will be represented * as a non-null {@link JsonNode} (one that returns true * for {@link JsonNode#isNull()} * * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) */ public JsonNode readTree(byte[] content) throws IOException { return _readTreeAndClose(_jsonFactory.createParser(content)); } /** * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances. * Returns root of the resulting tree (where root can consist of just a single node if the current * event is a value event, not container). * * @param file File of which contents to parse as JSON for building a tree instance * * @return a {@link JsonNode}, if valid JSON content found; null * if input has no content to bind -- note, however, that if * JSON null token is found, it will be represented * as a non-null {@link JsonNode} (one that returns true * for {@link JsonNode#isNull()} * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) */ public JsonNode readTree(File file) throws IOException, JsonProcessingException { return _readTreeAndClose(_jsonFactory.createParser(file)); } /** * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances. * Returns root of the resulting tree (where root can consist of just a single node if the current * event is a value event, not container). * * @param source URL to use for fetching contents to parse as JSON for building a tree instance * * @return a {@link JsonNode}, if valid JSON content found; null * if input has no content to bind -- note, however, that if * JSON null token is found, it will be represented * as a non-null {@link JsonNode} (one that returns true * for {@link JsonNode#isNull()} * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) */ public JsonNode readTree(URL source) throws IOException { return _readTreeAndClose(_jsonFactory.createParser(source)); } /* /********************************************************** /* Public API (from ObjectCodec): serialization /* (mapping from Java types to Json) /********************************************************** */ /** * Method that can be used to serialize any Java value as * JSON output, using provided {@link JsonGenerator}. */ @Override public void writeValue(JsonGenerator g, Object value) throws IOException, JsonGenerationException, JsonMappingException { SerializationConfig config = getSerializationConfig(); /* 12-May-2015/2.6, tatu: Looks like we do NOT want to call the usual * 'config.initialize(g)` here, since it is assumed that generator * has been configured by caller. But for some reason we don't * trust indentation settings... */ // 10-Aug-2012, tatu: as per [Issue#12], must handle indentation: if (config.isEnabled(SerializationFeature.INDENT_OUTPUT)) { if (g.getPrettyPrinter() == null) { g.setPrettyPrinter(config.constructDefaultPrettyPrinter()); } } if (config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { _writeCloseableValue(g, value, config); } else { _serializerProvider(config).serializeValue(g, value); if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) { g.flush(); } } } /* /********************************************************** /* Public API (from TreeCodec via ObjectCodec): Tree Model support /********************************************************** */ @Override public void writeTree(JsonGenerator jgen, TreeNode rootNode) throws IOException, JsonProcessingException { SerializationConfig config = getSerializationConfig(); _serializerProvider(config).serializeValue(jgen, rootNode); if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) { jgen.flush(); } } /** * Method to serialize given JSON Tree, using generator * provided. */ public void writeTree(JsonGenerator jgen, JsonNode rootNode) throws IOException, JsonProcessingException { SerializationConfig config = getSerializationConfig(); _serializerProvider(config).serializeValue(jgen, rootNode); if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) { jgen.flush(); } } /** *

* Note: return type is co-variant, as basic ObjectCodec * abstraction cannot refer to concrete node types (as it's * part of core package, whereas impls are part of mapper * package) */ @Override public ObjectNode createObjectNode() { return _deserializationConfig.getNodeFactory().objectNode(); } /** *

* Note: return type is co-variant, as basic ObjectCodec * abstraction cannot refer to concrete node types (as it's * part of core package, whereas impls are part of mapper * package) */ @Override public ArrayNode createArrayNode() { return _deserializationConfig.getNodeFactory().arrayNode(); } /** * Method for constructing a {@link JsonParser} out of JSON tree * representation. * * @param n Root node of the tree that resulting parser will read from */ @Override public JsonParser treeAsTokens(TreeNode n) { return new TreeTraversingParser((JsonNode) n, this); } /** * Convenience conversion method that will bind data given JSON tree * contains into specific value (usually bean) type. *

* Functionally equivalent to: *

     *   objectMapper.convertValue(n, valueClass);
     *
*/ @SuppressWarnings("unchecked") @Override public T treeToValue(TreeNode n, Class valueType) throws JsonProcessingException { try { // Simple cast when we just want to cast to, say, ObjectNode // ... one caveat; while everything is Object.class, let's not take shortcut if (valueType != Object.class && valueType.isAssignableFrom(n.getClass())) { return (T) n; } // 20-Apr-2016, tatu: Another thing: for VALUE_EMBEDDED_OBJECT, assume similar // short-cut coercion if (n.asToken() == JsonToken.VALUE_EMBEDDED_OBJECT) { if (n instanceof POJONode) { Object ob = ((POJONode) n).getPojo(); if ((ob == null) || valueType.isInstance(ob)) { return (T) ob; } } } return readValue(treeAsTokens(n), valueType); } catch (JsonProcessingException e) { throw e; } catch (IOException e) { // should not occur, no real i/o... throw new IllegalArgumentException(e.getMessage(), e); } } /** * Reverse of {@link #treeToValue}; given a value (usually bean), will * construct equivalent JSON Tree representation. Functionally similar * to serializing value into JSON and parsing JSON as tree, but * more efficient. *

* NOTE: while results are usually identical to that of serialization followed * by deserialization, this is not always the case. In some cases serialization * into intermediate representation will retain encapsulation of things like * raw value ({@link com.fasterxml.jackson.databind.util.RawValue}) or basic * node identity ({@link JsonNode}). If so, result is a valid tree, but values * are not re-constructed through actual JSON representation. So if transformation * requires actual materialization of JSON (or other data format that this mapper * produces), it will be necessary to do actual serialization. * * @param Actual node type; usually either basic {@link JsonNode} or * {@link com.fasterxml.jackson.databind.node.ObjectNode} * @param fromValue Bean value to convert * @return Root node of the resulting JSON tree */ @SuppressWarnings({ "unchecked", "resource" }) public T valueToTree(Object fromValue) throws IllegalArgumentException { if (fromValue == null) return null; TokenBuffer buf = new TokenBuffer(this, false); if (isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { buf = buf.forceUseOfBigDecimal(true); } JsonNode result; try { writeValue(buf, fromValue); JsonParser p = buf.asParser(); result = readTree(p); p.close(); } catch (IOException e) { // should not occur, no real i/o... throw new IllegalArgumentException(e.getMessage(), e); } return (T) result; } /* /********************************************************** /* Extended Public API, accessors /********************************************************** */ /** * Method that can be called to check whether mapper thinks * it could serialize an instance of given Class. * Check is done * by checking whether a serializer can be found for the type. *

* NOTE: since this method does NOT throw exceptions, but internal * processing may, caller usually has little information as to why * serialization would fail. If you want access to internal {@link Exception}, * call {@link #canSerialize(Class, AtomicReference)} instead. * * @return True if mapper can find a serializer for instances of * given class (potentially serializable), false otherwise (not * serializable) */ public boolean canSerialize(Class type) { return _serializerProvider(getSerializationConfig()).hasSerializerFor(type, null); } /** * Method similar to {@link #canSerialize(Class)} but that can return * actual {@link Throwable} that was thrown when trying to construct * serializer: this may be useful in figuring out what the actual problem is. * * @since 2.3 */ public boolean canSerialize(Class type, AtomicReference cause) { return _serializerProvider(getSerializationConfig()).hasSerializerFor(type, cause); } /** * Method that can be called to check whether mapper thinks * it could deserialize an Object of given type. * Check is done by checking whether a registered deserializer can * be found or built for the type; if not (either by no mapping being * found, or through an Exception being thrown, false * is returned. *

* NOTE: in case an exception is thrown during course of trying * co construct matching deserializer, it will be effectively swallowed. * If you want access to that exception, call * {@link #canDeserialize(JavaType, AtomicReference)} instead. * * @return True if mapper can find a serializer for instances of * given class (potentially serializable), false otherwise (not * serializable) */ public boolean canDeserialize(JavaType type) { return createDeserializationContext(null, getDeserializationConfig()).hasValueDeserializerFor(type, null); } /** * Method similar to {@link #canDeserialize(JavaType)} but that can return * actual {@link Throwable} that was thrown when trying to construct * serializer: this may be useful in figuring out what the actual problem is. * * @since 2.3 */ public boolean canDeserialize(JavaType type, AtomicReference cause) { return createDeserializationContext(null, getDeserializationConfig()).hasValueDeserializerFor(type, cause); } /* /********************************************************** /* Extended Public API, deserialization, /* convenience methods /********************************************************** */ /** * Method to deserialize JSON content from given file into given Java type. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @SuppressWarnings("unchecked") public T readValue(File src, Class valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType)); } /** * Method to deserialize JSON content from given file into given Java type. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @SuppressWarnings({ "unchecked", "rawtypes" }) public T readValue(File src, TypeReference valueTypeRef) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef)); } /** * Method to deserialize JSON content from given file into given Java type. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @SuppressWarnings("unchecked") public T readValue(File src, JavaType valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType); } /** * Method to deserialize JSON content from given resource into given Java type. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @SuppressWarnings("unchecked") public T readValue(URL src, Class valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType)); } /** * Method to deserialize JSON content from given resource into given Java type. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @SuppressWarnings({ "unchecked", "rawtypes" }) public T readValue(URL src, TypeReference valueTypeRef) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef)); } @SuppressWarnings("unchecked") public T readValue(URL src, JavaType valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType); } /** * Method to deserialize JSON content from given JSON content String. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @SuppressWarnings("unchecked") public T readValue(String content, Class valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueType)); } /** * Method to deserialize JSON content from given JSON content String. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @SuppressWarnings({ "unchecked", "rawtypes" }) public T readValue(String content, TypeReference valueTypeRef) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueTypeRef)); } /** * Method to deserialize JSON content from given JSON content String. * * @throws IOException if a low-level I/O problem (unexpected end-of-input, * network error) occurs (passed through as-is without additional wrapping -- note * that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS} * does NOT result in wrapping of exception even if enabled) * @throws JsonParseException if underlying input contains invalid content * of type {@link JsonParser} supports (JSON for default case) * @throws JsonMappingException if the input JSON structure does not match structure * expected for result type (or has other mismatch issues) */ @SuppressWarnings("unchecked") public T readValue(String content, JavaType valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(content), valueType); } @SuppressWarnings("unchecked") public T readValue(Reader src, Class valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType)); } @SuppressWarnings({ "unchecked", "rawtypes" }) public T readValue(Reader src, TypeReference valueTypeRef) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef)); } @SuppressWarnings("unchecked") public T readValue(Reader src, JavaType valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType); } @SuppressWarnings("unchecked") public T readValue(InputStream src, Class valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType)); } @SuppressWarnings({ "unchecked", "rawtypes" }) public T readValue(InputStream src, TypeReference valueTypeRef) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef)); } @SuppressWarnings("unchecked") public T readValue(InputStream src, JavaType valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType); } @SuppressWarnings("unchecked") public T readValue(byte[] src, Class valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType)); } @SuppressWarnings("unchecked") public T readValue(byte[] src, int offset, int len, Class valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), _typeFactory.constructType(valueType)); } @SuppressWarnings({ "unchecked", "rawtypes" }) public T readValue(byte[] src, TypeReference valueTypeRef) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef)); } @SuppressWarnings({ "unchecked", "rawtypes" }) public T readValue(byte[] src, int offset, int len, TypeReference valueTypeRef) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), _typeFactory.constructType(valueTypeRef)); } @SuppressWarnings("unchecked") public T readValue(byte[] src, JavaType valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType); } @SuppressWarnings("unchecked") public T readValue(byte[] src, int offset, int len, JavaType valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), valueType); } @SuppressWarnings("unchecked") public T readValue(DataInput src, Class valueType) throws IOException { return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType)); } @SuppressWarnings("unchecked") public T readValue(DataInput src, JavaType valueType) throws IOException { return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType); } /* /********************************************************** /* Extended Public API: serialization /* (mapping from Java types to JSON) /********************************************************** */ /** * Method that can be used to serialize any Java value as * JSON output, written to File provided. */ public void writeValue(File resultFile, Object value) throws IOException, JsonGenerationException, JsonMappingException { _configAndWriteValue(_jsonFactory.createGenerator(resultFile, JsonEncoding.UTF8), value); } /** * Method that can be used to serialize any Java value as * JSON output, using output stream provided (using encoding * {@link JsonEncoding#UTF8}). *

* Note: method does not close the underlying stream explicitly * here; however, {@link JsonFactory} this mapper uses may choose * to close the stream depending on its settings (by default, * it will try to close it when {@link JsonGenerator} we construct * is closed). */ public void writeValue(OutputStream out, Object value) throws IOException, JsonGenerationException, JsonMappingException { _configAndWriteValue(_jsonFactory.createGenerator(out, JsonEncoding.UTF8), value); } /** * @since 2.8 */ public void writeValue(DataOutput out, Object value) throws IOException { _configAndWriteValue(_jsonFactory.createGenerator(out, JsonEncoding.UTF8), value); } /** * Method that can be used to serialize any Java value as * JSON output, using Writer provided. *

* Note: method does not close the underlying stream explicitly * here; however, {@link JsonFactory} this mapper uses may choose * to close the stream depending on its settings (by default, * it will try to close it when {@link JsonGenerator} we construct * is closed). */ public void writeValue(Writer w, Object value) throws IOException, JsonGenerationException, JsonMappingException { _configAndWriteValue(_jsonFactory.createGenerator(w), value); } /** * Method that can be used to serialize any Java value as * a String. Functionally equivalent to calling * {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter} * and constructing String, but more efficient. *

* Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it. */ @SuppressWarnings("resource") public String writeValueAsString(Object value) throws JsonProcessingException { // alas, we have to pull the recycler directly here... SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler()); try { _configAndWriteValue(_jsonFactory.createGenerator(sw), value); } catch (JsonProcessingException e) { throw e; } catch (IOException e) { // shouldn't really happen, but is declared as possibility so: throw JsonMappingException.fromUnexpectedIOE(e); } return sw.getAndClear(); } /** * Method that can be used to serialize any Java value as * a byte array. Functionally equivalent to calling * {@link #writeValue(Writer,Object)} with {@link java.io.ByteArrayOutputStream} * and getting bytes, but more efficient. * Encoding used will be UTF-8. *

* Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it. */ @SuppressWarnings("resource") public byte[] writeValueAsBytes(Object value) throws JsonProcessingException { ByteArrayBuilder bb = new ByteArrayBuilder(_jsonFactory._getBufferRecycler()); try { _configAndWriteValue(_jsonFactory.createGenerator(bb, JsonEncoding.UTF8), value); } catch (JsonProcessingException e) { // to support [JACKSON-758] throw e; } catch (IOException e) { // shouldn't really happen, but is declared as possibility so: throw JsonMappingException.fromUnexpectedIOE(e); } byte[] result = bb.toByteArray(); bb.release(); return result; } /* /********************************************************** /* Extended Public API: constructing ObjectWriters /* for more advanced configuration /********************************************************** */ /** * Convenience method for constructing {@link ObjectWriter} * with default settings. */ public ObjectWriter writer() { return _newWriter(getSerializationConfig()); } /** * Factory method for constructing {@link ObjectWriter} with * specified feature enabled (compared to settings that this * mapper instance has). */ public ObjectWriter writer(SerializationFeature feature) { return _newWriter(getSerializationConfig().with(feature)); } /** * Factory method for constructing {@link ObjectWriter} with * specified features enabled (compared to settings that this * mapper instance has). */ public ObjectWriter writer(SerializationFeature first, SerializationFeature... other) { return _newWriter(getSerializationConfig().with(first, other)); } /** * Factory method for constructing {@link ObjectWriter} that will * serialize objects using specified {@link DateFormat}; or, if * null passed, using timestamp (64-bit number. */ public ObjectWriter writer(DateFormat df) { return _newWriter(getSerializationConfig().with(df)); } /** * Factory method for constructing {@link ObjectWriter} that will * serialize objects using specified JSON View (filter). */ public ObjectWriter writerWithView(Class serializationView) { return _newWriter(getSerializationConfig().withView(serializationView)); } /** * Factory method for constructing {@link ObjectWriter} that will * serialize objects using specified root type, instead of actual * runtime type of value. Type must be a super-type of runtime type. *

* Main reason for using this method is performance, as writer is able * to pre-fetch serializer to use before write, and if writer is used * more than once this avoids addition per-value serializer lookups. * * @since 2.5 */ public ObjectWriter writerFor(Class rootType) { return _newWriter(getSerializationConfig(), ((rootType == null) ? null :_typeFactory.constructType(rootType)), /*PrettyPrinter*/null); } /** * Factory method for constructing {@link ObjectWriter} that will * serialize objects using specified root type, instead of actual * runtime type of value. Type must be a super-type of runtime type. *

* Main reason for using this method is performance, as writer is able * to pre-fetch serializer to use before write, and if writer is used * more than once this avoids addition per-value serializer lookups. * * @since 2.5 */ public ObjectWriter writerFor(TypeReference rootType) { return _newWriter(getSerializationConfig(), ((rootType == null) ? null : _typeFactory.constructType(rootType)), /*PrettyPrinter*/null); } /** * Factory method for constructing {@link ObjectWriter} that will * serialize objects using specified root type, instead of actual * runtime type of value. Type must be a super-type of runtime type. *

* Main reason for using this method is performance, as writer is able * to pre-fetch serializer to use before write, and if writer is used * more than once this avoids addition per-value serializer lookups. * * @since 2.5 */ public ObjectWriter writerFor(JavaType rootType) { return _newWriter(getSerializationConfig(), rootType, /*PrettyPrinter*/null); } /** * Factory method for constructing {@link ObjectWriter} that will * serialize objects using specified pretty printer for indentation * (or if null, no pretty printer) */ public ObjectWriter writer(PrettyPrinter pp) { if (pp == null) { // need to use a marker to indicate explicit disabling of pp pp = ObjectWriter.NULL_PRETTY_PRINTER; } return _newWriter(getSerializationConfig(), /*root type*/ null, pp); } /** * Factory method for constructing {@link ObjectWriter} that will * serialize objects using the default pretty printer for indentation */ public ObjectWriter writerWithDefaultPrettyPrinter() { SerializationConfig config = getSerializationConfig(); return _newWriter(config, /*root type*/ null, config.getDefaultPrettyPrinter()); } /** * Factory method for constructing {@link ObjectWriter} that will * serialize objects using specified filter provider. */ public ObjectWriter writer(FilterProvider filterProvider) { return _newWriter(getSerializationConfig().withFilters(filterProvider)); } /** * Factory method for constructing {@link ObjectWriter} that will * pass specific schema object to {@link JsonGenerator} used for * writing content. * * @param schema Schema to pass to generator */ public ObjectWriter writer(FormatSchema schema) { _verifySchemaType(schema); return _newWriter(getSerializationConfig(), schema); } /** * Factory method for constructing {@link ObjectWriter} that will * use specified Base64 encoding variant for Base64-encoded binary data. * * @since 2.1 */ public ObjectWriter writer(Base64Variant defaultBase64) { return _newWriter(getSerializationConfig().with(defaultBase64)); } /** * Factory method for constructing {@link ObjectReader} that will * use specified character escaping details for output. * * @since 2.3 */ public ObjectWriter writer(CharacterEscapes escapes) { return _newWriter(getSerializationConfig()).with(escapes); } /** * Factory method for constructing {@link ObjectWriter} that will * use specified default attributes. * * @since 2.3 */ public ObjectWriter writer(ContextAttributes attrs) { return _newWriter(getSerializationConfig().with(attrs)); } /** * @deprecated Since 2.5, use {@link #writerFor(Class)} instead */ @Deprecated public ObjectWriter writerWithType(Class rootType) { return _newWriter(getSerializationConfig(), // 15-Mar-2013, tatu: Important! Indicate that static typing is needed: ((rootType == null) ? null :_typeFactory.constructType(rootType)), /*PrettyPrinter*/null); } /** * @deprecated Since 2.5, use {@link #writerFor(TypeReference)} instead */ @Deprecated public ObjectWriter writerWithType(TypeReference rootType) { return _newWriter(getSerializationConfig(), // 15-Mar-2013, tatu: Important! Indicate that static typing is needed: ((rootType == null) ? null : _typeFactory.constructType(rootType)), /*PrettyPrinter*/null); } /** * @deprecated Since 2.5, use {@link #writerFor(JavaType)} instead */ @Deprecated public ObjectWriter writerWithType(JavaType rootType) { return _newWriter(getSerializationConfig(), rootType, /*PrettyPrinter*/null); } /* /********************************************************** /* Extended Public API: constructing ObjectReaders /* for more advanced configuration /********************************************************** */ /** * Factory method for constructing {@link ObjectReader} with * default settings. Note that the resulting instance is NOT usable as is, * without defining expected value type. */ public ObjectReader reader() { return _newReader(getDeserializationConfig()).with(_injectableValues); } /** * Factory method for constructing {@link ObjectReader} with * specified feature enabled (compared to settings that this * mapper instance has). * Note that the resulting instance is NOT usable as is, * without defining expected value type. */ public ObjectReader reader(DeserializationFeature feature) { return _newReader(getDeserializationConfig().with(feature)); } /** * Factory method for constructing {@link ObjectReader} with * specified features enabled (compared to settings that this * mapper instance has). * Note that the resulting instance is NOT usable as is, * without defining expected value type. */ public ObjectReader reader(DeserializationFeature first, DeserializationFeature... other) { return _newReader(getDeserializationConfig().with(first, other)); } /** * Factory method for constructing {@link ObjectReader} that will * update given Object (usually Bean, but can be a Collection or Map * as well, but NOT an array) with JSON data. Deserialization occurs * normally except that the root-level value in JSON is not used for * instantiating a new object; instead give updateable object is used * as root. * Runtime type of value object is used for locating deserializer, * unless overridden by other factory methods of {@link ObjectReader} */ public ObjectReader readerForUpdating(Object valueToUpdate) { JavaType t = _typeFactory.constructType(valueToUpdate.getClass()); return _newReader(getDeserializationConfig(), t, valueToUpdate, null, _injectableValues); } /** * Factory method for constructing {@link ObjectReader} that will * read or update instances of specified type * * @since 2.6 */ public ObjectReader readerFor(JavaType type) { return _newReader(getDeserializationConfig(), type, null, null, _injectableValues); } /** * Factory method for constructing {@link ObjectReader} that will * read or update instances of specified type * * @since 2.6 */ public ObjectReader readerFor(Class type) { return _newReader(getDeserializationConfig(), _typeFactory.constructType(type), null, null, _injectableValues); } /** * Factory method for constructing {@link ObjectReader} that will * read or update instances of specified type * * @since 2.6 */ public ObjectReader readerFor(TypeReference type) { return _newReader(getDeserializationConfig(), _typeFactory.constructType(type), null, null, _injectableValues); } /** * Factory method for constructing {@link ObjectReader} that will * use specified {@link JsonNodeFactory} for constructing JSON trees. */ public ObjectReader reader(JsonNodeFactory f) { return _newReader(getDeserializationConfig()).with(f); } /** * Factory method for constructing {@link ObjectReader} that will * pass specific schema object to {@link JsonParser} used for * reading content. * * @param schema Schema to pass to parser */ public ObjectReader reader(FormatSchema schema) { _verifySchemaType(schema); return _newReader(getDeserializationConfig(), null, null, schema, _injectableValues); } /** * Factory method for constructing {@link ObjectReader} that will * use specified injectable values. * * @param injectableValues Injectable values to use */ public ObjectReader reader(InjectableValues injectableValues) { return _newReader(getDeserializationConfig(), null, null, null, injectableValues); } /** * Factory method for constructing {@link ObjectReader} that will * deserialize objects using specified JSON View (filter). */ public ObjectReader readerWithView(Class view) { return _newReader(getDeserializationConfig().withView(view)); } /** * Factory method for constructing {@link ObjectReader} that will * use specified Base64 encoding variant for Base64-encoded binary data. * * @since 2.1 */ public ObjectReader reader(Base64Variant defaultBase64) { return _newReader(getDeserializationConfig().with(defaultBase64)); } /** * Factory method for constructing {@link ObjectReader} that will * use specified default attributes. * * @since 2.3 */ public ObjectReader reader(ContextAttributes attrs) { return _newReader(getDeserializationConfig().with(attrs)); } /** * @deprecated Since 2.5, use {@link #readerFor(JavaType)} instead */ @Deprecated public ObjectReader reader(JavaType type) { return _newReader(getDeserializationConfig(), type, null, null, _injectableValues); } /** * @deprecated Since 2.5, use {@link #readerFor(Class)} instead */ @Deprecated public ObjectReader reader(Class type) { return _newReader(getDeserializationConfig(), _typeFactory.constructType(type), null, null, _injectableValues); } /** * @deprecated Since 2.5, use {@link #readerFor(TypeReference)} instead */ @Deprecated public ObjectReader reader(TypeReference type) { return _newReader(getDeserializationConfig(), _typeFactory.constructType(type), null, null, _injectableValues); } /* /********************************************************** /* Extended Public API: convenience type conversion /********************************************************** */ /** * Convenience method for doing two-step conversion from given value, into * instance of given value type, if (but only if!) conversion is needed. * If given value is already of requested type, value is returned as is. *

* This method is functionally similar to first * serializing given value into JSON, and then binding JSON data into value * of given type, but should be more efficient since full serialization does * not (need to) occur. * However, same converters (serializers, deserializers) will be used as for * data binding, meaning same object mapper configuration works. *

* Note that it is possible that in some cases behavior does differ from * full serialize-then-deserialize cycle: in most case differences are * unintentional (that is, flaws to fix) and should be reported. * It is not guaranteed, however, that the behavior is 100% the same: * the goal is just to allow efficient value conversions for structurally * compatible Objects, according to standard Jackson configuration. *

* Further note that functianality is not designed to support "advanced" use * cases, such as conversion of polymorphic values, or cases where Object Identity * is used. * * @throws IllegalArgumentException If conversion fails due to incompatible type; * if so, root cause will contain underlying checked exception data binding * functionality threw */ @SuppressWarnings("unchecked") public T convertValue(Object fromValue, Class toValueType) throws IllegalArgumentException { return (T) _convert(fromValue, _typeFactory.constructType(toValueType)); } /** * See {@link #convertValue(Object, Class)} */ @SuppressWarnings("unchecked") public T convertValue(Object fromValue, TypeReference toValueTypeRef) throws IllegalArgumentException { return (T) _convert(fromValue, _typeFactory.constructType(toValueTypeRef)); } /** * See {@link #convertValue(Object, Class)} */ @SuppressWarnings("unchecked") public T convertValue(Object fromValue, JavaType toValueType) throws IllegalArgumentException { return (T) _convert(fromValue, toValueType); } /** * Actual conversion implementation: instead of using existing read * and write methods, much of code is inlined. Reason for this is * that we must avoid root value wrapping/unwrapping both for efficiency and * for correctness. If root value wrapping/unwrapping is actually desired, * caller must use explicit writeValue and * readValue methods. */ @SuppressWarnings("resource") protected Object _convert(Object fromValue, JavaType toValueType) throws IllegalArgumentException { // [databind#1433] Do not shortcut null values. // This defaults primitives and fires deserializer getNullValue hooks. if (fromValue != null) { // also, as per [databind#11], consider case for simple cast // But with caveats: one is that while everything is Object.class, we don't // want to "optimize" that out; and the other is that we also do not want // to lose conversions of generic types. Class targetType = toValueType.getRawClass(); if (targetType != Object.class && !toValueType.hasGenericTypes() && targetType.isAssignableFrom(fromValue.getClass())) { return fromValue; } } // Then use TokenBuffer, which is a JsonGenerator: TokenBuffer buf = new TokenBuffer(this, false); if (isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { buf = buf.forceUseOfBigDecimal(true); } try { // inlined 'writeValue' with minor changes: // first: disable wrapping when writing SerializationConfig config = getSerializationConfig().without(SerializationFeature.WRAP_ROOT_VALUE); // no need to check for closing of TokenBuffer _serializerProvider(config).serializeValue(buf, fromValue); // then matching read, inlined 'readValue' with minor mods: final JsonParser p = buf.asParser(); Object result; // ok to pass in existing feature flags; unwrapping handled by mapper final DeserializationConfig deserConfig = getDeserializationConfig(); JsonToken t = _initForReading(p, toValueType); if (t == JsonToken.VALUE_NULL) { DeserializationContext ctxt = createDeserializationContext(p, deserConfig); result = _findRootDeserializer(ctxt, toValueType).getNullValue(ctxt); } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { result = null; } else { // pointing to event other than null DeserializationContext ctxt = createDeserializationContext(p, deserConfig); JsonDeserializer deser = _findRootDeserializer(ctxt, toValueType); // note: no handling of unwrapping result = deser.deserialize(p, ctxt); } p.close(); return result; } catch (IOException e) { // should not occur, no real i/o... throw new IllegalArgumentException(e.getMessage(), e); } } /** * Convenience method similar to {@link #convertValue(Object, JavaType)} but one * in which *

* Implementation is approximately as follows: *

    *
  1. Serialize `updateWithValue` into {@link TokenBuffer}
  2. *
  3. Construct {@link ObjectReader} with `valueToUpdate` (using {@link #readerForUpdating(Object)}) *
  4. *
  5. Construct {@link JsonParser} (using {@link TokenBuffer#asParser()}) *
  6. *
  7. Update using {@link ObjectReader#readValue(JsonParser)}. *
  8. *
  9. Return `valueToUpdate` *
  10. *
*

* Note that update is "shallow" in that only first level of properties (or, immediate contents * of container to update) are modified, unless properties themselves indicate that * merging should be applied for contents. Such merging can be specified using * annotations (see JsonMerge) as well as using "config overrides" (see * {@link #configOverride(Class)} and {@link #setDefaultMergeable(Boolean)}). * * @param valueToUpdate Object to update * @param overrides Object to conceptually serialize and merge into value to * update; can be thought of as a provider for overrides to apply. * * @return Either the first argument (`valueToUpdate`), if it is mutable; or a result of * creating new instance that is result of "merging" values (for example, "updating" a * Java array will create a new array) * * @throws JsonMappingException if there are structural incompatibilities that prevent update. * * @since 2.9 */ @SuppressWarnings("resource") public T updateValue(T valueToUpdate, Object overrides) throws JsonMappingException { T result = valueToUpdate; if ((valueToUpdate != null) && (overrides != null)) { TokenBuffer buf = new TokenBuffer(this, false); if (isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { buf = buf.forceUseOfBigDecimal(true); } try { SerializationConfig config = getSerializationConfig(). without(SerializationFeature.WRAP_ROOT_VALUE); _serializerProvider(config).serializeValue(buf, overrides); JsonParser p = buf.asParser(); result = readerForUpdating(valueToUpdate).readValue(p); p.close(); } catch (IOException e) { // should not occur, no real i/o... if (e instanceof JsonMappingException) { throw (JsonMappingException) e; } // 17-Mar-2017, tatu: Really ought not happen... throw JsonMappingException.fromUnexpectedIOE(e); } } return result; } /* /********************************************************** /* Extended Public API: JSON Schema generation /********************************************************** */ /** * Generate Json-schema * instance for specified class. * * @param t The class to generate schema for * @return Constructed JSON schema. * * @deprecated Since 2.6 use external JSON Schema generator (https://github.com/FasterXML/jackson-module-jsonSchema) * (which under the hood calls {@link #acceptJsonFormatVisitor(JavaType, JsonFormatVisitorWrapper)}) */ @Deprecated public com.fasterxml.jackson.databind.jsonschema.JsonSchema generateJsonSchema(Class t) throws JsonMappingException { return _serializerProvider(getSerializationConfig()).generateJsonSchema(t); } /** * Method for visiting type hierarchy for given type, using specified visitor. *

* This method can be used for things like * generating JSON Schema * instance for specified type. * * @param type Type to generate schema for (possibly with generic signature) * * @since 2.1 */ public void acceptJsonFormatVisitor(Class type, JsonFormatVisitorWrapper visitor) throws JsonMappingException { acceptJsonFormatVisitor(_typeFactory.constructType(type), visitor); } /** * Method for visiting type hierarchy for given type, using specified visitor. * Visitation uses Serializer hierarchy and related properties *

* This method can be used for things like * generating JSON Schema * instance for specified type. * * @param type Type to generate schema for (possibly with generic signature) * * @since 2.1 */ public void acceptJsonFormatVisitor(JavaType type, JsonFormatVisitorWrapper visitor) throws JsonMappingException { if (type == null) { throw new IllegalArgumentException("type must be provided"); } _serializerProvider(getSerializationConfig()).acceptJsonFormatVisitor(type, visitor); } /* /********************************************************** /* Internal methods for serialization, overridable /********************************************************** */ /** * Overridable helper method used for constructing * {@link SerializerProvider} to use for serialization. */ protected DefaultSerializerProvider _serializerProvider(SerializationConfig config) { return _serializerProvider.createInstance(config, _serializerFactory); } /** * Method called to configure the generator as necessary and then * call write functionality */ protected final void _configAndWriteValue(JsonGenerator g, Object value) throws IOException { SerializationConfig cfg = getSerializationConfig(); cfg.initialize(g); // since 2.5 if (cfg.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { _configAndWriteCloseable(g, value, cfg); return; } try { _serializerProvider(cfg).serializeValue(g, value); } catch (Exception e) { ClassUtil.closeOnFailAndThrowAsIOE(g, e); return; } g.close(); } /** * Helper method used when value to serialize is {@link Closeable} and its close() * method is to be called right after serialization has been called */ private final void _configAndWriteCloseable(JsonGenerator g, Object value, SerializationConfig cfg) throws IOException { Closeable toClose = (Closeable) value; try { _serializerProvider(cfg).serializeValue(g, value); Closeable tmpToClose = toClose; toClose = null; tmpToClose.close(); } catch (Exception e) { ClassUtil.closeOnFailAndThrowAsIOE(g, toClose, e); return; } g.close(); } /** * Helper method used when value to serialize is {@link Closeable} and its close() * method is to be called right after serialization has been called */ private final void _writeCloseableValue(JsonGenerator g, Object value, SerializationConfig cfg) throws IOException { Closeable toClose = (Closeable) value; try { _serializerProvider(cfg).serializeValue(g, value); if (cfg.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) { g.flush(); } } catch (Exception e) { ClassUtil.closeOnFailAndThrowAsIOE(null, toClose, e); return; } toClose.close(); } /* /********************************************************** /* Internal methods for deserialization, overridable /********************************************************** */ /** * Actual implementation of value reading+binding operation. */ protected Object _readValue(DeserializationConfig cfg, JsonParser p, JavaType valueType) throws IOException { /* First: may need to read the next token, to initialize * state (either before first read from parser, or after * previous token has been cleared) */ Object result; JsonToken t = _initForReading(p, valueType); final DeserializationContext ctxt = createDeserializationContext(p, cfg); if (t == JsonToken.VALUE_NULL) { // Ask JsonDeserializer what 'null value' to use: result = _findRootDeserializer(ctxt, valueType).getNullValue(ctxt); } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { result = null; } else { // pointing to event other than null JsonDeserializer deser = _findRootDeserializer(ctxt, valueType); // ok, let's get the value if (cfg.useRootWrapping()) { result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser); } else { result = deser.deserialize(p, ctxt); } } // Need to consume the token too p.clearCurrentToken(); if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) { _verifyNoTrailingTokens(p, ctxt, valueType); } return result; } protected Object _readMapAndClose(JsonParser p0, JavaType valueType) throws IOException { try (JsonParser p = p0) { Object result; JsonToken t = _initForReading(p, valueType); final DeserializationConfig cfg = getDeserializationConfig(); final DeserializationContext ctxt = createDeserializationContext(p, cfg); if (t == JsonToken.VALUE_NULL) { // Ask JsonDeserializer what 'null value' to use: result = _findRootDeserializer(ctxt, valueType).getNullValue(ctxt); } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { result = null; } else { JsonDeserializer deser = _findRootDeserializer(ctxt, valueType); if (cfg.useRootWrapping()) { result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser); } else { result = deser.deserialize(p, ctxt); } ctxt.checkUnresolvedObjectId(); } if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) { _verifyNoTrailingTokens(p, ctxt, valueType); } return result; } } /** * Similar to {@link #_readMapAndClose} but specialized for JsonNode * reading. * * @since 2.9 */ protected JsonNode _readTreeAndClose(JsonParser p0) throws IOException { try (JsonParser p = p0) { final JavaType valueType = JSON_NODE_TYPE; DeserializationConfig cfg = getDeserializationConfig(); // 27-Oct-2016, tatu: Need to inline `_initForReading()` due to // special requirements by tree reading (no fail on eof) cfg.initialize(p); // since 2.5 JsonToken t = p.getCurrentToken(); if (t == null) { t = p.nextToken(); if (t == null) { // [databind#1406]: expose end-of-input as `null` return null; } } if (t == JsonToken.VALUE_NULL) { return cfg.getNodeFactory().nullNode(); } DeserializationContext ctxt = createDeserializationContext(p, cfg); JsonDeserializer deser = _findRootDeserializer(ctxt, valueType); Object result; if (cfg.useRootWrapping()) { result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser); } else { result = deser.deserialize(p, ctxt); if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) { _verifyNoTrailingTokens(p, ctxt, valueType); } } // No ObjectIds so can ignore // ctxt.checkUnresolvedObjectId(); return (JsonNode) result; } } protected Object _unwrapAndDeserialize(JsonParser p, DeserializationContext ctxt, DeserializationConfig config, JavaType rootType, JsonDeserializer deser) throws IOException { PropertyName expRootName = config.findRootName(rootType); // 12-Jun-2015, tatu: Should try to support namespaces etc but... String expSimpleName = expRootName.getSimpleName(); if (p.getCurrentToken() != JsonToken.START_OBJECT) { ctxt.reportWrongTokenException(rootType, JsonToken.START_OBJECT, "Current token not START_OBJECT (needed to unwrap root name '%s'), but %s", expSimpleName, p.getCurrentToken()); } if (p.nextToken() != JsonToken.FIELD_NAME) { ctxt.reportWrongTokenException(rootType, JsonToken.FIELD_NAME, "Current token not FIELD_NAME (to contain expected root name '%s'), but %s", expSimpleName, p.getCurrentToken()); } String actualName = p.getCurrentName(); if (!expSimpleName.equals(actualName)) { ctxt.reportInputMismatch(rootType, "Root name '%s' does not match expected ('%s') for type %s", actualName, expSimpleName, rootType); } // ok, then move to value itself.... p.nextToken(); Object result = deser.deserialize(p, ctxt); // and last, verify that we now get matching END_OBJECT if (p.nextToken() != JsonToken.END_OBJECT) { ctxt.reportWrongTokenException(rootType, JsonToken.END_OBJECT, "Current token not END_OBJECT (to match wrapper object with root name '%s'), but %s", expSimpleName, p.getCurrentToken()); } if (config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) { _verifyNoTrailingTokens(p, ctxt, rootType); } return result; } /** * Internal helper method called to create an instance of {@link DeserializationContext} * for deserializing a single root value. * Can be overridden if a custom context is needed. */ protected DefaultDeserializationContext createDeserializationContext(JsonParser p, DeserializationConfig cfg) { return _deserializationContext.createInstance(cfg, p, _injectableValues); } /** * Method called to ensure that given parser is ready for reading * content for data binding. * * @return First token to be used for data binding after this call: * can never be null as exception will be thrown if parser cannot * provide more tokens. * * @throws IOException if the underlying input source has problems during * parsing * @throws JsonParseException if parser has problems parsing content * @throws JsonMappingException if the parser does not have any more * content to map (note: Json "null" value is considered content; * enf-of-stream not) */ protected JsonToken _initForReading(JsonParser p, JavaType targetType) throws IOException { _deserializationConfig.initialize(p); // since 2.5 // 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) { // Throw mapping exception, since it's failure to map, // not an actual parsing problem throw MismatchedInputException.from(p, targetType, "No content to map due to end-of-input"); } } return t; } @Deprecated // since 2.9, use method that takes JavaType too protected JsonToken _initForReading(JsonParser p) throws IOException { return _initForReading(p, null); } /** * @since 2.9 */ protected final void _verifyNoTrailingTokens(JsonParser p, DeserializationContext ctxt, JavaType bindType) throws IOException { JsonToken t = p.nextToken(); if (t != null) { Class bt = ClassUtil.rawClass(bindType); ctxt.reportTrailingTokens(bt, p, t); } } /* /********************************************************** /* Internal methods, other /********************************************************** */ /** * Method called to locate deserializer for the passed root-level value. */ protected JsonDeserializer _findRootDeserializer(DeserializationContext ctxt, JavaType valueType) throws JsonMappingException { // First: have we already seen it? JsonDeserializer deser = _rootDeserializers.get(valueType); if (deser != null) { return deser; } // Nope: need to ask provider to resolve it deser = ctxt.findRootValueDeserializer(valueType); if (deser == null) { // can this happen? return ctxt.reportBadDefinition(valueType, "Cannot find a deserializer for type "+valueType); } _rootDeserializers.put(valueType, deser); return deser; } /** * @since 2.2 */ protected void _verifySchemaType(FormatSchema schema) { if (schema != null) { if (!_jsonFactory.canUseSchema(schema)) { throw new IllegalArgumentException("Cannot use FormatSchema of type "+schema.getClass().getName() +" for format "+_jsonFactory.getFormatName()); } } } } ObjectReader.java000066400000000000000000002116071325620701100336530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.*; import java.net.URL; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.filter.FilteringParserDelegate; import com.fasterxml.jackson.core.filter.JsonPointerBasedFilter; import com.fasterxml.jackson.core.filter.TokenFilter; import com.fasterxml.jackson.core.type.ResolvedType; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.cfg.ContextAttributes; import com.fasterxml.jackson.databind.deser.DataFormatReaders; import com.fasterxml.jackson.databind.deser.DefaultDeserializationContext; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.TreeTraversingParser; import com.fasterxml.jackson.databind.type.SimpleType; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Builder object that can be used for per-serialization configuration of * deserialization parameters, such as root type to use or object * to update (instead of constructing new instance). *

* Uses "mutant factory" pattern so that instances are immutable * (and thus fully thread-safe with no external synchronization); * new instances are constructed for different configurations. * Instances are initially constructed by {@link ObjectMapper} and can be * reused, shared, cached; both because of thread-safety and because * instances are relatively light-weight. *

* NOTE: this class is NOT meant as sub-classable (with Jackson 2.8 and * above) by users. It is left as non-final mostly to allow frameworks * that require bytecode generation for proxying and similar use cases, * but there is no expecation that functionality should be extended * by sub-classing. */ public class ObjectReader extends ObjectCodec implements Versioned, java.io.Serializable // since 2.1 { private static final long serialVersionUID = 2L; // since 2.9 private final static JavaType JSON_NODE_TYPE = SimpleType.constructUnsafe(JsonNode.class); /* /********************************************************** /* Immutable configuration from ObjectMapper /********************************************************** */ /** * General serialization configuration settings; while immutable, * can use copy-constructor to create modified instances as necessary. */ protected final DeserializationConfig _config; /** * Blueprint instance of deserialization context; used for creating * actual instance when needed. */ protected final DefaultDeserializationContext _context; /** * Factory used for constructing {@link JsonGenerator}s */ protected final JsonFactory _parserFactory; /** * Flag that indicates whether root values are expected to be unwrapped or not */ protected final boolean _unwrapRoot; /** * Filter to be consider for JsonParser. * Default value to be null as filter not considered. */ private final TokenFilter _filter; /* /********************************************************** /* Configuration that can be changed during building /********************************************************** */ /** * Declared type of value to instantiate during deserialization. * Defines which deserializer to use; as well as base type of instance * to construct if an updatable value is not configured to be used * (subject to changes by embedded type information, for polymorphic * types). If {@link #_valueToUpdate} is non-null, only used for * locating deserializer. */ protected final JavaType _valueType; /** * We may pre-fetch deserializer as soon as {@link #_valueType} * is known, and if so, reuse it afterwards. * This allows avoiding further deserializer lookups and increases * performance a bit on cases where readers are reused. * * @since 2.1 */ protected final JsonDeserializer _rootDeserializer; /** * Instance to update with data binding; if any. If null, * a new instance is created, if non-null, properties of * this value object will be updated instead. * Note that value can be of almost any type, except not * {@link com.fasterxml.jackson.databind.type.ArrayType}; array * types cannot be modified because array size is immutable. */ protected final Object _valueToUpdate; /** * When using data format that uses a schema, schema is passed * to parser. */ protected final FormatSchema _schema; /** * Values that can be injected during deserialization, if any. */ protected final InjectableValues _injectableValues; /** * Optional detector used for auto-detecting data format that byte-based * input uses. *

* NOTE: If defined non-null, readValue() methods that take * {@link Reader} or {@link String} input will fail with exception, * because format-detection only works on byte-sources. Also, if format * cannot be detect reliably (as per detector settings), * a {@link JsonParseException} will be thrown). * * @since 2.1 */ protected final DataFormatReaders _dataFormatReaders; /* /********************************************************** /* Caching /********************************************************** */ /** * Root-level cached deserializers. * Passed by {@link ObjectMapper}, shared with it. */ final protected ConcurrentHashMap> _rootDeserializers; /* /********************************************************** /* Life-cycle, construction /********************************************************** */ /** * Constructor used by {@link ObjectMapper} for initial instantiation */ protected ObjectReader(ObjectMapper mapper, DeserializationConfig config) { this(mapper, config, null, null, null, null); } /** * Constructor called when a root deserializer should be fetched based * on other configuration. */ protected ObjectReader(ObjectMapper mapper, DeserializationConfig config, JavaType valueType, Object valueToUpdate, FormatSchema schema, InjectableValues injectableValues) { _config = config; _context = mapper._deserializationContext; _rootDeserializers = mapper._rootDeserializers; _parserFactory = mapper._jsonFactory; _valueType = valueType; _valueToUpdate = valueToUpdate; _schema = schema; _injectableValues = injectableValues; _unwrapRoot = config.useRootWrapping(); _rootDeserializer = _prefetchRootDeserializer(valueType); _dataFormatReaders = null; _filter = null; } /** * Copy constructor used for building variations. */ protected ObjectReader(ObjectReader base, DeserializationConfig config, JavaType valueType, JsonDeserializer rootDeser, Object valueToUpdate, FormatSchema schema, InjectableValues injectableValues, DataFormatReaders dataFormatReaders) { _config = config; _context = base._context; _rootDeserializers = base._rootDeserializers; _parserFactory = base._parserFactory; _valueType = valueType; _rootDeserializer = rootDeser; _valueToUpdate = valueToUpdate; _schema = schema; _injectableValues = injectableValues; _unwrapRoot = config.useRootWrapping(); _dataFormatReaders = dataFormatReaders; _filter = base._filter; } /** * Copy constructor used when modifying simple feature flags */ protected ObjectReader(ObjectReader base, DeserializationConfig config) { _config = config; _context = base._context; _rootDeserializers = base._rootDeserializers; _parserFactory = base._parserFactory; _valueType = base._valueType; _rootDeserializer = base._rootDeserializer; _valueToUpdate = base._valueToUpdate; _schema = base._schema; _injectableValues = base._injectableValues; _unwrapRoot = config.useRootWrapping(); _dataFormatReaders = base._dataFormatReaders; _filter = base._filter; } protected ObjectReader(ObjectReader base, JsonFactory f) { // may need to override ordering, based on data format capabilities _config = base._config .with(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, f.requiresPropertyOrdering()); _context = base._context; _rootDeserializers = base._rootDeserializers; _parserFactory = f; _valueType = base._valueType; _rootDeserializer = base._rootDeserializer; _valueToUpdate = base._valueToUpdate; _schema = base._schema; _injectableValues = base._injectableValues; _unwrapRoot = base._unwrapRoot; _dataFormatReaders = base._dataFormatReaders; _filter = base._filter; } protected ObjectReader(ObjectReader base, TokenFilter filter) { _config = base._config; _context = base._context; _rootDeserializers = base._rootDeserializers; _parserFactory = base._parserFactory; _valueType = base._valueType; _rootDeserializer = base._rootDeserializer; _valueToUpdate = base._valueToUpdate; _schema = base._schema; _injectableValues = base._injectableValues; _unwrapRoot = base._unwrapRoot; _dataFormatReaders = base._dataFormatReaders; _filter = filter; } /** * Method that will return version information stored in and read from jar * that contains this class. */ @Override public Version version() { return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION; } /* /********************************************************** /* Helper methods used internally for invoking constructors /* Need to be overridden if sub-classing (not recommended) /* is used. /********************************************************** */ /** * Overridable factory method called by various "withXxx()" methods * * @since 2.5 */ protected ObjectReader _new(ObjectReader base, JsonFactory f) { return new ObjectReader(base, f); } /** * Overridable factory method called by various "withXxx()" methods * * @since 2.5 */ protected ObjectReader _new(ObjectReader base, DeserializationConfig config) { return new ObjectReader(base, config); } /** * Overridable factory method called by various "withXxx()" methods * * @since 2.5 */ protected ObjectReader _new(ObjectReader base, DeserializationConfig config, JavaType valueType, JsonDeserializer rootDeser, Object valueToUpdate, FormatSchema schema, InjectableValues injectableValues, DataFormatReaders dataFormatReaders) { return new ObjectReader(base, config, valueType, rootDeser, valueToUpdate, schema, injectableValues, dataFormatReaders); } /** * Factory method used to create {@link MappingIterator} instances; * either default, or custom subtype. * * @since 2.5 */ protected MappingIterator _newIterator(JsonParser p, DeserializationContext ctxt, JsonDeserializer deser, boolean parserManaged) { return new MappingIterator(_valueType, p, ctxt, deser, parserManaged, _valueToUpdate); } /* /********************************************************** /* Methods for initializing parser instance to use /********************************************************** */ protected JsonToken _initForReading(DeserializationContext ctxt, JsonParser p) throws IOException { if (_schema != null) { p.setSchema(_schema); } _config.initialize(p); // since 2.5 /* 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) { // Throw mapping exception, since it's failure to map, not an actual parsing problem ctxt.reportInputMismatch(_valueType, "No content to map due to end-of-input"); } } return t; } /** * Alternative to {@link #_initForReading} used in cases where reading * of multiple values means that we may or may not want to advance the stream, * but need to do other initialization. *

* Base implementation only sets configured {@link FormatSchema}, if any, on parser. * * @since 2.8 */ protected void _initForMultiRead(DeserializationContext ctxt, JsonParser p) throws IOException { if (_schema != null) { p.setSchema(_schema); } _config.initialize(p); } /* /********************************************************** /* Life-cycle, fluent factory methods for DeserializationFeatures /********************************************************** */ /** * Method for constructing a new reader instance that is configured * with specified feature enabled. */ public ObjectReader with(DeserializationFeature feature) { return _with(_config.with(feature)); } /** * Method for constructing a new reader instance that is configured * with specified features enabled. */ public ObjectReader with(DeserializationFeature first, DeserializationFeature... other) { return _with(_config.with(first, other)); } /** * Method for constructing a new reader instance that is configured * with specified features enabled. */ public ObjectReader withFeatures(DeserializationFeature... features) { return _with(_config.withFeatures(features)); } /** * Method for constructing a new reader instance that is configured * with specified feature disabled. */ public ObjectReader without(DeserializationFeature feature) { return _with(_config.without(feature)); } /** * Method for constructing a new reader instance that is configured * with specified features disabled. */ public ObjectReader without(DeserializationFeature first, DeserializationFeature... other) { return _with(_config.without(first, other)); } /** * Method for constructing a new reader instance that is configured * with specified features disabled. */ public ObjectReader withoutFeatures(DeserializationFeature... features) { return _with(_config.withoutFeatures(features)); } /* /********************************************************** /* Life-cycle, fluent factory methods for JsonParser.Features /********************************************************** */ /** * Method for constructing a new reader instance that is configured * with specified feature enabled. */ public ObjectReader with(JsonParser.Feature feature) { return _with(_config.with(feature)); } /** * Method for constructing a new reader instance that is configured * with specified features enabled. */ public ObjectReader withFeatures(JsonParser.Feature... features) { return _with(_config.withFeatures(features)); } /** * Method for constructing a new reader instance that is configured * with specified feature disabled. */ public ObjectReader without(JsonParser.Feature feature) { return _with(_config.without(feature)); } /** * Method for constructing a new reader instance that is configured * with specified features disabled. */ public ObjectReader withoutFeatures(JsonParser.Feature... features) { return _with(_config.withoutFeatures(features)); } /* /********************************************************** /* Life-cycle, fluent factory methods for FormatFeature (2.7) /********************************************************** */ /** * Method for constructing a new reader instance that is configured * with specified feature enabled. * * @since 2.7 */ public ObjectReader with(FormatFeature feature) { return _with(_config.with(feature)); } /** * Method for constructing a new reader instance that is configured * with specified features enabled. * * @since 2.7 */ public ObjectReader withFeatures(FormatFeature... features) { return _with(_config.withFeatures(features)); } /** * Method for constructing a new reader instance that is configured * with specified feature disabled. * * @since 2.7 */ public ObjectReader without(FormatFeature feature) { return _with(_config.without(feature)); } /** * Method for constructing a new reader instance that is configured * with specified features disabled. * * @since 2.7 */ public ObjectReader withoutFeatures(FormatFeature... features) { return _with(_config.withoutFeatures(features)); } /* /********************************************************** /* Life-cycle, fluent factory methods, other /********************************************************** */ /** * Convenience method to bind from {@link JsonPointer}. * {@link JsonPointerBasedFilter} is registered and will be used for parsing later. * @since 2.6 */ public ObjectReader at(final String value) { return new ObjectReader(this, new JsonPointerBasedFilter(value)); } /** * Convenience method to bind from {@link JsonPointer} * {@link JsonPointerBasedFilter} is registered and will be used for parsing later. * @since 2.6 */ public ObjectReader at(final JsonPointer pointer) { return new ObjectReader(this, new JsonPointerBasedFilter(pointer)); } /** * Mutant factory method that will construct a new instance that has * specified underlying {@link DeserializationConfig}. *

* NOTE: use of this method is not recommended, as there are many other * re-configuration methods available. */ public ObjectReader with(DeserializationConfig config) { return _with(config); } /** * Method for constructing a new instance with configuration that uses * passed {@link InjectableValues} to provide injectable values. *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectReader with(InjectableValues injectableValues) { if (_injectableValues == injectableValues) { return this; } return _new(this, _config, _valueType, _rootDeserializer, _valueToUpdate, _schema, injectableValues, _dataFormatReaders); } /** * Method for constructing a new reader instance with configuration that uses * passed {@link JsonNodeFactory} for constructing {@link JsonNode} * instances. *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectReader with(JsonNodeFactory f) { return _with(_config.with(f)); } /** * Method for constructing a new reader instance with configuration that uses * passed {@link JsonFactory} for constructing underlying Readers. *

* NOTE: only factories that DO NOT REQUIRE SPECIAL MAPPERS * (that is, ones that return false for * {@link JsonFactory#requiresCustomCodec()}) can be used: trying * to use one that requires custom codec will throw exception * * @since 2.1 */ public ObjectReader with(JsonFactory f) { if (f == _parserFactory) { return this; } ObjectReader r = _new(this, f); // Also, try re-linking, if possible... if (f.getCodec() == null) { f.setCodec(r); } return r; } /** * Method for constructing a new instance with configuration that * specifies what root name to expect for "root name unwrapping". * See {@link DeserializationConfig#withRootName(String)} for * details. *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectReader withRootName(String rootName) { return _with(_config.withRootName(rootName)); } /** * @since 2.6 */ public ObjectReader withRootName(PropertyName rootName) { return _with(_config.withRootName(rootName)); } /** * Convenience method that is same as calling: * * withRootName("") * * which will forcibly prevent use of root name wrapping when writing * values with this {@link ObjectReader}. * * @since 2.6 */ public ObjectReader withoutRootName() { return _with(_config.withRootName(PropertyName.NO_NAME)); } /** * Method for constructing a new instance with configuration that * passes specified {@link FormatSchema} to {@link JsonParser} that * is constructed for parsing content. *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectReader with(FormatSchema schema) { if (_schema == schema) { return this; } _verifySchemaType(schema); return _new(this, _config, _valueType, _rootDeserializer, _valueToUpdate, schema, _injectableValues, _dataFormatReaders); } /** * Method for constructing a new reader instance that is configured * to data bind into specified type. *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. * * @since 2.5 */ public ObjectReader forType(JavaType valueType) { if (valueType != null && valueType.equals(_valueType)) { return this; } JsonDeserializer rootDeser = _prefetchRootDeserializer(valueType); // type is stored here, no need to make a copy of config DataFormatReaders det = _dataFormatReaders; if (det != null) { det = det.withType(valueType); } return _new(this, _config, valueType, rootDeser, _valueToUpdate, _schema, _injectableValues, det); } /** * Method for constructing a new reader instance that is configured * to data bind into specified type. *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. * * @since 2.5 */ public ObjectReader forType(Class valueType) { return forType(_config.constructType(valueType)); } /** * Method for constructing a new reader instance that is configured * to data bind into specified type. *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. * * @since 2.5 */ public ObjectReader forType(TypeReference valueTypeRef) { return forType(_config.getTypeFactory().constructType(valueTypeRef.getType())); } /** * @deprecated since 2.5 Use {@link #forType(JavaType)} instead */ @Deprecated public ObjectReader withType(JavaType valueType) { return forType(valueType); } /** * @deprecated since 2.5 Use {@link #forType(Class)} instead */ @Deprecated public ObjectReader withType(Class valueType) { return forType(_config.constructType(valueType)); } /** * @deprecated since 2.5 Use {@link #forType(Class)} instead */ @Deprecated public ObjectReader withType(java.lang.reflect.Type valueType) { return forType(_config.getTypeFactory().constructType(valueType)); } /** * @deprecated since 2.5 Use {@link #forType(TypeReference)} instead */ @Deprecated public ObjectReader withType(TypeReference valueTypeRef) { return forType(_config.getTypeFactory().constructType(valueTypeRef.getType())); } /** * Method for constructing a new instance with configuration that * updates passed Object (as root value), instead of constructing * a new value. *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectReader withValueToUpdate(Object value) { if (value == _valueToUpdate) return this; if (value == null) { // 18-Oct-2016, tatu: Actually, should be allowed, to remove value // to update, if any return _new(this, _config, _valueType, _rootDeserializer, null, _schema, _injectableValues, _dataFormatReaders); } JavaType t; /* no real benefit from pre-fetching, as updating readers are much * less likely to be reused, and value type may also be forced * with a later chained call... */ if (_valueType == null) { t = _config.constructType(value.getClass()); } else { t = _valueType; } return _new(this, _config, t, _rootDeserializer, value, _schema, _injectableValues, _dataFormatReaders); } /** * Method for constructing a new instance with configuration that * uses specified View for filtering. *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectReader withView(Class activeView) { return _with(_config.withView(activeView)); } public ObjectReader with(Locale l) { return _with(_config.with(l)); } public ObjectReader with(TimeZone tz) { return _with(_config.with(tz)); } public ObjectReader withHandler(DeserializationProblemHandler h) { return _with(_config.withHandler(h)); } public ObjectReader with(Base64Variant defaultBase64) { return _with(_config.with(defaultBase64)); } /** * Fluent factory method for constructing a reader that will try to * auto-detect underlying data format, using specified list of * {@link JsonFactory} instances, and default {@link DataFormatReaders} settings * (for customized {@link DataFormatReaders}, you can construct instance yourself). * to construct appropriate {@link JsonParser} for actual parsing. *

* Note: since format detection only works with byte sources, it is possible to * get a failure from some 'readValue()' methods. Also, if input cannot be reliably * (enough) detected as one of specified types, an exception will be thrown. *

* Note: not all {@link JsonFactory} types can be passed: specifically, ones that * require "custom codec" (like XML factory) will not work. Instead, use * method that takes {@link ObjectReader} instances instead of factories. * * @param readers Data formats accepted, in decreasing order of priority (that is, * matches checked in listed order, first match wins) * * @return Newly configured writer instance * * @since 2.1 */ public ObjectReader withFormatDetection(ObjectReader... readers) { return withFormatDetection(new DataFormatReaders(readers)); } /** * Fluent factory method for constructing a reader that will try to * auto-detect underlying data format, using specified * {@link DataFormatReaders}. *

* NOTE: since format detection only works with byte sources, it is possible to * get a failure from some 'readValue()' methods. Also, if input cannot be reliably * (enough) detected as one of specified types, an exception will be thrown. * * @param readers DataFormatReaders to use for detecting underlying format. * * @return Newly configured writer instance * * @since 2.1 */ public ObjectReader withFormatDetection(DataFormatReaders readers) { return _new(this, _config, _valueType, _rootDeserializer, _valueToUpdate, _schema, _injectableValues, readers); } /** * @since 2.3 */ public ObjectReader with(ContextAttributes attrs) { return _with(_config.with(attrs)); } /** * @since 2.3 */ public ObjectReader withAttributes(Map attrs) { return _with(_config.withAttributes(attrs)); } /** * @since 2.3 */ public ObjectReader withAttribute(Object key, Object value) { return _with( _config.withAttribute(key, value)); } /** * @since 2.3 */ public ObjectReader withoutAttribute(Object key) { return _with(_config.withoutAttribute(key)); } /* /********************************************************** /* Overridable factory methods may override /********************************************************** */ protected ObjectReader _with(DeserializationConfig newConfig) { if (newConfig == _config) { return this; } ObjectReader r = _new(this, newConfig); if (_dataFormatReaders != null) { r = r.withFormatDetection(_dataFormatReaders.with(newConfig)); } return r; } /* /********************************************************** /* Simple accessors /********************************************************** */ public boolean isEnabled(DeserializationFeature f) { return _config.isEnabled(f); } public boolean isEnabled(MapperFeature f) { return _config.isEnabled(f); } public boolean isEnabled(JsonParser.Feature f) { return _parserFactory.isEnabled(f); } /** * @since 2.2 */ public DeserializationConfig getConfig() { return _config; } /** * @since 2.1 */ @Override public JsonFactory getFactory() { return _parserFactory; } public TypeFactory getTypeFactory() { return _config.getTypeFactory(); } /** * @since 2.3 */ public ContextAttributes getAttributes() { return _config.getAttributes(); } /** * @since 2.6 */ public InjectableValues getInjectableValues() { return _injectableValues; } /* /********************************************************** /* Deserialization methods; basic ones to support ObjectCodec first /* (ones that take JsonParser) /********************************************************** */ /** * Method that binds content read using given parser, using * configuration of this reader, including expected result type. * Value return is either newly constructed, or root value that * was specified with {@link #withValueToUpdate(Object)}. *

* NOTE: this method never tries to auto-detect format, since actual * (data-format specific) parser is given. */ @SuppressWarnings("unchecked") public T readValue(JsonParser p) throws IOException { return (T) _bind(p, _valueToUpdate); } /** * Convenience method that binds content read using given parser, using * configuration of this reader, except that expected value type * is specified with the call (instead of currently configured root type). * Value return is either newly constructed, or root value that * was specified with {@link #withValueToUpdate(Object)}. *

* NOTE: this method never tries to auto-detect format, since actual * (data-format specific) parser is given. */ @SuppressWarnings("unchecked") @Override public T readValue(JsonParser p, Class valueType) throws IOException { return (T) forType(valueType).readValue(p); } /** * Convenience method that binds content read using given parser, using * configuration of this reader, except that expected value type * is specified with the call (instead of currently configured root type). * Value return is either newly constructed, or root value that * was specified with {@link #withValueToUpdate(Object)}. *

* NOTE: this method never tries to auto-detect format, since actual * (data-format specific) parser is given. */ @SuppressWarnings("unchecked") @Override public T readValue(JsonParser p, TypeReference valueTypeRef) throws IOException { return (T) forType(valueTypeRef).readValue(p); } /** * Convenience method that binds content read using given parser, using * configuration of this reader, except that expected value type * is specified with the call (instead of currently configured root type). * Value return is either newly constructed, or root value that * was specified with {@link #withValueToUpdate(Object)}. *

* NOTE: this method never tries to auto-detect format, since actual * (data-format specific) parser is given. */ @Override @SuppressWarnings("unchecked") public T readValue(JsonParser p, ResolvedType valueType) throws IOException { return (T) forType((JavaType)valueType).readValue(p); } /** * Type-safe overloaded method, basically alias for {@link #readValue(JsonParser, ResolvedType)}. *

* NOTE: this method never tries to auto-detect format, since actual * (data-format specific) parser is given. */ @SuppressWarnings("unchecked") public T readValue(JsonParser p, JavaType valueType) throws IOException { return (T) forType(valueType).readValue(p); } /** * Convenience method that is equivalent to: *

     *   withType(valueType).readValues(p);
     *
*

* Method reads a sequence of Objects from parser stream. * Sequence can be either root-level "unwrapped" sequence (without surrounding * JSON array), or a sequence contained in a JSON Array. * In either case {@link JsonParser} MUST point to the first token of * the first element, OR not point to any token (in which case it is advanced * to the next token). This means, specifically, that for wrapped sequences, * parser MUST NOT point to the surrounding START_ARRAY (one that * contains values to read) but rather to the token following it which is the first * token of the first value to read. *

* NOTE: this method never tries to auto-detect format, since actual * (data-format specific) parser is given. */ @Override public Iterator readValues(JsonParser p, Class valueType) throws IOException { return forType(valueType).readValues(p); } /** * Convenience method that is equivalent to: *

     *   withType(valueTypeRef).readValues(p);
     *
*

* Method reads a sequence of Objects from parser stream. * Sequence can be either root-level "unwrapped" sequence (without surrounding * JSON array), or a sequence contained in a JSON Array. * In either case {@link JsonParser} MUST point to the first token of * the first element, OR not point to any token (in which case it is advanced * to the next token). This means, specifically, that for wrapped sequences, * parser MUST NOT point to the surrounding START_ARRAY (one that * contains values to read) but rather to the token following it which is the first * token of the first value to read. *

* NOTE: this method never tries to auto-detect format, since actual * (data-format specific) parser is given. */ @Override public Iterator readValues(JsonParser p, TypeReference valueTypeRef) throws IOException { return forType(valueTypeRef).readValues(p); } /** * Convenience method that is equivalent to: *

     *   withType(valueType).readValues(p);
     *
*

* Method reads a sequence of Objects from parser stream. * Sequence can be either root-level "unwrapped" sequence (without surrounding * JSON array), or a sequence contained in a JSON Array. * In either case {@link JsonParser} MUST point to the first token of * the first element, OR not point to any token (in which case it is advanced * to the next token). This means, specifically, that for wrapped sequences, * parser MUST NOT point to the surrounding START_ARRAY (one that * contains values to read) but rather to the token following it which is the first * token of the first value to read. *

* NOTE: this method never tries to auto-detect format, since actual * (data-format specific) parser is given. */ @Override public Iterator readValues(JsonParser p, ResolvedType valueType) throws IOException { return readValues(p, (JavaType) valueType); } /** * Convenience method that is equivalent to: *

     *   withType(valueType).readValues(p);
     *
*

* Method reads a sequence of Objects from parser stream. * Sequence can be either root-level "unwrapped" sequence (without surrounding * JSON array), or a sequence contained in a JSON Array. * In either case {@link JsonParser} MUST point to the first token of * the first element, OR not point to any token (in which case it is advanced * to the next token). This means, specifically, that for wrapped sequences, * parser MUST NOT point to the surrounding START_ARRAY (one that * contains values to read) but rather to the token following it which is the first * token of the first value to read. *

* NOTE: this method never tries to auto-detect format, since actual * (data-format specific) parser is given. */ public Iterator readValues(JsonParser p, JavaType valueType) throws IOException { return forType(valueType).readValues(p); } /* /********************************************************** /* TreeCodec impl /********************************************************** */ @Override public JsonNode createArrayNode() { return _config.getNodeFactory().arrayNode(); } @Override public JsonNode createObjectNode() { return _config.getNodeFactory().objectNode(); } @Override public JsonParser treeAsTokens(TreeNode n) { // 05-Dec-2017, tatu: Important! Must clear "valueToUpdate" since we do not // want update to be applied here, as a side effect ObjectReader codec = withValueToUpdate(null); return new TreeTraversingParser((JsonNode) n, codec); } /** * Convenience method that binds content read using given parser, using * configuration of this reader, except that content is bound as * JSON tree instead of configured root value type. *

* Note: if an object was specified with {@link #withValueToUpdate}, it * will be ignored. *

* NOTE: this method never tries to auto-detect format, since actual * (data-format specific) parser is given. */ @SuppressWarnings("unchecked") @Override public T readTree(JsonParser p) throws IOException { return (T) _bindAsTree(p); } @Override public void writeTree(JsonGenerator g, TreeNode rootNode) { throw new UnsupportedOperationException(); } /* /********************************************************** /* Deserialization methods; others similar to what ObjectMapper has /********************************************************** */ /** * Method that binds content read from given input source, * using configuration of this reader. * Value return is either newly constructed, or root value that * was specified with {@link #withValueToUpdate(Object)}. */ @SuppressWarnings("unchecked") public T readValue(InputStream src) throws IOException { if (_dataFormatReaders != null) { return (T) _detectBindAndClose(_dataFormatReaders.findFormat(src), false); } return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false)); } /** * Method that binds content read from given input source, * using configuration of this reader. * Value return is either newly constructed, or root value that * was specified with {@link #withValueToUpdate(Object)}. */ @SuppressWarnings("unchecked") public T readValue(Reader src) throws IOException { if (_dataFormatReaders != null) { _reportUndetectableSource(src); } return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false)); } /** * Method that binds content read from given JSON string, * using configuration of this reader. * Value return is either newly constructed, or root value that * was specified with {@link #withValueToUpdate(Object)}. */ @SuppressWarnings("unchecked") public T readValue(String src) throws IOException { if (_dataFormatReaders != null) { _reportUndetectableSource(src); } return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false)); } /** * Method that binds content read from given byte array, * using configuration of this reader. * Value return is either newly constructed, or root value that * was specified with {@link #withValueToUpdate(Object)}. */ @SuppressWarnings("unchecked") public T readValue(byte[] src) throws IOException { if (_dataFormatReaders != null) { return (T) _detectBindAndClose(src, 0, src.length); } return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false)); } /** * Method that binds content read from given byte array, * using configuration of this reader. * Value return is either newly constructed, or root value that * was specified with {@link #withValueToUpdate(Object)}. */ @SuppressWarnings("unchecked") public T readValue(byte[] src, int offset, int length) throws IOException { if (_dataFormatReaders != null) { return (T) _detectBindAndClose(src, offset, length); } return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src, offset, length), false)); } @SuppressWarnings("unchecked") public T readValue(File src) throws IOException { if (_dataFormatReaders != null) { return (T) _detectBindAndClose(_dataFormatReaders.findFormat(_inputStream(src)), true); } return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false)); } /** * Method that binds content read from given input source, * using configuration of this reader. * Value return is either newly constructed, or root value that * was specified with {@link #withValueToUpdate(Object)}. */ @SuppressWarnings("unchecked") public T readValue(URL src) throws IOException { if (_dataFormatReaders != null) { return (T) _detectBindAndClose(_dataFormatReaders.findFormat(_inputStream(src)), true); } return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false)); } /** * Convenience method for converting results from given JSON tree into given * value type. Basically short-cut for: *

     *   objectReader.readValue(src.traverse())
     *
*/ @SuppressWarnings({ "unchecked", "resource" }) public T readValue(JsonNode src) throws IOException { if (_dataFormatReaders != null) { _reportUndetectableSource(src); } return (T) _bindAndClose(_considerFilter(treeAsTokens(src), false)); } /** * @since 2.8 */ @SuppressWarnings("unchecked") public T readValue(DataInput src) throws IOException { if (_dataFormatReaders != null) { _reportUndetectableSource(src); } return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false)); } /** * Method that reads content from given input source, * using configuration of this reader, and binds it as JSON Tree. *

* Note that if an object was specified with a call to * {@link #withValueToUpdate(Object)} * it will just be ignored; result is always a newly constructed * {@link JsonNode} instance. */ public JsonNode readTree(InputStream in) throws IOException { if (_dataFormatReaders != null) { return _detectBindAndCloseAsTree(in); } return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(in), false)); } /** * Method that reads content from given input source, * using configuration of this reader, and binds it as JSON Tree. *

* Note that if an object was specified with a call to * {@link #withValueToUpdate(Object)} * it will just be ignored; result is always a newly constructed * {@link JsonNode} instance. */ public JsonNode readTree(Reader r) throws IOException { if (_dataFormatReaders != null) { _reportUndetectableSource(r); } return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(r), false)); } /** * Method that reads content from given JSON input String, * using configuration of this reader, and binds it as JSON Tree. *

* Note that if an object was specified with a call to * {@link #withValueToUpdate(Object)} * it will just be ignored; result is always a newly constructed * {@link JsonNode} instance. */ public JsonNode readTree(String json) throws IOException { if (_dataFormatReaders != null) { _reportUndetectableSource(json); } return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(json), false)); } public JsonNode readTree(DataInput src) throws IOException { if (_dataFormatReaders != null) { _reportUndetectableSource(src); } return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(src), false)); } /* /********************************************************** /* Deserialization methods; reading sequence of values /********************************************************** */ /** * Method for reading sequence of Objects from parser stream. *

* Sequence can be either root-level "unwrapped" sequence (without surrounding * JSON array), or a sequence contained in a JSON Array. * In either case {@link JsonParser} must point to the first token of * the first element, OR not point to any token (in which case it is advanced * to the next token). This means, specifically, that for wrapped sequences, * parser MUST NOT point to the surrounding START_ARRAY but rather * to the token following it. */ public MappingIterator readValues(JsonParser p) throws IOException { DeserializationContext ctxt = createDeserializationContext(p); // false -> do not close as caller gave parser instance return _newIterator(p, ctxt, _findRootDeserializer(ctxt), false); } /** * Method for reading sequence of Objects from parser stream. *

* Sequence can be either wrapped or unwrapped root-level sequence: * wrapped means that the elements are enclosed in JSON Array; * and unwrapped that elements are directly accessed at main level. * Assumption is that iff the first token of the document is * START_ARRAY, we have a wrapped sequence; otherwise * unwrapped. For wrapped sequences, leading START_ARRAY * is skipped, so that for both cases, underlying {@link JsonParser} * will point to what is expected to be the first token of the first * element. *

* Note that the wrapped vs unwrapped logic means that it is NOT * possible to use this method for reading an unwrapped sequence * of elements written as JSON Arrays: to read such sequences, one * has to use {@link #readValues(JsonParser)}, making sure parser * points to the first token of the first element (i.e. the second * START_ARRAY which is part of the first element). */ public MappingIterator readValues(InputStream src) throws IOException { if (_dataFormatReaders != null) { return _detectBindAndReadValues(_dataFormatReaders.findFormat(src), false); } return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src), true)); } /** * Overloaded version of {@link #readValue(InputStream)}. */ @SuppressWarnings("resource") public MappingIterator readValues(Reader src) throws IOException { if (_dataFormatReaders != null) { _reportUndetectableSource(src); } JsonParser p = _considerFilter(_parserFactory.createParser(src), true); DeserializationContext ctxt = createDeserializationContext(p); _initForMultiRead(ctxt, p); p.nextToken(); return _newIterator(p, ctxt, _findRootDeserializer(ctxt), true); } /** * Overloaded version of {@link #readValue(InputStream)}. * * @param json String that contains JSON content to parse */ @SuppressWarnings("resource") public MappingIterator readValues(String json) throws IOException { if (_dataFormatReaders != null) { _reportUndetectableSource(json); } JsonParser p = _considerFilter(_parserFactory.createParser(json), true); DeserializationContext ctxt = createDeserializationContext(p); _initForMultiRead(ctxt, p); p.nextToken(); return _newIterator(p, ctxt, _findRootDeserializer(ctxt), true); } /** * Overloaded version of {@link #readValue(InputStream)}. */ public MappingIterator readValues(byte[] src, int offset, int length) throws IOException { if (_dataFormatReaders != null) { return _detectBindAndReadValues(_dataFormatReaders.findFormat(src, offset, length), false); } return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src, offset, length), true)); } /** * Overloaded version of {@link #readValue(InputStream)}. */ public final MappingIterator readValues(byte[] src) throws IOException { return readValues(src, 0, src.length); } /** * Overloaded version of {@link #readValue(InputStream)}. */ public MappingIterator readValues(File src) throws IOException { if (_dataFormatReaders != null) { return _detectBindAndReadValues( _dataFormatReaders.findFormat(_inputStream(src)), false); } return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src), true)); } /** * Overloaded version of {@link #readValue(InputStream)}. * * @param src URL to read to access JSON content to parse. */ public MappingIterator readValues(URL src) throws IOException { if (_dataFormatReaders != null) { return _detectBindAndReadValues( _dataFormatReaders.findFormat(_inputStream(src)), true); } return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src), true)); } /** * @since 2.8 */ public MappingIterator readValues(DataInput src) throws IOException { if (_dataFormatReaders != null) { _reportUndetectableSource(src); } return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src), true)); } /* /********************************************************** /* Implementation of rest of ObjectCodec methods /********************************************************** */ @Override public T treeToValue(TreeNode n, Class valueType) throws JsonProcessingException { try { return readValue(treeAsTokens(n), valueType); } catch (JsonProcessingException e) { throw e; } catch (IOException e) { // should not occur, no real i/o... throw JsonMappingException.fromUnexpectedIOE(e); } } @Override public void writeValue(JsonGenerator gen, Object value) throws IOException { throw new UnsupportedOperationException("Not implemented for ObjectReader"); } /* /********************************************************** /* Helper methods, data-binding /********************************************************** */ /** * Actual implementation of value reading+binding operation. */ protected Object _bind(JsonParser p, Object valueToUpdate) throws IOException { /* First: may need to read the next token, to initialize state (either * before first read from parser, or after previous token has been cleared) */ Object result; final DeserializationContext ctxt = createDeserializationContext(p); JsonToken t = _initForReading(ctxt, p); if (t == JsonToken.VALUE_NULL) { if (valueToUpdate == null) { result = _findRootDeserializer(ctxt).getNullValue(ctxt); } else { result = valueToUpdate; } } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { result = valueToUpdate; } else { // pointing to event other than null JsonDeserializer deser = _findRootDeserializer(ctxt); if (_unwrapRoot) { result = _unwrapAndDeserialize(p, ctxt, _valueType, deser); } else { if (valueToUpdate == null) { result = deser.deserialize(p, ctxt); } else { // 20-Mar-2017, tatu: Important! May be different from `valueToUpdate` // for immutable Objects like Java arrays; logical result result = deser.deserialize(p, ctxt, valueToUpdate); } } } // Need to consume the token too p.clearCurrentToken(); if (_config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) { _verifyNoTrailingTokens(p, ctxt, _valueType); } return result; } protected Object _bindAndClose(JsonParser p0) throws IOException { try (JsonParser p = p0) { Object result; DeserializationContext ctxt = createDeserializationContext(p); JsonToken t = _initForReading(ctxt, p); if (t == JsonToken.VALUE_NULL) { if (_valueToUpdate == null) { result = _findRootDeserializer(ctxt).getNullValue(ctxt); } else { result = _valueToUpdate; } } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { result = _valueToUpdate; } else { JsonDeserializer deser = _findRootDeserializer(ctxt); if (_unwrapRoot) { result = _unwrapAndDeserialize(p, ctxt, _valueType, deser); } else { if (_valueToUpdate == null) { result = deser.deserialize(p, ctxt); } else { deser.deserialize(p, ctxt, _valueToUpdate); result = _valueToUpdate; } } } if (_config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) { _verifyNoTrailingTokens(p, ctxt, _valueType); } return result; } } protected final JsonNode _bindAndCloseAsTree(JsonParser p0) throws IOException { try (JsonParser p = p0) { return _bindAsTree(p); } } protected final JsonNode _bindAsTree(JsonParser p) throws IOException { // 27-Oct-2016, tatu: Need to inline `_initForReading()` due to // special requirements by tree reading (no fail on eof) _config.initialize(p); if (_schema != null) { p.setSchema(_schema); } JsonToken t = p.getCurrentToken(); if (t == null) { t = p.nextToken(); if (t == null) { // [databind#1406]: expose end-of-input as `null` return null; } } DeserializationContext ctxt = createDeserializationContext(p); if (t == JsonToken.VALUE_NULL) { return ctxt.getNodeFactory().nullNode(); } JsonDeserializer deser = _findTreeDeserializer(ctxt); Object result; if (_unwrapRoot) { result = _unwrapAndDeserialize(p, ctxt, JSON_NODE_TYPE, deser); } else { result = deser.deserialize(p, ctxt); if (_config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) { _verifyNoTrailingTokens(p, ctxt, JSON_NODE_TYPE); } } return (JsonNode) result; } /** * @since 2.1 */ protected MappingIterator _bindAndReadValues(JsonParser p) throws IOException { DeserializationContext ctxt = createDeserializationContext(p); _initForMultiRead(ctxt, p); p.nextToken(); return _newIterator(p, ctxt, _findRootDeserializer(ctxt), true); } protected Object _unwrapAndDeserialize(JsonParser p, DeserializationContext ctxt, JavaType rootType, JsonDeserializer deser) throws IOException { PropertyName expRootName = _config.findRootName(rootType); // 12-Jun-2015, tatu: Should try to support namespaces etc but... String expSimpleName = expRootName.getSimpleName(); if (p.getCurrentToken() != JsonToken.START_OBJECT) { ctxt.reportWrongTokenException(rootType, JsonToken.START_OBJECT, "Current token not START_OBJECT (needed to unwrap root name '%s'), but %s", expSimpleName, p.getCurrentToken()); } if (p.nextToken() != JsonToken.FIELD_NAME) { ctxt.reportWrongTokenException(rootType, JsonToken.FIELD_NAME, "Current token not FIELD_NAME (to contain expected root name '%s'), but %s", expSimpleName, p.getCurrentToken()); } String actualName = p.getCurrentName(); if (!expSimpleName.equals(actualName)) { ctxt.reportInputMismatch(rootType, "Root name '%s' does not match expected ('%s') for type %s", actualName, expSimpleName, rootType); } // ok, then move to value itself.... p.nextToken(); Object result; if (_valueToUpdate == null) { result = deser.deserialize(p, ctxt); } else { deser.deserialize(p, ctxt, _valueToUpdate); result = _valueToUpdate; } // and last, verify that we now get matching END_OBJECT if (p.nextToken() != JsonToken.END_OBJECT) { ctxt.reportWrongTokenException(rootType, JsonToken.END_OBJECT, "Current token not END_OBJECT (to match wrapper object with root name '%s'), but %s", expSimpleName, p.getCurrentToken()); } if (_config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) { _verifyNoTrailingTokens(p, ctxt, _valueType); } return result; } /** * Consider filter when creating JsonParser. */ protected JsonParser _considerFilter(final JsonParser p, boolean multiValue) { // 26-Mar-2016, tatu: Need to allow multiple-matches at least if we have // have a multiple-value read (that is, "readValues()"). return ((_filter == null) || FilteringParserDelegate.class.isInstance(p)) ? p : new FilteringParserDelegate(p, _filter, false, multiValue); } /** * @since 2.9 */ protected final void _verifyNoTrailingTokens(JsonParser p, DeserializationContext ctxt, JavaType bindType) throws IOException { JsonToken t = p.nextToken(); if (t != null) { Class bt = ClassUtil.rawClass(bindType); if (bt == null) { if (_valueToUpdate != null) { bt = _valueToUpdate.getClass(); } } ctxt.reportTrailingTokens(bt, p, t); } } /* /********************************************************** /* Internal methods, format auto-detection /********************************************************** */ @SuppressWarnings("resource") protected Object _detectBindAndClose(byte[] src, int offset, int length) throws IOException { DataFormatReaders.Match match = _dataFormatReaders.findFormat(src, offset, length); if (!match.hasMatch()) { _reportUnkownFormat(_dataFormatReaders, match); } JsonParser p = match.createParserWithMatch(); return match.getReader()._bindAndClose(p); } @SuppressWarnings("resource") protected Object _detectBindAndClose(DataFormatReaders.Match match, boolean forceClosing) throws IOException { if (!match.hasMatch()) { _reportUnkownFormat(_dataFormatReaders, match); } JsonParser p = match.createParserWithMatch(); // One more thing: we Own the input stream now; and while it's // not super clean way to do it, we must ensure closure so: if (forceClosing) { p.enable(JsonParser.Feature.AUTO_CLOSE_SOURCE); } // important: use matching ObjectReader (may not be 'this') return match.getReader()._bindAndClose(p); } @SuppressWarnings("resource") protected MappingIterator _detectBindAndReadValues(DataFormatReaders.Match match, boolean forceClosing) throws IOException { if (!match.hasMatch()) { _reportUnkownFormat(_dataFormatReaders, match); } JsonParser p = match.createParserWithMatch(); // One more thing: we Own the input stream now; and while it's // not super clean way to do it, we must ensure closure so: if (forceClosing) { p.enable(JsonParser.Feature.AUTO_CLOSE_SOURCE); } // important: use matching ObjectReader (may not be 'this') return match.getReader()._bindAndReadValues(p); } @SuppressWarnings("resource") protected JsonNode _detectBindAndCloseAsTree(InputStream in) throws IOException { DataFormatReaders.Match match = _dataFormatReaders.findFormat(in); if (!match.hasMatch()) { _reportUnkownFormat(_dataFormatReaders, match); } JsonParser p = match.createParserWithMatch(); p.enable(JsonParser.Feature.AUTO_CLOSE_SOURCE); return match.getReader()._bindAndCloseAsTree(p); } /** * Method called to indicate that format detection failed to detect format * of given input */ protected void _reportUnkownFormat(DataFormatReaders detector, DataFormatReaders.Match match) throws JsonProcessingException { // 17-Aug-2015, tatu: Unfortunately, no parser/generator available so: throw new JsonParseException(null, "Cannot detect format from input, does not look like any of detectable formats " +detector.toString()); } /* /********************************************************** /* Internal methods, other /********************************************************** */ /** * @since 2.2 */ protected void _verifySchemaType(FormatSchema schema) { if (schema != null) { if (!_parserFactory.canUseSchema(schema)) { throw new IllegalArgumentException("Cannot use FormatSchema of type "+schema.getClass().getName() +" for format "+_parserFactory.getFormatName()); } } } /** * Internal helper method called to create an instance of {@link DeserializationContext} * for deserializing a single root value. * Can be overridden if a custom context is needed. */ protected DefaultDeserializationContext createDeserializationContext(JsonParser p) { return _context.createInstance(_config, p, _injectableValues); } protected InputStream _inputStream(URL src) throws IOException { return src.openStream(); } protected InputStream _inputStream(File f) throws IOException { return new FileInputStream(f); } protected void _reportUndetectableSource(Object src) throws JsonProcessingException { // 17-Aug-2015, tatu: Unfortunately, no parser/generator available so: throw new JsonParseException(null, "Cannot use source of type " +src.getClass().getName()+" with format auto-detection: must be byte- not char-based"); } /* /********************************************************** /* Helper methods, locating deserializers etc /********************************************************** */ /** * Method called to locate deserializer for the passed root-level value. */ protected JsonDeserializer _findRootDeserializer(DeserializationContext ctxt) throws JsonMappingException { if (_rootDeserializer != null) { return _rootDeserializer; } // Sanity check: must have actual type... JavaType t = _valueType; if (t == null) { ctxt.reportBadDefinition((JavaType) null, "No value type configured for ObjectReader"); } // First: have we already seen it? JsonDeserializer deser = _rootDeserializers.get(t); if (deser != null) { return deser; } // Nope: need to ask provider to resolve it deser = ctxt.findRootValueDeserializer(t); if (deser == null) { // can this happen? ctxt.reportBadDefinition(t, "Cannot find a deserializer for type "+t); } _rootDeserializers.put(t, deser); return deser; } /** * @since 2.6 */ protected JsonDeserializer _findTreeDeserializer(DeserializationContext ctxt) throws JsonMappingException { JsonDeserializer deser = _rootDeserializers.get(JSON_NODE_TYPE); if (deser == null) { // Nope: need to ask provider to resolve it deser = ctxt.findRootValueDeserializer(JSON_NODE_TYPE); if (deser == null) { // can this happen? ctxt.reportBadDefinition(JSON_NODE_TYPE, "Cannot find a deserializer for type "+JSON_NODE_TYPE); } _rootDeserializers.put(JSON_NODE_TYPE, deser); } return deser; } /** * Method called to locate deserializer ahead of time, if permitted * by configuration. Method also is NOT to throw an exception if * access fails. */ protected JsonDeserializer _prefetchRootDeserializer(JavaType valueType) { if ((valueType == null) || !_config.isEnabled(DeserializationFeature.EAGER_DESERIALIZER_FETCH)) { return null; } // already cached? JsonDeserializer deser = _rootDeserializers.get(valueType); if (deser == null) { try { // If not, need to resolve; for which we need a temporary context as well: DeserializationContext ctxt = createDeserializationContext(null); deser = ctxt.findRootValueDeserializer(valueType); if (deser != null) { _rootDeserializers.put(valueType, deser); } return deser; } catch (JsonProcessingException e) { // need to swallow? } } return deser; } } ObjectWriter.java000066400000000000000000001355761325620701100337370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.*; import java.text.*; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.CharacterEscapes; import com.fasterxml.jackson.core.io.SegmentedStringWriter; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.util.*; import com.fasterxml.jackson.databind.cfg.ContextAttributes; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.*; import com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Builder object that can be used for per-serialization configuration of * serialization parameters, such as JSON View and root type to use. * (and thus fully thread-safe with no external synchronization); * new instances are constructed for different configurations. * Instances are initially constructed by {@link ObjectMapper} and can be * reused in completely thread-safe manner with no explicit synchronization */ public class ObjectWriter implements Versioned, java.io.Serializable // since 2.1 { private static final long serialVersionUID = 1; // since 2.5 /** * We need to keep track of explicit disabling of pretty printing; * easiest to do by a token value. */ protected final static PrettyPrinter NULL_PRETTY_PRINTER = new MinimalPrettyPrinter(); /* /********************************************************** /* Immutable configuration from ObjectMapper /********************************************************** */ /** * General serialization configuration settings */ protected final SerializationConfig _config; protected final DefaultSerializerProvider _serializerProvider; protected final SerializerFactory _serializerFactory; /** * Factory used for constructing {@link JsonGenerator}s */ protected final JsonFactory _generatorFactory; /* /********************************************************** /* Configuration that can be changed via mutant factories /********************************************************** */ /** * Container for settings that need to be passed to {@link JsonGenerator} * constructed for serializing values. * * @since 2.5 */ protected final GeneratorSettings _generatorSettings; /** * We may pre-fetch serializer if root type * is known (has been explicitly declared), and if so, reuse it afterwards. * This allows avoiding further serializer lookups and increases * performance a bit on cases where readers are reused. * * @since 2.5 */ protected final Prefetch _prefetch; /* /********************************************************** /* Life-cycle, constructors /********************************************************** */ /** * Constructor used by {@link ObjectMapper} for initial instantiation */ protected ObjectWriter(ObjectMapper mapper, SerializationConfig config, JavaType rootType, PrettyPrinter pp) { _config = config; _serializerProvider = mapper._serializerProvider; _serializerFactory = mapper._serializerFactory; _generatorFactory = mapper._jsonFactory; _generatorSettings = (pp == null) ? GeneratorSettings.empty : new GeneratorSettings(pp, null, null, null); // 29-Apr-2014, tatu: There is no "untyped serializer", so: if (rootType == null || rootType.hasRawClass(Object.class)) { _prefetch = Prefetch.empty; } else { rootType = rootType.withStaticTyping(); _prefetch = Prefetch.empty.forRootType(this, rootType); } } /** * Alternative constructor for initial instantiation by {@link ObjectMapper} */ protected ObjectWriter(ObjectMapper mapper, SerializationConfig config) { _config = config; _serializerProvider = mapper._serializerProvider; _serializerFactory = mapper._serializerFactory; _generatorFactory = mapper._jsonFactory; _generatorSettings = GeneratorSettings.empty; _prefetch = Prefetch.empty; } /** * Alternative constructor for initial instantiation by {@link ObjectMapper} */ protected ObjectWriter(ObjectMapper mapper, SerializationConfig config, FormatSchema s) { _config = config; _serializerProvider = mapper._serializerProvider; _serializerFactory = mapper._serializerFactory; _generatorFactory = mapper._jsonFactory; _generatorSettings = (s == null) ? GeneratorSettings.empty : new GeneratorSettings(null, s, null, null); _prefetch = Prefetch.empty; } /** * Copy constructor used for building variations. */ protected ObjectWriter(ObjectWriter base, SerializationConfig config, GeneratorSettings genSettings, Prefetch prefetch) { _config = config; _serializerProvider = base._serializerProvider; _serializerFactory = base._serializerFactory; _generatorFactory = base._generatorFactory; _generatorSettings = genSettings; _prefetch = prefetch; } /** * Copy constructor used for building variations. */ protected ObjectWriter(ObjectWriter base, SerializationConfig config) { _config = config; _serializerProvider = base._serializerProvider; _serializerFactory = base._serializerFactory; _generatorFactory = base._generatorFactory; _generatorSettings = base._generatorSettings; _prefetch = base._prefetch; } /** * @since 2.3 */ protected ObjectWriter(ObjectWriter base, JsonFactory f) { // may need to override ordering, based on data format capabilities _config = base._config .with(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, f.requiresPropertyOrdering()); _serializerProvider = base._serializerProvider; _serializerFactory = base._serializerFactory; _generatorFactory = f; _generatorSettings = base._generatorSettings; _prefetch = base._prefetch; } /** * Method that will return version information stored in and read from jar * that contains this class. */ @Override public Version version() { return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION; } /* /********************************************************** /* Methods sub-classes MUST override, used for constructing /* writer instances, (re)configuring parser instances. /* Added in 2.5 /********************************************************** */ /** * Overridable factory method called by various "withXxx()" methods * * @since 2.5 */ protected ObjectWriter _new(ObjectWriter base, JsonFactory f) { return new ObjectWriter(base, f); } /** * Overridable factory method called by various "withXxx()" methods * * @since 2.5 */ protected ObjectWriter _new(ObjectWriter base, SerializationConfig config) { if (config == _config) { return this; } return new ObjectWriter(base, config); } /** * Overridable factory method called by various "withXxx()" methods. * It assumes `this` as base for settings other than those directly * passed in. * * @since 2.5 */ protected ObjectWriter _new(GeneratorSettings genSettings, Prefetch prefetch) { if ((_generatorSettings == genSettings) && (_prefetch == prefetch)) { return this; } return new ObjectWriter(this, _config, genSettings, prefetch); } /** * Overridable factory method called by {@link #writeValues(OutputStream)} * method (and its various overrides), and initializes it as necessary. * * @since 2.5 */ @SuppressWarnings("resource") protected SequenceWriter _newSequenceWriter(boolean wrapInArray, JsonGenerator gen, boolean managedInput) throws IOException { _configureGenerator(gen); return new SequenceWriter(_serializerProvider(), gen, managedInput, _prefetch) .init(wrapInArray); } /* /********************************************************** /* Life-cycle, fluent factories for SerializationFeature /********************************************************** */ /** * Method for constructing a new instance that is configured * with specified feature enabled. */ public ObjectWriter with(SerializationFeature feature) { return _new(this, _config.with(feature)); } /** * Method for constructing a new instance that is configured * with specified features enabled. */ public ObjectWriter with(SerializationFeature first, SerializationFeature... other) { return _new(this, _config.with(first, other)); } /** * Method for constructing a new instance that is configured * with specified features enabled. */ public ObjectWriter withFeatures(SerializationFeature... features) { return _new(this, _config.withFeatures(features)); } /** * Method for constructing a new instance that is configured * with specified feature enabled. */ public ObjectWriter without(SerializationFeature feature) { return _new(this, _config.without(feature)); } /** * Method for constructing a new instance that is configured * with specified features enabled. */ public ObjectWriter without(SerializationFeature first, SerializationFeature... other) { return _new(this, _config.without(first, other)); } /** * Method for constructing a new instance that is configured * with specified features enabled. */ public ObjectWriter withoutFeatures(SerializationFeature... features) { return _new(this, _config.withoutFeatures(features)); } /* /********************************************************** /* Life-cycle, fluent factories for JsonGenerator.Feature (2.5) /********************************************************** */ /** * @since 2.5 */ public ObjectWriter with(JsonGenerator.Feature feature) { return _new(this, _config.with(feature)); } /** * @since 2.5 */ public ObjectWriter withFeatures(JsonGenerator.Feature... features) { return _new(this, _config.withFeatures(features)); } /** * @since 2.5 */ public ObjectWriter without(JsonGenerator.Feature feature) { return _new(this, _config.without(feature)); } /** * @since 2.5 */ public ObjectWriter withoutFeatures(JsonGenerator.Feature... features) { return _new(this, _config.withoutFeatures(features)); } /* /********************************************************** /* Life-cycle, fluent factories for FormatFeature (2.7) /********************************************************** */ /** * @since 2.7 */ public ObjectWriter with(FormatFeature feature) { return _new(this, _config.with(feature)); } /** * @since 2.7 */ public ObjectWriter withFeatures(FormatFeature... features) { return _new(this, _config.withFeatures(features)); } /** * @since 2.7 */ public ObjectWriter without(FormatFeature feature) { return _new(this, _config.without(feature)); } /** * @since 2.7 */ public ObjectWriter withoutFeatures(FormatFeature... features) { return _new(this, _config.withoutFeatures(features)); } /* /********************************************************** /* Life-cycle, fluent factories, type-related /********************************************************** */ /** * Method that will construct a new instance that uses specific type * as the root type for serialization, instead of runtime dynamic * type of the root object itself. *

* Note that method does NOT change state of this reader, but * rather construct and returns a newly configured instance. * * @since 2.5 */ public ObjectWriter forType(JavaType rootType) { return _new(_generatorSettings, _prefetch.forRootType(this, rootType)); } /** * Method that will construct a new instance that uses specific type * as the root type for serialization, instead of runtime dynamic * type of the root object itself. * * @since 2.5 */ public ObjectWriter forType(Class rootType) { if (rootType == Object.class) { return forType((JavaType) null); } return forType(_config.constructType(rootType)); } /** * Method that will construct a new instance that uses specific type * as the root type for serialization, instead of runtime dynamic * type of the root object itself. * * @since 2.5 */ public ObjectWriter forType(TypeReference rootType) { return forType(_config.getTypeFactory().constructType(rootType.getType())); } /** * @deprecated since 2.5 Use {@link #forType(JavaType)} instead */ @Deprecated // since 2.5 public ObjectWriter withType(JavaType rootType) { return forType(rootType); } /** * @deprecated since 2.5 Use {@link #forType(Class)} instead */ @Deprecated // since 2.5 public ObjectWriter withType(Class rootType) { return forType(rootType); } /** * @deprecated since 2.5 Use {@link #forType(TypeReference)} instead */ @Deprecated // since 2.5 public ObjectWriter withType(TypeReference rootType) { return forType(rootType); } /* /********************************************************** /* Life-cycle, fluent factories, other /********************************************************** */ /** * Fluent factory method that will construct a new writer instance that will * use specified date format for serializing dates; or if null passed, one * that will serialize dates as numeric timestamps. *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectWriter with(DateFormat df) { return _new(this, _config.with(df)); } /** * Method that will construct a new instance that will use the default * pretty printer for serialization. */ public ObjectWriter withDefaultPrettyPrinter() { return with(_config.getDefaultPrettyPrinter()); } /** * Method that will construct a new instance that uses specified * provider for resolving filter instances by id. */ public ObjectWriter with(FilterProvider filterProvider) { if (filterProvider == _config.getFilterProvider()) { return this; } return _new(this, _config.withFilters(filterProvider)); } /** * Method that will construct a new instance that will use specified pretty * printer (or, if null, will not do any pretty-printing) */ public ObjectWriter with(PrettyPrinter pp) { return _new(_generatorSettings.with(pp), _prefetch); } /** * Method for constructing a new instance with configuration that * specifies what root name to use for "root element wrapping". * See {@link SerializationConfig#withRootName(String)} for details. *

* Note that method does NOT change state of this reader, but * rather construct and returns a newly configured instance. * * @param rootName Root name to use, if non-empty; `null` for "use defaults", * and empty String ("") for "do NOT add root wrapper" */ public ObjectWriter withRootName(String rootName) { return _new(this, _config.withRootName(rootName)); } /** * @since 2.6 */ public ObjectWriter withRootName(PropertyName rootName) { return _new(this, _config.withRootName(rootName)); } /** * Convenience method that is same as calling: * * withRootName("") * * which will forcibly prevent use of root name wrapping when writing * values with this {@link ObjectWriter}. * * @since 2.6 */ public ObjectWriter withoutRootName() { return _new(this, _config.withRootName(PropertyName.NO_NAME)); } /** * Method that will construct a new instance that uses specific format schema * for serialization. *

* Note that method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectWriter with(FormatSchema schema) { _verifySchemaType(schema); return _new(_generatorSettings.with(schema), _prefetch); } /** * @deprecated Since 2.5 use {@link #with(FormatSchema)} instead */ @Deprecated public ObjectWriter withSchema(FormatSchema schema) { return with(schema); } /** * Method that will construct a new instance that uses specified * serialization view for serialization (with null basically disables * view processing) *

* Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectWriter withView(Class view) { return _new(this, _config.withView(view)); } public ObjectWriter with(Locale l) { return _new(this, _config.with(l)); } public ObjectWriter with(TimeZone tz) { return _new(this, _config.with(tz)); } /** * Method that will construct a new instance that uses specified default * {@link Base64Variant} for base64 encoding * * @since 2.1 */ public ObjectWriter with(Base64Variant b64variant) { return _new(this, _config.with(b64variant)); } /** * @since 2.3 */ public ObjectWriter with(CharacterEscapes escapes) { return _new(_generatorSettings.with(escapes), _prefetch); } /** * @since 2.3 */ public ObjectWriter with(JsonFactory f) { return (f == _generatorFactory) ? this : _new(this, f); } /** * @since 2.3 */ public ObjectWriter with(ContextAttributes attrs) { return _new(this, _config.with(attrs)); } /** * Mutant factory method that allows construction of a new writer instance * that uses specified set of default attribute values. * * @since 2.3 */ public ObjectWriter withAttributes(Map attrs) { return _new(this, _config.withAttributes(attrs)); } /** * @since 2.3 */ public ObjectWriter withAttribute(Object key, Object value) { return _new(this, _config.withAttribute(key, value)); } /** * @since 2.3 */ public ObjectWriter withoutAttribute(Object key) { return _new(this, _config.withoutAttribute(key)); } /** * @since 2.5 */ public ObjectWriter withRootValueSeparator(String sep) { return _new(_generatorSettings.withRootValueSeparator(sep), _prefetch); } /** * @since 2.5 */ public ObjectWriter withRootValueSeparator(SerializableString sep) { return _new(_generatorSettings.withRootValueSeparator(sep), _prefetch); } /* /********************************************************** /* Factory methods for sequence writers (2.5) /********************************************************** */ /** * Method for creating a {@link SequenceWriter} to write a sequence of root * values using configuration of this {@link ObjectWriter}. * Sequence is not surrounded by JSON array; some backend types may not * support writing of such sequences as root level. * Resulting writer needs to be {@link SequenceWriter#close()}d after all * values have been written to ensure closing of underlying generator and * output stream. * * @param out Target file to write value sequence to. * * @since 2.5 */ public SequenceWriter writeValues(File out) throws IOException { return _newSequenceWriter(false, _generatorFactory.createGenerator(out, JsonEncoding.UTF8), true); } /** * Method for creating a {@link SequenceWriter} to write a sequence of root * values using configuration of this {@link ObjectWriter}. * Sequence is not surrounded by JSON array; some backend types may not * support writing of such sequences as root level. * Resulting writer needs to be {@link SequenceWriter#close()}d after all * values have been written to ensure that all content gets flushed by * the generator. However, since a {@link JsonGenerator} is explicitly passed, * it will NOT be closed when {@link SequenceWriter#close()} is called. * * @param gen Low-level generator caller has already constructed that will * be used for actual writing of token stream. * * @since 2.5 */ public SequenceWriter writeValues(JsonGenerator gen) throws IOException { _configureGenerator(gen); return _newSequenceWriter(false, gen, false); } /** * Method for creating a {@link SequenceWriter} to write a sequence of root * values using configuration of this {@link ObjectWriter}. * Sequence is not surrounded by JSON array; some backend types may not * support writing of such sequences as root level. * Resulting writer needs to be {@link SequenceWriter#close()}d after all * values have been written to ensure closing of underlying generator and * output stream. * * @param out Target writer to use for writing the token stream * * @since 2.5 */ public SequenceWriter writeValues(Writer out) throws IOException { return _newSequenceWriter(false, _generatorFactory.createGenerator(out), true); } /** * Method for creating a {@link SequenceWriter} to write a sequence of root * values using configuration of this {@link ObjectWriter}. * Sequence is not surrounded by JSON array; some backend types may not * support writing of such sequences as root level. * Resulting writer needs to be {@link SequenceWriter#close()}d after all * values have been written to ensure closing of underlying generator and * output stream. * * @param out Physical output stream to use for writing the token stream * * @since 2.5 */ public SequenceWriter writeValues(OutputStream out) throws IOException { return _newSequenceWriter(false, _generatorFactory.createGenerator(out, JsonEncoding.UTF8), true); } /** * @since 2.8 */ public SequenceWriter writeValues(DataOutput out) throws IOException { return _newSequenceWriter(false, _generatorFactory.createGenerator(out), true); } /** * Method for creating a {@link SequenceWriter} to write an array of * root-level values, using configuration of this {@link ObjectWriter}. * Resulting writer needs to be {@link SequenceWriter#close()}d after all * values have been written to ensure closing of underlying generator and * output stream. *

* Note that the type to use with {@link ObjectWriter#forType(Class)} needs to * be type of individual values (elements) to write and NOT matching array * or {@link java.util.Collection} type. * * @param out File to write token stream to * * @since 2.5 */ public SequenceWriter writeValuesAsArray(File out) throws IOException { return _newSequenceWriter(true, _generatorFactory.createGenerator(out, JsonEncoding.UTF8), true); } /** * Method for creating a {@link SequenceWriter} to write an array of * root-level values, using configuration of this {@link ObjectWriter}. * Resulting writer needs to be {@link SequenceWriter#close()}d after all * values have been written to ensure that all content gets flushed by * the generator. However, since a {@link JsonGenerator} is explicitly passed, * it will NOT be closed when {@link SequenceWriter#close()} is called. *

* Note that the type to use with {@link ObjectWriter#forType(Class)} needs to * be type of individual values (elements) to write and NOT matching array * or {@link java.util.Collection} type. * * @param gen Underlying generator to use for writing the token stream * * @since 2.5 */ public SequenceWriter writeValuesAsArray(JsonGenerator gen) throws IOException { return _newSequenceWriter(true, gen, false); } /** * Method for creating a {@link SequenceWriter} to write an array of * root-level values, using configuration of this {@link ObjectWriter}. * Resulting writer needs to be {@link SequenceWriter#close()}d after all * values have been written to ensure closing of underlying generator and * output stream. *

* Note that the type to use with {@link ObjectWriter#forType(Class)} needs to * be type of individual values (elements) to write and NOT matching array * or {@link java.util.Collection} type. * * @param out Writer to use for writing the token stream * * @since 2.5 */ public SequenceWriter writeValuesAsArray(Writer out) throws IOException { return _newSequenceWriter(true, _generatorFactory.createGenerator(out), true); } /** * Method for creating a {@link SequenceWriter} to write an array of * root-level values, using configuration of this {@link ObjectWriter}. * Resulting writer needs to be {@link SequenceWriter#close()}d after all * values have been written to ensure closing of underlying generator and * output stream. *

* Note that the type to use with {@link ObjectWriter#forType(Class)} needs to * be type of individual values (elements) to write and NOT matching array * or {@link java.util.Collection} type. * * @param out Physical output stream to use for writing the token stream * * @since 2.5 */ public SequenceWriter writeValuesAsArray(OutputStream out) throws IOException { return _newSequenceWriter(true, _generatorFactory.createGenerator(out, JsonEncoding.UTF8), true); } /** * @since 2.8 */ public SequenceWriter writeValuesAsArray(DataOutput out) throws IOException { return _newSequenceWriter(true, _generatorFactory.createGenerator(out), true); } /* /********************************************************** /* Simple accessors /********************************************************** */ public boolean isEnabled(SerializationFeature f) { return _config.isEnabled(f); } public boolean isEnabled(MapperFeature f) { return _config.isEnabled(f); } /** * @since 2.9 */ @Deprecated public boolean isEnabled(JsonParser.Feature f) { return _generatorFactory.isEnabled(f); } /** * @since 2.9 */ public boolean isEnabled(JsonGenerator.Feature f) { return _generatorFactory.isEnabled(f); } /** * @since 2.2 */ public SerializationConfig getConfig() { return _config; } /** * @since 2.2 */ public JsonFactory getFactory() { return _generatorFactory; } public TypeFactory getTypeFactory() { return _config.getTypeFactory(); } /** * Diagnostics method that can be called to check whether this writer * has pre-fetched serializer to use: pre-fetching improves performance * when writer instances are reused as it avoids a per-call serializer * lookup. * * @since 2.2 */ public boolean hasPrefetchedSerializer() { return _prefetch.hasSerializer(); } /** * @since 2.3 */ public ContextAttributes getAttributes() { return _config.getAttributes(); } /* /********************************************************** /* Serialization methods; ones from ObjectCodec first /********************************************************** */ /** * Method that can be used to serialize any Java value as * JSON output, using provided {@link JsonGenerator}. */ public void writeValue(JsonGenerator gen, Object value) throws IOException { _configureGenerator(gen); if (_config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { Closeable toClose = (Closeable) value; try { _prefetch.serialize(gen, value, _serializerProvider()); if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) { gen.flush(); } } catch (Exception e) { ClassUtil.closeOnFailAndThrowAsIOE(null, toClose, e); return; } toClose.close(); } else { _prefetch.serialize(gen, value, _serializerProvider()); if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) { gen.flush(); } } } /* /********************************************************** /* Serialization methods, others /********************************************************** */ /** * Method that can be used to serialize any Java value as * JSON output, written to File provided. */ public void writeValue(File resultFile, Object value) throws IOException, JsonGenerationException, JsonMappingException { _configAndWriteValue(_generatorFactory.createGenerator(resultFile, JsonEncoding.UTF8), value); } /** * Method that can be used to serialize any Java value as * JSON output, using output stream provided (using encoding * {@link JsonEncoding#UTF8}). *

* Note: method does not close the underlying stream explicitly * here; however, {@link JsonFactory} this mapper uses may choose * to close the stream depending on its settings (by default, * it will try to close it when {@link JsonGenerator} we construct * is closed). */ public void writeValue(OutputStream out, Object value) throws IOException, JsonGenerationException, JsonMappingException { _configAndWriteValue(_generatorFactory.createGenerator(out, JsonEncoding.UTF8), value); } /** * Method that can be used to serialize any Java value as * JSON output, using Writer provided. *

* Note: method does not close the underlying stream explicitly * here; however, {@link JsonFactory} this mapper uses may choose * to close the stream depending on its settings (by default, * it will try to close it when {@link JsonGenerator} we construct * is closed). */ public void writeValue(Writer w, Object value) throws IOException, JsonGenerationException, JsonMappingException { _configAndWriteValue(_generatorFactory.createGenerator(w), value); } /** * @since 2.8 */ public void writeValue(DataOutput out, Object value) throws IOException { _configAndWriteValue(_generatorFactory.createGenerator(out), value); } /** * Method that can be used to serialize any Java value as * a String. Functionally equivalent to calling * {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter} * and constructing String, but more efficient. *

* Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it. */ @SuppressWarnings("resource") public String writeValueAsString(Object value) throws JsonProcessingException { // alas, we have to pull the recycler directly here... SegmentedStringWriter sw = new SegmentedStringWriter(_generatorFactory._getBufferRecycler()); try { _configAndWriteValue(_generatorFactory.createGenerator(sw), value); } catch (JsonProcessingException e) { throw e; } catch (IOException e) { // shouldn't really happen, but is declared as possibility so: throw JsonMappingException.fromUnexpectedIOE(e); } return sw.getAndClear(); } /** * Method that can be used to serialize any Java value as * a byte array. Functionally equivalent to calling * {@link #writeValue(Writer,Object)} with {@link java.io.ByteArrayOutputStream} * and getting bytes, but more efficient. * Encoding used will be UTF-8. *

* Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it. */ @SuppressWarnings("resource") public byte[] writeValueAsBytes(Object value) throws JsonProcessingException { ByteArrayBuilder bb = new ByteArrayBuilder(_generatorFactory._getBufferRecycler()); try { _configAndWriteValue(_generatorFactory.createGenerator(bb, JsonEncoding.UTF8), value); } catch (JsonProcessingException e) { // to support [JACKSON-758] throw e; } catch (IOException e) { // shouldn't really happen, but is declared as possibility so: throw JsonMappingException.fromUnexpectedIOE(e); } byte[] result = bb.toByteArray(); bb.release(); return result; } /* /********************************************************** /* Other public methods /********************************************************** */ /** * Method for visiting type hierarchy for given type, using specified visitor. * Visitation uses Serializer hierarchy and related properties *

* This method can be used for things like * generating Json Schema * instance for specified type. * * @param type Type to generate schema for (possibly with generic signature) * * @since 2.2 */ public void acceptJsonFormatVisitor(JavaType type, JsonFormatVisitorWrapper visitor) throws JsonMappingException { if (type == null) { throw new IllegalArgumentException("type must be provided"); } _serializerProvider().acceptJsonFormatVisitor(type, visitor); } /** * Since 2.6 */ public void acceptJsonFormatVisitor(Class rawType, JsonFormatVisitorWrapper visitor) throws JsonMappingException { acceptJsonFormatVisitor(_config.constructType(rawType), visitor); } public boolean canSerialize(Class type) { return _serializerProvider().hasSerializerFor(type, null); } /** * Method for checking whether instances of given type can be serialized, * and optionally why (as per {@link Throwable} returned). * * @since 2.3 */ public boolean canSerialize(Class type, AtomicReference cause) { return _serializerProvider().hasSerializerFor(type, cause); } /* /********************************************************** /* Overridable helper methods /********************************************************** */ /** * Overridable helper method used for constructing * {@link SerializerProvider} to use for serialization. */ protected DefaultSerializerProvider _serializerProvider() { return _serializerProvider.createInstance(_config, _serializerFactory); } /* /********************************************************** /* Internal methods /********************************************************** */ /** * @since 2.2 */ protected void _verifySchemaType(FormatSchema schema) { if (schema != null) { if (!_generatorFactory.canUseSchema(schema)) { throw new IllegalArgumentException("Cannot use FormatSchema of type "+schema.getClass().getName() +" for format "+_generatorFactory.getFormatName()); } } } /** * Method called to configure the generator as necessary and then * call write functionality */ protected final void _configAndWriteValue(JsonGenerator gen, Object value) throws IOException { _configureGenerator(gen); if (_config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { _writeCloseable(gen, value); return; } try { _prefetch.serialize(gen, value, _serializerProvider()); } catch (Exception e) { ClassUtil.closeOnFailAndThrowAsIOE(gen, e); return; } gen.close(); } /** * Helper method used when value to serialize is {@link Closeable} and its close() * method is to be called right after serialization has been called */ private final void _writeCloseable(JsonGenerator gen, Object value) throws IOException { Closeable toClose = (Closeable) value; try { _prefetch.serialize(gen, value, _serializerProvider()); Closeable tmpToClose = toClose; toClose = null; tmpToClose.close(); } catch (Exception e) { ClassUtil.closeOnFailAndThrowAsIOE(gen, toClose, e); return; } gen.close(); } /** * Helper method called to set or override settings of passed-in * {@link JsonGenerator} * * @since 2.5 */ protected final void _configureGenerator(JsonGenerator gen) { // order is slightly significant: both may change PrettyPrinter // settings. _config.initialize(gen); // since 2.5 _generatorSettings.initialize(gen); } /* /********************************************************** /* Helper classes for configuration /********************************************************** */ /** * Helper class used for containing settings specifically related * to (re)configuring {@link JsonGenerator} constructed for * writing output. * * @since 2.5 */ public final static class GeneratorSettings implements java.io.Serializable { private static final long serialVersionUID = 1L; public final static GeneratorSettings empty = new GeneratorSettings(null, null, null, null); /** * To allow for dynamic enabling/disabling of pretty printing, * pretty printer can be optionally configured for writer * as well */ public final PrettyPrinter prettyPrinter; /** * When using data format that uses a schema, schema is passed * to generator. */ public final FormatSchema schema; /** * Caller may want to specify character escaping details, either as * defaults, or on call-by-call basis. */ public final CharacterEscapes characterEscapes; /** * Caller may want to override so-called "root value separator", * String added (verbatim, with no quoting or escaping) between * values in root context. Default value is a single space character, * but this is often changed to linefeed. */ public final SerializableString rootValueSeparator; public GeneratorSettings(PrettyPrinter pp, FormatSchema sch, CharacterEscapes esc, SerializableString rootSep) { prettyPrinter = pp; schema = sch; characterEscapes = esc; rootValueSeparator = rootSep; } public GeneratorSettings with(PrettyPrinter pp) { // since null would mean "don't care", need to use placeholder to indicate "disable" if (pp == null) { pp = NULL_PRETTY_PRINTER; } return (pp == prettyPrinter) ? this : new GeneratorSettings(pp, schema, characterEscapes, rootValueSeparator); } public GeneratorSettings with(FormatSchema sch) { return (schema == sch) ? this : new GeneratorSettings(prettyPrinter, sch, characterEscapes, rootValueSeparator); } public GeneratorSettings with(CharacterEscapes esc) { return (characterEscapes == esc) ? this : new GeneratorSettings(prettyPrinter, schema, esc, rootValueSeparator); } public GeneratorSettings withRootValueSeparator(String sep) { if (sep == null) { if (rootValueSeparator == null) { return this; } return new GeneratorSettings(prettyPrinter, schema, characterEscapes, null); } if (sep.equals(_rootValueSeparatorAsString())) { return this; } return new GeneratorSettings(prettyPrinter, schema, characterEscapes, new SerializedString(sep)); } public GeneratorSettings withRootValueSeparator(SerializableString sep) { if (sep == null) { if (rootValueSeparator == null) { return this; } return new GeneratorSettings(prettyPrinter, schema, characterEscapes, null); } if (sep.equals(rootValueSeparator)) { return this; } return new GeneratorSettings(prettyPrinter, schema, characterEscapes, sep); } private final String _rootValueSeparatorAsString() { return (rootValueSeparator == null) ? null : rootValueSeparator.getValue(); } /** * @since 2.6 */ public void initialize(JsonGenerator gen) { PrettyPrinter pp = prettyPrinter; if (prettyPrinter != null) { if (pp == NULL_PRETTY_PRINTER) { gen.setPrettyPrinter(null); } else { if (pp instanceof Instantiatable) { pp = (PrettyPrinter) ((Instantiatable) pp).createInstance(); } gen.setPrettyPrinter(pp); } } if (characterEscapes != null) { gen.setCharacterEscapes(characterEscapes); } if (schema != null) { gen.setSchema(schema); } if (rootValueSeparator != null) { gen.setRootValueSeparator(rootValueSeparator); } } } /** * As a minor optimization, we will make an effort to pre-fetch a serializer, * or at least relevant TypeSerializer, if given enough * information. * * @since 2.5 */ public final static class Prefetch implements java.io.Serializable { private static final long serialVersionUID = 1L; public final static Prefetch empty = new Prefetch(null, null, null); /** * Specified root serialization type to use; can be same * as runtime type, but usually one of its super types * (parent class or interface it implements). */ private final JavaType rootType; /** * We may pre-fetch serializer if {@link #rootType} * is known, and if so, reuse it afterwards. * This allows avoiding further serializer lookups and increases * performance a bit on cases where readers are reused. */ private final JsonSerializer valueSerializer; /** * When dealing with polymorphic types, we cannot pre-fetch * serializer, but can pre-fetch {@link TypeSerializer}. */ private final TypeSerializer typeSerializer; private Prefetch(JavaType rootT, JsonSerializer ser, TypeSerializer typeSer) { rootType = rootT; valueSerializer = ser; typeSerializer = typeSer; } public Prefetch forRootType(ObjectWriter parent, JavaType newType) { // First: if nominal type not defined, or trivial (java.lang.Object), // not thing much to do boolean noType = (newType == null) || newType.isJavaLangObject(); if (noType) { if ((rootType == null) || (valueSerializer == null)) { return this; } return new Prefetch(null, null, typeSerializer); } if (newType.equals(rootType)) { return this; } if (parent.isEnabled(SerializationFeature.EAGER_SERIALIZER_FETCH)) { DefaultSerializerProvider prov = parent._serializerProvider(); // 17-Dec-2014, tatu: Need to be bit careful here; TypeSerializers are NOT cached, // so although it'd seem like a good idea to look for those first, and avoid // serializer for polymorphic types, it is actually more efficient to do the // reverse here. try { JsonSerializer ser = prov.findTypedValueSerializer(newType, true, null); // Important: for polymorphic types, "unwrap"... if (ser instanceof TypeWrappedSerializer) { return new Prefetch(newType, null, ((TypeWrappedSerializer) ser).typeSerializer()); } return new Prefetch(newType, ser, null); } catch (JsonProcessingException e) { // need to swallow? ; } } return new Prefetch(newType, null, typeSerializer); } public final JsonSerializer getValueSerializer() { return valueSerializer; } public final TypeSerializer getTypeSerializer() { return typeSerializer; } public boolean hasSerializer() { return (valueSerializer != null) || (typeSerializer != null); } public void serialize(JsonGenerator gen, Object value, DefaultSerializerProvider prov) throws IOException { if (typeSerializer != null) { prov.serializePolymorphic(gen, value, rootType, valueSerializer, typeSerializer); } else if (valueSerializer != null) { prov.serializeValue(gen, value, rootType, valueSerializer); } else if (rootType != null) { prov.serializeValue(gen, value, rootType); } else { prov.serializeValue(gen, value); } } } } PropertyMetadata.java000066400000000000000000000205451325620701100346060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; /** * Simple container class used for storing "additional" metadata about * properties. Carved out to reduce number of distinct properties that * actual property implementations and place holders need to store; * since instances are immutable, they can be freely shared. * * @since 2.3 */ public class PropertyMetadata implements java.io.Serializable { private static final long serialVersionUID = -1; public final static PropertyMetadata STD_REQUIRED = new PropertyMetadata(Boolean.TRUE, null, null, null, null, null, null); public final static PropertyMetadata STD_OPTIONAL = new PropertyMetadata(Boolean.FALSE, null, null, null, null, null, null); public final static PropertyMetadata STD_REQUIRED_OR_OPTIONAL = new PropertyMetadata(null, null, null, null, null, null, null); /** * Helper class used for containing information about expected merge * information for this property, if merging is expected. * * @since 2.9 */ public final static class MergeInfo // NOTE: need not be Serializable, not persisted { public final AnnotatedMember getter; /** * Flag that is set if the information came from global defaults, * and not from explicit per-property annotations or per-type * config overrides. */ public final boolean fromDefaults; protected MergeInfo(AnnotatedMember getter, boolean fromDefaults) { this.getter = getter; this.fromDefaults = fromDefaults; } public static MergeInfo createForDefaults(AnnotatedMember getter) { return new MergeInfo(getter, true); } public static MergeInfo createForTypeOverride(AnnotatedMember getter) { return new MergeInfo(getter, false); } public static MergeInfo createForPropertyOverride(AnnotatedMember getter) { return new MergeInfo(getter, false); } } /** * Three states: required, not required and unknown; unknown represented * as null. */ protected final Boolean _required; /** * Optional human-readable description associated with the property. */ protected final String _description; /** * Optional index of the property within containing Object. * * @since 2.4 */ protected final Integer _index; /** * Optional default value, as String, for property; not used for * any functionality by core databind, offered as metadata for * extensions. */ protected final String _defaultValue; /** * Settings regarding merging, if property is determined to possibly * be mergeable (possibly since global settings may be omitted for * non-mergeable types). *

* NOTE: transient since it is assumed that this information is only * relevant during initial setup and not needed after full initialization. * May be changed if this proves necessary. * * @since 2.9 */ protected final transient MergeInfo _mergeInfo; /** * Settings regarding handling of incoming `null`s, both for value itself * and, for structured types, content values (array/Collection elements, * Map values). * * @since 2.9 */ protected Nulls _valueNulls, _contentNulls; /* /********************************************************** /* Construction, configuration /********************************************************** */ /** * @since 2.9 */ protected PropertyMetadata(Boolean req, String desc, Integer index, String def, MergeInfo mergeInfo, Nulls valueNulls, Nulls contentNulls) { _required = req; _description = desc; _index = index; _defaultValue = (def == null || def.isEmpty()) ? null : def; _mergeInfo = mergeInfo; _valueNulls = valueNulls; _contentNulls = contentNulls; } /** * @since 2.8.8 */ public static PropertyMetadata construct(Boolean req, String desc, Integer index, String defaultValue) { if ((desc != null) || (index != null) || (defaultValue != null)) { return new PropertyMetadata(req, desc, index, defaultValue, null, null, null); } if (req == null) { return STD_REQUIRED_OR_OPTIONAL; } return req ? STD_REQUIRED : STD_OPTIONAL; } @Deprecated // since 2.8.8 public static PropertyMetadata construct(boolean req, String desc, Integer index, String defaultValue) { if (desc != null || index != null || defaultValue != null) { return new PropertyMetadata(req, desc, index, defaultValue, null, null, null); } return req ? STD_REQUIRED : STD_OPTIONAL; } /** * Minor optimization: let's canonicalize back to placeholders in cases * where there is no real data to consider */ protected Object readResolve() { if ((_description == null) && (_index == null) && (_defaultValue == null) && (_mergeInfo == null) && (_valueNulls == null) && (_contentNulls == null)) { if (_required == null) { return STD_REQUIRED_OR_OPTIONAL; } return _required.booleanValue() ? STD_REQUIRED : STD_OPTIONAL; } return this; } public PropertyMetadata withDescription(String desc) { return new PropertyMetadata(_required, desc, _index, _defaultValue, _mergeInfo, _valueNulls, _contentNulls); } /** * @since 2.9 */ public PropertyMetadata withMergeInfo(MergeInfo mergeInfo) { return new PropertyMetadata(_required, _description, _index, _defaultValue, mergeInfo, _valueNulls, _contentNulls); } /** * @since 2.9 */ public PropertyMetadata withNulls(Nulls valueNulls, Nulls contentNulls) { return new PropertyMetadata(_required, _description, _index, _defaultValue, _mergeInfo, valueNulls, contentNulls); } public PropertyMetadata withDefaultValue(String def) { if ((def == null) || def.isEmpty()) { if (_defaultValue == null) { return this; } def = null; } else if (def.equals(_defaultValue)) { return this; } return new PropertyMetadata(_required, _description, _index, def, _mergeInfo, _valueNulls, _contentNulls); } public PropertyMetadata withIndex(Integer index) { return new PropertyMetadata(_required, _description, index, _defaultValue, _mergeInfo, _valueNulls, _contentNulls); } public PropertyMetadata withRequired(Boolean b) { if (b == null) { if (_required == null) { return this; } } else if (b.equals(_required)) { return this; } return new PropertyMetadata(b, _description, _index, _defaultValue, _mergeInfo, _valueNulls, _contentNulls); } /* /********************************************************** /* Accessors /********************************************************** */ public String getDescription() { return _description; } /** * @since 2.5 */ public String getDefaultValue() { return _defaultValue; } /** * Accessor for determining whether property has declared "default value", * which may be used by extension modules. * * @since 2.6 */ public boolean hasDefaultValue() { return (_defaultValue != null); } public boolean isRequired() { return (_required != null) && _required.booleanValue(); } public Boolean getRequired() { return _required; } /** * @since 2.4 */ public Integer getIndex() { return _index; } /** * @since 2.4 */ public boolean hasIndex() { return _index != null; } /** * @since 2.9 */ public MergeInfo getMergeInfo() { return _mergeInfo; } /** * @since 2.9 */ public Nulls getValueNulls() { return _valueNulls; } /** * @since 2.9 */ public Nulls getContentNulls() { return _contentNulls; } } PropertyName.java000066400000000000000000000170761325620701100337530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.core.util.InternCache; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Simple value class used for containing names of properties as defined * by annotations (and possibly other configuration sources). * * @since 2.1 */ public class PropertyName implements java.io.Serializable { private static final long serialVersionUID = 1L; // 2.5 private final static String _USE_DEFAULT = ""; private final static String _NO_NAME = ""; /** * Special placeholder value that indicates that name to use should be * based on the standard heuristics. This can be different from returning * null, as null means "no information available, whereas this value * indicates explicit defaulting. */ public final static PropertyName USE_DEFAULT = new PropertyName(_USE_DEFAULT, null); /** * Special placeholder value that indicates that there is no name associated. * Exact semantics to use (if any) depend on actual annotation in use, but * commonly this value disables behavior for which name would be needed. */ public final static PropertyName NO_NAME = new PropertyName(new String(_NO_NAME), null); /** * Basic name of the property. */ protected final String _simpleName; /** * Additional namespace, for formats that have such concept (JSON * does not, XML does, for example). */ protected final String _namespace; /** * Lazily-constructed efficient representation of the simple name. *

* NOTE: not defined as volatile to avoid performance problem with * concurrent access in multi-core environments; due to statelessness * of {@link SerializedString} at most leads to multiple instantiations. * * @since 2.4 */ protected SerializableString _encodedSimple; public PropertyName(String simpleName) { this(simpleName, null); } public PropertyName(String simpleName, String namespace) { _simpleName = ClassUtil.nonNullString(simpleName); _namespace = namespace; } // To support JDK serialization, recovery of Singleton instance protected Object readResolve() { if (_namespace == null) { if (_simpleName == null || _USE_DEFAULT.equals(_simpleName)) { return USE_DEFAULT; } // 30-Oct-2016, tatu: I don't see how this could ever occur... // or how to distinguish USE_DEFAULT/NO_NAME from serialized /* if (_simpleName.equals(_NO_NAME)) { return NO_NAME; } */ } return this; } /** * @since 2.6 */ public static PropertyName construct(String simpleName) { if (simpleName == null || simpleName.length() == 0) { return USE_DEFAULT; } return new PropertyName(InternCache.instance.intern(simpleName), null); } public static PropertyName construct(String simpleName, String ns) { if (simpleName == null) { simpleName = ""; } if (ns == null && simpleName.length() == 0) { return USE_DEFAULT; } return new PropertyName(InternCache.instance.intern(simpleName), ns); } public PropertyName internSimpleName() { if (_simpleName.length() == 0) { // empty String is canonical already return this; } String interned = InternCache.instance.intern(_simpleName); if (interned == _simpleName) { // was already interned return this; } return new PropertyName(interned, _namespace); } /** * Fluent factory method for constructing an instance with different * simple name. */ public PropertyName withSimpleName(String simpleName) { if (simpleName == null) { simpleName = ""; } if (simpleName.equals(_simpleName)) { return this; } return new PropertyName(simpleName, _namespace); } /** * Fluent factory method for constructing an instance with different * namespace. */ public PropertyName withNamespace(String ns) { if (ns == null) { if (_namespace == null) { return this; } } else if (ns.equals(_namespace)) { return this; } return new PropertyName(_simpleName, ns); } /* /********************************************************** /* Accessors /********************************************************** */ public String getSimpleName() { return _simpleName; } /** * Accessor that may be used to get lazily-constructed efficient * representation of the simple name. * * @since 2.4 */ public SerializableString simpleAsEncoded(MapperConfig config) { SerializableString sstr = _encodedSimple; if (sstr == null) { if (config == null) { sstr = new SerializedString(_simpleName); } else { sstr = config.compileString(_simpleName); } _encodedSimple = sstr; } return sstr; } public String getNamespace() { return _namespace; } public boolean hasSimpleName() { return _simpleName.length() > 0; } /** * @since 2.3 */ public boolean hasSimpleName(String str) { // _simpleName never null so... return _simpleName.equals(str); } public boolean hasNamespace() { return _namespace != null; } /** * Method that is basically equivalent of: *

     *   !hasSimpleName() << !hasNamespace();
     *
* * @since 2.4 */ public boolean isEmpty() { return (_namespace == null) && (_simpleName.isEmpty()); } /* /********************************************************** /* Std method overrides /********************************************************** */ @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; /* 13-Nov-2012, tatu: by default, require strict type equality. * Re-evaluate if this becomes an issue. */ if (o.getClass() != getClass()) return false; // 13-Nov-2012, tatu: Should we have specific rules on matching USE_DEFAULT? // (like, it only ever matching exact instance) // If we did, would need to check symmetrically; that is, if either 'this' // or 'o' was USE_DEFAULT, both would have to be. PropertyName other = (PropertyName) o; if (_simpleName == null) { if (other._simpleName != null) return false; } else if (!_simpleName.equals(other._simpleName)) { return false; } if (_namespace == null) { return (null == other._namespace); } return _namespace.equals(other._namespace); } @Override public int hashCode() { if (_namespace == null) { return _simpleName.hashCode(); } return _namespace.hashCode() ^ _simpleName.hashCode(); } @Override public String toString() { if (_namespace == null) { return _simpleName; } return "{"+_namespace + "}" + _simpleName; } } PropertyNamingStrategy.java000066400000000000000000000424141325620701100360210ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.AnnotatedField; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; /** * Class that defines how names of JSON properties ("external names") * are derived from names of POJO methods and fields ("internal names"), * in cases where they are not * auto-detected and no explicit annotations exist for naming. * Methods are passed information about POJO member for which name is needed, * as well as default name that would be used if no custom strategy was used. *

* Default (empty) implementation returns suggested ("default") name unmodified. *

* Note that the strategy is guaranteed to be called once per logical property * (which may be represented by multiple members; such as pair of a getter and * a setter), but may be called for each: implementations should not count on * exact number of times, and should work for any member that represent a * property. *

* In absence of a registered custom strategy, default Java property naming strategy * is used, which leaves field names as is, and removes set/get/is prefix * from methods (as well as lower-cases initial sequence of capitalized * characters). */ @SuppressWarnings("serial") public class PropertyNamingStrategy // NOTE: was abstract until 2.7 implements java.io.Serializable { /** * Naming convention used in languages like C, where words are in lower-case * letters, separated by underscores. * See {@link SnakeCaseStrategy} for details. * * @since 2.7 (was formerly called {@link #CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES}) */ public static final PropertyNamingStrategy SNAKE_CASE = new SnakeCaseStrategy(); /** * Naming convention used in languages like Pascal, where words are capitalized * and no separator is used between words. * See {@link PascalCaseStrategy} for details. * * @since 2.7 (was formerly called {@link #PASCAL_CASE_TO_CAMEL_CASE}) */ public static final PropertyNamingStrategy UPPER_CAMEL_CASE = new UpperCamelCaseStrategy(); /** * Naming convention used in Java, where words other than first are capitalized * and no separator is used between words. Since this is the native Java naming convention, * naming strategy will not do any transformation between names in data (JSON) and * POJOS. * * @since 2.7 (was formerly called {@link #PASCAL_CASE_TO_CAMEL_CASE}) */ public static final PropertyNamingStrategy LOWER_CAMEL_CASE = new PropertyNamingStrategy(); /** * Naming convention in which all words of the logical name are in lower case, and * no separator is used between words. * See {@link LowerCaseStrategy} for details. * * @since 2.4 */ public static final PropertyNamingStrategy LOWER_CASE = new LowerCaseStrategy(); /** * Naming convention used in languages like Lisp, where words are in lower-case * letters, separated by hyphens. * See {@link KebabCaseStrategy} for details. * * @since 2.7 */ public static final PropertyNamingStrategy KEBAB_CASE = new KebabCaseStrategy(); /* /********************************************************** /* API /********************************************************** */ /** * Method called to find external name (name used in JSON) for given logical * POJO property, * as defined by given field. * * @param config Configuration in used: either SerializationConfig * or DeserializationConfig, depending on whether method is called * during serialization or deserialization * @param field Field used to access property * @param defaultName Default name that would be used for property in absence of custom strategy * * @return Logical name to use for property that the field represents */ public String nameForField(MapperConfig config, AnnotatedField field, String defaultName) { return defaultName; } /** * Method called to find external name (name used in JSON) for given logical * POJO property, * as defined by given getter method; typically called when building a serializer. * (but not always -- when using "getter-as-setter", may be called during * deserialization) * * @param config Configuration in used: either SerializationConfig * or DeserializationConfig, depending on whether method is called * during serialization or deserialization * @param method Method used to access property. * @param defaultName Default name that would be used for property in absence of custom strategy * * @return Logical name to use for property that the method represents */ public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return defaultName; } /** * Method called to find external name (name used in JSON) for given logical * POJO property, * as defined by given setter method; typically called when building a deserializer * (but not necessarily only then). * * @param config Configuration in used: either SerializationConfig * or DeserializationConfig, depending on whether method is called * during serialization or deserialization * @param method Method used to access property. * @param defaultName Default name that would be used for property in absence of custom strategy * * @return Logical name to use for property that the method represents */ public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return defaultName; } /** * Method called to find external name (name used in JSON) for given logical * POJO property, * as defined by given constructor parameter; typically called when building a deserializer * (but not necessarily only then). * * @param config Configuration in used: either SerializationConfig * or DeserializationConfig, depending on whether method is called * during serialization or deserialization * @param ctorParam Constructor parameter used to pass property. * @param defaultName Default name that would be used for property in absence of custom strategy */ public String nameForConstructorParameter(MapperConfig config, AnnotatedParameter ctorParam, String defaultName) { return defaultName; } /* /********************************************************** /* Public base class for simple implementations /********************************************************** */ public static abstract class PropertyNamingStrategyBase extends PropertyNamingStrategy { @Override public String nameForField(MapperConfig config, AnnotatedField field, String defaultName) { return translate(defaultName); } @Override public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return translate(defaultName); } @Override public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return translate(defaultName); } @Override public String nameForConstructorParameter(MapperConfig config, AnnotatedParameter ctorParam, String defaultName) { return translate(defaultName); } public abstract String translate(String propertyName); } /* /********************************************************** /* Standard implementations /********************************************************** */ /** * A {@link PropertyNamingStrategy} that translates typical camel case Java * property names to lower case JSON element names, separated by * underscores. This implementation is somewhat lenient, in that it * provides some additional translations beyond strictly translating from * camel case only. In particular, the following translations are applied * by this PropertyNamingStrategy. * *

  • Every upper case letter in the Java property name is translated * into two characters, an underscore and the lower case equivalent of the * target character, with three exceptions. *
    1. For contiguous sequences of upper case letters, characters after * the first character are replaced only by their lower case equivalent, * and are not preceded by an underscore. *
      • This provides for reasonable translations of upper case acronyms, * e.g., "theWWW" is translated to "the_www".
    2. *
    3. An upper case character in the first position of the Java property * name is not preceded by an underscore character, and is translated only * to its lower case equivalent. *
      • For example, "Results" is translated to "results", * and not to "_results".
    4. *
    5. An upper case character in the Java property name that is already * preceded by an underscore character is translated only to its lower case * equivalent, and is not preceded by an additional underscore. *
      • For example, "user_Name" is translated to * "user_name", and not to "user__name" (with two * underscore characters).
  • *
  • If the Java property name starts with an underscore, then that * underscore is not included in the translated name, unless the Java * property name is just one character in length, i.e., it is the * underscore character. This applies only to the first character of the * Java property name.
* * These rules result in the following additional example translations from * Java property names to JSON element names. *
  • "userName" is translated to "user_name"
  • *
  • "UserName" is translated to "user_name"
  • *
  • "USER_NAME" is translated to "user_name"
  • *
  • "user_name" is translated to "user_name" (unchanged)
  • *
  • "user" is translated to "user" (unchanged)
  • *
  • "User" is translated to "user"
  • *
  • "USER" is translated to "user"
  • *
  • "_user" is translated to "user"
  • *
  • "_User" is translated to "user"
  • *
  • "__user" is translated to "_user" * (the first of two underscores was removed)
  • *
  • "user__name" is translated to "user__name" * (unchanged, with two underscores)
* * @since 2.7 (was previously called } */ public static class SnakeCaseStrategy extends PropertyNamingStrategyBase { @Override public String translate(String input) { if (input == null) return input; // garbage in, garbage out int length = input.length(); StringBuilder result = new StringBuilder(length * 2); int resultLength = 0; boolean wasPrevTranslated = false; for (int i = 0; i < length; i++) { char c = input.charAt(i); if (i > 0 || c != '_') // skip first starting underscore { if (Character.isUpperCase(c)) { if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_') { result.append('_'); resultLength++; } c = Character.toLowerCase(c); wasPrevTranslated = true; } else { wasPrevTranslated = false; } result.append(c); resultLength++; } } return resultLength > 0 ? result.toString() : input; } } /** * A {@link PropertyNamingStrategy} that translates typical camelCase Java * property names to PascalCase JSON element names (i.e., with a capital * first letter). In particular, the following translations are applied by * this PropertyNamingStrategy. * *
  • The first lower-case letter in the Java property name is translated * into its equivalent upper-case representation.
* * This rules result in the following example translation from * Java property names to JSON element names. *
  • "userName" is translated to "UserName"
* * @since 2.7 (was formerly called {@link PascalCaseStrategy}) */ public static class UpperCamelCaseStrategy extends PropertyNamingStrategyBase { /** * Converts camelCase to PascalCase * * For example, "userName" would be converted to * "UserName". * * @param input formatted as camelCase string * @return input converted to PascalCase format */ @Override public String translate(String input) { if (input == null || input.length() == 0){ return input; // garbage in, garbage out } // Replace first lower-case letter with upper-case equivalent char c = input.charAt(0); char uc = Character.toUpperCase(c); if (c == uc) { return input; } StringBuilder sb = new StringBuilder(input); sb.setCharAt(0, uc); return sb.toString(); } } /** * Simple strategy where external name simply only uses lower-case characters, * and no separators. * Conversion from internal name like "someOtherValue" would be into external name * if "someothervalue". * * @since 2.4 */ public static class LowerCaseStrategy extends PropertyNamingStrategyBase { @Override public String translate(String input) { return input.toLowerCase(); } } /** * Naming strategy similar to {@link SnakeCaseStrategy}, but instead of underscores * as separators, uses hyphens. Naming convention traditionally used for languages * like Lisp. * * @since 2.7 */ public static class KebabCaseStrategy extends PropertyNamingStrategyBase { @Override public String translate(String input) { if (input == null) return input; // garbage in, garbage out int length = input.length(); if (length == 0) { return input; } StringBuilder result = new StringBuilder(length + (length >> 1)); int upperCount = 0; for (int i = 0; i < length; ++i) { char ch = input.charAt(i); char lc = Character.toLowerCase(ch); if (lc == ch) { // lower-case letter means we can get new word // but need to check for multi-letter upper-case (acronym), where assumption // is that the last upper-case char is start of a new word if (upperCount > 1) { // so insert hyphen before the last character now result.insert(result.length() - 1, '-'); } upperCount = 0; } else { // Otherwise starts new word, unless beginning of string if ((upperCount == 0) && (i > 0)) { result.append('-'); } ++upperCount; } result.append(lc); } return result.toString(); } } /* /********************************************************** /* Deprecated variants, aliases /********************************************************** */ /** * @deprecated Since 2.7 use {@link #SNAKE_CASE} instead; */ @Deprecated // since 2.7 public static final PropertyNamingStrategy CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES = SNAKE_CASE; /** * @deprecated Since 2.7 use {@link #UPPER_CAMEL_CASE} instead; */ @Deprecated // since 2.7 public static final PropertyNamingStrategy PASCAL_CASE_TO_CAMEL_CASE = UPPER_CAMEL_CASE; /** * @deprecated In 2.7 use {@link SnakeCaseStrategy} instead */ @Deprecated public static class LowerCaseWithUnderscoresStrategy extends SnakeCaseStrategy {} /** * @deprecated In 2.7 use {@link UpperCamelCaseStrategy} instead */ @Deprecated public static class PascalCaseStrategy extends UpperCamelCaseStrategy {} } RuntimeJsonMappingException.java000066400000000000000000000010501325620701100367570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; /** * Wrapper used when interface does not allow throwing a checked * {@link JsonMappingException} */ @SuppressWarnings("serial") public class RuntimeJsonMappingException extends RuntimeException { public RuntimeJsonMappingException(JsonMappingException cause) { super(cause); } public RuntimeJsonMappingException(String message) { super(message); } public RuntimeJsonMappingException(String message, JsonMappingException cause) { super(message, cause); } } SequenceWriter.java000066400000000000000000000256541325620701100342740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.Closeable; import java.io.IOException; import java.util.Collection; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; import com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer; /** * Writer class similar to {@link ObjectWriter}, except that it can be used * for writing sequences of values, not just a single value. * The main use case is in writing very long sequences, or sequences where * values are incrementally produced; cases where it would be impractical * or at least inconvenient to construct a wrapper container around values * (or where no JSON array is desired around values). *

* Differences from {@link ObjectWriter} include: *

    *
  • Instances of {@link SequenceWriter} are stateful, and not thread-safe: * if sharing, external synchronization must be used. *
  • Explicit {@link #close} is needed after all values have been written * ({@link ObjectWriter} can auto-close after individual value writes) *
* * @since 2.5 */ public class SequenceWriter implements Versioned, java.io.Closeable, java.io.Flushable { /* /********************************************************** /* Configuration /********************************************************** */ protected final DefaultSerializerProvider _provider; protected final SerializationConfig _config; protected final JsonGenerator _generator; protected final JsonSerializer _rootSerializer; protected final TypeSerializer _typeSerializer; protected final boolean _closeGenerator; protected final boolean _cfgFlush; protected final boolean _cfgCloseCloseable; /* /********************************************************** /* State /********************************************************** */ /** * If {@link #_rootSerializer} is not defined (no root type * was used for constructing {@link ObjectWriter}), we will * use simple scheme for keeping track of serializers needed. * Assumption is that */ protected PropertySerializerMap _dynamicSerializers; /** * State flag for keeping track of need to write matching END_ARRAY, * if a START_ARRAY was written during initialization */ protected boolean _openArray; protected boolean _closed; /* /********************************************************** /* Life-cycle /********************************************************** */ public SequenceWriter(DefaultSerializerProvider prov, JsonGenerator gen, boolean closeGenerator, ObjectWriter.Prefetch prefetch) throws IOException { _provider = prov; _generator = gen; _closeGenerator = closeGenerator; _rootSerializer = prefetch.getValueSerializer(); _typeSerializer = prefetch.getTypeSerializer(); _config = prov.getConfig(); _cfgFlush = _config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE); _cfgCloseCloseable = _config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE); // important: need to cache "root value" serializers, to handle polymorphic // types properly _dynamicSerializers = PropertySerializerMap.emptyForRootValues(); } public SequenceWriter init(boolean wrapInArray) throws IOException { if (wrapInArray) { _generator.writeStartArray(); _openArray = true; } return this; } /* /********************************************************** /* Public API, basic accessors /********************************************************** */ /** * Method that will return version information stored in and read from jar * that contains this class. */ @Override public Version version() { return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION; } /* /********************************************************** /* Public API, write operations, related /********************************************************** */ /** * Method for writing given value into output, as part of sequence * to write. If root type was specified for {@link ObjectWriter}, * value must be of compatible type (same or subtype). */ public SequenceWriter write(Object value) throws IOException { if (value == null) { _provider.serializeValue(_generator, null); return this; } if (_cfgCloseCloseable && (value instanceof Closeable)) { return _writeCloseableValue(value); } JsonSerializer ser = _rootSerializer; if (ser == null) { Class type = value.getClass(); ser = _dynamicSerializers.serializerFor(type); if (ser == null) { ser = _findAndAddDynamic(type); } } _provider.serializeValue(_generator, value, null, ser); if (_cfgFlush) { _generator.flush(); } return this; } /** * Method for writing given value into output, as part of sequence * to write; further, full type (often generic, like {@link java.util.Map} * is passed in case a new * {@link JsonSerializer} needs to be fetched to handle type * * If root type was specified for {@link ObjectWriter}, * value must be of compatible type (same or subtype). */ public SequenceWriter write(Object value, JavaType type) throws IOException { if (value == null) { _provider.serializeValue(_generator, null); return this; } if (_cfgCloseCloseable && (value instanceof Closeable)) { return _writeCloseableValue(value, type); } /* 15-Dec-2014, tatu: I wonder if this could become problematic. It shouldn't * really, since trying to use differently paramterized types in a sequence * is likely to run into other issues. But who knows; if it does become an * issue, may need to implement alternative, JavaType-based map. */ JsonSerializer ser = _dynamicSerializers.serializerFor(type.getRawClass()); if (ser == null) { ser = _findAndAddDynamic(type); } _provider.serializeValue(_generator, value, type, ser); if (_cfgFlush) { _generator.flush(); } return this; } public SequenceWriter writeAll(Object[] value) throws IOException { for (int i = 0, len = value.length; i < len; ++i) { write(value[i]); } return this; } // NOTE: redundant wrt variant that takes Iterable, but cannot remove or even // deprecate due to backwards-compatibility needs public > SequenceWriter writeAll(C container) throws IOException { for (Object value : container) { write(value); } return this; } /** * @since 2.7 */ public SequenceWriter writeAll(Iterable iterable) throws IOException { for (Object value : iterable) { write(value); } return this; } @Override public void flush() throws IOException { if (!_closed) { _generator.flush(); } } @Override public void close() throws IOException { if (!_closed) { _closed = true; if (_openArray) { _openArray = false; _generator.writeEndArray(); } if (_closeGenerator) { _generator.close(); } } } /* /********************************************************** /* Internal helper methods, serializer lookups /********************************************************** */ protected SequenceWriter _writeCloseableValue(Object value) throws IOException { Closeable toClose = (Closeable) value; try { JsonSerializer ser = _rootSerializer; if (ser == null) { Class type = value.getClass(); ser = _dynamicSerializers.serializerFor(type); if (ser == null) { ser = _findAndAddDynamic(type); } } _provider.serializeValue(_generator, value, null, ser); if (_cfgFlush) { _generator.flush(); } Closeable tmpToClose = toClose; toClose = null; tmpToClose.close(); } finally { if (toClose != null) { try { toClose.close(); } catch (IOException ioe) { } } } return this; } protected SequenceWriter _writeCloseableValue(Object value, JavaType type) throws IOException { Closeable toClose = (Closeable) value; try { // 15-Dec-2014, tatu: As per above, could be problem that we do not pass generic type JsonSerializer ser = _dynamicSerializers.serializerFor(type.getRawClass()); if (ser == null) { ser = _findAndAddDynamic(type); } _provider.serializeValue(_generator, value, type, ser); if (_cfgFlush) { _generator.flush(); } Closeable tmpToClose = toClose; toClose = null; tmpToClose.close(); } finally { if (toClose != null) { try { toClose.close(); } catch (IOException ioe) { } } } return this; } private final JsonSerializer _findAndAddDynamic(Class type) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result; if (_typeSerializer == null) { result = _dynamicSerializers.findAndAddRootValueSerializer(type, _provider); } else { result = _dynamicSerializers.addSerializer(type, new TypeWrappedSerializer(_typeSerializer, _provider.findValueSerializer(type, null))); } _dynamicSerializers = result.map; return result.serializer; } private final JsonSerializer _findAndAddDynamic(JavaType type) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result; if (_typeSerializer == null) { result = _dynamicSerializers.findAndAddRootValueSerializer(type, _provider); } else { result = _dynamicSerializers.addSerializer(type, new TypeWrappedSerializer(_typeSerializer, _provider.findValueSerializer(type, null))); } _dynamicSerializers = result.map; return result.serializer; } } SerializationConfig.java000066400000000000000000000705661325620701100352740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.text.DateFormat; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.core.util.Instantiatable; import com.fasterxml.jackson.databind.cfg.*; import com.fasterxml.jackson.databind.introspect.SimpleMixInResolver; import com.fasterxml.jackson.databind.jsontype.SubtypeResolver; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.SerializerFactory; import com.fasterxml.jackson.databind.util.RootNameLookup; /** * Object that contains baseline configuration for serialization * process. An instance is owned by {@link ObjectMapper}, which * passes an immutable instance for serialization process to * {@link SerializerProvider} and {@link SerializerFactory} * (either directly, or through {@link ObjectWriter}. *

* Note that instances are considered immutable and as such no copies * should need to be created for sharing; all copying is done with * "fluent factory" methods. */ public final class SerializationConfig extends MapperConfigBase implements java.io.Serializable // since 2.1 { // since 2.5 private static final long serialVersionUID = 1; // since 2.6 protected final static PrettyPrinter DEFAULT_PRETTY_PRINTER = new DefaultPrettyPrinter(); /* /********************************************************** /* Configured helper objects /********************************************************** */ /** * Object used for resolving filter ids to filter instances. * Non-null if explicitly defined; null by default. */ protected final FilterProvider _filterProvider; /** * If "default pretty-printing" is enabled, it will create the instance * from this blueprint object. * * @since 2.6 */ protected final PrettyPrinter _defaultPrettyPrinter; /* /********************************************************** /* Serialization features /********************************************************** */ /** * Set of {@link SerializationFeature}s enabled. */ protected final int _serFeatures; /* /********************************************************** /* Generator features: generic, format-specific /********************************************************** */ /** * States of {@link com.fasterxml.jackson.core.JsonGenerator.Feature}s to enable/disable. */ protected final int _generatorFeatures; /** * Bitflag of {@link com.fasterxml.jackson.core.JsonGenerator.Feature}s to enable/disable */ protected final int _generatorFeaturesToChange; /** * States of {@link com.fasterxml.jackson.core.FormatFeature}s to enable/disable. * * @since 2.7 */ protected final int _formatWriteFeatures; /** * Bitflag of {@link com.fasterxml.jackson.core.FormatFeature}s to enable/disable * * @since 2.7 */ protected final int _formatWriteFeaturesToChange; /* /********************************************************** /* Life-cycle, primary constructors for new instances /********************************************************** */ /** * Constructor used by ObjectMapper to create default configuration object instance. * * @since 2.9 */ public SerializationConfig(BaseSettings base, SubtypeResolver str, SimpleMixInResolver mixins, RootNameLookup rootNames, ConfigOverrides configOverrides) { super(base, str, mixins, rootNames, configOverrides); _serFeatures = collectFeatureDefaults(SerializationFeature.class); _filterProvider = null; _defaultPrettyPrinter = DEFAULT_PRETTY_PRINTER; _generatorFeatures = 0; _generatorFeaturesToChange = 0; _formatWriteFeatures = 0; _formatWriteFeaturesToChange = 0; } /** * Copy-constructor used for making a copy to be used by new {@link ObjectMapper}. * * @since 2.9 */ protected SerializationConfig(SerializationConfig src, SimpleMixInResolver mixins, RootNameLookup rootNames, ConfigOverrides configOverrides) { super(src, mixins, rootNames, configOverrides); _serFeatures = src._serFeatures; _filterProvider = src._filterProvider; _defaultPrettyPrinter = src._defaultPrettyPrinter; _generatorFeatures = src._generatorFeatures; _generatorFeaturesToChange = src._generatorFeaturesToChange; _formatWriteFeatures = src._formatWriteFeatures; _formatWriteFeaturesToChange = src._formatWriteFeaturesToChange; } /* /********************************************************** /* Life-cycle, secondary constructors to support /* "mutant factories", with single property changes /********************************************************** */ private SerializationConfig(SerializationConfig src, SubtypeResolver str) { super(src, str); _serFeatures = src._serFeatures; _filterProvider = src._filterProvider; _defaultPrettyPrinter = src._defaultPrettyPrinter; _generatorFeatures = src._generatorFeatures; _generatorFeaturesToChange = src._generatorFeaturesToChange; _formatWriteFeatures = src._formatWriteFeatures; _formatWriteFeaturesToChange = src._formatWriteFeaturesToChange; } private SerializationConfig(SerializationConfig src, int mapperFeatures, int serFeatures, int generatorFeatures, int generatorFeatureMask, int formatFeatures, int formatFeaturesMask) { super(src, mapperFeatures); _serFeatures = serFeatures; _filterProvider = src._filterProvider; _defaultPrettyPrinter = src._defaultPrettyPrinter; _generatorFeatures = generatorFeatures; _generatorFeaturesToChange = generatorFeatureMask; _formatWriteFeatures = formatFeatures; _formatWriteFeaturesToChange = formatFeaturesMask; } private SerializationConfig(SerializationConfig src, BaseSettings base) { super(src, base); _serFeatures = src._serFeatures; _filterProvider = src._filterProvider; _defaultPrettyPrinter = src._defaultPrettyPrinter; _generatorFeatures = src._generatorFeatures; _generatorFeaturesToChange = src._generatorFeaturesToChange; _formatWriteFeatures = src._formatWriteFeatures; _formatWriteFeaturesToChange = src._formatWriteFeaturesToChange; } private SerializationConfig(SerializationConfig src, FilterProvider filters) { super(src); _serFeatures = src._serFeatures; _filterProvider = filters; _defaultPrettyPrinter = src._defaultPrettyPrinter; _generatorFeatures = src._generatorFeatures; _generatorFeaturesToChange = src._generatorFeaturesToChange; _formatWriteFeatures = src._formatWriteFeatures; _formatWriteFeaturesToChange = src._formatWriteFeaturesToChange; } private SerializationConfig(SerializationConfig src, Class view) { super(src, view); _serFeatures = src._serFeatures; _filterProvider = src._filterProvider; _defaultPrettyPrinter = src._defaultPrettyPrinter; _generatorFeatures = src._generatorFeatures; _generatorFeaturesToChange = src._generatorFeaturesToChange; _formatWriteFeatures = src._formatWriteFeatures; _formatWriteFeaturesToChange = src._formatWriteFeaturesToChange; } private SerializationConfig(SerializationConfig src, PropertyName rootName) { super(src, rootName); _serFeatures = src._serFeatures; _filterProvider = src._filterProvider; _defaultPrettyPrinter = src._defaultPrettyPrinter; _generatorFeatures = src._generatorFeatures; _generatorFeaturesToChange = src._generatorFeaturesToChange; _formatWriteFeatures = src._formatWriteFeatures; _formatWriteFeaturesToChange = src._formatWriteFeaturesToChange; } /** * @since 2.1 */ protected SerializationConfig(SerializationConfig src, ContextAttributes attrs) { super(src, attrs); _serFeatures = src._serFeatures; _filterProvider = src._filterProvider; _defaultPrettyPrinter = src._defaultPrettyPrinter; _generatorFeatures = src._generatorFeatures; _generatorFeaturesToChange = src._generatorFeaturesToChange; _formatWriteFeatures = src._formatWriteFeatures; _formatWriteFeaturesToChange = src._formatWriteFeaturesToChange; } /** * @since 2.1 */ protected SerializationConfig(SerializationConfig src, SimpleMixInResolver mixins) { super(src, mixins); _serFeatures = src._serFeatures; _filterProvider = src._filterProvider; _defaultPrettyPrinter = src._defaultPrettyPrinter; _generatorFeatures = src._generatorFeatures; _generatorFeaturesToChange = src._generatorFeaturesToChange; _formatWriteFeatures = src._formatWriteFeatures; _formatWriteFeaturesToChange = src._formatWriteFeaturesToChange; } /** * @since 2.6 */ protected SerializationConfig(SerializationConfig src, PrettyPrinter defaultPP) { super(src); _serFeatures = src._serFeatures; _filterProvider = src._filterProvider; _defaultPrettyPrinter = defaultPP; _generatorFeatures = src._generatorFeatures; _generatorFeaturesToChange = src._generatorFeaturesToChange; _formatWriteFeatures = src._formatWriteFeatures; _formatWriteFeaturesToChange = src._formatWriteFeaturesToChange; } /* /********************************************************** /* Life-cycle, factory methods from MapperConfig(Base) /********************************************************** */ @Override // since 2.9 protected final SerializationConfig _withBase(BaseSettings newBase) { return (_base == newBase) ? this : new SerializationConfig(this, newBase); } @Override // since 2.9 protected final SerializationConfig _withMapperFeatures(int mapperFeatures) { return new SerializationConfig(this, mapperFeatures, _serFeatures, _generatorFeatures, _generatorFeaturesToChange, _formatWriteFeatures, _formatWriteFeaturesToChange); } @Override public SerializationConfig withRootName(PropertyName rootName) { if (rootName == null) { if (_rootName == null) { return this; } } else if (rootName.equals(_rootName)) { return this; } return new SerializationConfig(this, rootName); } @Override public SerializationConfig with(SubtypeResolver str) { return (str == _subtypeResolver)? this : new SerializationConfig(this, str); } @Override public SerializationConfig withView(Class view) { return (_view == view) ? this : new SerializationConfig(this, view); } @Override public SerializationConfig with(ContextAttributes attrs) { return (attrs == _attributes) ? this : new SerializationConfig(this, attrs); } /* /********************************************************** /* Factory method overrides /********************************************************** */ /** * In addition to constructing instance with specified date format, * will enable or disable SerializationFeature.WRITE_DATES_AS_TIMESTAMPS * (enable if format set as null; disable if non-null) */ @Override public SerializationConfig with(DateFormat df) { SerializationConfig cfg = super.with(df); // Also need to toggle this feature based on existence of date format: if (df == null) { return cfg.with(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); } return cfg.without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); } /* /********************************************************** /* Factory methods for SerializationFeature /********************************************************** */ /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature enabled. */ public SerializationConfig with(SerializationFeature feature) { int newSerFeatures = _serFeatures | feature.getMask(); return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures, _generatorFeatures, _generatorFeaturesToChange, _formatWriteFeatures, _formatWriteFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. */ public SerializationConfig with(SerializationFeature first, SerializationFeature... features) { int newSerFeatures = _serFeatures | first.getMask(); for (SerializationFeature f : features) { newSerFeatures |= f.getMask(); } return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures, _generatorFeatures, _generatorFeaturesToChange, _formatWriteFeatures, _formatWriteFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. */ public SerializationConfig withFeatures(SerializationFeature... features) { int newSerFeatures = _serFeatures; for (SerializationFeature f : features) { newSerFeatures |= f.getMask(); } return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures, _generatorFeatures, _generatorFeaturesToChange, _formatWriteFeatures, _formatWriteFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature disabled. */ public SerializationConfig without(SerializationFeature feature) { int newSerFeatures = _serFeatures & ~feature.getMask(); return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures, _generatorFeatures, _generatorFeaturesToChange, _formatWriteFeatures, _formatWriteFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. */ public SerializationConfig without(SerializationFeature first, SerializationFeature... features) { int newSerFeatures = _serFeatures & ~first.getMask(); for (SerializationFeature f : features) { newSerFeatures &= ~f.getMask(); } return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures, _generatorFeatures, _generatorFeaturesToChange, _formatWriteFeatures, _formatWriteFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. */ public SerializationConfig withoutFeatures(SerializationFeature... features) { int newSerFeatures = _serFeatures; for (SerializationFeature f : features) { newSerFeatures &= ~f.getMask(); } return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures, _generatorFeatures, _generatorFeaturesToChange, _formatWriteFeatures, _formatWriteFeaturesToChange); } /* /********************************************************** /* Factory methods for JsonGenerator.Feature (2.5) /********************************************************** */ /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature enabled. * * @since 2.5 */ public SerializationConfig with(JsonGenerator.Feature feature) { int newSet = _generatorFeatures | feature.getMask(); int newMask = _generatorFeaturesToChange | feature.getMask(); return ((_generatorFeatures == newSet) && (_generatorFeaturesToChange == newMask)) ? this : new SerializationConfig(this, _mapperFeatures, _serFeatures, newSet, newMask, _formatWriteFeatures, _formatWriteFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. * * @since 2.5 */ public SerializationConfig withFeatures(JsonGenerator.Feature... features) { int newSet = _generatorFeatures; int newMask = _generatorFeaturesToChange; for (JsonGenerator.Feature f : features) { int mask = f.getMask(); newSet |= mask; newMask |= mask; } return ((_generatorFeatures == newSet) && (_generatorFeaturesToChange == newMask)) ? this : new SerializationConfig(this, _mapperFeatures, _serFeatures, newSet, newMask, _formatWriteFeatures, _formatWriteFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature disabled. * * @since 2.5 */ public SerializationConfig without(JsonGenerator.Feature feature) { int newSet = _generatorFeatures & ~feature.getMask(); int newMask = _generatorFeaturesToChange | feature.getMask(); return ((_generatorFeatures == newSet) && (_generatorFeaturesToChange == newMask)) ? this : new SerializationConfig(this, _mapperFeatures, _serFeatures, newSet, newMask, _formatWriteFeatures, _formatWriteFeaturesToChange); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. * * @since 2.5 */ public SerializationConfig withoutFeatures(JsonGenerator.Feature... features) { int newSet = _generatorFeatures; int newMask = _generatorFeaturesToChange; for (JsonGenerator.Feature f : features) { int mask = f.getMask(); newSet &= ~mask; newMask |= mask; } return ((_generatorFeatures == newSet) && (_generatorFeaturesToChange == newMask)) ? this : new SerializationConfig(this, _mapperFeatures, _serFeatures, newSet, newMask, _formatWriteFeatures, _formatWriteFeaturesToChange); } /* /********************************************************** /* Factory methods for FormatFeature (2.7) /********************************************************** */ /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature enabled. * * @since 2.7 */ public SerializationConfig with(FormatFeature feature) { int newSet = _formatWriteFeatures | feature.getMask(); int newMask = _formatWriteFeaturesToChange | feature.getMask(); return ((_formatWriteFeatures == newSet) && (_formatWriteFeaturesToChange == newMask)) ? this : new SerializationConfig(this, _mapperFeatures, _serFeatures, _generatorFeatures, _generatorFeaturesToChange, newSet, newMask); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. * * @since 2.7 */ public SerializationConfig withFeatures(FormatFeature... features) { int newSet = _formatWriteFeatures; int newMask = _formatWriteFeaturesToChange; for (FormatFeature f : features) { int mask = f.getMask(); newSet |= mask; newMask |= mask; } return ((_formatWriteFeatures == newSet) && (_formatWriteFeaturesToChange == newMask)) ? this : new SerializationConfig(this, _mapperFeatures, _serFeatures, _generatorFeatures, _generatorFeaturesToChange, newSet, newMask); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature disabled. * * @since 2.7 */ public SerializationConfig without(FormatFeature feature) { int newSet = _formatWriteFeatures & ~feature.getMask(); int newMask = _formatWriteFeaturesToChange | feature.getMask(); return ((_formatWriteFeatures == newSet) && (_formatWriteFeaturesToChange == newMask)) ? this : new SerializationConfig(this, _mapperFeatures, _serFeatures, _generatorFeatures, _generatorFeaturesToChange, newSet, newMask); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. * * @since 2.7 */ public SerializationConfig withoutFeatures(FormatFeature... features) { int newSet = _formatWriteFeatures; int newMask = _formatWriteFeaturesToChange; for (FormatFeature f : features) { int mask = f.getMask(); newSet &= ~mask; newMask |= mask; } return ((_formatWriteFeatures == newSet) && (_formatWriteFeaturesToChange == newMask)) ? this : new SerializationConfig(this, _mapperFeatures, _serFeatures, _generatorFeatures, _generatorFeaturesToChange, newSet, newMask); } /* /********************************************************** /* Factory methods, other /********************************************************** */ public SerializationConfig withFilters(FilterProvider filterProvider) { return (filterProvider == _filterProvider) ? this : new SerializationConfig(this, filterProvider); } /** * Mutant factory method for constructing a new instance with different * default inclusion criteria configuration. * * @since 2.7 * * @deprecated Since 2.9; not needed any more */ @Deprecated public SerializationConfig withPropertyInclusion(JsonInclude.Value incl) { _configOverrides.setDefaultInclusion(incl); return this; } /** * @since 2.6 */ public SerializationConfig withDefaultPrettyPrinter(PrettyPrinter pp) { return (_defaultPrettyPrinter == pp) ? this: new SerializationConfig(this, pp); } /* /********************************************************** /* Factories for objects configured here /********************************************************** */ public PrettyPrinter constructDefaultPrettyPrinter() { PrettyPrinter pp = _defaultPrettyPrinter; if (pp instanceof Instantiatable) { pp = (PrettyPrinter) ((Instantiatable) pp).createInstance(); } return pp; } /* /********************************************************** /* JsonParser initialization /********************************************************** */ /** * Method called by {@link ObjectMapper} and {@link ObjectWriter} * to modify those {@link com.fasterxml.jackson.core.JsonGenerator.Feature} settings * that have been configured via this config instance. * * @since 2.5 */ public void initialize(JsonGenerator g) { if (SerializationFeature.INDENT_OUTPUT.enabledIn(_serFeatures)) { // but do not override an explicitly set one if (g.getPrettyPrinter() == null) { PrettyPrinter pp = constructDefaultPrettyPrinter(); if (pp != null) { g.setPrettyPrinter(pp); } } } @SuppressWarnings("deprecation") boolean useBigDec = SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN.enabledIn(_serFeatures); int mask = _generatorFeaturesToChange; if ((mask != 0) || useBigDec) { int newFlags = _generatorFeatures; // although deprecated, needs to be supported for now if (useBigDec) { int f = JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN.getMask(); newFlags |= f; mask |= f; } g.overrideStdFeatures(newFlags, mask); } if (_formatWriteFeaturesToChange != 0) { g.overrideFormatFeatures(_formatWriteFeatures, _formatWriteFeaturesToChange); } } /* /********************************************************** /* Configuration: default settings with per-type overrides /********************************************************** */ /** * @deprecated Since 2.7 use {@link #getDefaultPropertyInclusion} instead */ @Deprecated public JsonInclude.Include getSerializationInclusion() { JsonInclude.Include incl = getDefaultPropertyInclusion().getValueInclusion(); return (incl == JsonInclude.Include.USE_DEFAULTS) ? JsonInclude.Include.ALWAYS : incl; } /* /********************************************************** /* Configuration: other /********************************************************** */ @Override public boolean useRootWrapping() { if (_rootName != null) { // empty String disables wrapping; non-empty enables return !_rootName.isEmpty(); } return isEnabled(SerializationFeature.WRAP_ROOT_VALUE); } public final boolean isEnabled(SerializationFeature f) { return (_serFeatures & f.getMask()) != 0; } /** * Accessor method that first checks if we have any overrides * for feature, and only if not, checks state of passed-in * factory. * * @since 2.5 */ public final boolean isEnabled(JsonGenerator.Feature f, JsonFactory factory) { int mask = f.getMask(); if ((_generatorFeaturesToChange & mask) != 0) { return (_generatorFeatures & f.getMask()) != 0; } return factory.isEnabled(f); } /** * "Bulk" access method for checking that all features specified by * mask are enabled. * * @since 2.3 */ public final boolean hasSerializationFeatures(int featureMask) { return (_serFeatures & featureMask) == featureMask; } public final int getSerializationFeatures() { return _serFeatures; } /** * Method for getting provider used for locating filters given * id (which is usually provided with filter annotations). * Will be null if no provided was set for {@link ObjectWriter} * (or if serialization directly called from {@link ObjectMapper}) */ public FilterProvider getFilterProvider() { return _filterProvider; } /** * Accessor for configured blueprint "default" {@link PrettyPrinter} to * use, if default pretty-printing is enabled. *

* NOTE: returns the "blueprint" instance, and does NOT construct * an instance ready to use; call {@link #constructDefaultPrettyPrinter()} if * actually usable instance is desired. * * @since 2.6 */ public PrettyPrinter getDefaultPrettyPrinter() { return _defaultPrettyPrinter; } /* /********************************************************** /* Introspection methods /********************************************************** */ /** * Method that will introspect full bean properties for the purpose * of building a bean serializer */ @SuppressWarnings("unchecked") public T introspect(JavaType type) { return (T) getClassIntrospector().forSerialization(this, type, this); } } SerializationFeature.java000066400000000000000000000433401325620701100354500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import com.fasterxml.jackson.databind.cfg.ConfigFeature; /** * Enumeration that defines simple on/off features that affect * the way Java objects are serialized. *

* Note that features can be set both through * {@link ObjectMapper} (as sort of defaults) and through * {@link ObjectWriter}. * In first case these defaults must follow "config-then-use" patterns * (i.e. defined once, not changed afterwards); all per-call * changes must be done using {@link ObjectWriter}. */ public enum SerializationFeature implements ConfigFeature { /* /****************************************************** /* Generic output features /****************************************************** */ /** * Feature that can be enabled to make root value (usually JSON * Object but can be any type) wrapped within a single property * JSON object, where key as the "root name", as determined by * annotation introspector (esp. for JAXB that uses * @XmlRootElement.name) or fallback (non-qualified * class name). * Feature is mostly intended for JAXB compatibility. *

* Feature is disabled by default. */ WRAP_ROOT_VALUE(false), /** * Feature that allows enabling (or disabling) indentation * for the underlying generator, using the default pretty * printer configured for {@link ObjectMapper} (and * {@link ObjectWriter}s created from mapper). *

* Note that the default pretty printer is only used if * no explicit {@link com.fasterxml.jackson.core.PrettyPrinter} has been configured * for the generator or {@link ObjectWriter}. *

* Feature is disabled by default. */ INDENT_OUTPUT(false), /* /****************************************************** /* Error handling features /****************************************************** */ /** * Feature that determines what happens when no accessors are * found for a type (and there are no annotations to indicate * it is meant to be serialized). If enabled (default), an * exception is thrown to indicate these as non-serializable * types; if disabled, they are serialized as empty Objects, * i.e. without any properties. *

* Note that empty types that this feature has only effect on * those "empty" beans that do not have any recognized annotations * (like @JsonSerialize): ones that do have annotations * do not result in an exception being thrown. *

* Feature is enabled by default. */ FAIL_ON_EMPTY_BEANS(true), /** * Feature that determines what happens when a direct self-reference * is detected by a POJO (and no Object Id handling is enabled for it): * either a {@link JsonMappingException} is * thrown (if true), or reference is normally processed (false). *

* Feature is enabled by default. * * @since 2.4 */ FAIL_ON_SELF_REFERENCES(true), /** * Feature that determines whether Jackson code should catch * and wrap {@link Exception}s (but never {@link Error}s!) * to add additional information about * location (within input) of problem or not. If enabled, * most exceptions will be caught and re-thrown (exception * specifically being that {@link java.io.IOException}s may be passed * as is, since they are declared as throwable); this can be * convenient both in that all exceptions will be checked and * declared, and so there is more contextual information. * However, sometimes calling application may just want "raw" * unchecked exceptions passed as is. *

*

* Feature is enabled by default. */ WRAP_EXCEPTIONS(true), /** * Feature that determines what happens when an object which * normally has type information included by Jackson is used * in conjunction with {@link com.fasterxml.jackson.annotation.JsonUnwrapped}. * In the default (enabled) state, an error will be thrown when * an unwrapped object has type information. When disabled, the * object will be unwrapped and the type information discarded. *

* Feature is enabled by default. * * @since 2.4 */ FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS(true), /* /****************************************************** /* Output life cycle features /****************************************************** */ /** * Feature that determines whether close method of * serialized root level objects (ones for which ObjectMapper's * writeValue() (or equivalent) method is called) * that implement {@link java.io.Closeable} * is called after serialization or not. If enabled, close() will * be called after serialization completes (whether succesfully, or * due to an error manifested by an exception being thrown). You can * think of this as sort of "finally" processing. *

* NOTE: only affects behavior with root objects, and not other * objects reachable from the root object. Put another way, only one * call will be made for each 'writeValue' call. *

* Feature is disabled by default. */ CLOSE_CLOSEABLE(false), /** * Feature that determines whether JsonGenerator.flush() is * called after writeValue() method that takes JsonGenerator * as an argument completes (i.e. does NOT affect methods * that use other destinations); same for methods in {@link ObjectWriter}. * 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), /* /****************************************************** /* Datatype-specific serialization configuration /****************************************************** */ /** * 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; the default), * or as something else (usually textual representation). * If textual representation is used, the actual format is * one returned by a call to * {@link com.fasterxml.jackson.databind.SerializationConfig#getDateFormat}: * the default setting being {@link com.fasterxml.jackson.databind.util.StdDateFormat}, * which corresponds to format String of "yyyy-MM-dd'T'HH:mm:ss.SSSZ" * (see {@link java.text.DateFormat} for details of format Strings). *

* Note: whether this feature affects handling of other date-related * types depend on handlers of those types, although ideally they * should use this feature *

* Note: whether {@link java.util.Map} keys are serialized as Strings * or not is controlled using {@link #WRITE_DATE_KEYS_AS_TIMESTAMPS}. *

* Feature is enabled by default, so that date/time are by default * serialized as timestamps. */ WRITE_DATES_AS_TIMESTAMPS(true), /** * Feature that determines whether {@link java.util.Date}s * (and sub-types) used as {@link java.util.Map} keys are serialized * as timestamps or not (if not, will be serialized as textual * values). *

* Default value is 'false', meaning that Date-valued Map keys are serialized * as textual (ISO-8601) values. *

* Feature is disabled by default. */ WRITE_DATE_KEYS_AS_TIMESTAMPS(false), /** * Feature that determines whether date/date-time values should be serialized * so that they include timezone id, in cases where type itself contains * timezone information. Including this information may lead to compatibility * issues because ISO-8601 specification does not define formats that include * such information. *

* If enabled, Timezone id should be included using format specified * with Java 8 DateTimeFormatter#ISO_ZONED_DATE_TIME definition * (for example, '2011-12-03T10:15:30+01:00[Europe/Paris]'). *

* Note: setting has no relevance if date/time values are serialized as timestamps. *

* Feature is disabled by default, so that zone id is NOT included; rather, timezone * offset is used for ISO-8601 compatibility (if any timezone information is * included in value). * * @since 2.6 */ WRITE_DATES_WITH_ZONE_ID(false), /** * Feature that determines whether time values that represents time periods * (durations, periods, ranges) are to be serialized by default using * a numeric (true) or textual (false) representations. Note that numeric * representation may mean either simple number, or an array of numbers, * depending on type. *

* Note: whether {@link java.util.Map} keys are serialized as Strings * or not is controlled using {@link #WRITE_DATE_KEYS_AS_TIMESTAMPS}. *

* Feature is enabled by default, so that period/duration are by default * serialized as timestamps. * * @since 2.5 */ WRITE_DURATIONS_AS_TIMESTAMPS(true), /** * Feature that determines how type char[] is serialized: * when enabled, will be serialized as an explict JSON array (with * single-character Strings as values); when disabled, defaults to * serializing them as Strings (which is more compact). *

* Feature is disabled by default. */ WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS(false), /** * Feature that determines standard serialization mechanism used for * Enum values: if enabled, return value of Enum.toString() * is used; if disabled, return value of Enum.name() is used. *

* Note: this feature should usually have same value * as {@link DeserializationFeature#READ_ENUMS_USING_TO_STRING}. *

* Feature is disabled by default. */ WRITE_ENUMS_USING_TO_STRING(false), /** * Feature that determines whethere Java Enum values are serialized * as numbers (true), or textual values (false). If textual values are * used, other settings are also considered. * If this feature is enabled, * return value of Enum.ordinal() * (an integer) will be used as the serialization. *

* Note that this feature has precedence over {@link #WRITE_ENUMS_USING_TO_STRING}, * which is only considered if this feature is set to false. *

* Feature is disabled by default. */ WRITE_ENUMS_USING_INDEX(false), /** * Feature that determines whether Map entries with null values are * to be serialized (true) or not (false). *

* NOTE: unlike other {@link SerializationFeature}s, this feature cannot be * dynamically changed on per-call basis, because its effect is considered during * construction of serializers and property handlers. *

* Feature is enabled by default. * * @deprecated Since 2.9 there are better mechanism for specifying filtering; specifically * using {@link com.fasterxml.jackson.annotation.JsonInclude} or configuration overrides * (see {@link ObjectMapper#configOverride(Class)}}). */ @Deprecated // since 2.9 WRITE_NULL_MAP_VALUES(true), /** * Feature that determines whether Container properties (POJO properties * with declared value of Collection or array; i.e. things that produce JSON * arrays) that are empty (have no elements) * will be serialized as empty JSON arrays (true), or suppressed from output (false). *

* Note that this does not change behavior of {@link java.util.Map}s, or * "Collection-like" types. *

* NOTE: unlike other {@link SerializationFeature}s, this feature cannot be * dynamically changed on per-call basis, because its effect is considered during * construction of serializers and property handlers. *

* Feature is enabled by default. * * @deprecated Since 2.8 there are better mechanism for specifying filtering; specifically * using {@link com.fasterxml.jackson.annotation.JsonInclude} or configuration overrides. */ @Deprecated // since 2.8 WRITE_EMPTY_JSON_ARRAYS(true), /** * Feature added for interoperability, to work with oddities of * so-called "BadgerFish" convention. * Feature determines handling of single element {@link java.util.Collection}s * and arrays: if enabled, {@link java.util.Collection}s and arrays that contain exactly * one element will be serialized as if that element itself was serialized. *

* When enabled, a POJO with array that normally looks like this: *

     *  { "arrayProperty" : [ 1 ] }
     *
* will instead be serialized as *
     *  { "arrayProperty" : 1 }
     *
*

* Note that this feature is counterpart to {@link DeserializationFeature#ACCEPT_SINGLE_VALUE_AS_ARRAY} * (that is, usually both are enabled, or neither is). *

* Feature is disabled by default, so that no special handling is done. */ WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED(false), /** * Feature that determines whether {@link java.math.BigDecimal} entries are * serialized using {@link java.math.BigDecimal#toPlainString()} to prevent * values to be written using scientific notation. *

* NOTE: since this feature typically requires use of * {@link com.fasterxml.jackson.core.JsonGenerator#writeNumber(String)} * it may cause compatibility problems since not all {@link com.fasterxml.jackson.core.JsonGenerator} * implementations support such mode of output: usually only text-based formats * support it. *

* Feature is disabled by default. * * @deprecated Since 2.5: use {@link com.fasterxml.jackson.core.JsonGenerator.Feature#WRITE_BIGDECIMAL_AS_PLAIN} instead * (using {@link ObjectWriter#with(com.fasterxml.jackson.core.JsonGenerator.Feature)}). */ @Deprecated // since 2.5 WRITE_BIGDECIMAL_AS_PLAIN(false), /** * Feature that controls whether numeric timestamp values are * to be written using nanosecond timestamps (enabled) or not (disabled); * if and only if datatype supports such resolution. * Only newer datatypes (such as Java8 Date/Time) support such resolution -- * older types (pre-Java8 java.util.Date etc) and Joda do not -- * and this setting has no effect on such types. *

* If disabled, standard millisecond timestamps are assumed. * This is the counterpart to {@link SerializationFeature#WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS}. *

* Feature is enabled by default, to support most accurate time values possible. * * @since 2.2 */ WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS(true), /** * Feature that determines whether {@link java.util.Map} entries are first * sorted by key before serialization or not: if enabled, additional sorting * step is performed if necessary (not necessary for {@link java.util.SortedMap}s), * if disabled, no additional sorting is needed. *

* Feature is disabled by default. */ ORDER_MAP_ENTRIES_BY_KEYS(false), /* /****************************************************** /* Other /****************************************************** */ /** * Feature that determines whether {@link ObjectWriter} should * try to eagerly fetch necessary {@link JsonSerializer} when * possible. This improves performance in cases where similarly * configured {@link ObjectWriter} instance is used multiple * times; and should not significantly affect single-use cases. *

* Note that there should not be any need to normally disable this * feature: only consider that if there are actual perceived problems. *

* Feature is enabled by default. * * @since 2.1 */ EAGER_SERIALIZER_FETCH(true), /** * Feature that determines whether Object Identity is compared using * true JVM-level identity of Object (false); or, equals() method. * Latter is sometimes useful when dealing with Database-bound objects with * ORM libraries (like Hibernate). Note that Object itself is actually compared, * and NOT Object Id; naming of this feature is somewhat confusing, so it is important * that Object for which identity is to be preserved are considered equal, * above and beyond ids (which are always compared using equality anyway). *

* NOTE: due to the way functionality is implemented, it is very important that * in addition to overriding {@link Object#equals} for Objects to match (to be considered * "same") it is also necessary to ensure that {@link Object#hashCode()} is overridden * to produce the exact same value for equal instances. *

* Feature is disabled by default; meaning that strict identity is used, not * equals() * * @since 2.3 */ USE_EQUALITY_FOR_OBJECT_ID(false) ; private final boolean _defaultState; private final int _mask; private SerializationFeature(boolean defaultState) { _defaultState = defaultState; _mask = (1 << ordinal()); } @Override public boolean enabledByDefault() { return _defaultState; } @Override public int getMask() { return _mask; } @Override public boolean enabledIn(int flags) { return (flags & _mask) != 0; } } SerializerProvider.java000066400000000000000000001521051325620701100351430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.IOException; import java.text.DateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.cfg.ContextAttributes; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; import com.fasterxml.jackson.databind.exc.InvalidTypeIdException; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.*; import com.fasterxml.jackson.databind.ser.impl.FailingSerializer; import com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap; import com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer; import com.fasterxml.jackson.databind.ser.impl.UnknownSerializer; import com.fasterxml.jackson.databind.ser.impl.WritableObjectId; import com.fasterxml.jackson.databind.ser.std.NullSerializer; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Class that defines API used by {@link ObjectMapper} and * {@link JsonSerializer}s to obtain serializers capable of serializing * instances of specific types; as well as the default implementation * of the functionality. *

* Provider handles caching aspects of serializer handling; all construction * details are delegated to {@link SerializerFactory} instance. *

* Object life-cycle is such that an initial instance ("blueprint") is created * and referenced by {@link ObjectMapper} and {@link ObjectWriter} intances; * but for actual usage, a configured instance is created by using * a create method in sub-class * {@link com.fasterxml.jackson.databind.ser.DefaultSerializerProvider}. * Only this instance can be used for actual serialization calls; blueprint * object is only to be used for creating instances. */ public abstract class SerializerProvider extends DatabindContext { /** * Setting for determining whether mappings for "unknown classes" should be * cached for faster resolution. Usually this isn't needed, but maybe it * is in some cases? */ protected final static boolean CACHE_UNKNOWN_MAPPINGS = false; public final static JsonSerializer DEFAULT_NULL_KEY_SERIALIZER = new FailingSerializer("Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)"); /** * Placeholder serializer used when java.lang.Object typed property * is marked to be serialized. *
* NOTE: starting with 2.6, this instance is NOT used for any other types, and * separate instances are constructed for "empty" Beans. *

* NOTE: changed to protected for 2.3; no need to be publicly available. */ protected final static JsonSerializer DEFAULT_UNKNOWN_SERIALIZER = new UnknownSerializer(); /* /********************************************************** /* Configuration, general /********************************************************** */ /** * Serialization configuration to use for serialization processing. */ final protected SerializationConfig _config; /** * View used for currently active serialization, if any. * Only set for non-blueprint instances. */ final protected Class _serializationView; /* /********************************************************** /* Configuration, factories /********************************************************** */ /** * Factory used for constructing actual serializer instances. * Only set for non-blueprint instances. */ final protected SerializerFactory _serializerFactory; /* /********************************************************** /* Helper objects for caching, reuse /********************************************************** */ /** * Cache for doing type-to-value-serializer lookups. */ final protected SerializerCache _serializerCache; /** * Lazily-constructed holder for per-call attributes. * Only set for non-blueprint instances. * * @since 2.3 */ protected transient ContextAttributes _attributes; /* /********************************************************** /* Configuration, specialized serializers /********************************************************** */ /** * Serializer that gets called for values of types for which no * serializers can be constructed. *

* The default serializer will simply thrown an exception. */ protected JsonSerializer _unknownTypeSerializer = DEFAULT_UNKNOWN_SERIALIZER; /** * Serializer used to output non-null keys of Maps (which will get * output as JSON Objects), if not null; if null, us the standard * default key serializer. */ protected JsonSerializer _keySerializer; /** * Serializer used to output a null value. Default implementation * writes nulls using {@link JsonGenerator#writeNull}. */ protected JsonSerializer _nullValueSerializer = NullSerializer.instance; /** * Serializer used to (try to) output a null key, due to an entry of * {@link java.util.Map} having null key. * The default implementation will throw an exception if this happens; * alternative implementation (like one that would write an Empty String) * can be defined. */ protected JsonSerializer _nullKeySerializer = DEFAULT_NULL_KEY_SERIALIZER; /* /********************************************************** /* State, for non-blueprint instances: generic /********************************************************** */ /** * For fast lookups, we will have a local non-shared read-only * map that contains serializers previously fetched. */ protected final ReadOnlyClassToSerializerMap _knownSerializers; /** * Lazily acquired and instantiated formatter object: initialized * first time it is needed, reused afterwards. Used via instances * (not blueprints), so that access need not be thread-safe. */ protected DateFormat _dateFormat; /** * Flag set to indicate that we are using vanilla null value serialization * * @since 2.3 */ protected final boolean _stdNullValueSerializer; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * Constructor for creating master (or "blue-print") provider object, * which is only used as the template for constructing per-binding * instances. */ public SerializerProvider() { _config = null; _serializerFactory = null; _serializerCache = new SerializerCache(); // Blueprints doesn't have access to any serializers... _knownSerializers = null; _serializationView = null; _attributes = null; // not relevant for blueprint instance, could set either way: _stdNullValueSerializer = true; } /** * "Copy-constructor", used by sub-classes when creating actual non-blueprint * instances to use. * * @param src Blueprint object used as the baseline for this instance */ protected SerializerProvider(SerializerProvider src, SerializationConfig config, SerializerFactory f) { _serializerFactory = f; _config = config; _serializerCache = src._serializerCache; _unknownTypeSerializer = src._unknownTypeSerializer; _keySerializer = src._keySerializer; _nullValueSerializer = src._nullValueSerializer; _nullKeySerializer = src._nullKeySerializer; _stdNullValueSerializer = (_nullValueSerializer == DEFAULT_NULL_KEY_SERIALIZER); _serializationView = config.getActiveView(); _attributes = config.getAttributes(); /* Non-blueprint instances do have a read-only map; one that doesn't * need synchronization for lookups. */ _knownSerializers = _serializerCache.getReadOnlyLookupMap(); } /** * Copy-constructor used when making a copy of a blueprint instance. * * @since 2.5 */ protected SerializerProvider(SerializerProvider src) { // since this is assumed to be a blue-print instance, many settings missing: _config = null; _serializationView = null; _serializerFactory = null; _knownSerializers = null; // and others initialized to default empty state _serializerCache = new SerializerCache(); _unknownTypeSerializer = src._unknownTypeSerializer; _keySerializer = src._keySerializer; _nullValueSerializer = src._nullValueSerializer; _nullKeySerializer = src._nullKeySerializer; _stdNullValueSerializer = src._stdNullValueSerializer; } /* /********************************************************** /* Methods for configuring default settings /********************************************************** */ /** * Method that can be used to specify serializer that will be * used to write JSON property names matching null keys for Java * Maps (which will throw an exception if try write such property * name) */ public void setDefaultKeySerializer(JsonSerializer ks) { if (ks == null) { throw new IllegalArgumentException("Cannot pass null JsonSerializer"); } _keySerializer = ks; } /** * Method that can be used to specify serializer that will be * used to write JSON values matching Java null values * instead of default one (which simply writes JSON null). *

* Note that you can get finer control over serializer to use by overriding * {@link #findNullValueSerializer}, which gets called once per each * property. */ public void setNullValueSerializer(JsonSerializer nvs) { if (nvs == null) { throw new IllegalArgumentException("Cannot pass null JsonSerializer"); } _nullValueSerializer = nvs; } /** * Method that can be used to specify serializer to use for serializing * all non-null JSON property names, unless more specific key serializer * is found (i.e. if not custom key serializer has been registered for * Java type). *

* Note that key serializer registration are different from value serializer * registrations. */ public void setNullKeySerializer(JsonSerializer nks) { if (nks == null) { throw new IllegalArgumentException("Cannot pass null JsonSerializer"); } _nullKeySerializer = nks; } /* /********************************************************** /* DatabindContext implementation (and closely related /* but ser-specific) /********************************************************** */ /** * Method for accessing configuration for the serialization processing. */ @Override public final SerializationConfig getConfig() { return _config; } @Override public final AnnotationIntrospector getAnnotationIntrospector() { return _config.getAnnotationIntrospector(); } @Override public final TypeFactory getTypeFactory() { return _config.getTypeFactory(); } @Override public final Class getActiveView() { return _serializationView; } /** * @deprecated Since 2.2, use {@link #getActiveView} instead. */ @Deprecated public final Class getSerializationView() { return _serializationView; } @Override public final boolean canOverrideAccessModifiers() { return _config.canOverrideAccessModifiers(); } @Override public final boolean isEnabled(MapperFeature feature) { return _config.isEnabled(feature); } @Override public final JsonFormat.Value getDefaultPropertyFormat(Class baseType) { return _config.getDefaultPropertyFormat(baseType); } /** * @since 2.8 */ public final JsonInclude.Value getDefaultPropertyInclusion(Class baseType) { return _config.getDefaultPropertyInclusion(); } /** * Method for accessing default Locale to use: convenience method for *
     *   getConfig().getLocale();
     *
*/ @Override public Locale getLocale() { return _config.getLocale(); } /** * Method for accessing default TimeZone to use: convenience method for *
     *   getConfig().getTimeZone();
     *
*/ @Override public TimeZone getTimeZone() { return _config.getTimeZone(); } /* /********************************************************** /* Generic attributes (2.3+) /********************************************************** */ @Override public Object getAttribute(Object key) { return _attributes.getAttribute(key); } @Override public SerializerProvider setAttribute(Object key, Object value) { _attributes = _attributes.withPerCallAttribute(key, value); return this; } /* /********************************************************** /* Access to general configuration /********************************************************** */ /** * Convenience method for checking whether specified serialization * feature is enabled or not. * Shortcut for: *
     *  getConfig().isEnabled(feature);
     *
*/ public final boolean isEnabled(SerializationFeature feature) { return _config.isEnabled(feature); } /** * "Bulk" access method for checking that all features specified by * mask are enabled. * * @since 2.3 */ public final boolean hasSerializationFeatures(int featureMask) { return _config.hasSerializationFeatures(featureMask); } /** * Convenience method for accessing provider to find serialization filters used, * equivalent to calling: *
     *   getConfig().getFilterProvider();
     *
*/ public final FilterProvider getFilterProvider() { return _config.getFilterProvider(); } /** *

* NOTE: current implementation simply returns `null` as generator is not yet * assigned to this provider. * * @since 2.8 */ public JsonGenerator getGenerator() { return null; } /* /********************************************************** /* Access to Object Id aspects /********************************************************** */ /** * Method called to find the Object Id for given POJO, if one * has been generated. Will always return a non-null Object; * contents vary depending on whether an Object Id already * exists or not. */ public abstract WritableObjectId findObjectId(Object forPojo, ObjectIdGenerator generatorType); /* /********************************************************** /* General serializer locating functionality /********************************************************** */ /** * Method called to get hold of a serializer for a value of given type; * or if no such serializer can be found, a default handler (which * may do a best-effort generic serialization or just simply * throw an exception when invoked). *

* Note: this method is only called for non-null values; not for keys * or null values. For these, check out other accessor methods. *

* Note that serializers produced should NOT handle polymorphic serialization * aspects; separate {@link TypeSerializer} is to be constructed by caller * if and as necessary. * * @throws JsonMappingException if there are fatal problems with * accessing suitable serializer; including that of not * finding any serializer */ @SuppressWarnings("unchecked") public JsonSerializer findValueSerializer(Class valueType, BeanProperty property) throws JsonMappingException { // Fast lookup from local lookup thingy works? JsonSerializer ser = _knownSerializers.untypedValueSerializer(valueType); if (ser == null) { // If not, maybe shared map already has it? ser = _serializerCache.untypedValueSerializer(valueType); if (ser == null) { // ... possibly as fully typed? ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType)); if (ser == null) { // If neither, must create ser = _createAndCacheUntypedSerializer(valueType); // Not found? Must use the unknown type serializer, which will report error later on if (ser == null) { ser = getUnknownTypeSerializer(valueType); // Should this be added to lookups? if (CACHE_UNKNOWN_MAPPINGS) { _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); } return ser; } } } } // at this point, resolution has occured, but not contextualization return (JsonSerializer) handleSecondaryContextualization(ser, property); } /** * Similar to {@link #findValueSerializer(Class,BeanProperty)}, but takes * full generics-aware type instead of raw class. * This is necessary for accurate handling of external type information, * to handle polymorphic types. *

* Note: this call will also contextualize serializer before returning it. * * @param property When creating secondary serializers, property for which * serializer is needed: annotations of the property (or bean that contains it) * may be checked to create contextual serializers. */ @SuppressWarnings("unchecked") public JsonSerializer findValueSerializer(JavaType valueType, BeanProperty property) throws JsonMappingException { if (valueType == null) { reportMappingProblem("Null passed for `valueType` of `findValueSerializer()`"); } // (see comments from above method) JsonSerializer ser = _knownSerializers.untypedValueSerializer(valueType); if (ser == null) { ser = _serializerCache.untypedValueSerializer(valueType); if (ser == null) { ser = _createAndCacheUntypedSerializer(valueType); if (ser == null) { ser = getUnknownTypeSerializer(valueType.getRawClass()); if (CACHE_UNKNOWN_MAPPINGS) { _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); } return ser; } } } return (JsonSerializer) handleSecondaryContextualization(ser, property); } /** * Method variant used when we do NOT want contextualization to happen; it will need * to be handled at a later point, but caller wants to be able to do that * as needed; sometimes to avoid infinite loops * * @since 2.5 */ public JsonSerializer findValueSerializer(Class valueType) throws JsonMappingException { // (see comments from above method) JsonSerializer ser = _knownSerializers.untypedValueSerializer(valueType); if (ser == null) { ser = _serializerCache.untypedValueSerializer(valueType); if (ser == null) { ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType)); if (ser == null) { ser = _createAndCacheUntypedSerializer(valueType); if (ser == null) { ser = getUnknownTypeSerializer(valueType); if (CACHE_UNKNOWN_MAPPINGS) { _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); } } } } } return ser; } /** * Method variant used when we do NOT want contextualization to happen; it will need * to be handled at a later point, but caller wants to be able to do that * as needed; sometimes to avoid infinite loops * * @since 2.5 */ public JsonSerializer findValueSerializer(JavaType valueType) throws JsonMappingException { // (see comments from above method) JsonSerializer ser = _knownSerializers.untypedValueSerializer(valueType); if (ser == null) { ser = _serializerCache.untypedValueSerializer(valueType); if (ser == null) { ser = _createAndCacheUntypedSerializer(valueType); if (ser == null) { ser = getUnknownTypeSerializer(valueType.getRawClass()); if (CACHE_UNKNOWN_MAPPINGS) { _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); } } } } return ser; } /** * Similar to {@link #findValueSerializer(JavaType, BeanProperty)}, but used * when finding "primary" property value serializer (one directly handling * value of the property). Difference has to do with contextual resolution, * and method(s) called: this method should only be called when caller is * certain that this is the primary property value serializer. * * @param property Property that is being handled; will never be null, and its * type has to match valueType parameter. * * @since 2.3 */ @SuppressWarnings("unchecked") public JsonSerializer findPrimaryPropertySerializer(JavaType valueType, BeanProperty property) throws JsonMappingException { JsonSerializer ser = _knownSerializers.untypedValueSerializer(valueType); if (ser == null) { ser = _serializerCache.untypedValueSerializer(valueType); if (ser == null) { ser = _createAndCacheUntypedSerializer(valueType); if (ser == null) { ser = getUnknownTypeSerializer(valueType.getRawClass()); // Should this be added to lookups? if (CACHE_UNKNOWN_MAPPINGS) { _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); } return ser; } } } return (JsonSerializer) handlePrimaryContextualization(ser, property); } /** * @since 2.3 */ @SuppressWarnings("unchecked") public JsonSerializer findPrimaryPropertySerializer(Class valueType, BeanProperty property) throws JsonMappingException { JsonSerializer ser = _knownSerializers.untypedValueSerializer(valueType); if (ser == null) { ser = _serializerCache.untypedValueSerializer(valueType); if (ser == null) { ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType)); if (ser == null) { ser = _createAndCacheUntypedSerializer(valueType); if (ser == null) { ser = getUnknownTypeSerializer(valueType); if (CACHE_UNKNOWN_MAPPINGS) { _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); } return ser; } } } } return (JsonSerializer) handlePrimaryContextualization(ser, property); } /** * Method called to locate regular serializer, matching type serializer, * and if both found, wrap them in a serializer that calls both in correct * sequence. This method is currently only used for root-level serializer * handling to allow for simpler caching. A call can always be replaced * by equivalent calls to access serializer and type serializer separately. * * @param valueType Type for purpose of locating a serializer; usually dynamic * runtime type, but can also be static declared type, depending on configuration * @param cache Whether resulting value serializer should be cached or not; this is just * a hint * @param property When creating secondary serializers, property for which * serializer is needed: annotations of the property (or bean that contains it) * may be checked to create contextual serializers. */ public JsonSerializer findTypedValueSerializer(Class valueType, boolean cache, BeanProperty property) throws JsonMappingException { // Two-phase lookups; local non-shared cache, then shared: JsonSerializer ser = _knownSerializers.typedValueSerializer(valueType); if (ser != null) { return ser; } // If not, maybe shared map already has it? ser = _serializerCache.typedValueSerializer(valueType); if (ser != null) { return ser; } // Well, let's just compose from pieces: ser = findValueSerializer(valueType, property); TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config, _config.constructType(valueType)); if (typeSer != null) { typeSer = typeSer.forProperty(property); ser = new TypeWrappedSerializer(typeSer, ser); } if (cache) { _serializerCache.addTypedSerializer(valueType, ser); } return ser; } /** * Method called to locate regular serializer, matching type serializer, * and if both found, wrap them in a serializer that calls both in correct * sequence. This method is currently only used for root-level serializer * handling to allow for simpler caching. A call can always be replaced * by equivalent calls to access serializer and type serializer separately. * * @param valueType Declared type of value being serialized (which may not * be actual runtime type); used for finding both value serializer and * type serializer to use for adding polymorphic type (if any) * @param cache Whether resulting value serializer should be cached or not; this is just * a hint * @param property When creating secondary serializers, property for which * serializer is needed: annotations of the property (or bean that contains it) * may be checked to create contextual serializers. */ public JsonSerializer findTypedValueSerializer(JavaType valueType, boolean cache, BeanProperty property) throws JsonMappingException { // Two-phase lookups; local non-shared cache, then shared: JsonSerializer ser = _knownSerializers.typedValueSerializer(valueType); if (ser != null) { return ser; } // If not, maybe shared map already has it? ser = _serializerCache.typedValueSerializer(valueType); if (ser != null) { return ser; } // Well, let's just compose from pieces: ser = findValueSerializer(valueType, property); TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config, valueType); if (typeSer != null) { typeSer = typeSer.forProperty(property); ser = new TypeWrappedSerializer(typeSer, ser); } if (cache) { _serializerCache.addTypedSerializer(valueType, ser); } return ser; } /** * Method called to get the {@link TypeSerializer} to use for including Type Id necessary * for serializing for the given Java class. * Useful for schema generators. * * @since 2.6 */ public TypeSerializer findTypeSerializer(JavaType javaType) throws JsonMappingException { return _serializerFactory.createTypeSerializer(_config, javaType); } /** * Method called to get the serializer to use for serializing * non-null Map keys. Separation from regular * {@link #findValueSerializer} method is because actual write * method must be different (@link JsonGenerator#writeFieldName}; * but also since behavior for some key types may differ. *

* Note that the serializer itself can be called with instances * of any Java object, but not nulls. */ public JsonSerializer findKeySerializer(JavaType keyType, BeanProperty property) throws JsonMappingException { JsonSerializer ser = _serializerFactory.createKeySerializer(_config, keyType, _keySerializer); // 25-Feb-2011, tatu: As per [JACKSON-519], need to ensure contextuality works here, too return _handleContextualResolvable(ser, property); } /** * @since 2.7 */ public JsonSerializer findKeySerializer(Class rawKeyType, BeanProperty property) throws JsonMappingException { return findKeySerializer(_config.constructType(rawKeyType), property); } /* /******************************************************** /* Accessors for specialized serializers /******************************************************** */ /** * @since 2.0 */ public JsonSerializer getDefaultNullKeySerializer() { return _nullKeySerializer; } /** * @since 2.0 */ public JsonSerializer getDefaultNullValueSerializer() { return _nullValueSerializer; } /** * Method called to get the serializer to use for serializing * Map keys that are nulls: this is needed since JSON does not allow * any non-String value as key, including null. *

* Typically, returned serializer * will either throw an exception, or use an empty String; but * other behaviors are possible. */ /** * Method called to find a serializer to use for null values for given * declared type. Note that type is completely based on declared type, * since nulls in Java have no type and thus runtime type cannot be * determined. * * @since 2.0 */ public JsonSerializer findNullKeySerializer(JavaType serializationType, BeanProperty property) throws JsonMappingException { return _nullKeySerializer; } /** * Method called to get the serializer to use for serializing null * values for specified property. *

* Default implementation simply calls {@link #getDefaultNullValueSerializer()}; * can be overridden to add custom null serialization for properties * of certain type or name. This gives method full granularity to basically * override null handling for any specific property or class of properties. * * @since 2.0 */ public JsonSerializer findNullValueSerializer(BeanProperty property) throws JsonMappingException { return _nullValueSerializer; } /** * Method called to get the serializer to use if provider * cannot determine an actual type-specific serializer * to use; typically when none of {@link SerializerFactory} * instances are able to construct a serializer. *

* Typically, returned serializer will throw an exception, * although alternatively {@link com.fasterxml.jackson.databind.ser.std.ToStringSerializer} * could be returned as well. * * @param unknownType Type for which no serializer is found */ public JsonSerializer getUnknownTypeSerializer(Class unknownType) { // 23-Apr-2015, tatu: Only return shared instance if nominal type is Object.class if (unknownType == Object.class) { return _unknownTypeSerializer; } // otherwise construct explicit instance with property handled type return new UnknownSerializer(unknownType); } /** * Helper method called to see if given serializer is considered to be * something returned by {@link #getUnknownTypeSerializer}, that is, something * for which no regular serializer was found or constructed. * * @since 2.5 */ public boolean isUnknownTypeSerializer(JsonSerializer ser) { if ((ser == _unknownTypeSerializer) || (ser == null)) { return true; } // 23-Apr-2015, tatu: "empty" serializer is trickier; needs to consider // error handling if (isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) { if (ser.getClass() == UnknownSerializer.class) { return true; } } return false; } /* /********************************************************** /* Methods for creating instances based on annotations /********************************************************** */ /** * Method that can be called to construct and configure serializer instance, * either given a {@link Class} to instantiate (with default constructor), * or an uninitialized serializer instance. * Either way, serialize will be properly resolved * (via {@link com.fasterxml.jackson.databind.ser.ResolvableSerializer}) and/or contextualized * (via {@link com.fasterxml.jackson.databind.ser.ContextualSerializer}) as necessary. * * @param annotated Annotated entity that contained definition * @param serDef Serializer definition: either an instance or class */ public abstract JsonSerializer serializerInstance(Annotated annotated, Object serDef) throws JsonMappingException; /** * Method that can be called to construct and configure {@link JsonInclude} * filter instance, * given a {@link Class} to instantiate (with default constructor, by default). * * @param forProperty (optional) If filter is created for a property, that property; * `null` if filter created via defaulting, global or per-type. * * @since 2.9 */ public abstract Object includeFilterInstance(BeanPropertyDefinition forProperty, Class filterClass) throws JsonMappingException; /** * Follow-up method that may be called after calling {@link #includeFilterInstance}, * to check handling of `null` values by the filter. * * @since 2.9 */ public abstract boolean includeFilterSuppressNulls(Object filter) throws JsonMappingException; /* /********************************************************** /* Support for contextualization /********************************************************** */ /** * Method called for primary property serializers (ones * directly created to serialize values of a POJO property), * to handle details of resolving * {@link ContextualSerializer} with given property context. * * @param property Property for which the given primary serializer is used; never null. * * @since 2.3 */ public JsonSerializer handlePrimaryContextualization(JsonSerializer ser, BeanProperty property) throws JsonMappingException { if (ser != null) { if (ser instanceof ContextualSerializer) { ser = ((ContextualSerializer) ser).createContextual(this, property); } } return ser; } /** * Method called for secondary property serializers (ones * NOT directly created to serialize values of a POJO property * but instead created as a dependant serializer -- such as value serializers * for structured types, or serializers for root values) * to handle details of resolving * {@link ContextualDeserializer} with given property context. * Given that these serializers are not directly related to given property * (or, in case of root value property, to any property), annotations * accessible may or may not be relevant. * * @param property Property for which serializer is used, if any; null * when deserializing root values * * @since 2.3 */ public JsonSerializer handleSecondaryContextualization(JsonSerializer ser, BeanProperty property) throws JsonMappingException { if (ser != null) { if (ser instanceof ContextualSerializer) { ser = ((ContextualSerializer) ser).createContextual(this, property); } } return ser; } /* /******************************************************** /* Convenience methods for serializing using default methods /******************************************************** */ /** * Convenience method that will serialize given value (which can be * null) using standard serializer locating functionality. It can * be called for all values including field and Map values, but usually * field values are best handled calling * {@link #defaultSerializeField} instead. */ public final void defaultSerializeValue(Object value, JsonGenerator gen) throws IOException { if (value == null) { if (_stdNullValueSerializer) { // minor perf optimization gen.writeNull(); } else { _nullValueSerializer.serialize(null, gen, this); } } else { Class cls = value.getClass(); findTypedValueSerializer(cls, true, null).serialize(value, gen, this); } } /** * Convenience method that will serialize given field with specified * value. Value may be null. Serializer is done using the usual * null) using standard serializer locating functionality. */ public final void defaultSerializeField(String fieldName, Object value, JsonGenerator gen) throws IOException { gen.writeFieldName(fieldName); if (value == null) { /* Note: can't easily check for suppression at this point * any more; caller must check it. */ if (_stdNullValueSerializer) { // minor perf optimization gen.writeNull(); } else { _nullValueSerializer.serialize(null, gen, this); } } else { Class cls = value.getClass(); findTypedValueSerializer(cls, true, null).serialize(value, gen, this); } } /** * Method that will handle serialization of Date(-like) values, using * {@link SerializationConfig} settings to determine expected serialization * behavior. * Note: date here means "full" date, that is, date AND time, as per * Java convention (and not date-only values like in SQL) */ public final void defaultSerializeDateValue(long timestamp, JsonGenerator gen) throws IOException { if (isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)) { gen.writeNumber(timestamp); } else { gen.writeString(_dateFormat().format(new Date(timestamp))); } } /** * Method that will handle serialization of Date(-like) values, using * {@link SerializationConfig} settings to determine expected serialization * behavior. * Note: date here means "full" date, that is, date AND time, as per * Java convention (and not date-only values like in SQL) */ public final void defaultSerializeDateValue(Date date, JsonGenerator gen) throws IOException { if (isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)) { gen.writeNumber(date.getTime()); } else { gen.writeString(_dateFormat().format(date)); } } /** * Method that will handle serialization of Dates used as {@link java.util.Map} keys, * based on {@link SerializationFeature#WRITE_DATE_KEYS_AS_TIMESTAMPS} * value (and if using textual representation, configured date format) */ public void defaultSerializeDateKey(long timestamp, JsonGenerator gen) throws IOException { if (isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)) { gen.writeFieldName(String.valueOf(timestamp)); } else { gen.writeFieldName(_dateFormat().format(new Date(timestamp))); } } /** * Method that will handle serialization of Dates used as {@link java.util.Map} keys, * based on {@link SerializationFeature#WRITE_DATE_KEYS_AS_TIMESTAMPS} * value (and if using textual representation, configured date format) */ public void defaultSerializeDateKey(Date date, JsonGenerator gen) throws IOException { if (isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)) { gen.writeFieldName(String.valueOf(date.getTime())); } else { gen.writeFieldName(_dateFormat().format(date)); } } public final void defaultSerializeNull(JsonGenerator gen) throws IOException { if (_stdNullValueSerializer) { // minor perf optimization gen.writeNull(); } else { _nullValueSerializer.serialize(null, gen, this); } } /* /******************************************************** /* Error reporting /******************************************************** */ /** * Helper method called to indicate problem; default behavior is to construct and * throw a {@link JsonMappingException}, but in future may collect more than one * and only throw after certain number, or at the end of serialization. * * @since 2.8 */ public void reportMappingProblem(String message, Object... args) throws JsonMappingException { throw mappingException(message, args); } /** * Helper method called to indicate problem in POJO (serialization) definitions or settings * regarding specific Java type, unrelated to actual JSON content to map. * Default behavior is to construct and throw a {@link JsonMappingException}. * * @since 2.9 */ public T reportBadTypeDefinition(BeanDescription bean, String msg, Object... msgArgs) throws JsonMappingException { String beanDesc = "N/A"; if (bean != null) { beanDesc = ClassUtil.nameOf(bean.getBeanClass()); } msg = String.format("Invalid type definition for type %s: %s", beanDesc, _format(msg, msgArgs)); throw InvalidDefinitionException.from(getGenerator(), msg, bean, null); } /** * Helper method called to indicate problem in POJO (serialization) definitions or settings * regarding specific property (of a type), unrelated to actual JSON content to map. * Default behavior is to construct and throw a {@link JsonMappingException}. * * @since 2.9 */ public T reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop, String message, Object... msgArgs) throws JsonMappingException { message = _format(message, msgArgs); String propName = "N/A"; if (prop != null) { propName = _quotedString(prop.getName()); } String beanDesc = "N/A"; if (bean != null) { beanDesc = ClassUtil.nameOf(bean.getBeanClass()); } message = String.format("Invalid definition for property %s (of type %s): %s", propName, beanDesc, message); throw InvalidDefinitionException.from(getGenerator(), message, bean, prop); } @Override public T reportBadDefinition(JavaType type, String msg) throws JsonMappingException { throw InvalidDefinitionException.from(getGenerator(), msg, type); } /** * @since 2.9 */ public T reportBadDefinition(JavaType type, String msg, Throwable cause) throws JsonMappingException { InvalidDefinitionException e = InvalidDefinitionException.from(getGenerator(), msg, type); e.initCause(cause); throw e; } /** * @since 2.9 */ public T reportBadDefinition(Class raw, String msg, Throwable cause) throws JsonMappingException { InvalidDefinitionException e = InvalidDefinitionException.from(getGenerator(), msg, constructType(raw)); e.initCause(cause); throw e; } /** * Helper method called to indicate problem; default behavior is to construct and * throw a {@link JsonMappingException}, but in future may collect more than one * and only throw after certain number, or at the end of serialization. * * @since 2.8 */ public void reportMappingProblem(Throwable t, String message, Object... msgArgs) throws JsonMappingException { message = _format(message, msgArgs); throw JsonMappingException.from(getGenerator(), message, t); } @Override public JsonMappingException invalidTypeIdException(JavaType baseType, String typeId, String extraDesc) { String msg = String.format("Could not resolve type id '%s' as a subtype of %s", typeId, baseType); return InvalidTypeIdException.from(null, _colonConcat(msg, extraDesc), baseType, typeId); } /* /******************************************************** /* Error reporting, deprecated methods /******************************************************** */ /** * Factory method for constructing a {@link JsonMappingException}; * usually only indirectly used by calling * {@link #reportMappingProblem(String, Object...)}. * * @since 2.6 * * @deprecated Since 2.9 */ @Deprecated // since 2.9 public JsonMappingException mappingException(String message, Object... msgArgs) { return JsonMappingException.from(getGenerator(), _format(message, msgArgs)); } /** * Factory method for constructing a {@link JsonMappingException}; * usually only indirectly used by calling * {@link #reportMappingProblem(Throwable, String, Object...)} * * @since 2.8 * * @deprecated Since 2.9 */ @Deprecated // since 2.9 protected JsonMappingException mappingException(Throwable t, String message, Object... msgArgs) { return JsonMappingException.from(getGenerator(), _format(message, msgArgs), t); } /* /******************************************************** /* Helper methods /******************************************************** */ protected void _reportIncompatibleRootType(Object value, JavaType rootType) throws IOException { // One special case: allow primitive/wrapper type coercion if (rootType.isPrimitive()) { Class wrapperType = ClassUtil.wrapperType(rootType.getRawClass()); // If it's just difference between wrapper, primitive, let it slide if (wrapperType.isAssignableFrom(value.getClass())) { return; } } reportBadDefinition(rootType, String.format( "Incompatible types: declared root type (%s) vs %s", rootType, ClassUtil.classNameOf(value))); } /** * Method that will try to find a serializer, either from cache * or by constructing one; but will not return an "unknown" serializer * if this cannot be done but rather returns null. * * @return Serializer if one can be found, null if not. */ protected JsonSerializer _findExplicitUntypedSerializer(Class runtimeType) throws JsonMappingException { // Fast lookup from local lookup thingy works? JsonSerializer ser = _knownSerializers.untypedValueSerializer(runtimeType); if (ser == null) { // If not, maybe shared map already has it? ser = _serializerCache.untypedValueSerializer(runtimeType); if (ser == null) { ser = _createAndCacheUntypedSerializer(runtimeType); } } /* 18-Sep-2014, tatu: This is unfortunate patch over related change * that pushes creation of "unknown type" serializer deeper down * in BeanSerializerFactory; as a result, we need to "undo" creation * here. */ if (isUnknownTypeSerializer(ser)) { return null; } return ser; } /* /********************************************************** /* Low-level methods for actually constructing and initializing /* serializers /********************************************************** */ /** * Method that will try to construct a value serializer; and if * one is successfully created, cache it for reuse. */ protected JsonSerializer _createAndCacheUntypedSerializer(Class rawType) throws JsonMappingException { JavaType fullType = _config.constructType(rawType); JsonSerializer ser; try { ser = _createUntypedSerializer(fullType); } catch (IllegalArgumentException iae) { /* We better only expose checked exceptions, since those * are what caller is expected to handle */ ser = null; // doesn't matter but compiler whines otherwise reportMappingProblem(iae, iae.getMessage()); } if (ser != null) { // 21-Dec-2015, tatu: Best to cache for both raw and full-type key _serializerCache.addAndResolveNonTypedSerializer(rawType, fullType, ser, this); } return ser; } protected JsonSerializer _createAndCacheUntypedSerializer(JavaType type) throws JsonMappingException { JsonSerializer ser; try { ser = _createUntypedSerializer(type); } catch (IllegalArgumentException iae) { // We better only expose checked exceptions, since those // are what caller is expected to handle ser = null; reportMappingProblem(iae, iae.getMessage()); } if (ser != null) { // 21-Dec-2015, tatu: Should we also cache using raw key? _serializerCache.addAndResolveNonTypedSerializer(type, ser, this); } return ser; } /** * @since 2.1 */ protected JsonSerializer _createUntypedSerializer(JavaType type) throws JsonMappingException { /* 27-Mar-2015, tatu: Wish I knew exactly why/what, but [databind#738] * can be prevented by synchronizing on cache (not on 'this', however, * since there's one instance per serialization). * Perhaps not-yet-resolved instance might be exposed too early to callers. */ synchronized (_serializerCache) { // 17-Feb-2013, tatu: Used to call deprecated method (that passed property) return (JsonSerializer)_serializerFactory.createSerializer(this, type); } } /** * Helper method called to resolve and contextualize given * serializer, if and as necessary. */ @SuppressWarnings("unchecked") protected JsonSerializer _handleContextualResolvable(JsonSerializer ser, BeanProperty property) throws JsonMappingException { if (ser instanceof ResolvableSerializer) { ((ResolvableSerializer) ser).resolve(this); } return (JsonSerializer) handleSecondaryContextualization(ser, property); } @SuppressWarnings("unchecked") protected JsonSerializer _handleResolvable(JsonSerializer ser) throws JsonMappingException { if (ser instanceof ResolvableSerializer) { ((ResolvableSerializer) ser).resolve(this); } return (JsonSerializer) ser; } /* /********************************************************** /* Internal methods /********************************************************** */ protected final DateFormat _dateFormat() { if (_dateFormat != null) { return _dateFormat; } /* At this point, all timezone configuration should have occurred, with respect * to default dateformat configuration. But we still better clone * an instance as formatters are stateful, not thread-safe. */ DateFormat df = _config.getDateFormat(); _dateFormat = df = (DateFormat) df.clone(); // [databind#939]: 26-Sep-2015, tatu: With 2.6, formatter has been (pre)configured // with TimeZone, so we should NOT try overriding it unlike with earlier versions /* TimeZone tz = getTimeZone(); if (tz != df.getTimeZone()) { df.setTimeZone(tz); } */ return df; } } jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotation/000077500000000000000000000000001325620701100327015ustar00rootroot00000000000000JacksonStdImpl.java000066400000000000000000000014221325620701100363510ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotationpackage com.fasterxml.jackson.databind.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.fasterxml.jackson.annotation.JacksonAnnotation; /** * Marker interface used to indicate implementation classes * (serializers, deserializers etc) that are standard ones Jackson * uses; not custom ones that application has added. It can be * added in cases where certain optimizations can be made if * default instances are uses; for example when handling conversions * of "natural" JSON types like Strings, booleans and numbers. */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation public @interface JacksonStdImpl { } JsonAppend.java000066400000000000000000000107151325620701100355320ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotationpackage com.fasterxml.jackson.databind.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter; /** * Annotation that may be used to add "virtual" properties to be written * after regular properties (although ordering may be changed using * both standard @JsonPropertyOrder annotation, and * properties of this annotation). * * @since 2.5 */ @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @com.fasterxml.jackson.annotation.JacksonAnnotation public @interface JsonAppend { /** * Set of attribute-backed properties to include when serializing * a POJO. */ public Attr[] attrs() default { }; /** * Set of general virtual properties to include when serializing a POJO. */ public Prop[] props() default { }; /** * Indicator used to determine whether properties defined are to be * appended after (false) or prepended before (true) regular properties. * Affects all kinds of properties defined using this annotation. */ public boolean prepend() default false; /** * Definition of a single attribute-backed property. * Attribute-backed properties will be appended after (or prepended before, * as per {@link #prepend}) regular properties * in specified order, although their placement may be further changed * by the usual property-ordering functionality (alphabetic sorting; * explicit ordering) */ public @interface Attr { /** * Name of attribute of which value to serialize. Is also used as the * name of external property to write, unless overridden by * assigning a value for {@link #propName()}. */ public String value(); /** * Name to use for serializing value of the attribute; if not defined, * {@link #value} will be used instead. */ public String propName() default ""; /** * Optional namespace to use; only relevant for data formats that use * namespaces (like XML). */ public String propNamespace() default ""; /** * When to include attribute-property. Default value indicates that * property should only be written if specified attribute has a non-null * value. */ public JsonInclude.Include include() default JsonInclude.Include.NON_NULL; /** * Metadata about property, similar to * {@link com.fasterxml.jackson.annotation.JsonProperty#required()}. */ public boolean required() default false; } /** * Definition of a single general virtual property. */ public @interface Prop { /** * Actual implementation class (a subtype of {@link VirtualBeanPropertyWriter}) * of the property to instantiate (using the no-argument default constructor). */ public Class value(); /** * Name of the property to possibly use for serializing (although implementation * may choose to not use this information). */ public String name() default ""; /** * Optional namespace to use along with {@link #name}; * only relevant for data formats that use namespaces (like XML). */ public String namespace() default ""; /** * When to include value of the property. Default value indicates that * property should only be written if specified attribute has a non-null * value. As with other properties, actual property implementation may or may * not choose to use this inclusion information. */ public JsonInclude.Include include() default JsonInclude.Include.NON_NULL; /** * Metadata about property, similar to * {@link com.fasterxml.jackson.annotation.JsonProperty#required()}. */ public boolean required() default false; /** * Nominal type of the property. Passed as type information for related * virtual objects, and may (or may not be) used by implementation * for choosing serializer to use. */ public Class type() default Object.class; } } JsonDeserialize.java000066400000000000000000000137121325620701100365630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotationpackage com.fasterxml.jackson.databind.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.util.Converter; /** * Annotation use for configuring deserialization aspects, by attaching * to "setter" methods or fields, or to value classes. * When annotating value classes, configuration is used for instances * of the value class but can be overridden by more specific annotations * (ones that attach to methods or fields). *

* An example annotation would be: *

 *  @JsonDeserialize(using=MySerializer.class,
 *    as=MyHashMap.class,
 *    keyAs=MyHashKey.class,
 *    contentAs=MyHashValue.class
 *  )
 *
*

* Something to note on usage: *

    *
  • All other annotations regarding behavior during building should be on Builder * class and NOT on target POJO class: for example @JsonIgnoreProperties should be on * Builder to prevent "unknown property" errors. *
  • *
  • Similarly configuration overrides (see {@link com.fasterxml.jackson.databind.ObjectMapper#configOverride}) * should be targeted at Builder class, not target POJO class. *
  • *
* */ @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @com.fasterxml.jackson.annotation.JacksonAnnotation public @interface JsonDeserialize { // // // Annotations for explicitly specifying deserialize/builder /** * Deserializer class to use for deserializing associated value. * Depending on what is annotated, * value is either an instance of annotated class (used globablly * anywhere where class deserializer is needed); or only used for * deserializing property access via a setter method. */ @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties public Class using() default JsonDeserializer.None.class; /** * Deserializer class to use for deserializing contents (elements * of a Collection/array, values of Maps) of annotated property. * Can only be used on instances (methods, fields, constructors), * and not value classes themselves. */ @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties public Class contentUsing() default JsonDeserializer.None.class; /** * Deserializer class to use for deserializing Map keys * of annotated property. * Can only be used on instances (methods, fields, constructors), * and not value classes themselves. */ public Class keyUsing() default KeyDeserializer.None.class; /** * Annotation for specifying if an external Builder class is to * be used for building up deserialized instances of annotated * class. If so, an instance of referenced class is first constructed * (possibly using a Creator method; or if none defined, using default * constructor), and its "with-methods" are used for populating fields; * and finally "build-method" is invoked to complete deserialization. */ public Class builder() default Void.class; // // // Annotations for specifying intermediate Converters (2.2+) /** * Which helper object (if any) is to be used to convert from Jackson-bound * intermediate type (source type of converter) into actual property type * (which must be same as result type of converter). This is often used * for two-step deserialization; Jackson binds data into suitable intermediate * type (like Tree representation), and converter then builds actual property * type. * * @since 2.2 */ @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties public Class converter() default Converter.None.class; /** * Similar to {@link #converter}, but used for values of structures types * (List, arrays, Maps). * * @since 2.2 */ @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties public Class contentConverter() default Converter.None.class; // // // Annotations for explicitly specifying deserialization type // // // (which is used for choosing deserializer, if not explicitly // // // specified /** * Concrete type to deserialize values as, instead of type otherwise * declared. Must be a subtype of declared type; otherwise an * exception may be thrown by deserializer. *

* Bogus type {@link Void} can be used to indicate that declared * type is used as is (i.e. this annotation property has no setting); * this since annotation properties are not allowed to have null value. *

* Note: if {@link #using} is also used it has precedence * (since it directly specified * deserializer, whereas this would only be used to locate the * deserializer) * and value of this annotation property is ignored. */ public Class as() default Void.class; /** * Concrete type to deserialize keys of {@link java.util.Map} as, * instead of type otherwise declared. * Must be a subtype of declared type; otherwise an exception may be * thrown by deserializer. */ public Class keyAs() default Void.class; /** * Concrete type to deserialize content (elements * of a Collection/array, values of Maps) values as, * instead of type otherwise declared. * Must be a subtype of declared type; otherwise an exception may be * thrown by deserializer. */ public Class contentAs() default Void.class; } JsonNaming.java000066400000000000000000000020761325620701100355350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotationpackage com.fasterxml.jackson.databind.annotation; import java.lang.annotation.*; import com.fasterxml.jackson.databind.PropertyNamingStrategy; /** * Annotation that can be used to indicate a {@link PropertyNamingStrategy} * to use for annotated class. Overrides the global (default) strategy. * Note that if the {@link #value} property is omitted, its default value * means "use default naming" (that is, no alternate naming method is used). * This can be used as an override with mix-ins. * * @since 2.1 */ @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @com.fasterxml.jackson.annotation.JacksonAnnotation public @interface JsonNaming { /** * @return Type of {@link PropertyNamingStrategy} to use, if any; default value of * PropertyNamingStrategy.class means "no strategy specified" * (and may also be used for overriding to remove otherwise applicable * naming strategy) */ public Class value() default PropertyNamingStrategy.class; } JsonPOJOBuilder.java000066400000000000000000000064301325620701100364000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotationpackage com.fasterxml.jackson.databind.annotation; import java.lang.annotation.*; /** * Annotation used to configure details of a Builder class: * instances of which are used as Builders for deserialized * POJO values, instead of POJOs being instantiated using * constructors or factory methods. * Note that this annotation is NOT used to define what is * the Builder class for a POJO: rather, this is determined * by {@link JsonDeserialize#builder} property of {@link JsonDeserialize}. *

* Annotation is typically used if the naming convention * of a Builder class is different from defaults: *

    *
  • By default, setters are expected to have names like `withName()` (for property "name"); * override by {@link #withPrefix()} property. *
  • *
*

* In addition to configuration using this annotation, note that many other configuration * annotations are also applied to Builders, for example * {@link com.fasterxml.jackson.annotation.JsonIgnoreProperties} can be used to ignore * "unknown" properties. * * @since 2.0 */ @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @com.fasterxml.jackson.annotation.JacksonAnnotation public @interface JsonPOJOBuilder { /** * @since 2.9 */ public final static String DEFAULT_BUILD_METHOD = "build"; /** * @since 2.9 */ public final static String DEFAULT_WITH_PREFIX = "with"; /** * Property to use for re-defining which zero-argument method * is considered the actual "build-method": method called after * all data has been bound, and the actual instance needs to * be instantiated. *

* Default value is "build". */ public String buildMethodName() default DEFAULT_BUILD_METHOD; /** * Property used for (re)defining name prefix to use for * auto-detecting "with-methods": methods that are similar to * "set-methods" (in that they take an argument), but that * may also return the new builder instance to use * (which may be 'this', or a new modified builder instance). * Note that in addition to this prefix, it is also possible * to use {@link com.fasterxml.jackson.annotation.JsonProperty} * annotation to indicate "with-methods" (as well as * {@link com.fasterxml.jackson.annotation.JsonSetter}). *

* Default value is "with", so that method named "withValue()" * would be used for binding JSON property "value" (using type * indicated by the argument; or one defined with annotations. */ public String withPrefix() default DEFAULT_WITH_PREFIX; /* /********************************************************** /* Helper classes /********************************************************** */ /** * Simple value container for containing values read from * {@link JsonPOJOBuilder} annotation instance. */ public class Value { public final String buildMethodName; public final String withPrefix; public Value(JsonPOJOBuilder ann) { this(ann.buildMethodName(), ann.withPrefix()); } public Value(String buildMethodName, String withPrefix) { this.buildMethodName = buildMethodName; this.withPrefix = withPrefix; } } } JsonSerialize.java000066400000000000000000000237621325620701100362600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotationpackage com.fasterxml.jackson.databind.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.util.Converter; /** * Annotation used for configuring serialization aspects, by attaching * to "getter" methods or fields, or to value classes. * When annotating value classes, configuration is used for instances * of the value class but can be overridden by more specific annotations * (ones that attach to methods or fields). *

* An example annotation would be: *

 *  @JsonSerialize(using=MySerializer.class,
 *    as=MySubClass.class,
 *    typing=JsonSerialize.Typing.STATIC
 *  )
 *
* (which would be redundant, since some properties block others: * specifically, 'using' has precedence over 'as', which has precedence * over 'typing' setting) */ @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @com.fasterxml.jackson.annotation.JacksonAnnotation public @interface JsonSerialize { // // // Annotations for explicitly specifying deserializer /** * Serializer class to use for * serializing associated value. Depending on what is annotated, * value is either an instance of annotated class (used globablly * anywhere where class serializer is needed); or only used for * serializing property access via a getter method. */ @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties public Class using() default JsonSerializer.None.class; /** * Serializer class to use for serializing contents (elements * of a Collection/array, values of Maps) of annotated property. * Can only be used on properties (methods, fields, constructors), * and not value classes themselves (as they are typically generic) */ @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties public Class contentUsing() default JsonSerializer.None.class; /** * Serializer class to use for serializing Map keys * of annotated property. * Can only be used on properties (methods, fields, constructors), * and not value classes themselves. */ @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties public Class keyUsing() default JsonSerializer.None.class; /** * Serializer class to use for serializing nulls for properties that * are annotated, instead of the * default null serializer. * Note that using this property when annotation types (classes) has * no effect currently (it is possible this could be improved in future). * * @since 2.3 */ @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties public Class nullsUsing() default JsonSerializer.None.class; // // // Annotations for type handling, explicit declaration // // // (type used for choosing deserializer, if not explicitly // // // specified) /** * Supertype (of declared type, which itself is supertype of runtime type) * to use as type when locating serializer to use. *

* Bogus type {@link Void} can be used to indicate that declared * type is used as is (i.e. this annotation property has no setting); * this since annotation properties are not allowed to have null value. *

* Note: if {@link #using} is also used it has precedence * (since it directly specifies * serializer, whereas this would only be used to locate the * serializer) * and value of this annotation property is ignored. */ public Class as() default Void.class; /** * Concrete type to serialize keys of {@link java.util.Map} as, * instead of type otherwise declared. * Must be a supertype of declared type; otherwise an exception may be * thrown by serializer. */ public Class keyAs() default Void.class; /** * Concrete type to serialize content value (elements * of a Collection/array, values of Maps) as, * instead of type otherwise declared. * Must be a supertype of declared type; otherwise an exception may be * thrown by serializer. */ public Class contentAs() default Void.class; /** * Whether type detection used is dynamic or static: that is, * whether actual runtime type is used (dynamic), or just the * declared type (static). *

* Note that Jackson 2.3 changed default to DEFAULT_TYPING, * which is roughly same as saying "whatever". * This is important as it allows avoiding accidental overrides * at property level. */ public Typing typing() default Typing.DEFAULT_TYPING; // // // Annotations for specifying intermediate Converters (2.2+) /** * Which helper object is to be used to convert type into something * that Jackson knows how to serialize; either because base type * cannot be serialized easily, or just to alter serialization. * * @since 2.2 */ @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties public Class converter() default Converter.None.class; /** * Similar to {@link #converter}, but used for values of structures types * (List, arrays, Maps). * Note that this property does NOT have effect when used as Class annotation; * it can only be used as property annotation: this because association between * container and value types is loose and as such converters seldom make sense * for such usage. * * @since 2.2 */ @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties public Class contentConverter() default Converter.None.class; // // // Annotation(s) for inclusion criteria /** * Which properties of annotated Bean are * to be included in serialization (has no effect on other types * like enums, primitives or collections). * Choices are "all", "properties that have value other than null" * and "properties that have non-default value" (i.e. default value * being property setting for a Bean constructed with default no-arg * constructor, often null). *

* This property has been replaced by special-purpose {@link com.fasterxml.jackson.annotation.JsonInclude} * annotation, introduced in Jackson 2.0. *

* Note that Jackson 2.3 changed default to DEFAULT_INCLUSION, * which is roughly same as saying "whatever". This is important because * it allows hierarchic default values to be used. * * @deprecated As of Jackson 2.0, this annotation has been replaced * by {@link com.fasterxml.jackson.annotation.JsonInclude} */ @Deprecated public Inclusion include() default Inclusion.DEFAULT_INCLUSION; /* /********************************************************** /* Value enumerations needed /********************************************************** */ /** * Enumeration used with {@link JsonSerialize#include} property * to define which properties * of Java Beans are to be included in serialization */ @Deprecated // since 2.0, marked deprecated in 2.6 public enum Inclusion { /** * Value that indicates that properties are to be always included, * independent of value */ ALWAYS, /** * Value that indicates that only properties with non-null * values are to be included. */ NON_NULL, /** * Value that indicates that only properties that have values * that differ from default settings (meaning values they have * when Bean is constructed with its no-arguments constructor) * are to be included. Value is generally not useful with * {@link java.util.Map}s, since they have no default values; * and if used, works same as {@link #ALWAYS}. */ NON_DEFAULT, /** * Value that indicates that only properties that have values * that values that are null or what is considered empty are * not to be included. * Emptiness is defined for following type: *

    *
  • For {@link java.util.Collection}s and {@link java.util.Map}s, * method isEmpty() is called; *
  • *
  • For Java arrays, empty arrays are ones with length of 0 *
  • *
  • For Java {@link java.lang.String}s, length() is called, * and return value of 0 indicates empty String *
  • *
* For other types, non-null values are to be included. */ NON_EMPTY, /** * Pseudo-value that is used to indicate * "use whatever is default used at higher level". * * @since 2.3 */ DEFAULT_INCLUSION ; } /** * Enumeration used with {@link JsonSerialize#typing} property * to define whether type detection is based on dynamic runtime * type (DYNAMIC) or declared type (STATIC). */ public enum Typing { /** * Value that indicates that the actual dynamic runtime type is to * be used. */ DYNAMIC, /** * Value that indicates that the static declared type is to * be used. */ STATIC, /** * Pseudo-value that is used to indicate * "use whatever is default used at higher level". * * @since 2.3 */ DEFAULT_TYPING ; } } JsonTypeIdResolver.java000066400000000000000000000025201325620701100372360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotationpackage com.fasterxml.jackson.databind.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.fasterxml.jackson.annotation.JacksonAnnotation; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; /** * Annotation that can be used to plug a custom type identifier handler * ({@link TypeIdResolver}) * to be used by * {@link com.fasterxml.jackson.databind.jsontype.TypeSerializer}s * and {@link com.fasterxml.jackson.databind.jsontype.TypeDeserializer}s * for converting between java types and type id included in JSON content. * In simplest cases this can be a simple class with static mapping between * type names and matching classes. *

* NOTE: since 2.4, applicable to properties as well (should have been long time * ago, but problem only found then) */ @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation public @interface JsonTypeIdResolver { /** * Defines implementation class of {@link TypeIdResolver} to use for * converting between external type id (type name) and actual * type of object. */ public Class value(); } JsonTypeResolver.java000066400000000000000000000023231325620701100367620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotationpackage com.fasterxml.jackson.databind.annotation; import java.lang.annotation.*; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; /** * Annotation that can be used to explicitly define custom resolver * used for handling serialization and deserialization of type information, * needed for handling of polymorphic types (or sometimes just for linking * abstract types to concrete types) *

* NOTE: since 2.4, applicable to properties as well (should have been long time * ago, but problem only found then) */ @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @com.fasterxml.jackson.annotation.JacksonAnnotation public @interface JsonTypeResolver { /** * Defines implementation class of {@link TypeResolverBuilder} which is used to construct * actual {@link com.fasterxml.jackson.databind.jsontype.TypeDeserializer} and {@link com.fasterxml.jackson.databind.jsontype.TypeDeserializer} * instances that handle reading and writing addition type information needed to support polymorphic * deserialization. */ public Class> value(); } JsonValueInstantiator.java000066400000000000000000000013411325620701100377720ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotationpackage com.fasterxml.jackson.databind.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.fasterxml.jackson.databind.deser.ValueInstantiator; /** * Annotation that can be used to indicate a {@link ValueInstantiator} to use * for creating instances of specified type. */ @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @com.fasterxml.jackson.annotation.JacksonAnnotation public @interface JsonValueInstantiator { /** * @return {@link ValueInstantiator} to use for annotated type */ public Class value(); } NoClass.java000066400000000000000000000012611325620701100350270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotationpackage com.fasterxml.jackson.databind.annotation; /** * Marker class used with annotations to indicate "no class". This is * a silly but necessary work-around -- annotations cannot take nulls * as either default or explicit values. Hence for class values we must * explicitly use a bogus placeholder to denote equivalent of * "no class" (for which 'null' is usually the natural choice). *

* Note that since 2.4, most (but not all! * {@link com.fasterxml.jackson.annotation.JsonTypeInfo#defaultImpl} is * a notable exception}) usage should start using * {@link java.lang.Void} instead as the "not defined" marker. */ public final class NoClass { private NoClass() { } } package-info.java000066400000000000000000000004201325620701100360050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/annotation/** * Annotations that directly depend on classes in databinding bundle * (not just Jackson core) and cannot be included * in Jackson core annotations package (because it cannot have any * external dependencies). */ package com.fasterxml.jackson.databind.annotation; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfg/000077500000000000000000000000001325620701100312665ustar00rootroot00000000000000BaseSettings.java000066400000000000000000000307361325620701100344560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import java.text.DateFormat; import java.util.Locale; import java.util.TimeZone; import com.fasterxml.jackson.core.Base64Variant; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair; import com.fasterxml.jackson.databind.introspect.ClassIntrospector; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.StdDateFormat; /** * Immutable container class used to store simple configuration * settings. Since instances are fully immutable, instances can * be freely shared and used without synchronization. */ public final class BaseSettings implements java.io.Serializable { // for 2.6 private static final long serialVersionUID = 1L; /** * We will use a default TimeZone as the baseline. */ private static final TimeZone DEFAULT_TIMEZONE = // TimeZone.getDefault() /* [databind#915] 05-Nov-2015, tatu: Changed to UTC, from earlier * baseline of GMT (up to 2.6) */ TimeZone.getTimeZone("UTC"); /* /********************************************************** /* Configuration settings; introspection, related /********************************************************** */ /** * Introspector used to figure out Bean properties needed for bean serialization * and deserialization. Overridable so that it is possible to change low-level * details of introspection, like adding new annotation types. */ protected final ClassIntrospector _classIntrospector; /** * Introspector used for accessing annotation value based configuration. */ protected final AnnotationIntrospector _annotationIntrospector; /** * Custom property naming strategy in use, if any. */ protected final PropertyNamingStrategy _propertyNamingStrategy; /** * Specific factory used for creating {@link JavaType} instances; * needed to allow modules to add more custom type handling * (mostly to support types of non-Java JVM languages) */ protected final TypeFactory _typeFactory; /* /********************************************************** /* Configuration settings; type resolution /********************************************************** */ /** * Type information handler used for "untyped" values (ones declared * to have type Object.class) */ protected final TypeResolverBuilder _typeResolverBuilder; /* /********************************************************** /* Configuration settings; other /********************************************************** */ /** * Custom date format to use for de-serialization. If specified, will be * used instead of {@link com.fasterxml.jackson.databind.util.StdDateFormat}. *

* Note that the configured format object will be cloned once per * deserialization process (first time it is needed) */ protected final DateFormat _dateFormat; /** * Object used for creating instances of handlers (serializers, deserializers, * type and type id resolvers), given class to instantiate. This is typically * used to do additional configuration (with dependency injection, for example) * beyond simply construction of instances; or to use alternative constructors. */ protected final HandlerInstantiator _handlerInstantiator; /** * Default {@link java.util.Locale} used with serialization formats. * Default value is {@link Locale#getDefault()}. */ protected final Locale _locale; /** * Default {@link java.util.TimeZone} used with serialization formats, * if (and only if!) explicitly set by use; otherwise `null` to indicate * "use default", which means "UTC" (from Jackson 2.7); earlier versions * (up to 2.6) used "GMT". *

* Note that if a new value is set, timezone is also assigned to * {@link #_dateFormat} of this object. */ protected final TimeZone _timeZone; /** * Explicitly default {@link Base64Variant} to use for handling * binary data (byte[]), used with data formats * that use base64 encoding (like JSON, CSV). * * @since 2.1 */ protected final Base64Variant _defaultBase64; /* /********************************************************** /* Construction /********************************************************** */ public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai, PropertyNamingStrategy pns, TypeFactory tf, TypeResolverBuilder typer, DateFormat dateFormat, HandlerInstantiator hi, Locale locale, TimeZone tz, Base64Variant defaultBase64) { _classIntrospector = ci; _annotationIntrospector = ai; _propertyNamingStrategy = pns; _typeFactory = tf; _typeResolverBuilder = typer; _dateFormat = dateFormat; _handlerInstantiator = hi; _locale = locale; _timeZone = tz; _defaultBase64 = defaultBase64; } /* /********************************************************** /* Factory methods /********************************************************** */ public BaseSettings withClassIntrospector(ClassIntrospector ci) { if (_classIntrospector == ci) { return this; } return new BaseSettings(ci, _annotationIntrospector, _propertyNamingStrategy, _typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale, _timeZone, _defaultBase64); } public BaseSettings withAnnotationIntrospector(AnnotationIntrospector ai) { if (_annotationIntrospector == ai) { return this; } return new BaseSettings(_classIntrospector, ai, _propertyNamingStrategy, _typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale, _timeZone, _defaultBase64); } public BaseSettings withInsertedAnnotationIntrospector(AnnotationIntrospector ai) { return withAnnotationIntrospector(AnnotationIntrospectorPair.create(ai, _annotationIntrospector)); } public BaseSettings withAppendedAnnotationIntrospector(AnnotationIntrospector ai) { return withAnnotationIntrospector(AnnotationIntrospectorPair.create(_annotationIntrospector, ai)); } /* public BaseSettings withVisibility(PropertyAccessor forMethod, JsonAutoDetect.Visibility visibility) { return new BaseSettings(_classIntrospector, _annotationIntrospector, _visibilityChecker.withVisibility(forMethod, visibility), _propertyNamingStrategy, _typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale, _timeZone, _defaultBase64); } */ public BaseSettings withPropertyNamingStrategy(PropertyNamingStrategy pns) { if (_propertyNamingStrategy == pns) { return this; } return new BaseSettings(_classIntrospector, _annotationIntrospector, pns, _typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale, _timeZone, _defaultBase64); } public BaseSettings withTypeFactory(TypeFactory tf) { if (_typeFactory == tf) { return this; } return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, tf, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale, _timeZone, _defaultBase64); } public BaseSettings withTypeResolverBuilder(TypeResolverBuilder typer) { if (_typeResolverBuilder == typer) { return this; } return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory, typer, _dateFormat, _handlerInstantiator, _locale, _timeZone, _defaultBase64); } public BaseSettings withDateFormat(DateFormat df) { if (_dateFormat == df) { return this; } // 26-Sep-2015, tatu: Related to [databind#939], let's try to force TimeZone if // (but only if!) it has been set explicitly. if ((df != null) && hasExplicitTimeZone()) { df = _force(df, _timeZone); } return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory, _typeResolverBuilder, df, _handlerInstantiator, _locale, _timeZone, _defaultBase64); } public BaseSettings withHandlerInstantiator(HandlerInstantiator hi) { if (_handlerInstantiator == hi) { return this; } return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory, _typeResolverBuilder, _dateFormat, hi, _locale, _timeZone, _defaultBase64); } public BaseSettings with(Locale l) { if (_locale == l) { return this; } return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, l, _timeZone, _defaultBase64); } /** * Fluent factory for constructing a new instance that uses specified TimeZone. * Note that timezone used with also be assigned to configured {@link DateFormat}, * changing time formatting defaults. */ public BaseSettings with(TimeZone tz) { if (tz == null) { throw new IllegalArgumentException(); } if (tz == _timeZone) { return this; } DateFormat df = _force(_dateFormat, tz); return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory, _typeResolverBuilder, df, _handlerInstantiator, _locale, tz, _defaultBase64); } /** * @since 2.1 */ public BaseSettings with(Base64Variant base64) { if (base64 == _defaultBase64) { return this; } return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale, _timeZone, base64); } /* /********************************************************** /* API /********************************************************** */ public ClassIntrospector getClassIntrospector() { return _classIntrospector; } public AnnotationIntrospector getAnnotationIntrospector() { return _annotationIntrospector; } public PropertyNamingStrategy getPropertyNamingStrategy() { return _propertyNamingStrategy; } public TypeFactory getTypeFactory() { return _typeFactory; } public TypeResolverBuilder getTypeResolverBuilder() { return _typeResolverBuilder; } public DateFormat getDateFormat() { return _dateFormat; } public HandlerInstantiator getHandlerInstantiator() { return _handlerInstantiator; } public Locale getLocale() { return _locale; } public TimeZone getTimeZone() { TimeZone tz = _timeZone; return (tz == null) ? DEFAULT_TIMEZONE : tz; } /** * Accessor that may be called to determine whether this settings object * has been explicitly configured with a TimeZone (true), or is still * relying on the default settings (false). * * @since 2.7 */ public boolean hasExplicitTimeZone() { return (_timeZone != null); } public Base64Variant getBase64Variant() { return _defaultBase64; } /* /********************************************************** /* Helper methods /********************************************************** */ private DateFormat _force(DateFormat df, TimeZone tz) { if (df instanceof StdDateFormat) { return ((StdDateFormat) df).withTimeZone(tz); } // we don't know if original format might be shared; better create a clone: df = (DateFormat) df.clone(); df.setTimeZone(tz); return df; } } ConfigFeature.java000066400000000000000000000013011325620701100345660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; /** * Interface that actual SerializationFeature enumerations used by * {@link MapperConfig} implementations must implement. * Necessary since enums cannot be extended using normal * inheritance, but can implement interfaces */ public interface ConfigFeature { /** * Accessor for checking whether this feature is enabled by default. */ public boolean enabledByDefault(); /** * Returns bit mask for this feature instance */ public int getMask(); /** * Convenience method for checking whether feature is enabled in given bitmask * * @since 2.6 */ public boolean enabledIn(int flags); } ConfigOverride.java000066400000000000000000000077231325620701100347700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonSetter; /** * Configuration object that is accessed by databinding functionality * to find overrides to configuration of properties, based on declared * type of the property. Such overrides have precedence over annotations * attached to actual type ({@link java.lang.Class}), but can be further * overridden by annotations attached to the property itself. * * @since 2.8 */ public abstract class ConfigOverride { /** * Definitions of format overrides, if any. */ protected JsonFormat.Value _format; /** * Definitions of inclusion defaults to use for properties included in this POJO type. * Overrides global defaults, may be overridden by per-property-type (see * {@link #_includeAsProperty}) and per-property overrides (annotations). */ protected JsonInclude.Value _include; /** * Definitions of inclusion defaults for properties of this specified type (regardless * of POJO in which they are included). * Overrides global defaults, per-POJO inclusion defaults (see {#link {@link #_include}}), * may be overridden by per-property overrides. * * @since 2.9 */ protected JsonInclude.Value _includeAsProperty; /** * Definitions of property ignoral (whether to serialize, deserialize * given logical property) overrides, if any. */ protected JsonIgnoreProperties.Value _ignorals; /** * Definitions of setter overrides regarding null handling * * @since 2.9 */ protected JsonSetter.Value _setterInfo; /** * Overrides for auto-detection visibility rules for this type. * * @since 2.9 */ protected JsonAutoDetect.Value _visibility; /** * Flag that indicates whether "is ignorable type" is specified for this type; * and if so, is it to be ignored (true) or not ignored (false); `null` is * used to indicate "not specified", in which case other configuration (class * annotation) is used. */ protected Boolean _isIgnoredType; /** * Flag that indicates whether properties of this type default to being merged * or not. */ protected Boolean _mergeable; protected ConfigOverride() { } protected ConfigOverride(ConfigOverride src) { _format = src._format; _include = src._include; _includeAsProperty = src._includeAsProperty; _ignorals = src._ignorals; _isIgnoredType = src._isIgnoredType; _mergeable = src._mergeable; } /** * Accessor for immutable "empty" instance that has no configuration overrides defined. * * @since 2.9 */ public static ConfigOverride empty() { return Empty.INSTANCE; } public JsonFormat.Value getFormat() { return _format; } public JsonInclude.Value getInclude() { return _include; } /** * @since 2.9 */ public JsonInclude.Value getIncludeAsProperty() { return _includeAsProperty; } public JsonIgnoreProperties.Value getIgnorals() { return _ignorals; } public Boolean getIsIgnoredType() { return _isIgnoredType; } /** * @since 2.9 */ public JsonSetter.Value getSetterInfo() { return _setterInfo; } /** * @since 2.9 */ public JsonAutoDetect.Value getVisibility() { return _visibility; } /** * @since 2.9 */ public Boolean getMergeable() { return _mergeable; } /** * Implementation used solely for "empty" instance; has no mutators * and is not changed by core functionality. * * @since 2.9 */ final static class Empty extends ConfigOverride { final static Empty INSTANCE = new Empty(); private Empty() { } } } ConfigOverrides.java000066400000000000000000000106571325620701100351530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import java.util.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.databind.introspect.VisibilityChecker; /** * Container for individual {@link ConfigOverride} values. * * @since 2.8 */ public class ConfigOverrides implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Per-type override definitions */ protected Map, MutableConfigOverride> _overrides; // // // Global defaulting /** * @since 2.9 */ protected JsonInclude.Value _defaultInclusion; /** * @since 2.9 */ protected JsonSetter.Value _defaultSetterInfo; /** * @since 2.9 */ protected VisibilityChecker _visibilityChecker; /** * @since 2.9 */ protected Boolean _defaultMergeable; /* /********************************************************** /* Life cycle /********************************************************** */ public ConfigOverrides() { this(null, // !!! TODO: change to (ALWAYS, ALWAYS)? JsonInclude.Value.empty(), JsonSetter.Value.empty(), VisibilityChecker.Std.defaultInstance(), null ); } protected ConfigOverrides(Map, MutableConfigOverride> overrides, JsonInclude.Value defIncl, JsonSetter.Value defSetter, VisibilityChecker defVisibility, Boolean defMergeable) { _overrides = overrides; _defaultInclusion = defIncl; _defaultSetterInfo = defSetter; _visibilityChecker = defVisibility; _defaultMergeable = defMergeable; } public ConfigOverrides copy() { Map, MutableConfigOverride> newOverrides; if (_overrides == null) { newOverrides = null; } else { newOverrides = _newMap(); for (Map.Entry, MutableConfigOverride> entry : _overrides.entrySet()) { newOverrides.put(entry.getKey(), entry.getValue().copy()); } } return new ConfigOverrides(newOverrides, _defaultInclusion, _defaultSetterInfo, _visibilityChecker, _defaultMergeable); } /* /********************************************************** /* Per-type override access /********************************************************** */ public ConfigOverride findOverride(Class type) { if (_overrides == null) { return null; } return _overrides.get(type); } public MutableConfigOverride findOrCreateOverride(Class type) { if (_overrides == null) { _overrides = _newMap(); } MutableConfigOverride override = _overrides.get(type); if (override == null) { override = new MutableConfigOverride(); _overrides.put(type, override); } return override; } /* /********************************************************** /* Global defaults access /********************************************************** */ public JsonInclude.Value getDefaultInclusion() { return _defaultInclusion; } public JsonSetter.Value getDefaultSetterInfo() { return _defaultSetterInfo; } public Boolean getDefaultMergeable() { return _defaultMergeable; } /** * @since 2.9 */ public VisibilityChecker getDefaultVisibility() { return _visibilityChecker; } /** * @since 2.9 */ public void setDefaultInclusion(JsonInclude.Value v) { _defaultInclusion = v; } /** * @since 2.9 */ public void setDefaultSetterInfo(JsonSetter.Value v) { _defaultSetterInfo = v; } /** * @since 2.9 */ public void setDefaultMergeable(Boolean v) { _defaultMergeable = v; } /** * @since 2.9 */ public void setDefaultVisibility(VisibilityChecker v) { _visibilityChecker = v; } /* /********************************************************** /* Helper methods /********************************************************** */ protected Map, MutableConfigOverride> _newMap() { return new HashMap, MutableConfigOverride>(); } } ContextAttributes.java000066400000000000000000000162471325620701100355570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import java.util.*; /** * Helper class used for storing and accessing per-call attributes. * Storage is two-layered: at higher precedence, we have actual per-call * attributes; and at lower precedence, default attributes that may be * defined for Object readers and writers. *

* Note that the way mutability is implemented differs between kinds * of attributes, to account for thread-safety: per-call attributes * are handled assuming that instances are never shared, whereas * changes to per-reader/per-writer attributes are made assuming * sharing, by creating new copies instead of modifying state. * This allows sharing of default values without per-call copying, but * requires two-level lookup on access. * * @since 2.3 */ public abstract class ContextAttributes { public static ContextAttributes getEmpty() { return Impl.getEmpty(); } /* /********************************************************** /* Per-reader/writer access /********************************************************** */ public abstract ContextAttributes withSharedAttribute(Object key, Object value); public abstract ContextAttributes withSharedAttributes(Map attributes); public abstract ContextAttributes withoutSharedAttribute(Object key); /* /********************************************************** /* Per-operation (serialize/deserialize) access /********************************************************** */ /** * Accessor for value of specified attribute */ public abstract Object getAttribute(Object key); /** * Mutator used during call (via context) to set value of "non-shared" * part of attribute set. */ public abstract ContextAttributes withPerCallAttribute(Object key, Object value); /* /********************************************************** /* Default implementation /********************************************************** */ public static class Impl extends ContextAttributes implements java.io.Serializable // just so ObjectReader/ObjectWriter can retain configs { private static final long serialVersionUID = 1L; protected final static Impl EMPTY = new Impl(Collections.emptyMap()); protected final static Object NULL_SURROGATE = new Object(); /** * Shared attributes that we cannot modify in-place. */ protected final Map _shared; /** * Per-call attributes that we can directly modify, since they are not * shared between threads. *

* NOTE: typed as Object-to-Object, unlike {@link #_shared}, because * we need to be able to modify contents, and wildcard type would * complicate that access. */ protected transient Map _nonShared; /* /********************************************************** /* Construction, factory methods /********************************************************** */ protected Impl(Map shared) { _shared = shared; _nonShared = null; } protected Impl(Map shared, Map nonShared) { _shared = shared; _nonShared = nonShared; } public static ContextAttributes getEmpty() { return EMPTY; } /* /********************************************************** /* Per-reader/writer mutant factories /********************************************************** */ @Override public ContextAttributes withSharedAttribute(Object key, Object value) { Map m; // need to cover one special case, since EMPTY uses Immutable map: if (this == EMPTY) { m = new HashMap(8); } else { m = _copy(_shared); } m.put(key, value); return new Impl(m); } @Override public ContextAttributes withSharedAttributes(Map shared) { return new Impl(shared); } @Override public ContextAttributes withoutSharedAttribute(Object key) { // first couple of trivial optimizations if (_shared.isEmpty()) { return this; } if (_shared.containsKey(key)) { if (_shared.size() == 1) { return EMPTY; } } else { // if we didn't have it anyway, return as-is return this; } // otherwise make copy, modify Map m = _copy(_shared); m.remove(key); return new Impl(m); } /* /********************************************************** /* Per-call access /********************************************************** */ @Override public Object getAttribute(Object key) { if (_nonShared != null) { Object ob = _nonShared.get(key); if (ob != null) { if (ob == NULL_SURROGATE) { return null; } return ob; } } return _shared.get(key); } @Override public ContextAttributes withPerCallAttribute(Object key, Object value) { // First: null value may need masking if (value == null) { // need to mask nulls to ensure default values won't be showing if (_shared.containsKey(key)) { value = NULL_SURROGATE; } else if ((_nonShared == null) || !_nonShared.containsKey(key)) { // except if non-mutable shared list has no entry, we don't care return this; } else { _nonShared.remove(key); return this; } } // a special case: create non-shared instance if need be if (_nonShared == null) { return nonSharedInstance(key, value); } _nonShared.put(key, value); return this; } /* /********************************************************** /* Internal methods /********************************************************** */ /** * Overridable method that creates initial non-shared instance, * with the first explicit set value. */ protected ContextAttributes nonSharedInstance(Object key, Object value) { Map m = new HashMap(); if (value == null) { value = NULL_SURROGATE; } m.put(key, value); return new Impl(_shared, m); } private Map _copy(Map src) { return new HashMap(src); } } } DeserializerFactoryConfig.java000066400000000000000000000215471325620701100371630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import com.fasterxml.jackson.databind.AbstractTypeResolver; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.deser.std.StdKeyDeserializers; import com.fasterxml.jackson.databind.util.ArrayBuilders; import com.fasterxml.jackson.databind.util.ArrayIterator; /** * Configuration settings container class for {@link DeserializerFactory}. */ public class DeserializerFactoryConfig implements java.io.Serializable // since 2.1 { private static final long serialVersionUID = 1L; // since 2.5 protected final static Deserializers[] NO_DESERIALIZERS = new Deserializers[0]; protected final static BeanDeserializerModifier[] NO_MODIFIERS = new BeanDeserializerModifier[0]; protected final static AbstractTypeResolver[] NO_ABSTRACT_TYPE_RESOLVERS = new AbstractTypeResolver[0]; protected final static ValueInstantiators[] NO_VALUE_INSTANTIATORS = new ValueInstantiators[0]; /** * By default we plug default key deserializers using as "just another" set of * of key deserializers. * * @since 2.2 */ protected final static KeyDeserializers[] DEFAULT_KEY_DESERIALIZERS = new KeyDeserializers[] { new StdKeyDeserializers() }; /** * List of providers for additional deserializers, checked before considering default * basic or bean deserializers. */ protected final Deserializers[] _additionalDeserializers; /** * List of providers for additional key deserializers, checked before considering * standard key deserializers. */ protected final KeyDeserializers[] _additionalKeyDeserializers; /** * List of modifiers that can change the way {@link BeanDeserializer} instances * are configured and constructed. */ protected final BeanDeserializerModifier[] _modifiers; /** * List of objects that may be able to resolve abstract types to * concrete types. Used by functionality like "mr Bean" to materialize * types as needed. */ protected final AbstractTypeResolver[] _abstractTypeResolvers; /** * List of objects that know how to create instances of POJO types; * possibly using custom construction (non-annoted constructors; factory * methods external to value type etc). * Used to support objects that are created using non-standard methods; * or to support post-constructor functionality. */ protected final ValueInstantiators[] _valueInstantiators; /** * Constructor for creating basic configuration with no additional * handlers. */ public DeserializerFactoryConfig() { this(null, null, null, null, null); } /** * Copy-constructor that will create an instance that contains defined * set of additional deserializer providers. */ protected DeserializerFactoryConfig(Deserializers[] allAdditionalDeserializers, KeyDeserializers[] allAdditionalKeyDeserializers, BeanDeserializerModifier[] modifiers, AbstractTypeResolver[] atr, ValueInstantiators[] vi) { _additionalDeserializers = (allAdditionalDeserializers == null) ? NO_DESERIALIZERS : allAdditionalDeserializers; _additionalKeyDeserializers = (allAdditionalKeyDeserializers == null) ? DEFAULT_KEY_DESERIALIZERS : allAdditionalKeyDeserializers; _modifiers = (modifiers == null) ? NO_MODIFIERS : modifiers; _abstractTypeResolvers = (atr == null) ? NO_ABSTRACT_TYPE_RESOLVERS : atr; _valueInstantiators = (vi == null) ? NO_VALUE_INSTANTIATORS : vi; } /** * Fluent/factory method used to construct a configuration object that * has same deserializer providers as this instance, plus one specified * as argument. Additional provider will be added before existing ones, * meaning it has priority over existing definitions. */ public DeserializerFactoryConfig withAdditionalDeserializers(Deserializers additional) { if (additional == null) { throw new IllegalArgumentException("Cannot pass null Deserializers"); } Deserializers[] all = ArrayBuilders.insertInListNoDup(_additionalDeserializers, additional); return new DeserializerFactoryConfig(all, _additionalKeyDeserializers, _modifiers, _abstractTypeResolvers, _valueInstantiators); } /** * Fluent/factory method used to construct a configuration object that * has same key deserializer providers as this instance, plus one specified * as argument. Additional provider will be added before existing ones, * meaning it has priority over existing definitions. */ public DeserializerFactoryConfig withAdditionalKeyDeserializers(KeyDeserializers additional) { if (additional == null) { throw new IllegalArgumentException("Cannot pass null KeyDeserializers"); } KeyDeserializers[] all = ArrayBuilders.insertInListNoDup(_additionalKeyDeserializers, additional); return new DeserializerFactoryConfig(_additionalDeserializers, all, _modifiers, _abstractTypeResolvers, _valueInstantiators); } /** * Fluent/factory method used to construct a configuration object that * has same configuration as this instance plus one additional * deserialiazer modifier. Added modifier has the highest priority (that is, it * gets called before any already registered modifier). */ public DeserializerFactoryConfig withDeserializerModifier(BeanDeserializerModifier modifier) { if (modifier == null) { throw new IllegalArgumentException("Cannot pass null modifier"); } BeanDeserializerModifier[] all = ArrayBuilders.insertInListNoDup(_modifiers, modifier); return new DeserializerFactoryConfig(_additionalDeserializers, _additionalKeyDeserializers, all, _abstractTypeResolvers, _valueInstantiators); } /** * Fluent/factory method used to construct a configuration object that * has same configuration as this instance plus one additional * abstract type resolver. * Added resolver has the highest priority (that is, it * gets called before any already registered resolver). */ public DeserializerFactoryConfig withAbstractTypeResolver(AbstractTypeResolver resolver) { if (resolver == null) { throw new IllegalArgumentException("Cannot pass null resolver"); } AbstractTypeResolver[] all = ArrayBuilders.insertInListNoDup(_abstractTypeResolvers, resolver); return new DeserializerFactoryConfig(_additionalDeserializers, _additionalKeyDeserializers, _modifiers, all, _valueInstantiators); } /** * Fluent/factory method used to construct a configuration object that * has same configuration as this instance plus specified additional * value instantiator provider object. * Added instantiator provider has the highest priority (that is, it * gets called before any already registered resolver). * * @param instantiators Object that can provide {@link com.fasterxml.jackson.databind.deser.ValueInstantiator}s for * constructing POJO values during deserialization */ public DeserializerFactoryConfig withValueInstantiators(ValueInstantiators instantiators) { if (instantiators == null) { throw new IllegalArgumentException("Cannot pass null resolver"); } ValueInstantiators[] all = ArrayBuilders.insertInListNoDup(_valueInstantiators, instantiators); return new DeserializerFactoryConfig(_additionalDeserializers, _additionalKeyDeserializers, _modifiers, _abstractTypeResolvers, all); } public boolean hasDeserializers() { return _additionalDeserializers.length > 0; } public boolean hasKeyDeserializers() { return _additionalKeyDeserializers.length > 0; } public boolean hasDeserializerModifiers() { return _modifiers.length > 0; } public boolean hasAbstractTypeResolvers() { return _abstractTypeResolvers.length > 0; } public boolean hasValueInstantiators() { return _valueInstantiators.length > 0; } public Iterable deserializers() { return new ArrayIterator(_additionalDeserializers); } public Iterable keyDeserializers() { return new ArrayIterator(_additionalKeyDeserializers); } public Iterable deserializerModifiers() { return new ArrayIterator(_modifiers); } public Iterable abstractTypeResolvers() { return new ArrayIterator(_abstractTypeResolvers); } public Iterable valueInstantiators() { return new ArrayIterator(_valueInstantiators); } } HandlerInstantiator.java000066400000000000000000000164461325620701100360420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdResolver; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter; import com.fasterxml.jackson.databind.util.Converter; /** * Helper class used for handling details of creating handler instances (things * like {@link JsonSerializer}s, {@link JsonDeserializer}s, various type * handlers) of specific types. Actual handler type has been resolved at this * point, so instantiator is strictly responsible for providing a configured * instance by constructing and configuring a new instance, or possibly by * recycling a shared instance. One use case is that of allowing * dependency injection, which would otherwise be difficult to do. *

* Custom instances are allowed to return null to indicate that caller should * use the default instantiation handling (which just means calling no-argument * constructor via reflection). *

* Care has to be taken to ensure that if instance returned is shared, it will * be thread-safe; caller will not synchronize access to returned instances. */ public abstract class HandlerInstantiator { /* /********************************************************** /* Public API /********************************************************** */ /** * Method called to get an instance of deserializer of specified type. * * @param config Deserialization configuration in effect * @param annotated Element (Class, Method, Field, constructor parameter) that * had annotation defining class of deserializer to construct (to allow * implementation use information from other annotations) * @param deserClass Class of deserializer instance to return * * @return Deserializer instance to use */ public abstract JsonDeserializer deserializerInstance(DeserializationConfig config, Annotated annotated, Class deserClass); /** * Method called to get an instance of key deserializer of specified type. * * @param config Deserialization configuration in effect * @param annotated Element (Class, Method, Field, constructor parameter) that * had annotation defining class of key deserializer to construct (to allow * implementation use information from other annotations) * @param keyDeserClass Class of key deserializer instance to return * * @return Key deserializer instance to use */ public abstract KeyDeserializer keyDeserializerInstance(DeserializationConfig config, Annotated annotated, Class keyDeserClass); /** * Method called to get an instance of serializer of specified type. * * @param config Serialization configuration in effect * @param annotated Element (Class, Method, Field) that * had annotation defining class of serializer to construct (to allow * implementation use information from other annotations) * @param serClass Class of serializer instance to return * * @return Serializer instance to use */ public abstract JsonSerializer serializerInstance(SerializationConfig config, Annotated annotated, Class serClass); /** * Method called to get an instance of TypeResolverBuilder of specified type. * * @param config Mapper configuration in effect (either SerializationConfig or * DeserializationConfig, depending on when instance is being constructed) * @param annotated annotated Element (Class, Method, Field) that * had annotation defining class of builder to construct (to allow * implementation use information from other annotations) * @param builderClass Class of builder instance to return * * @return TypeResolverBuilder instance to use */ public abstract TypeResolverBuilder typeResolverBuilderInstance(MapperConfig config, Annotated annotated, Class builderClass); /** * Method called to get an instance of TypeIdResolver of specified type. * * @param config Mapper configuration in effect (either SerializationConfig or * DeserializationConfig, depending on when instance is being constructed) * @param annotated annotated Element (Class, Method, Field) that * had annotation defining class of resolver to construct (to allow * implementation use information from other annotations) * @param resolverClass Class of resolver instance to return * * @return TypeResolverBuilder instance to use */ public abstract TypeIdResolver typeIdResolverInstance(MapperConfig config, Annotated annotated, Class resolverClass); /** * Method called to construct an instance of ValueInstantiator of specified type. */ public ValueInstantiator valueInstantiatorInstance(MapperConfig config, Annotated annotated, Class resolverClass) { return null; } /** * Method called to construct a ObjectIdHandler instance of specified type. * * @since 2.0 */ public ObjectIdGenerator objectIdGeneratorInstance(MapperConfig config, Annotated annotated, Class implClass) { return null; } public ObjectIdResolver resolverIdGeneratorInstance(MapperConfig config, Annotated annotated, Class implClass) { return null; } /** * Method called to construct a NamingStrategy instance used for specified * class. * * @since 2.1 */ public PropertyNamingStrategy namingStrategyInstance(MapperConfig config, Annotated annotated, Class implClass) { return null; } /** * Method called to construct a Converter instance used for specified class. * * @since 2.2 */ public Converter converterInstance(MapperConfig config, Annotated annotated, Class implClass) { return null; } /** * Method called to construct a {@link VirtualBeanPropertyWriter} instance * of specified type. * * @since 2.5 */ public VirtualBeanPropertyWriter virtualPropertyWriterInstance(MapperConfig config, Class implClass) { return null; } /** * Method called to construct a Filter (any Object with implementation of * equals(Object) that determines if given value is to be * excluded (true) or included (false)) to be used based on * {@link com.fasterxml.jackson.annotation.JsonInclude} annotation (or * equivalent). *

* Default implementation returns `null` to indicate that default instantiation * (use zero-arg constructor of the filterClass) should be * used. * * @since 2.9 */ public Object includeFilterInstance(SerializationConfig config, BeanPropertyDefinition forProperty, Class filterClass) { return null; } } MapperConfig.java000066400000000000000000000546101325620701100344320ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import java.text.DateFormat; import java.util.Locale; import java.util.TimeZone; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.Base64Variant; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.ClassIntrospector; import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector; import com.fasterxml.jackson.databind.introspect.VisibilityChecker; import com.fasterxml.jackson.databind.jsontype.SubtypeResolver; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Interface that defines functionality accessible through both * serialization and deserialization configuration objects; * accessors to mode-independent configuration settings * and such. * In addition, shared features are defined * in {@link MapperFeature}. *

* Small part of implementation is included here by aggregating * {@link BaseSettings} instance that contains configuration * that is shared between different types of instances. */ public abstract class MapperConfig> implements ClassIntrospector.MixInResolver, java.io.Serializable { private static final long serialVersionUID = 2L; // since 2.9 /** * @since 2.7 */ protected final static JsonInclude.Value EMPTY_INCLUDE = JsonInclude.Value.empty(); /** * @since 2.7 */ protected final static JsonFormat.Value EMPTY_FORMAT = JsonFormat.Value.empty(); /** * Set of shared mapper features enabled. */ protected final int _mapperFeatures; /** * Immutable container object for simple configuration settings. */ protected final BaseSettings _base; /* /********************************************************** /* Life-cycle: constructors /********************************************************** */ protected MapperConfig(BaseSettings base, int mapperFeatures) { _base = base; _mapperFeatures = mapperFeatures; } protected MapperConfig(MapperConfig src, int mapperFeatures) { _base = src._base; _mapperFeatures = mapperFeatures; } protected MapperConfig(MapperConfig src, BaseSettings base) { _base = base; _mapperFeatures = src._mapperFeatures; } protected MapperConfig(MapperConfig src) { _base = src._base; _mapperFeatures = src._mapperFeatures; } /** * Method that calculates bit set (flags) of all features that * are enabled by default. */ public static & ConfigFeature> int collectFeatureDefaults(Class enumClass) { int flags = 0; for (F value : enumClass.getEnumConstants()) { if (value.enabledByDefault()) { flags |= value.getMask(); } } return flags; } /* /********************************************************** /* Life-cycle: factory methods /********************************************************** */ /** * Method for constructing and returning a new instance with specified * mapper features enabled. */ public abstract T with(MapperFeature... features); /** * Method for constructing and returning a new instance with specified * mapper features disabled. */ public abstract T without(MapperFeature... features); /** * @since 2.3 */ public abstract T with(MapperFeature feature, boolean state); /* /********************************************************** /* Configuration: simple features /********************************************************** */ /** * Accessor for simple mapper features (which are shared for * serialization, deserialization) */ public final boolean isEnabled(MapperFeature f) { return (_mapperFeatures & f.getMask()) != 0; } /** * "Bulk" access method for checking that all features specified by * mask are enabled. * * @since 2.3 */ public final boolean hasMapperFeatures(int featureMask) { return (_mapperFeatures & featureMask) == featureMask; } /** * Method for determining whether annotation processing is enabled or not * (default settings are typically that it is enabled; must explicitly disable). * * @return True if annotation processing is enabled; false if not */ public final boolean isAnnotationProcessingEnabled() { return isEnabled(MapperFeature.USE_ANNOTATIONS); } /** * Accessor for determining whether it is ok to try to force override of access * modifiers to be able to get or set values of non-public Methods, Fields; * to invoke non-public Constructors, Methods; or to instantiate non-public * Classes. By default this is enabled, but on some platforms it needs to be * prevented since if this would violate security constraints and cause failures. * * @return True if access modifier overriding is allowed (and may be done for * any Field, Method, Constructor or Class); false to prevent any attempts * to override. */ public final boolean canOverrideAccessModifiers() { return isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS); } /** * Accessor for checking whether default settings for property handling * indicate that properties should be alphabetically ordered or not. */ public final boolean shouldSortPropertiesAlphabetically() { return isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); } /** * Accessor for checking whether configuration indicates that * "root wrapping" (use of an extra property/name pair at root level) * is expected or not. */ public abstract boolean useRootWrapping(); /* /********************************************************** /* Configuration: factory methods /********************************************************** */ /** * Method for constructing a specialized textual object that can typically * be serialized faster than basic {@link java.lang.String} (depending * on escaping needed if any, char-to-byte encoding if needed). * * @param src Text to represent * * @return Optimized text object constructed * * @since 2.4 */ public SerializableString compileString(String src) { /* 20-Jan-2014, tatu: For now we will just construct it directly, but * for 2.4 need to allow overriding to support non-standard extensions * to be used by extensions like Afterburner. */ return new SerializedString(src); } /* /********************************************************** /* Configuration: introspectors, mix-ins /********************************************************** */ public ClassIntrospector getClassIntrospector() { return _base.getClassIntrospector(); } /** * Method for getting {@link AnnotationIntrospector} configured * to introspect annotation values used for configuration. *

* Non-final since it is actually overridden by sub-classes (for now?) */ public AnnotationIntrospector getAnnotationIntrospector() { if (isEnabled(MapperFeature.USE_ANNOTATIONS)) { return _base.getAnnotationIntrospector(); } return NopAnnotationIntrospector.instance; } public final PropertyNamingStrategy getPropertyNamingStrategy() { return _base.getPropertyNamingStrategy(); } public final HandlerInstantiator getHandlerInstantiator() { return _base.getHandlerInstantiator(); } /* /********************************************************** /* Configuration: type and subtype handling /********************************************************** */ /** * Method called to locate a type info handler for types that do not have * one explicitly declared via annotations (or other configuration). * If such default handler is configured, it is returned; otherwise * null is returned. */ public final TypeResolverBuilder getDefaultTyper(JavaType baseType) { return _base.getTypeResolverBuilder(); } public abstract SubtypeResolver getSubtypeResolver(); public final TypeFactory getTypeFactory() { return _base.getTypeFactory(); } /** * Helper method that will construct {@link JavaType} for given * raw class. * This is a simple short-cut for: *

     *    getTypeFactory().constructType(cls);
     *
*/ public final JavaType constructType(Class cls) { return getTypeFactory().constructType(cls); } /** * Helper method that will construct {@link JavaType} for given * type reference * This is a simple short-cut for: *
     *    getTypeFactory().constructType(valueTypeRef);
     *
*/ public final JavaType constructType(TypeReference valueTypeRef) { return getTypeFactory().constructType(valueTypeRef.getType()); } public JavaType constructSpecializedType(JavaType baseType, Class subclass) { return getTypeFactory().constructSpecializedType(baseType, subclass); } /* /********************************************************** /* Configuration: introspection support /********************************************************** */ /** * Accessor for getting bean description that only contains class * annotations: useful if no getter/setter/creator information is needed. */ public BeanDescription introspectClassAnnotations(Class cls) { return introspectClassAnnotations(constructType(cls)); } /** * Accessor for getting bean description that only contains class * annotations: useful if no getter/setter/creator information is needed. */ public BeanDescription introspectClassAnnotations(JavaType type) { return getClassIntrospector().forClassAnnotations(this, type, this); } /** * Accessor for getting bean description that only contains immediate class * annotations: ones from the class, and its direct mix-in, if any, but * not from super types. */ public BeanDescription introspectDirectClassAnnotations(Class cls) { return introspectDirectClassAnnotations(constructType(cls)); } /** * Accessor for getting bean description that only contains immediate class * annotations: ones from the class, and its direct mix-in, if any, but * not from super types. */ public final BeanDescription introspectDirectClassAnnotations(JavaType type) { return getClassIntrospector().forDirectClassAnnotations(this, type, this); } /* /********************************************************** /* Configuration: default settings with per-type overrides /********************************************************** */ /** * Accessor for finding {@link ConfigOverride} to use for * properties of given type, if any exist; or return `null` if not. *

* Note that only directly associated override * is found; no type hierarchy traversal is performed. * * @since 2.8 * * @return Override object to use for the type, if defined; null if none. */ public abstract ConfigOverride findConfigOverride(Class type); /** * Accessor for finding {@link ConfigOverride} to use for * properties of given type, if any exist; or if none, return an immutable * "empty" instance with no overrides. *

* Note that only directly associated override * is found; no type hierarchy traversal is performed. * * @since 2.9 * * @return Override object to use for the type, never null (but may be empty) */ public abstract ConfigOverride getConfigOverride(Class type); /** * Accessor for default property inclusion to use for serialization, * used unless overridden by per-type or per-property overrides. * * @since 2.7 */ public abstract JsonInclude.Value getDefaultPropertyInclusion(); /** * Accessor for default property inclusion to use for serialization, * considering possible per-type override for given base type.
* NOTE: if no override found, defaults to value returned by * {@link #getDefaultPropertyInclusion()}. * * @since 2.7 */ public abstract JsonInclude.Value getDefaultPropertyInclusion(Class baseType); /** * Accessor for default property inclusion to use for serialization, * considering possible per-type override for given base type; but * if none found, returning given defaultIncl * * @param defaultIncl Inclusion setting to return if no overrides found. * * @since 2.8.2 */ public JsonInclude.Value getDefaultPropertyInclusion(Class baseType, JsonInclude.Value defaultIncl) { JsonInclude.Value v = getConfigOverride(baseType).getInclude(); if (v != null) { return v; } return defaultIncl; } /** * Accessor for default property inclusion to use for serialization, * considering possible per-type override for given base type and * possible per-type override for given property type.
* NOTE: if no override found, defaults to value returned by * {@link #getDefaultPropertyInclusion()}. * * @param baseType Type of the instance containing the targeted property. * @param propertyType Type of the property to look up inclusion setting for. * * @since 2.9 */ public abstract JsonInclude.Value getDefaultInclusion(Class baseType, Class propertyType); /** * Accessor for default property inclusion to use for serialization, * considering possible per-type override for given base type and * possible per-type override for given property type; but * if none found, returning given defaultIncl * * @param baseType Type of the instance containing the targeted property. * @param propertyType Type of the property to look up inclusion setting for. * @param defaultIncl Inclusion setting to return if no overrides found. * * @since 2.9 */ public JsonInclude.Value getDefaultInclusion(Class baseType, Class propertyType, JsonInclude.Value defaultIncl) { JsonInclude.Value baseOverride = getConfigOverride(baseType).getInclude(); JsonInclude.Value propOverride = getConfigOverride(propertyType).getIncludeAsProperty(); JsonInclude.Value result = JsonInclude.Value.mergeAll(defaultIncl, baseOverride, propOverride); return result; } /** * Accessor for default format settings to use for serialization (and, to a degree * deserialization), considering baseline settings and per-type defaults * for given base type (if any). * * @since 2.7 */ public abstract JsonFormat.Value getDefaultPropertyFormat(Class baseType); /** * Accessor for default property ignorals to use, if any, for given base type, * based on config overrides settings (see {@link #findConfigOverride(Class)}). * * @since 2.8 */ public abstract JsonIgnoreProperties.Value getDefaultPropertyIgnorals(Class baseType); /** * Helper method that may be called to see if there are property ignoral * definitions from annotations (via {@link AnnotatedClass}) or through * "config overrides". If both exist, config overrides have precedence * over class annotations. * * @since 2.8 */ public abstract JsonIgnoreProperties.Value getDefaultPropertyIgnorals(Class baseType, AnnotatedClass actualClass); /** * Accessor for object used for determining whether specific property elements * (method, constructors, fields) can be auto-detected based on * their visibility (access modifiers). Can be changed to allow * different minimum visibility levels for auto-detection. Note * that this is the global handler; individual types (classes) * can further override active checker used (using * {@link JsonAutoDetect} annotation) */ public abstract VisibilityChecker getDefaultVisibilityChecker(); /** * Accessor for object used for determining whether specific property elements * (method, constructors, fields) can be auto-detected based on * their visibility (access modifiers). This is based on global defaults * (as would be returned by {@link #getDefaultVisibilityChecker()}, but * then modified by possible class annotation (see {@link JsonAutoDetect}) * and/or per-type config override (see {@link ConfigOverride#getVisibility()}). * * @since 2.9 */ public abstract VisibilityChecker getDefaultVisibilityChecker(Class baseType, AnnotatedClass actualClass); /** * Accessor for the baseline setter info used as the global baseline, * not considering possible per-type overrides. * * @return Global base settings; never null * * @since 2.9 */ public abstract JsonSetter.Value getDefaultSetterInfo(); /** * Accessor for the baseline merge info used as the global baseline, * not considering possible per-type overrides. * * @return Global base settings, if any; `null` if none. * * @since 2.9 */ public abstract Boolean getDefaultMergeable(); /** * Accessor for the baseline merge info used for given type, including global * defaults if no type-specific overrides defined. * * @return Type-specific settings (if any); global defaults (same as * {@link #getDefaultMergeable()}) otherwise, if any defined; or `null` * if neither defined * * @since 2.9 */ public abstract Boolean getDefaultMergeable(Class baseType); /* /********************************************************** /* Configuration: other /********************************************************** */ /** * Method for accessing currently configured (textual) date format * that will be used for reading or writing date values (in case * of writing, only if textual output is configured; not if dates * are to be serialized as time stamps). *

* Note that typically {@link DateFormat} instances are not thread-safe * (at least ones provided by JDK): * this means that calling code should clone format instance before * using it. *

* This method is usually only called by framework itself, since there * are convenience methods available via * {@link DeserializationContext} and {@link SerializerProvider} that * take care of cloning and thread-safe reuse. */ public final DateFormat getDateFormat() { return _base.getDateFormat(); } /** * Method for accessing the default {@link java.util.Locale} to use * for formatting, unless overridden by local annotations. * Initially set to {@link Locale#getDefault()}. */ public final Locale getLocale() { return _base.getLocale(); } /** * Method for accessing the default {@link java.util.TimeZone} to use * for formatting, unless overridden by local annotations. * Initially set to {@link TimeZone#getDefault()}. */ public final TimeZone getTimeZone() { return _base.getTimeZone(); } /** * Accessor for finding currently active view, if any (null if none) */ public abstract Class getActiveView(); /** * Method called during deserialization if Base64 encoded content * needs to be decoded. Default version just returns default Jackson * uses, which is modified-mime which does not add linefeeds (because * those would have to be escaped in JSON strings); but this can * be configured on {@link ObjectWriter}. */ public Base64Variant getBase64Variant() { return _base.getBase64Variant(); } /** * Method for accessing per-instance shared (baseline/default) * attribute values; these are used as the basis for per-call * attributes. * * @since 2.3 */ public abstract ContextAttributes getAttributes(); /** * @since 2.6 */ public abstract PropertyName findRootName(JavaType rootType); /** * @since 2.6 */ public abstract PropertyName findRootName(Class rawRootType); /* /********************************************************** /* Methods for instantiating handlers /********************************************************** */ /** * Method that can be called to obtain an instance of TypeIdResolver of * specified type. */ public TypeResolverBuilder typeResolverBuilderInstance(Annotated annotated, Class> builderClass) { HandlerInstantiator hi = getHandlerInstantiator(); if (hi != null) { TypeResolverBuilder builder = hi.typeResolverBuilderInstance(this, annotated, builderClass); if (builder != null) { return builder; } } return (TypeResolverBuilder) ClassUtil.createInstance(builderClass, canOverrideAccessModifiers()); } /** * Method that can be called to obtain an instance of TypeIdResolver of * specified type. */ public TypeIdResolver typeIdResolverInstance(Annotated annotated, Class resolverClass) { HandlerInstantiator hi = getHandlerInstantiator(); if (hi != null) { TypeIdResolver builder = hi.typeIdResolverInstance(this, annotated, resolverClass); if (builder != null) { return builder; } } return (TypeIdResolver) ClassUtil.createInstance(resolverClass, canOverrideAccessModifiers()); } } MapperConfigBase.java000066400000000000000000000611431325620701100352240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import java.text.DateFormat; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.core.Base64Variant; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.ClassIntrospector; import com.fasterxml.jackson.databind.introspect.ClassIntrospector.MixInResolver; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.SimpleMixInResolver; import com.fasterxml.jackson.databind.introspect.VisibilityChecker; import com.fasterxml.jackson.databind.jsontype.SubtypeResolver; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.RootNameLookup; @SuppressWarnings("serial") public abstract class MapperConfigBase> extends MapperConfig implements java.io.Serializable { /** * @since 2.9 */ protected final static ConfigOverride EMPTY_OVERRIDE = ConfigOverride.empty(); private final static int DEFAULT_MAPPER_FEATURES = collectFeatureDefaults(MapperFeature.class); /** * @since 2.9 */ private final static int AUTO_DETECT_MASK = MapperFeature.AUTO_DETECT_FIELDS.getMask() | MapperFeature.AUTO_DETECT_GETTERS.getMask() | MapperFeature.AUTO_DETECT_IS_GETTERS.getMask() | MapperFeature.AUTO_DETECT_SETTERS.getMask() | MapperFeature.AUTO_DETECT_CREATORS.getMask() ; /* /********************************************************** /* Immutable config /********************************************************** */ /** * Mix-in annotation mappings to use, if any: immutable, * cannot be changed once defined. * * @since 2.6 */ protected final SimpleMixInResolver _mixIns; /** * Registered concrete subtypes that can be used instead of (or * in addition to) ones declared using annotations. *

* Note that instances are stateful and as such may need to be copied, * and may NOT be demoted down to {@link BaseSettings}. */ protected final SubtypeResolver _subtypeResolver; /** * Explicitly defined root name to use, if any; if empty * String, will disable root-name wrapping; if null, will * use defaults */ protected final PropertyName _rootName; /** * View to use for filtering out properties to serialize * or deserialize. * Null if none (will also be assigned null if Object.class * is defined), meaning that all properties are to be included. */ protected final Class _view; /** * Contextual attributes accessible (get and set) during processing, * on per-call basis. * * @since 2.3 */ protected final ContextAttributes _attributes; /** * Simple cache used for finding out possible root name for root name * wrapping. *

* Note that instances are stateful (for caching) and as such may need to be copied, * and may NOT be demoted down to {@link BaseSettings}. * * @since 2.6 */ protected final RootNameLookup _rootNames; /** * Configuration overrides to apply, keyed by type of property. * * @since 2.8 */ protected final ConfigOverrides _configOverrides; /* /********************************************************** /* Construction /********************************************************** */ /** * Constructor used when creating a new instance (compared to * that of creating fluent copies) * * @since 2.8 */ protected MapperConfigBase(BaseSettings base, SubtypeResolver str, SimpleMixInResolver mixins, RootNameLookup rootNames, ConfigOverrides configOverrides) { super(base, DEFAULT_MAPPER_FEATURES); _mixIns = mixins; _subtypeResolver = str; _rootNames = rootNames; _rootName = null; _view = null; // default to "no attributes" _attributes = ContextAttributes.getEmpty(); _configOverrides = configOverrides; } /** * @since 2.8 */ protected MapperConfigBase(MapperConfigBase src, SimpleMixInResolver mixins, RootNameLookup rootNames, ConfigOverrides configOverrides) { super(src); _mixIns = mixins; _subtypeResolver = src._subtypeResolver; _rootNames = rootNames; _rootName = src._rootName; _view = src._view; _attributes = src._attributes; _configOverrides = configOverrides; } /** * Pass-through constructor used when no changes are needed to the * base class. */ protected MapperConfigBase(MapperConfigBase src) { super(src); _mixIns = src._mixIns; _subtypeResolver = src._subtypeResolver; _rootNames = src._rootNames; _rootName = src._rootName; _view = src._view; _attributes = src._attributes; _configOverrides = src._configOverrides; } protected MapperConfigBase(MapperConfigBase src, BaseSettings base) { super(src, base); _mixIns = src._mixIns; _subtypeResolver = src._subtypeResolver; _rootNames = src._rootNames; _rootName = src._rootName; _view = src._view; _attributes = src._attributes; _configOverrides = src._configOverrides; } protected MapperConfigBase(MapperConfigBase src, int mapperFeatures) { super(src, mapperFeatures); _mixIns = src._mixIns; _subtypeResolver = src._subtypeResolver; _rootNames = src._rootNames; _rootName = src._rootName; _view = src._view; _attributes = src._attributes; _configOverrides = src._configOverrides; } protected MapperConfigBase(MapperConfigBase src, SubtypeResolver str) { super(src); _mixIns = src._mixIns; _subtypeResolver = str; _rootNames = src._rootNames; _rootName = src._rootName; _view = src._view; _attributes = src._attributes; _configOverrides = src._configOverrides; } protected MapperConfigBase(MapperConfigBase src, PropertyName rootName) { super(src); _mixIns = src._mixIns; _subtypeResolver = src._subtypeResolver; _rootNames = src._rootNames; _rootName = rootName; _view = src._view; _attributes = src._attributes; _configOverrides = src._configOverrides; } protected MapperConfigBase(MapperConfigBase src, Class view) { super(src); _mixIns = src._mixIns; _subtypeResolver = src._subtypeResolver; _rootNames = src._rootNames; _rootName = src._rootName; _view = view; _attributes = src._attributes; _configOverrides = src._configOverrides; } /** * @since 2.1 */ protected MapperConfigBase(MapperConfigBase src, SimpleMixInResolver mixins) { super(src); _mixIns = mixins; _subtypeResolver = src._subtypeResolver; _rootNames = src._rootNames; _rootName = src._rootName; _view = src._view; _attributes = src._attributes; _configOverrides = src._configOverrides; } /** * @since 2.3 */ protected MapperConfigBase(MapperConfigBase src, ContextAttributes attr) { super(src); _mixIns = src._mixIns; _subtypeResolver = src._subtypeResolver; _rootNames = src._rootNames; _rootName = src._rootName; _view = src._view; _attributes = attr; _configOverrides = src._configOverrides; } /* /********************************************************** /* Abstract fluent factory methods to be implemented by subtypes /********************************************************** */ /** * @since 2.9 (in this case, demoted from sub-classes) */ protected abstract T _withBase(BaseSettings newBase); /** * @since 2.9 (in this case, demoted from sub-classes) */ protected abstract T _withMapperFeatures(int mapperFeatures); /* /********************************************************** /* Additional shared fluent factory methods; features /********************************************************** */ /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. */ @SuppressWarnings("unchecked") @Override public final T with(MapperFeature... features) { int newMapperFlags = _mapperFeatures; for (MapperFeature f : features) { newMapperFlags |= f.getMask(); } if (newMapperFlags == _mapperFeatures) { return (T) this; } return _withMapperFeatures(newMapperFlags); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. */ @SuppressWarnings("unchecked") @Override public final T without(MapperFeature... features) { int newMapperFlags = _mapperFeatures; for (MapperFeature f : features) { newMapperFlags &= ~f.getMask(); } if (newMapperFlags == _mapperFeatures) { return (T) this; } return _withMapperFeatures(newMapperFlags); } @SuppressWarnings("unchecked") @Override public final T with(MapperFeature feature, boolean state) { int newMapperFlags; if (state) { newMapperFlags = _mapperFeatures | feature.getMask(); } else { newMapperFlags = _mapperFeatures & ~feature.getMask(); } if (newMapperFlags == _mapperFeatures) { return (T) this; } return _withMapperFeatures(newMapperFlags); } /* /********************************************************** /* Additional shared fluent factory methods; introspectors /********************************************************** */ /** * Method for constructing and returning a new instance with different * {@link AnnotationIntrospector} to use (replacing old one). *

* NOTE: make sure to register new instance with ObjectMapper * if directly calling this method. */ public final T with(AnnotationIntrospector ai) { return _withBase(_base.withAnnotationIntrospector(ai)); } /** * Method for constructing and returning a new instance with additional * {@link AnnotationIntrospector} appended (as the lowest priority one) */ public final T withAppendedAnnotationIntrospector(AnnotationIntrospector ai) { return _withBase(_base.withAppendedAnnotationIntrospector(ai)); } /** * Method for constructing and returning a new instance with additional * {@link AnnotationIntrospector} inserted (as the highest priority one) */ public final T withInsertedAnnotationIntrospector(AnnotationIntrospector ai) { return _withBase(_base.withInsertedAnnotationIntrospector(ai)); } /** * Method for constructing and returning a new instance with different * {@link ClassIntrospector} * to use. *

* NOTE: make sure to register new instance with ObjectMapper * if directly calling this method. */ public final T with(ClassIntrospector ci) { return _withBase(_base.withClassIntrospector(ci)); } /* /********************************************************** /* Additional shared fluent factory methods; attributes /********************************************************** */ /** * Method for constructing an instance that has specified * contextual attributes. * * @since 2.3 */ public abstract T with(ContextAttributes attrs); /** * Method for constructing an instance that has only specified * attributes, removing any attributes that exist before the call. * * @since 2.3 */ public T withAttributes(Map attributes) { return with(getAttributes().withSharedAttributes(attributes)); } /** * Method for constructing an instance that has specified * value for attribute for given key. * * @since 2.3 */ public T withAttribute(Object key, Object value) { return with(getAttributes().withSharedAttribute(key, value)); } /** * Method for constructing an instance that has no * value for attribute for given key. * * @since 2.3 */ public T withoutAttribute(Object key) { return with(getAttributes().withoutSharedAttribute(key)); } /* /********************************************************** /* Additional shared fluent factory methods; factories /********************************************************** */ /** * Method for constructing and returning a new instance with different * {@link TypeFactory} * to use. */ public final T with(TypeFactory tf) { return _withBase( _base.withTypeFactory(tf)); } /** * Method for constructing and returning a new instance with different * {@link TypeResolverBuilder} to use. */ public final T with(TypeResolverBuilder trb) { return _withBase(_base.withTypeResolverBuilder(trb)); } /** * Method for constructing and returning a new instance with different * {@link PropertyNamingStrategy} * to use. *

* NOTE: make sure to register new instance with ObjectMapper * if directly calling this method. */ public final T with(PropertyNamingStrategy pns) { return _withBase(_base.withPropertyNamingStrategy(pns)); } /** * Method for constructing and returning a new instance with different * {@link HandlerInstantiator} * to use. *

* NOTE: make sure to register new instance with ObjectMapper * if directly calling this method. */ public final T with(HandlerInstantiator hi) { return _withBase(_base.withHandlerInstantiator(hi)); } /* /********************************************************** /* Additional shared fluent factory methods; other /********************************************************** */ /** * Method for constructing and returning a new instance with different * default {@link Base64Variant} to use with base64-encoded binary values. */ public final T with(Base64Variant base64) { return _withBase(_base.with(base64)); } /** * Method for constructing and returning a new instance with different * {@link DateFormat} * to use. *

* NOTE: non-final since SerializationConfig needs to override this */ public T with(DateFormat df) { return _withBase(_base.withDateFormat(df)); } /** * Method for constructing and returning a new instance with different * default {@link java.util.Locale} to use for formatting. */ public final T with(Locale l) { return _withBase(_base.with(l)); } /** * Method for constructing and returning a new instance with different * default {@link java.util.TimeZone} to use for formatting of date values. */ public final T with(TimeZone tz) { return _withBase(_base.with(tz)); } /** * Method for constructing and returning a new instance with different * root name to use (none, if null). *

* Note that when a root name is set to a non-Empty String, this will automatically force use * of root element wrapping with given name. If empty String passed, will * disable root name wrapping; and if null used, will instead use * SerializationFeature to determine if to use wrapping, and annotation * (or default name) for actual root name to use. * * @param rootName to use: if null, means "use default" (clear setting); * if empty String ("") means that no root name wrapping is used; * otherwise defines root name to use. * * @since 2.6 */ public abstract T withRootName(PropertyName rootName); public T withRootName(String rootName) { if (rootName == null) { return withRootName((PropertyName) null); } return withRootName(PropertyName.construct(rootName)); } /** * Method for constructing and returning a new instance with different * {@link SubtypeResolver} * to use. *

* NOTE: make sure to register new instance with ObjectMapper * if directly calling this method. */ public abstract T with(SubtypeResolver str); /** * Method for constructing and returning a new instance with different * view to use. */ public abstract T withView(Class view); /* /********************************************************** /* Simple accessors /********************************************************** */ /** * Accessor for object used for finding out all reachable subtypes * for supertypes; needed when a logical type name is used instead * of class name (or custom scheme). */ @Override public final SubtypeResolver getSubtypeResolver() { return _subtypeResolver; } /** * @deprecated Since 2.6 use {@link #getFullRootName} instead. */ @Deprecated // since 2.6 public final String getRootName() { return (_rootName == null) ? null : _rootName.getSimpleName(); } /** * @since 2.6 */ public final PropertyName getFullRootName() { return _rootName; } @Override public final Class getActiveView() { return _view; } @Override public final ContextAttributes getAttributes() { return _attributes; } /* /********************************************************** /* Configuration access; default/overrides /********************************************************** */ @Override public final ConfigOverride getConfigOverride(Class type) { ConfigOverride override = _configOverrides.findOverride(type); return (override == null) ? EMPTY_OVERRIDE : override; } @Override public final ConfigOverride findConfigOverride(Class type) { return _configOverrides.findOverride(type); } @Override public final JsonInclude.Value getDefaultPropertyInclusion() { return _configOverrides.getDefaultInclusion(); } @Override public final JsonInclude.Value getDefaultPropertyInclusion(Class baseType) { JsonInclude.Value v = getConfigOverride(baseType).getInclude(); JsonInclude.Value def = getDefaultPropertyInclusion(); if (def == null) { return v; } return def.withOverrides(v); } @Override public final JsonInclude.Value getDefaultInclusion(Class baseType, Class propertyType) { JsonInclude.Value v = getConfigOverride(propertyType).getIncludeAsProperty(); JsonInclude.Value def = getDefaultPropertyInclusion(baseType); if (def == null) { return v; } return def.withOverrides(v); } @Override public final JsonFormat.Value getDefaultPropertyFormat(Class type) { ConfigOverride overrides = _configOverrides.findOverride(type); if (overrides != null) { JsonFormat.Value v = overrides.getFormat(); if (v != null) { return v; } } return EMPTY_FORMAT; } @Override public final JsonIgnoreProperties.Value getDefaultPropertyIgnorals(Class type) { ConfigOverride overrides = _configOverrides.findOverride(type); if (overrides != null) { JsonIgnoreProperties.Value v = overrides.getIgnorals(); if (v != null) { return v; } } // 01-May-2015, tatu: Could return `Value.empty()` but for now `null` // seems simpler as callers can avoid processing. return null; } @Override public final JsonIgnoreProperties.Value getDefaultPropertyIgnorals(Class baseType, AnnotatedClass actualClass) { AnnotationIntrospector intr = getAnnotationIntrospector(); JsonIgnoreProperties.Value base = (intr == null) ? null : intr.findPropertyIgnorals(actualClass); JsonIgnoreProperties.Value overrides = getDefaultPropertyIgnorals(baseType); return JsonIgnoreProperties.Value.merge(base, overrides); } @Override public final VisibilityChecker getDefaultVisibilityChecker() { VisibilityChecker vchecker = _configOverrides.getDefaultVisibility(); // then global overrides (disabling) // 05-Mar-2018, tatu: As per [databind#1947], need to see if any disabled if ((_mapperFeatures & AUTO_DETECT_MASK) != AUTO_DETECT_MASK) { if (!isEnabled(MapperFeature.AUTO_DETECT_FIELDS)) { vchecker = vchecker.withFieldVisibility(Visibility.NONE); } if (!isEnabled(MapperFeature.AUTO_DETECT_GETTERS)) { vchecker = vchecker.withGetterVisibility(Visibility.NONE); } if (!isEnabled(MapperFeature.AUTO_DETECT_IS_GETTERS)) { vchecker = vchecker.withIsGetterVisibility(Visibility.NONE); } if (!isEnabled(MapperFeature.AUTO_DETECT_SETTERS)) { vchecker = vchecker.withSetterVisibility(Visibility.NONE); } if (!isEnabled(MapperFeature.AUTO_DETECT_CREATORS)) { vchecker = vchecker.withCreatorVisibility(Visibility.NONE); } } return vchecker; } @Override // since 2.9 public final VisibilityChecker getDefaultVisibilityChecker(Class baseType, AnnotatedClass actualClass) { VisibilityChecker vc = getDefaultVisibilityChecker(); AnnotationIntrospector intr = getAnnotationIntrospector(); if (intr != null) { vc = intr.findAutoDetectVisibility(actualClass, vc); } ConfigOverride overrides = _configOverrides.findOverride(baseType); if (overrides != null) { vc = vc.withOverrides(overrides.getVisibility()); // ok to pass null } return vc; } @Override public final JsonSetter.Value getDefaultSetterInfo() { return _configOverrides.getDefaultSetterInfo(); } @Override public Boolean getDefaultMergeable() { return _configOverrides.getDefaultMergeable(); } @Override public Boolean getDefaultMergeable(Class baseType) { Boolean b; ConfigOverride cfg = _configOverrides.findOverride(baseType); if (cfg != null) { b = cfg.getMergeable(); if (b != null) { return b; } } return _configOverrides.getDefaultMergeable(); } /* /********************************************************** /* Other config access /********************************************************** */ @Override public PropertyName findRootName(JavaType rootType) { if (_rootName != null) { return _rootName; } return _rootNames.findRootName(rootType, this); } @Override public PropertyName findRootName(Class rawRootType) { if (_rootName != null) { return _rootName; } return _rootNames.findRootName(rawRootType, this); } /* /********************************************************** /* ClassIntrospector.MixInResolver impl: /********************************************************** */ /** * Method that will check if there are "mix-in" classes (with mix-in * annotations) for given class */ @Override public final Class findMixInClassFor(Class cls) { return _mixIns.findMixInClassFor(cls); } // Not really relevant here (should not get called) @Override public MixInResolver copy() { throw new UnsupportedOperationException(); } /** * Test-only method -- does not reflect possibly open-ended set that external * mix-in resolver might provide. */ public final int mixInCount() { return _mixIns.localSize(); } } MutableConfigOverride.java000066400000000000000000000047301325620701100362750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonSetter; /** * Extension of {@link ConfigOverride} that allows changing of * contained configuration settings. Exposed to * {@link com.fasterxml.jackson.databind.Module}s that want to set * overrides, but not exposed to functionality that wants to apply * overrides. * * @since 2.8 */ public class MutableConfigOverride extends ConfigOverride implements java.io.Serializable { private static final long serialVersionUID = 1L; public MutableConfigOverride() { super(); } protected MutableConfigOverride(MutableConfigOverride src) { super(src); } public MutableConfigOverride copy() { return new MutableConfigOverride(this); } public MutableConfigOverride setFormat(JsonFormat.Value v) { _format = v; return this; } /** * Override inclusion setting for all properties contained in POJOs of the * associated type. * * @param v Inclusion setting to apply contained properties. */ public MutableConfigOverride setInclude(JsonInclude.Value v) { _include = v; return this; } /** * Override inclusion setting for properties of the associated type * regardless of the type of the POJO containing it. * * @param v Inclusion setting to apply for properties of associated type. * * @since 2.9 */ public MutableConfigOverride setIncludeAsProperty(JsonInclude.Value v) { _includeAsProperty = v; return this; } public MutableConfigOverride setIgnorals(JsonIgnoreProperties.Value v) { _ignorals = v; return this; } public MutableConfigOverride setIsIgnoredType(Boolean v) { _isIgnoredType = v; return this; } /** * @since 2.9 */ public MutableConfigOverride setSetterInfo(JsonSetter.Value v) { _setterInfo = v; return this; } /** * @since 2.9 */ public MutableConfigOverride setVisibility(JsonAutoDetect.Value v) { _visibility = v; return this; } /** * @since 2.9 */ public MutableConfigOverride setMergeable(Boolean v) { _mergeable = v; return this; } } PackageVersion.java.in000066400000000000000000000011071325620701100353570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage @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; } } SerializerFactoryConfig.java000066400000000000000000000073611325620701100366500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import com.fasterxml.jackson.databind.ser.*; import com.fasterxml.jackson.databind.util.ArrayBuilders; import com.fasterxml.jackson.databind.util.ArrayIterator; /** * Configuration settings container class for * {@link SerializerFactory} implementations. */ public final class SerializerFactoryConfig implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Constant for empty Serializers array (which by definition * is stateless and reusable) */ protected final static Serializers[] NO_SERIALIZERS = new Serializers[0]; protected final static BeanSerializerModifier[] NO_MODIFIERS = new BeanSerializerModifier[0]; /** * List of providers for additional serializers, checked before considering default * basic or bean serialializers. */ protected final Serializers[] _additionalSerializers; /** * List of providers for additional key serializers, checked before considering default * key serialializers. */ protected final Serializers[] _additionalKeySerializers; /** * List of modifiers that can change the way {@link BeanSerializer} instances * are configured and constructed. */ protected final BeanSerializerModifier[] _modifiers; public SerializerFactoryConfig() { this(null, null, null); } protected SerializerFactoryConfig(Serializers[] allAdditionalSerializers, Serializers[] allAdditionalKeySerializers, BeanSerializerModifier[] modifiers) { _additionalSerializers = (allAdditionalSerializers == null) ? NO_SERIALIZERS : allAdditionalSerializers; _additionalKeySerializers = (allAdditionalKeySerializers == null) ? NO_SERIALIZERS : allAdditionalKeySerializers; _modifiers = (modifiers == null) ? NO_MODIFIERS : modifiers; } public SerializerFactoryConfig withAdditionalSerializers(Serializers additional) { if (additional == null) { throw new IllegalArgumentException("Cannot pass null Serializers"); } Serializers[] all = ArrayBuilders.insertInListNoDup(_additionalSerializers, additional); return new SerializerFactoryConfig(all, _additionalKeySerializers, _modifiers); } public SerializerFactoryConfig withAdditionalKeySerializers(Serializers additional) { if (additional == null) { throw new IllegalArgumentException("Cannot pass null Serializers"); } Serializers[] all = ArrayBuilders.insertInListNoDup(_additionalKeySerializers, additional); return new SerializerFactoryConfig(_additionalSerializers, all, _modifiers); } public SerializerFactoryConfig withSerializerModifier(BeanSerializerModifier modifier) { if (modifier == null) { throw new IllegalArgumentException("Cannot pass null modifier"); } BeanSerializerModifier[] modifiers = ArrayBuilders.insertInListNoDup(_modifiers, modifier); return new SerializerFactoryConfig(_additionalSerializers, _additionalKeySerializers, modifiers); } public boolean hasSerializers() { return _additionalSerializers.length > 0; } public boolean hasKeySerializers() { return _additionalKeySerializers.length > 0; } public boolean hasSerializerModifiers() { return _modifiers.length > 0; } public Iterable serializers() { return new ArrayIterator(_additionalSerializers); } public Iterable keySerializers() { return new ArrayIterator(_additionalKeySerializers); } public Iterable serializerModifiers() { return new ArrayIterator(_modifiers); } } package-info.java000066400000000000000000000004311325620701100343740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/cfg/** Package that contains most of configuration-related classes; exception being couple of most-commonly used configuration things (like Feature enumerations) that are at the main level (com.fasterxml.jackson.databind). */ package com.fasterxml.jackson.databind.cfg; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/000077500000000000000000000000001325620701100316315ustar00rootroot00000000000000AbstractDeserializer.java000066400000000000000000000322071325620701100365270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.annotation.ObjectIdResolver; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader; import com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator; import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.ObjectIdInfo; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; /** * Deserializer only used for abstract types used as placeholders during polymorphic * type handling deserialization. If so, there is no real deserializer associated * with nominal type, just {@link TypeDeserializer}; and any calls that do not * pass such resolver will result in an error. */ public class AbstractDeserializer extends JsonDeserializer implements ContextualDeserializer, // since 2.9 java.io.Serializable { private static final long serialVersionUID = 1L; protected final JavaType _baseType; protected final ObjectIdReader _objectIdReader; protected final Map _backRefProperties; protected transient Map _properties; // support for "native" types, which require special care: protected final boolean _acceptString; protected final boolean _acceptBoolean; protected final boolean _acceptInt; protected final boolean _acceptDouble; /* /********************************************************** /* Life cycle /********************************************************** */ /** * @since 2.9 * * @param props Regular properties: currently only needed to support property-annotated * Object Id handling with property inclusion (needed for determining type of Object Id * to bind) */ public AbstractDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, Map backRefProps, Map props) { _baseType = beanDesc.getType(); _objectIdReader = builder.getObjectIdReader(); _backRefProperties = backRefProps; _properties = props; Class cls = _baseType.getRawClass(); _acceptString = cls.isAssignableFrom(String.class); _acceptBoolean = (cls == Boolean.TYPE) || cls.isAssignableFrom(Boolean.class); _acceptInt = (cls == Integer.TYPE) || cls.isAssignableFrom(Integer.class); _acceptDouble = (cls == Double.TYPE) || cls.isAssignableFrom(Double.class); } @Deprecated // since 2.9 public AbstractDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, Map backRefProps) { this(builder, beanDesc, backRefProps, null); } protected AbstractDeserializer(BeanDescription beanDesc) { _baseType = beanDesc.getType(); _objectIdReader = null; _backRefProperties = null; Class cls = _baseType.getRawClass(); _acceptString = cls.isAssignableFrom(String.class); _acceptBoolean = (cls == Boolean.TYPE) || cls.isAssignableFrom(Boolean.class); _acceptInt = (cls == Integer.TYPE) || cls.isAssignableFrom(Integer.class); _acceptDouble = (cls == Double.TYPE) || cls.isAssignableFrom(Double.class); } /** * @since 2.9 */ protected AbstractDeserializer(AbstractDeserializer base, ObjectIdReader objectIdReader, Map props) { _baseType = base._baseType; _backRefProperties = base._backRefProperties; _acceptString = base._acceptString; _acceptBoolean = base._acceptBoolean; _acceptInt = base._acceptInt; _acceptDouble = base._acceptDouble; _objectIdReader = objectIdReader; _properties = props; } /** * Factory method used when constructing instances for non-POJO types, like * {@link java.util.Map}s. * * @since 2.3 */ public static AbstractDeserializer constructForNonPOJO(BeanDescription beanDesc) { return new AbstractDeserializer(beanDesc); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (property != null && intr != null) { final AnnotatedMember accessor = property.getMember(); if (accessor != null) { ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor); if (objectIdInfo != null) { // some code duplication here as well (from BeanDeserializerFactory) JavaType idType; ObjectIdGenerator idGen; SettableBeanProperty idProp = null; ObjectIdResolver resolver = ctxt.objectIdResolverInstance(accessor, objectIdInfo); // 2.1: allow modifications by "id ref" annotations as well: objectIdInfo = intr.findObjectReferenceInfo(accessor, objectIdInfo); Class implClass = objectIdInfo.getGeneratorType(); if (implClass == ObjectIdGenerators.PropertyGenerator.class) { PropertyName propName = objectIdInfo.getPropertyName(); idProp = (_properties == null) ? null : _properties.get(propName.getSimpleName()); if (idProp == null) { ctxt.reportBadDefinition(_baseType, String.format( "Invalid Object Id definition for %s: cannot find property with name '%s'", handledType().getName(), propName)); } idType = idProp.getType(); idGen = new PropertyBasedObjectIdGenerator(objectIdInfo.getScope()); /* ctxt.reportBadDefinition(_baseType, String.format( / "Invalid Object Id definition for abstract type %s: cannot use `PropertyGenerator` on polymorphic types using property annotation", handledType().getName())); */ } else { // other types simpler resolver = ctxt.objectIdResolverInstance(accessor, objectIdInfo); JavaType type = ctxt.constructType(implClass); idType = ctxt.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0]; idGen = ctxt.objectIdGeneratorInstance(accessor, objectIdInfo); } JsonDeserializer deser = ctxt.findRootValueDeserializer(idType); ObjectIdReader oir = ObjectIdReader.construct(idType, objectIdInfo.getPropertyName(), idGen, deser, idProp, resolver); return new AbstractDeserializer(this, oir, null); } } } if (_properties == null) { return this; } // Need to ensure properties are dropped at this point, regardless return new AbstractDeserializer(this, _objectIdReader, null); } /* /********************************************************** /* Public accessors /********************************************************** */ @Override public Class handledType() { return _baseType.getRawClass(); } @Override public boolean isCachable() { return true; } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { /* 23-Oct-2016, tatu: Not exactly sure what to do with this; polymorphic * type handling seems bit risky so for now claim it "may or may not be" * possible, which does allow explicit per-type/per-property merging attempts, * but avoids general-configuration merges */ return null; } /** * Overridden to return true for those instances that are * handling value for which Object Identity handling is enabled * (either via value type or referring property). */ @Override public ObjectIdReader getObjectIdReader() { return _objectIdReader; } /** * Method called by BeanDeserializer to resolve back reference * part of managed references. */ @Override public SettableBeanProperty findBackReference(String logicalName) { return (_backRefProperties == null) ? null : _backRefProperties.get(logicalName); } /* /********************************************************** /* Deserializer implementation /********************************************************** */ @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // Hmmh. One tricky question; for scalar, is it an Object Id, or "Natural" type? // for now, prefer Object Id: if (_objectIdReader != null) { JsonToken t = p.getCurrentToken(); if (t != null) { // Most commonly, a scalar (int id, uuid String, ...) if (t.isScalarValue()) { return _deserializeFromObjectId(p, ctxt); } // but, with 2.5+, a simple Object-wrapped value also legal: if (t == JsonToken.START_OBJECT) { t = p.nextToken(); } if ((t == JsonToken.FIELD_NAME) && _objectIdReader.maySerializeAsObject() && _objectIdReader.isValidReferencePropertyName(p.getCurrentName(), p)) { return _deserializeFromObjectId(p, ctxt); } } } // First: support "natural" values (which are always serialized without type info!) Object result = _deserializeIfNatural(p, ctxt); if (result != null) { return result; } return typeDeserializer.deserializeTypedFromObject(p, ctxt); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 16-Oct-2016, tatu: Let's pass non-null value instantiator so that we will // get proper exception type; needed to establish there are no creators // (since without ValueInstantiator this would not be known for certain) ValueInstantiator bogus = new ValueInstantiator.Base(_baseType); return ctxt.handleMissingInstantiator(_baseType.getRawClass(), bogus, p, "abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information"); } /* /********************************************************** /* Internal methods /********************************************************** */ protected Object _deserializeIfNatural(JsonParser p, DeserializationContext ctxt) throws IOException { /* There is a chance we might be "natural" types * (String, Boolean, Integer, Double), which do not include any type information... * Care must be taken to only return this if return type matches, however. * Finally, we may have to consider possibility of custom handlers for * these values: but for now this should work ok. */ switch (p.getCurrentTokenId()) { case JsonTokenId.ID_STRING: if (_acceptString) { return p.getText(); } break; case JsonTokenId.ID_NUMBER_INT: if (_acceptInt) { return p.getIntValue(); } break; case JsonTokenId.ID_NUMBER_FLOAT: if (_acceptDouble) { return Double.valueOf(p.getDoubleValue()); } break; case JsonTokenId.ID_TRUE: if (_acceptBoolean) { return Boolean.TRUE; } break; case JsonTokenId.ID_FALSE: if (_acceptBoolean) { return Boolean.FALSE; } break; } return null; } /** * Method called in cases where it looks like we got an Object Id * to parse and use as a reference. */ protected Object _deserializeFromObjectId(JsonParser p, DeserializationContext ctxt) throws IOException { Object id = _objectIdReader.readObjectReference(p, ctxt); ReadableObjectId roid = ctxt.findObjectId(id, _objectIdReader.generator, _objectIdReader.resolver); // do we have it resolved? Object pojo = roid.resolve(); if (pojo == null) { // not yet; should wait... throw new UnresolvedForwardReference(p, "Could not resolve Object Id ["+id+"] -- unresolved forward-reference?", p.getCurrentLocation(), roid); } return pojo; } } BasicDeserializerFactory.java000066400000000000000000003035301325620701100373350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JacksonInject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonCreator.Mode; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.deser.impl.CreatorCandidate; import com.fasterxml.jackson.databind.deser.impl.CreatorCollector; import com.fasterxml.jackson.databind.deser.impl.JavaUtilCollectionsDeserializers; import com.fasterxml.jackson.databind.deser.std.*; import com.fasterxml.jackson.databind.ext.OptionalHandlerFactory; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.type.*; import com.fasterxml.jackson.databind.util.*; /** * Abstract factory base class that can provide deserializers for standard * JDK classes, including collection classes and simple heuristics for * "upcasting" common collection interface types * (such as {@link java.util.Collection}). *

* Since all simple deserializers are eagerly instantiated, and there is * no additional introspection or customizability of these types, * this factory is stateless. */ @SuppressWarnings("serial") public abstract class BasicDeserializerFactory extends DeserializerFactory implements java.io.Serializable { private final static Class CLASS_OBJECT = Object.class; private final static Class CLASS_STRING = String.class; private final static Class CLASS_CHAR_SEQUENCE = CharSequence.class; private final static Class CLASS_ITERABLE = Iterable.class; private final static Class CLASS_MAP_ENTRY = Map.Entry.class; /** * We need a placeholder for creator properties that don't have name * but are marked with `@JsonWrapped` annotation. */ protected final static PropertyName UNWRAPPED_CREATOR_PARAM_NAME = new PropertyName("@JsonUnwrapped"); /* We do some defaulting for abstract Map classes and * interfaces, to avoid having to use exact types or annotations in * cases where the most common concrete Maps will do. */ @SuppressWarnings("rawtypes") final static HashMap> _mapFallbacks = new HashMap>(); static { _mapFallbacks.put(Map.class.getName(), LinkedHashMap.class); _mapFallbacks.put(ConcurrentMap.class.getName(), ConcurrentHashMap.class); _mapFallbacks.put(SortedMap.class.getName(), TreeMap.class); _mapFallbacks.put(java.util.NavigableMap.class.getName(), TreeMap.class); _mapFallbacks.put(java.util.concurrent.ConcurrentNavigableMap.class.getName(), java.util.concurrent.ConcurrentSkipListMap.class); } /* We do some defaulting for abstract Collection classes and * interfaces, to avoid having to use exact types or annotations in * cases where the most common concrete Collection will do. */ @SuppressWarnings("rawtypes") final static HashMap> _collectionFallbacks = new HashMap>(); static { _collectionFallbacks.put(Collection.class.getName(), ArrayList.class); _collectionFallbacks.put(List.class.getName(), ArrayList.class); _collectionFallbacks.put(Set.class.getName(), HashSet.class); _collectionFallbacks.put(SortedSet.class.getName(), TreeSet.class); _collectionFallbacks.put(Queue.class.getName(), LinkedList.class); // then JDK 1.6 types: /* 17-May-2013, tatu: [databind#216] Should be fine to use straight Class references EXCEPT * that some god-forsaken platforms (... looking at you, Android) do not * include these. So, use "soft" references... */ _collectionFallbacks.put("java.util.Deque", LinkedList.class); _collectionFallbacks.put("java.util.NavigableSet", TreeSet.class); } /* /********************************************************** /* Config /********************************************************** */ /** * Configuration settings for this factory; immutable instance (just like this * factory), new version created via copy-constructor (fluent-style) */ protected final DeserializerFactoryConfig _factoryConfig; /* /********************************************************** /* Life cycle /********************************************************** */ protected BasicDeserializerFactory(DeserializerFactoryConfig config) { _factoryConfig = config; } /** * Method for getting current {@link DeserializerFactoryConfig}. *

* Note that since instances are immutable, you can NOT change settings * by accessing an instance and calling methods: this will simply create * new instance of config object. */ public DeserializerFactoryConfig getFactoryConfig() { return _factoryConfig; } protected abstract DeserializerFactory withConfig(DeserializerFactoryConfig config); /* /******************************************************** /* Configuration handling: fluent factories /******************************************************** */ /** * Convenience method for creating a new factory instance with additional deserializer * provider. */ @Override public final DeserializerFactory withAdditionalDeserializers(Deserializers additional) { return withConfig(_factoryConfig.withAdditionalDeserializers(additional)); } /** * Convenience method for creating a new factory instance with additional * {@link KeyDeserializers}. */ @Override public final DeserializerFactory withAdditionalKeyDeserializers(KeyDeserializers additional) { return withConfig(_factoryConfig.withAdditionalKeyDeserializers(additional)); } /** * Convenience method for creating a new factory instance with additional * {@link BeanDeserializerModifier}. */ @Override public final DeserializerFactory withDeserializerModifier(BeanDeserializerModifier modifier) { return withConfig(_factoryConfig.withDeserializerModifier(modifier)); } /** * Convenience method for creating a new factory instance with additional * {@link AbstractTypeResolver}. */ @Override public final DeserializerFactory withAbstractTypeResolver(AbstractTypeResolver resolver) { return withConfig(_factoryConfig.withAbstractTypeResolver(resolver)); } /** * Convenience method for creating a new factory instance with additional * {@link ValueInstantiators}. */ @Override public final DeserializerFactory withValueInstantiators(ValueInstantiators instantiators) { return withConfig(_factoryConfig.withValueInstantiators(instantiators)); } /* /********************************************************** /* DeserializerFactory impl (partial): type mappings /********************************************************** */ @Override public JavaType mapAbstractType(DeserializationConfig config, JavaType type) throws JsonMappingException { // first, general mappings while (true) { JavaType next = _mapAbstractType2(config, type); if (next == null) { return type; } // Should not have to worry about cycles; but better verify since they will invariably occur... :-) // (also: guard against invalid resolution to a non-related type) Class prevCls = type.getRawClass(); Class nextCls = next.getRawClass(); if ((prevCls == nextCls) || !prevCls.isAssignableFrom(nextCls)) { throw new IllegalArgumentException("Invalid abstract type resolution from "+type+" to "+next+": latter is not a subtype of former"); } type = next; } } /** * Method that will find abstract type mapping for specified type, doing a single * lookup through registered abstract type resolvers; will not do recursive lookups. */ private JavaType _mapAbstractType2(DeserializationConfig config, JavaType type) throws JsonMappingException { Class currClass = type.getRawClass(); if (_factoryConfig.hasAbstractTypeResolvers()) { for (AbstractTypeResolver resolver : _factoryConfig.abstractTypeResolvers()) { JavaType concrete = resolver.findTypeMapping(config, type); if (ClassUtil.rawClass(concrete) != currClass) { return concrete; } } } return null; } /* /********************************************************** /* JsonDeserializerFactory impl (partial): ValueInstantiators /********************************************************** */ /** * Value instantiator is created both based on creator annotations, * and on optional externally provided instantiators (registered through * module interface). */ @Override public ValueInstantiator findValueInstantiator(DeserializationContext ctxt, BeanDescription beanDesc) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); ValueInstantiator instantiator = null; // Check @JsonValueInstantiator before anything else AnnotatedClass ac = beanDesc.getClassInfo(); Object instDef = ctxt.getAnnotationIntrospector().findValueInstantiator(ac); if (instDef != null) { instantiator = _valueInstantiatorInstance(config, ac, instDef); } if (instantiator == null) { // Second: see if some of standard Jackson/JDK types might provide value // instantiators. instantiator = _findStdValueInstantiator(config, beanDesc); if (instantiator == null) { instantiator = _constructDefaultValueInstantiator(ctxt, beanDesc); } } // finally: anyone want to modify ValueInstantiator? if (_factoryConfig.hasValueInstantiators()) { for (ValueInstantiators insts : _factoryConfig.valueInstantiators()) { instantiator = insts.findValueInstantiator(config, beanDesc, instantiator); // let's do sanity check; easier to spot buggy handlers if (instantiator == null) { ctxt.reportBadTypeDefinition(beanDesc, "Broken registered ValueInstantiators (of type %s): returned null ValueInstantiator", insts.getClass().getName()); } } } // Sanity check: does the chosen ValueInstantiator have incomplete creators? if (instantiator.getIncompleteParameter() != null) { final AnnotatedParameter nonAnnotatedParam = instantiator.getIncompleteParameter(); final AnnotatedWithParams ctor = nonAnnotatedParam.getOwner(); throw new IllegalArgumentException("Argument #"+nonAnnotatedParam.getIndex()+" of constructor "+ctor+" has no property name annotation; must have name when multiple-parameter constructor annotated as Creator"); } return instantiator; } private ValueInstantiator _findStdValueInstantiator(DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { Class raw = beanDesc.getBeanClass(); if (raw == JsonLocation.class) { return new JsonLocationInstantiator(); } // [databind#1868]: empty List/Set/Map if (Collection.class.isAssignableFrom(raw)) { if (Collections.EMPTY_SET.getClass() == raw) { return new ConstantValueInstantiator(Collections.EMPTY_SET); } if (Collections.EMPTY_LIST.getClass() == raw) { return new ConstantValueInstantiator(Collections.EMPTY_LIST); } } else if (Map.class.isAssignableFrom(raw)) { if (Collections.EMPTY_MAP.getClass() == raw) { return new ConstantValueInstantiator(Collections.EMPTY_MAP); } } return null; } /** * Method that will construct standard default {@link ValueInstantiator} * using annotations (like @JsonCreator) and visibility rules */ protected ValueInstantiator _constructDefaultValueInstantiator(DeserializationContext ctxt, BeanDescription beanDesc) throws JsonMappingException { CreatorCollector creators = new CreatorCollector(beanDesc, ctxt.getConfig()); AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); // need to construct suitable visibility checker: final DeserializationConfig config = ctxt.getConfig(); VisibilityChecker vchecker = config.getDefaultVisibilityChecker(beanDesc.getBeanClass(), beanDesc.getClassInfo()); /* 24-Sep-2014, tatu: Tricky part first; need to merge resolved property information * (which has creator parameters sprinkled around) with actual creator * declarations (which are needed to access creator annotation, amongst other things). * Easiest to combine that info first, then pass it to remaining processing. */ /* 15-Mar-2015, tatu: Alas, this won't help with constructors that only have implicit * names. Those will need to be resolved later on. */ Map creatorDefs = _findCreatorsFromProperties(ctxt, beanDesc); // Important: first add factory methods; then constructors, so // latter can override former! _addDeserializerFactoryMethods(ctxt, beanDesc, vchecker, intr, creators, creatorDefs); // constructors only usable on concrete types: if (beanDesc.getType().isConcrete()) { _addDeserializerConstructors(ctxt, beanDesc, vchecker, intr, creators, creatorDefs); } return creators.constructValueInstantiator(config); } protected Map _findCreatorsFromProperties(DeserializationContext ctxt, BeanDescription beanDesc) throws JsonMappingException { Map result = Collections.emptyMap(); for (BeanPropertyDefinition propDef : beanDesc.findProperties()) { Iterator it = propDef.getConstructorParameters(); while (it.hasNext()) { AnnotatedParameter param = it.next(); AnnotatedWithParams owner = param.getOwner(); BeanPropertyDefinition[] defs = result.get(owner); final int index = param.getIndex(); if (defs == null) { if (result.isEmpty()) { // since emptyMap is immutable need to create a 'real' one result = new LinkedHashMap(); } defs = new BeanPropertyDefinition[owner.getParameterCount()]; result.put(owner, defs); } else { if (defs[index] != null) { ctxt.reportBadTypeDefinition(beanDesc, "Conflict: parameter #%d of %s bound to more than one property; %s vs %s", index, owner, defs[index], propDef); } } defs[index] = propDef; } } return result; } public ValueInstantiator _valueInstantiatorInstance(DeserializationConfig config, Annotated annotated, Object instDef) throws JsonMappingException { if (instDef == null) { return null; } ValueInstantiator inst; if (instDef instanceof ValueInstantiator) { return (ValueInstantiator) instDef; } if (!(instDef instanceof Class)) { throw new IllegalStateException("AnnotationIntrospector returned key deserializer definition of type " +instDef.getClass().getName() +"; expected type KeyDeserializer or Class instead"); } Class instClass = (Class)instDef; if (ClassUtil.isBogusClass(instClass)) { return null; } if (!ValueInstantiator.class.isAssignableFrom(instClass)) { throw new IllegalStateException("AnnotationIntrospector returned Class "+instClass.getName() +"; expected Class"); } HandlerInstantiator hi = config.getHandlerInstantiator(); if (hi != null) { inst = hi.valueInstantiatorInstance(config, annotated, instClass); if (inst != null) { return inst; } } return (ValueInstantiator) ClassUtil.createInstance(instClass, config.canOverrideAccessModifiers()); } /* /********************************************************** /* Creator introspection /********************************************************** */ protected void _addDeserializerConstructors(DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker vchecker, AnnotationIntrospector intr, CreatorCollector creators, Map creatorParams) throws JsonMappingException { // 25-Jan-2017, tatu: As per [databind#1501], [databind#1502], [databind#1503], best // for now to skip attempts at using anything but no-args constructor (see // `InnerClassProperty` construction for that) final boolean isNonStaticInnerClass = beanDesc.isNonStaticInnerClass(); if (isNonStaticInnerClass) { // TODO: look for `@JsonCreator` annotated ones, throw explicit exception? return; } // First things first: the "default constructor" (zero-arg // constructor; whether implicit or explicit) is NOT included // in list of constructors, so needs to be handled separately. AnnotatedConstructor defaultCtor = beanDesc.findDefaultConstructor(); if (defaultCtor != null) { if (!creators.hasDefaultCreator() || _hasCreatorAnnotation(ctxt, defaultCtor)) { creators.setDefaultCreator(defaultCtor); } } // 21-Sep-2017, tatu: First let's handle explicitly annotated ones List nonAnnotated = new LinkedList<>(); int explCount = 0; for (AnnotatedConstructor ctor : beanDesc.getConstructors()) { JsonCreator.Mode creatorMode = intr.findCreatorAnnotation(ctxt.getConfig(), ctor); if (Mode.DISABLED == creatorMode) { continue; } if (creatorMode == null) { // let's check Visibility here, to avoid further processing for non-visible? if (vchecker.isCreatorVisible(ctor)) { nonAnnotated.add(CreatorCandidate.construct(intr, ctor, creatorParams.get(ctor))); } continue; } switch (creatorMode) { case DELEGATING: _addExplicitDelegatingCreator(ctxt, beanDesc, creators, CreatorCandidate.construct(intr, ctor, null)); break; case PROPERTIES: _addExplicitPropertyCreator(ctxt, beanDesc, creators, CreatorCandidate.construct(intr, ctor, creatorParams.get(ctor))); break; default: _addExplicitAnyCreator(ctxt, beanDesc, creators, CreatorCandidate.construct(intr, ctor, creatorParams.get(ctor))); break; } ++explCount; } // And only if and when those handled, consider potentially visible ones if (explCount > 0) { // TODO: split method into two since we could have expl factories return; } List implicitCtors = null; for (CreatorCandidate candidate : nonAnnotated) { final int argCount = candidate.paramCount(); final AnnotatedWithParams ctor = candidate.creator(); // some single-arg factory methods (String, number) are auto-detected if (argCount == 1) { BeanPropertyDefinition propDef = candidate.propertyDef(0); boolean useProps = _checkIfCreatorPropertyBased(intr, ctor, propDef); if (useProps) { SettableBeanProperty[] properties = new SettableBeanProperty[1]; PropertyName name = candidate.paramName(0); properties[0] = constructCreatorProperty(ctxt, beanDesc, name, 0, candidate.parameter(0), candidate.injection(0)); creators.addPropertyCreator(ctor, false, properties); } else { /*boolean added = */ _handleSingleArgumentCreator(creators, ctor, false, vchecker.isCreatorVisible(ctor)); // one more thing: sever link to creator property, to avoid possible later // problems with "unresolved" constructor property if (propDef != null) { ((POJOPropertyBuilder) propDef).removeConstructors(); } } // regardless, fully handled continue; } // 2 or more args; all params must have names or be injectable // 14-Mar-2015, tatu (2.6): Or, as per [#725], implicit names will also // do, with some constraints. But that will require bit post processing... int nonAnnotatedParamIndex = -1; SettableBeanProperty[] properties = new SettableBeanProperty[argCount]; int explicitNameCount = 0; int implicitWithCreatorCount = 0; int injectCount = 0; for (int i = 0; i < argCount; ++i) { final AnnotatedParameter param = ctor.getParameter(i); BeanPropertyDefinition propDef = candidate.propertyDef(i); JacksonInject.Value injectId = intr.findInjectableValue(param); final PropertyName name = (propDef == null) ? null : propDef.getFullName(); if (propDef != null && propDef.isExplicitlyNamed()) { ++explicitNameCount; properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId); continue; } if (injectId != null) { ++injectCount; properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId); continue; } NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param); if (unwrapper != null) { _reportUnwrappedCreatorProperty(ctxt, beanDesc, param); /* properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null); ++explicitNameCount; */ continue; } // One more thing: implicit names are ok iff ctor has creator annotation /* if (isCreator && (name != null && !name.isEmpty())) { ++implicitWithCreatorCount; properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId); continue; } */ if (nonAnnotatedParamIndex < 0) { nonAnnotatedParamIndex = i; } } final int namedCount = explicitNameCount + implicitWithCreatorCount; // Ok: if named or injectable, we have more work to do if ((explicitNameCount > 0) || (injectCount > 0)) { // simple case; everything covered: if ((namedCount + injectCount) == argCount) { creators.addPropertyCreator(ctor, false, properties); continue; } if ((explicitNameCount == 0) && ((injectCount + 1) == argCount)) { // Secondary: all but one injectable, one un-annotated (un-named) creators.addDelegatingCreator(ctor, false, properties, 0); continue; } // otherwise, epic fail? // 16-Mar-2015, tatu: due to [#725], need to be more permissive. For now let's // only report problem if there's no implicit name PropertyName impl = candidate.findImplicitParamName(nonAnnotatedParamIndex); if (impl == null || impl.isEmpty()) { // Let's consider non-static inner class as a special case... // 25-Jan-2017, tatu: Non-static inner classes skipped altogether, now /* if ((nonAnnotatedParamIndex == 0) && isNonStaticInnerClass) { throw new IllegalArgumentException("Non-static inner classes like " +ctor.getDeclaringClass().getName()+" cannot use @JsonCreator for constructors"); } */ ctxt.reportBadTypeDefinition(beanDesc, "Argument #%d of constructor %s has no property name annotation; must have name when multiple-parameter constructor annotated as Creator", nonAnnotatedParamIndex, ctor); } } // [#725]: as a fallback, all-implicit names may work as well if (!creators.hasDefaultCreator()) { if (implicitCtors == null) { implicitCtors = new LinkedList<>(); } implicitCtors.add(ctor); } } // last option, as per [#725]: consider implicit-names-only, visible constructor, // if just one found if ((implicitCtors != null) && !creators.hasDelegatingCreator() && !creators.hasPropertyBasedCreator()) { _checkImplicitlyNamedConstructors(ctxt, beanDesc, vchecker, intr, creators, implicitCtors); } } /** * Helper method called when there is the explicit "is-creator" with mode of "delegating" * * @since 2.9.2 */ protected void _addExplicitDelegatingCreator(DeserializationContext ctxt, BeanDescription beanDesc, CreatorCollector creators, CreatorCandidate candidate) throws JsonMappingException { // Somewhat simple: find injectable values, if any, ensure there is one // and just one delegated argument; report violations if any int ix = -1; final int argCount = candidate.paramCount(); SettableBeanProperty[] properties = new SettableBeanProperty[argCount]; for (int i = 0; i < argCount; ++i) { AnnotatedParameter param = candidate.parameter(i); JacksonInject.Value injectId = candidate.injection(i); if (injectId != null) { properties[i] = constructCreatorProperty(ctxt, beanDesc, null, i, param, injectId); continue; } if (ix < 0) { ix = i; continue; } // Illegal to have more than one value to delegate to ctxt.reportBadTypeDefinition(beanDesc, "More than one argument (#%d and #%d) left as delegating for Creator %s: only one allowed", ix, i, candidate); } // Also, let's require that one Delegating argument does eixt if (ix < 0) { ctxt.reportBadTypeDefinition(beanDesc, "No argument left as delegating for Creator %s: exactly one required", candidate); } // 17-Jan-2018, tatu: as per [databind#1853] need to ensure we will distinguish // "well-known" single-arg variants (String, int/long, boolean) from "generic" delegating... if (argCount == 1) { _handleSingleArgumentCreator(creators, candidate.creator(), true, true); // one more thing: sever link to creator property, to avoid possible later // problems with "unresolved" constructor property BeanPropertyDefinition paramDef = candidate.propertyDef(0); if (paramDef != null) { ((POJOPropertyBuilder) paramDef).removeConstructors(); } return; } creators.addDelegatingCreator(candidate.creator(), true, properties, ix); } /** * Helper method called when there is the explicit "is-creator" with mode of "properties-based" * * @since 2.9.2 */ protected void _addExplicitPropertyCreator(DeserializationContext ctxt, BeanDescription beanDesc, CreatorCollector creators, CreatorCandidate candidate) throws JsonMappingException { final int paramCount = candidate.paramCount(); SettableBeanProperty[] properties = new SettableBeanProperty[paramCount]; for (int i = 0; i < paramCount; ++i) { JacksonInject.Value injectId = candidate.injection(i); AnnotatedParameter param = candidate.parameter(i); PropertyName name = candidate.paramName(i); if (name == null) { // 21-Sep-2017, tatu: Looks like we want to block accidental use of Unwrapped, // as that will not work with Creators well at all NameTransformer unwrapper = ctxt.getAnnotationIntrospector().findUnwrappingNameTransformer(param); if (unwrapper != null) { _reportUnwrappedCreatorProperty(ctxt, beanDesc, param); /* properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null); ++explicitNameCount; */ } name = candidate.findImplicitParamName(i); // Must be injectable or have name; without either won't work if ((name == null) && (injectId == null)) { ctxt.reportBadTypeDefinition(beanDesc, "Argument #%d has no property name, is not Injectable: can not use as Creator %s", i, candidate); } } properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId); } creators.addPropertyCreator(candidate.creator(), true, properties); } /** * Helper method called when there is the explicit "is-creator", but no mode declaration. * * @since 2.9.2 */ protected void _addExplicitAnyCreator(DeserializationContext ctxt, BeanDescription beanDesc, CreatorCollector creators, CreatorCandidate candidate) throws JsonMappingException { // Looks like there's bit of magic regarding 1-parameter creators; others simpler: if (1 != candidate.paramCount()) { // Ok: for delegates, we want one and exactly one parameter without // injection AND without name int oneNotInjected = candidate.findOnlyParamWithoutInjection(); if (oneNotInjected >= 0) { // getting close; but most not have name if (candidate.paramName(oneNotInjected) == null) { _addExplicitDelegatingCreator(ctxt, beanDesc, creators, candidate); return; } } _addExplicitPropertyCreator(ctxt, beanDesc, creators, candidate); return; } AnnotatedParameter param = candidate.parameter(0); JacksonInject.Value injectId = candidate.injection(0); PropertyName paramName = candidate.explicitParamName(0); BeanPropertyDefinition paramDef = candidate.propertyDef(0); // If there's injection or explicit name, should be properties-based boolean useProps = (paramName != null) || (injectId != null); if (!useProps && (paramDef != null)) { // One more thing: if implicit name matches property with a getter // or field, we'll consider it property-based as well paramName = candidate.findImplicitParamName(0); useProps = (paramName != null) && paramDef.couldSerialize(); } if (useProps) { SettableBeanProperty[] properties = new SettableBeanProperty[] { constructCreatorProperty(ctxt, beanDesc, paramName, 0, param, injectId) }; creators.addPropertyCreator(candidate.creator(), true, properties); return; } _handleSingleArgumentCreator(creators, candidate.creator(), true, true); // one more thing: sever link to creator property, to avoid possible later // problems with "unresolved" constructor property if (paramDef != null) { ((POJOPropertyBuilder) paramDef).removeConstructors(); } } private boolean _checkIfCreatorPropertyBased(AnnotationIntrospector intr, AnnotatedWithParams creator, BeanPropertyDefinition propDef) { // If explicit name, or inject id, property-based if (((propDef != null) && propDef.isExplicitlyNamed()) || (intr.findInjectableValue(creator.getParameter(0)) != null)) { return true; } if (propDef != null) { // One more thing: if implicit name matches property with a getter // or field, we'll consider it property-based as well String implName = propDef.getName(); if (implName != null && !implName.isEmpty()) { if (propDef.couldSerialize()) { return true; } } } // in absence of everything else, default to delegating return false; } private void _checkImplicitlyNamedConstructors(DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker vchecker, AnnotationIntrospector intr, CreatorCollector creators, List implicitCtors) throws JsonMappingException { AnnotatedWithParams found = null; SettableBeanProperty[] foundProps = null; // Further checks: (a) must have names for all parameters, (b) only one visible // Also, since earlier matching of properties and creators relied on existence of // `@JsonCreator` (or equivalent) annotation, we need to do bit more re-inspection... main_loop: for (AnnotatedWithParams ctor : implicitCtors) { if (!vchecker.isCreatorVisible(ctor)) { continue; } // as per earlier notes, only end up here if no properties associated with creator final int argCount = ctor.getParameterCount(); SettableBeanProperty[] properties = new SettableBeanProperty[argCount]; for (int i = 0; i < argCount; ++i) { final AnnotatedParameter param = ctor.getParameter(i); final PropertyName name = _findParamName(param, intr); // must have name (implicit fine) if (name == null || name.isEmpty()) { continue main_loop; } properties[i] = constructCreatorProperty(ctxt, beanDesc, name, param.getIndex(), param, /*injectId*/ null); } if (found != null) { // only one allowed; but multiple not an error found = null; break; } found = ctor; foundProps = properties; } // found one and only one visible? Ship it! if (found != null) { creators.addPropertyCreator(found, /*isCreator*/ false, foundProps); BasicBeanDescription bbd = (BasicBeanDescription) beanDesc; // Also: add properties, to keep error messages complete wrt known properties... for (SettableBeanProperty prop : foundProps) { PropertyName pn = prop.getFullName(); if (!bbd.hasProperty(pn)) { BeanPropertyDefinition newDef = SimpleBeanPropertyDefinition.construct( ctxt.getConfig(), prop.getMember(), pn); bbd.addProperty(newDef); } } } } protected void _addDeserializerFactoryMethods (DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker vchecker, AnnotationIntrospector intr, CreatorCollector creators, Map creatorParams) throws JsonMappingException { List nonAnnotated = new LinkedList<>(); int explCount = 0; // 21-Sep-2017, tatu: First let's handle explicitly annotated ones for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) { JsonCreator.Mode creatorMode = intr.findCreatorAnnotation(ctxt.getConfig(), factory); final int argCount = factory.getParameterCount(); if (creatorMode == null) { // Only potentially accept 1-argument factory methods if ((argCount == 1) && vchecker.isCreatorVisible(factory)) { nonAnnotated.add(CreatorCandidate.construct(intr, factory, null)); } continue; } if (creatorMode == Mode.DISABLED) { continue; } // zero-arg method factory methods fine, as long as explicit if (argCount == 0) { creators.setDefaultCreator(factory); continue; } switch (creatorMode) { case DELEGATING: _addExplicitDelegatingCreator(ctxt, beanDesc, creators, CreatorCandidate.construct(intr, factory, null)); break; case PROPERTIES: _addExplicitPropertyCreator(ctxt, beanDesc, creators, CreatorCandidate.construct(intr, factory, creatorParams.get(factory))); break; case DEFAULT: default: _addExplicitAnyCreator(ctxt, beanDesc, creators, CreatorCandidate.construct(intr, factory, creatorParams.get(factory))); break; } ++explCount; } // And only if and when those handled, consider potentially visible ones if (explCount > 0) { // TODO: split method into two since we could have expl factories return; } // And then implicitly found for (CreatorCandidate candidate : nonAnnotated) { final int argCount = candidate.paramCount(); AnnotatedWithParams factory = candidate.creator(); final BeanPropertyDefinition[] propDefs = creatorParams.get(factory); // some single-arg factory methods (String, number) are auto-detected if (argCount != 1) { continue; // 2 and more args? Must be explicit, handled earlier } BeanPropertyDefinition argDef = candidate.propertyDef(0); boolean useProps = _checkIfCreatorPropertyBased(intr, factory, argDef); if (!useProps) { // not property based but delegating /*boolean added=*/ _handleSingleArgumentCreator(creators, factory, false, vchecker.isCreatorVisible(factory)); // 23-Sep-2016, tatu: [databind#1383]: Need to also sever link to avoid possible // later problems with "unresolved" constructor property if (argDef != null) { ((POJOPropertyBuilder) argDef).removeConstructors(); } continue; } AnnotatedParameter nonAnnotatedParam = null; SettableBeanProperty[] properties = new SettableBeanProperty[argCount]; int implicitNameCount = 0; int explicitNameCount = 0; int injectCount = 0; for (int i = 0; i < argCount; ++i) { final AnnotatedParameter param = factory.getParameter(i); BeanPropertyDefinition propDef = (propDefs == null) ? null : propDefs[i]; JacksonInject.Value injectable = intr.findInjectableValue(param); final PropertyName name = (propDef == null) ? null : propDef.getFullName(); if (propDef != null && propDef.isExplicitlyNamed()) { ++explicitNameCount; properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectable); continue; } if (injectable != null) { ++injectCount; properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectable); continue; } NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param); if (unwrapper != null) { _reportUnwrappedCreatorProperty(ctxt, beanDesc, param); /* properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null); ++implicitNameCount; */ continue; } // One more thing: implicit names are ok iff ctor has creator annotation /* if (isCreator) { if (name != null && !name.isEmpty()) { ++implicitNameCount; properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectable); continue; } } */ /* 25-Sep-2014, tatu: Actually, we may end up "losing" naming due to higher-priority constructor * (see TestCreators#testConstructorCreator() test). And just to avoid running into that problem, * let's add one more work around */ /* PropertyName name2 = _findExplicitParamName(param, intr); if (name2 != null && !name2.isEmpty()) { // Hmmh. Ok, fine. So what are we to do with it... ? // For now... skip. May need to revisit this, should this become problematic continue main_loop; } */ if (nonAnnotatedParam == null) { nonAnnotatedParam = param; } } final int namedCount = explicitNameCount + implicitNameCount; // Ok: if named or injectable, we have more work to do if (explicitNameCount > 0 || injectCount > 0) { // simple case; everything covered: if ((namedCount + injectCount) == argCount) { creators.addPropertyCreator(factory, false, properties); } else if ((explicitNameCount == 0) && ((injectCount + 1) == argCount)) { // secondary: all but one injectable, one un-annotated (un-named) creators.addDelegatingCreator(factory, false, properties, 0); } else { // otherwise, epic fail ctxt.reportBadTypeDefinition(beanDesc, "Argument #%d of factory method %s has no property name annotation; must have name when multiple-parameter constructor annotated as Creator", nonAnnotatedParam.getIndex(), factory); } } } } protected boolean _handleSingleArgumentCreator(CreatorCollector creators, AnnotatedWithParams ctor, boolean isCreator, boolean isVisible) { // otherwise either 'simple' number, String, or general delegate: Class type = ctor.getRawParameterType(0); if (type == String.class || type == CLASS_CHAR_SEQUENCE) { if (isCreator || isVisible) { creators.addStringCreator(ctor, isCreator); } return true; } if (type == int.class || type == Integer.class) { if (isCreator || isVisible) { creators.addIntCreator(ctor, isCreator); } return true; } if (type == long.class || type == Long.class) { if (isCreator || isVisible) { creators.addLongCreator(ctor, isCreator); } return true; } if (type == double.class || type == Double.class) { if (isCreator || isVisible) { creators.addDoubleCreator(ctor, isCreator); } return true; } if (type == boolean.class || type == Boolean.class) { if (isCreator || isVisible) { creators.addBooleanCreator(ctor, isCreator); } return true; } // Delegating Creator ok iff it has @JsonCreator (etc) if (isCreator) { creators.addDelegatingCreator(ctor, isCreator, null, 0); return true; } return false; } // 01-Dec-2016, tatu: As per [databind#265] we cannot yet support passing // of unwrapped values through creator properties, so fail fast protected void _reportUnwrappedCreatorProperty(DeserializationContext ctxt, BeanDescription beanDesc, AnnotatedParameter param) throws JsonMappingException { ctxt.reportBadDefinition(beanDesc.getType(), String.format( "Cannot define Creator parameter %d as `@JsonUnwrapped`: combination not yet supported", param.getIndex())); } /** * Method that will construct a property object that represents * a logical property passed via Creator (constructor or static * factory method) */ protected SettableBeanProperty constructCreatorProperty(DeserializationContext ctxt, BeanDescription beanDesc, PropertyName name, int index, AnnotatedParameter param, JacksonInject.Value injectable) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); PropertyMetadata metadata; { if (intr == null) { metadata = PropertyMetadata.STD_REQUIRED_OR_OPTIONAL; } else { Boolean b = intr.hasRequiredMarker(param); String desc = intr.findPropertyDescription(param); Integer idx = intr.findPropertyIndex(param); String def = intr.findPropertyDefaultValue(param); metadata = PropertyMetadata.construct(b, desc, idx, def); } } JavaType type = resolveMemberAndTypeAnnotations(ctxt, param, param.getType()); BeanProperty.Std property = new BeanProperty.Std(name, type, intr.findWrapperName(param), param, metadata); // Type deserializer: either comes from property (and already resolved) TypeDeserializer typeDeser = (TypeDeserializer) type.getTypeHandler(); // or if not, based on type being referenced: if (typeDeser == null) { typeDeser = findTypeDeserializer(config, type); } // Note: contextualization of typeDeser _should_ occur in constructor of CreatorProperty // so it is not called directly here Object injectableValueId = (injectable == null) ? null : injectable.getId(); SettableBeanProperty prop = new CreatorProperty(name, type, property.getWrapperName(), typeDeser, beanDesc.getClassAnnotations(), param, index, injectableValueId, metadata); JsonDeserializer deser = findDeserializerFromAnnotation(ctxt, param); if (deser == null) { deser = type.getValueHandler(); } if (deser != null) { // As per [databind#462] need to ensure we contextualize deserializer before passing it on deser = ctxt.handlePrimaryContextualization(deser, prop, type); prop = prop.withValueDeserializer(deser); } return prop; } private PropertyName _findParamName(AnnotatedParameter param, AnnotationIntrospector intr) { if (param != null && intr != null) { PropertyName name = intr.findNameForDeserialization(param); if (name != null) { return name; } // 14-Apr-2014, tatu: Need to also consider possible implicit name // (for JDK8, or via paranamer) String str = intr.findImplicitPropertyName(param); if (str != null && !str.isEmpty()) { return PropertyName.construct(str); } } return null; } /* /********************************************************** /* JsonDeserializerFactory impl: array deserializers /********************************************************** */ @Override public JsonDeserializer createArrayDeserializer(DeserializationContext ctxt, ArrayType type, final BeanDescription beanDesc) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); JavaType elemType = type.getContentType(); // Very first thing: is deserializer hard-coded for elements? JsonDeserializer contentDeser = elemType.getValueHandler(); // Then optional type info: if type has been resolved, we may already know type deserializer: TypeDeserializer elemTypeDeser = elemType.getTypeHandler(); // but if not, may still be possible to find: if (elemTypeDeser == null) { elemTypeDeser = findTypeDeserializer(config, elemType); } // 23-Nov-2010, tatu: Custom array deserializer? JsonDeserializer deser = _findCustomArrayDeserializer(type, config, beanDesc, elemTypeDeser, contentDeser); if (deser == null) { if (contentDeser == null) { Class raw = elemType.getRawClass(); if (elemType.isPrimitive()) { return PrimitiveArrayDeserializers.forType(raw); } if (raw == String.class) { return StringArrayDeserializer.instance; } } deser = new ObjectArrayDeserializer(type, contentDeser, elemTypeDeser); } // and then new with 2.2: ability to post-process it too (Issue#120) if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deser = mod.modifyArrayDeserializer(config, type, beanDesc, deser); } } return deser; } /* /********************************************************** /* JsonDeserializerFactory impl: Collection(-like) deserializers /********************************************************** */ @Override public JsonDeserializer createCollectionDeserializer(DeserializationContext ctxt, CollectionType type, BeanDescription beanDesc) throws JsonMappingException { JavaType contentType = type.getContentType(); // Very first thing: is deserializer hard-coded for elements? JsonDeserializer contentDeser = contentType.getValueHandler(); final DeserializationConfig config = ctxt.getConfig(); // Then optional type info: if type has been resolved, we may already know type deserializer: TypeDeserializer contentTypeDeser = contentType.getTypeHandler(); // but if not, may still be possible to find: if (contentTypeDeser == null) { contentTypeDeser = findTypeDeserializer(config, contentType); } // 23-Nov-2010, tatu: Custom deserializer? JsonDeserializer deser = _findCustomCollectionDeserializer(type, config, beanDesc, contentTypeDeser, contentDeser); if (deser == null) { Class collectionClass = type.getRawClass(); if (contentDeser == null) { // not defined by annotation // One special type: EnumSet: if (EnumSet.class.isAssignableFrom(collectionClass)) { deser = new EnumSetDeserializer(contentType, null); } } } /* One twist: if we are being asked to instantiate an interface or * abstract Collection, we need to either find something that implements * the thing, or give up. * * Note that we do NOT try to guess based on secondary interfaces * here; that would probably not work correctly since casts would * fail later on (as the primary type is not the interface we'd * be implementing) */ if (deser == null) { if (type.isInterface() || type.isAbstract()) { CollectionType implType = _mapAbstractCollectionType(type, config); if (implType == null) { // [databind#292]: Actually, may be fine, but only if polymorphich deser enabled if (type.getTypeHandler() == null) { throw new IllegalArgumentException("Cannot find a deserializer for non-concrete Collection type "+type); } deser = AbstractDeserializer.constructForNonPOJO(beanDesc); } else { type = implType; // But if so, also need to re-check creators... beanDesc = config.introspectForCreation(type); } } if (deser == null) { ValueInstantiator inst = findValueInstantiator(ctxt, beanDesc); if (!inst.canCreateUsingDefault()) { // [databind#161]: No default constructor for ArrayBlockingQueue... if (type.hasRawClass(ArrayBlockingQueue.class)) { return new ArrayBlockingQueueDeserializer(type, contentDeser, contentTypeDeser, inst); } // 10-Jan-2017, tatu: `java.util.Collections` types need help: deser = JavaUtilCollectionsDeserializers.findForCollection(ctxt, type); if (deser != null) { return deser; } } // Can use more optimal deserializer if content type is String, so: if (contentType.hasRawClass(String.class)) { // no value type deserializer because Strings are one of natural/native types: deser = new StringCollectionDeserializer(type, contentDeser, inst); } else { deser = new CollectionDeserializer(type, contentDeser, contentTypeDeser, inst); } } } // allow post-processing it too if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deser = mod.modifyCollectionDeserializer(config, type, beanDesc, deser); } } return deser; } protected CollectionType _mapAbstractCollectionType(JavaType type, DeserializationConfig config) { Class collectionClass = type.getRawClass(); collectionClass = _collectionFallbacks.get(collectionClass.getName()); if (collectionClass == null) { return null; } return (CollectionType) config.constructSpecializedType(type, collectionClass); } // Copied almost verbatim from "createCollectionDeserializer" -- should try to share more code @Override public JsonDeserializer createCollectionLikeDeserializer(DeserializationContext ctxt, CollectionLikeType type, final BeanDescription beanDesc) throws JsonMappingException { JavaType contentType = type.getContentType(); // Very first thing: is deserializer hard-coded for elements? JsonDeserializer contentDeser = contentType.getValueHandler(); final DeserializationConfig config = ctxt.getConfig(); // Then optional type info (1.5): if type has been resolved, we may already know type deserializer: TypeDeserializer contentTypeDeser = contentType.getTypeHandler(); // but if not, may still be possible to find: if (contentTypeDeser == null) { contentTypeDeser = findTypeDeserializer(config, contentType); } JsonDeserializer deser = _findCustomCollectionLikeDeserializer(type, config, beanDesc, contentTypeDeser, contentDeser); if (deser != null) { // and then new with 2.2: ability to post-process it too (Issue#120) if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deser = mod.modifyCollectionLikeDeserializer(config, type, beanDesc, deser); } } } return deser; } /* /********************************************************** /* JsonDeserializerFactory impl: Map(-like) deserializers /********************************************************** */ @Override public JsonDeserializer createMapDeserializer(DeserializationContext ctxt, MapType type, BeanDescription beanDesc) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); JavaType keyType = type.getKeyType(); JavaType contentType = type.getContentType(); // First: is there annotation-specified deserializer for values? @SuppressWarnings("unchecked") JsonDeserializer contentDeser = (JsonDeserializer) contentType.getValueHandler(); // Ok: need a key deserializer (null indicates 'default' here) KeyDeserializer keyDes = (KeyDeserializer) keyType.getValueHandler(); // Then optional type info; either attached to type, or resolved separately: TypeDeserializer contentTypeDeser = contentType.getTypeHandler(); // but if not, may still be possible to find: if (contentTypeDeser == null) { contentTypeDeser = findTypeDeserializer(config, contentType); } // 23-Nov-2010, tatu: Custom deserializer? JsonDeserializer deser = _findCustomMapDeserializer(type, config, beanDesc, keyDes, contentTypeDeser, contentDeser); if (deser == null) { // Value handling is identical for all, but EnumMap requires special handling for keys Class mapClass = type.getRawClass(); if (EnumMap.class.isAssignableFrom(mapClass)) { ValueInstantiator inst; // 06-Mar-2017, tatu: Should only need to check ValueInstantiator for // custom sub-classes, see [databind#1544] if (mapClass == EnumMap.class) { inst = null; } else { inst = findValueInstantiator(ctxt, beanDesc); } Class kt = keyType.getRawClass(); if (kt == null || !kt.isEnum()) { throw new IllegalArgumentException("Cannot construct EnumMap; generic (key) type not available"); } deser = new EnumMapDeserializer(type, inst, null, contentDeser, contentTypeDeser, null); } // Otherwise, generic handler works ok. /* But there is one more twist: if we are being asked to instantiate * an interface or abstract Map, we need to either find something * that implements the thing, or give up. * * Note that we do NOT try to guess based on secondary interfaces * here; that would probably not work correctly since casts would * fail later on (as the primary type is not the interface we'd * be implementing) */ if (deser == null) { if (type.isInterface() || type.isAbstract()) { @SuppressWarnings("rawtypes") Class fallback = _mapFallbacks.get(mapClass.getName()); if (fallback != null) { mapClass = fallback; type = (MapType) config.constructSpecializedType(type, mapClass); // But if so, also need to re-check creators... beanDesc = config.introspectForCreation(type); } else { // [databind#292]: Actually, may be fine, but only if polymorphic deser enabled if (type.getTypeHandler() == null) { throw new IllegalArgumentException("Cannot find a deserializer for non-concrete Map type "+type); } deser = AbstractDeserializer.constructForNonPOJO(beanDesc); } } else { // 10-Jan-2017, tatu: `java.util.Collections` types need help: deser = JavaUtilCollectionsDeserializers.findForMap(ctxt, type); if (deser != null) { return deser; } } if (deser == null) { ValueInstantiator inst = findValueInstantiator(ctxt, beanDesc); // 01-May-2016, tatu: Which base type to use here gets tricky, since // most often it ought to be `Map` or `EnumMap`, but due to abstract // mapping it will more likely be concrete type like `HashMap`. // So, for time being, just pass `Map.class` MapDeserializer md = new MapDeserializer(type, inst, keyDes, contentDeser, contentTypeDeser); JsonIgnoreProperties.Value ignorals = config.getDefaultPropertyIgnorals(Map.class, beanDesc.getClassInfo()); Set ignored = (ignorals == null) ? null : ignorals.findIgnoredForDeserialization(); md.setIgnorableProperties(ignored); deser = md; } } } if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deser = mod.modifyMapDeserializer(config, type, beanDesc, deser); } } return deser; } // Copied almost verbatim from "createMapDeserializer" -- should try to share more code @Override public JsonDeserializer createMapLikeDeserializer(DeserializationContext ctxt, MapLikeType type, final BeanDescription beanDesc) throws JsonMappingException { JavaType keyType = type.getKeyType(); JavaType contentType = type.getContentType(); final DeserializationConfig config = ctxt.getConfig(); // First: is there annotation-specified deserializer for values? @SuppressWarnings("unchecked") JsonDeserializer contentDeser = (JsonDeserializer) contentType.getValueHandler(); // Ok: need a key deserializer (null indicates 'default' here) KeyDeserializer keyDes = (KeyDeserializer) keyType.getValueHandler(); /* !!! 24-Jan-2012, tatu: NOTE: impls MUST use resolve() to find key deserializer! if (keyDes == null) { keyDes = p.findKeyDeserializer(config, keyType, property); } */ // Then optional type info (1.5); either attached to type, or resolve separately: TypeDeserializer contentTypeDeser = contentType.getTypeHandler(); // but if not, may still be possible to find: if (contentTypeDeser == null) { contentTypeDeser = findTypeDeserializer(config, contentType); } JsonDeserializer deser = _findCustomMapLikeDeserializer(type, config, beanDesc, keyDes, contentTypeDeser, contentDeser); if (deser != null) { // and then new with 2.2: ability to post-process it too (Issue#120) if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deser = mod.modifyMapLikeDeserializer(config, type, beanDesc, deser); } } } return deser; } /* /********************************************************** /* JsonDeserializerFactory impl: other types /********************************************************** */ /** * Factory method for constructing serializers of {@link Enum} types. */ @Override public JsonDeserializer createEnumDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); final Class enumClass = type.getRawClass(); // 23-Nov-2010, tatu: Custom deserializer? JsonDeserializer deser = _findCustomEnumDeserializer(enumClass, config, beanDesc); if (deser == null) { ValueInstantiator valueInstantiator = _constructDefaultValueInstantiator(ctxt, beanDesc); SettableBeanProperty[] creatorProps = (valueInstantiator == null) ? null : valueInstantiator.getFromObjectArguments(ctxt.getConfig()); // May have @JsonCreator for static factory method: for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) { if (_hasCreatorAnnotation(ctxt, factory)) { if (factory.getParameterCount() == 0) { // [databind#960] deser = EnumDeserializer.deserializerForNoArgsCreator(config, enumClass, factory); break; } Class returnType = factory.getRawReturnType(); // usually should be class, but may be just plain Enum (for Enum.valueOf()?) if (returnType.isAssignableFrom(enumClass)) { deser = EnumDeserializer.deserializerForCreator(config, enumClass, factory, valueInstantiator, creatorProps); break; } } } // Need to consider @JsonValue if one found if (deser == null) { deser = new EnumDeserializer(constructEnumResolver(enumClass, config, beanDesc.findJsonValueAccessor()), config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)); } } // and then post-process it too if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deser = mod.modifyEnumDeserializer(config, type, beanDesc, deser); } } return deser; } @Override public JsonDeserializer createTreeDeserializer(DeserializationConfig config, JavaType nodeType, BeanDescription beanDesc) throws JsonMappingException { @SuppressWarnings("unchecked") Class nodeClass = (Class) nodeType.getRawClass(); // 23-Nov-2010, tatu: Custom deserializer? JsonDeserializer custom = _findCustomTreeNodeDeserializer(nodeClass, config, beanDesc); if (custom != null) { return custom; } return JsonNodeDeserializer.getDeserializer(nodeClass); } @Override public JsonDeserializer createReferenceDeserializer(DeserializationContext ctxt, ReferenceType type, BeanDescription beanDesc) throws JsonMappingException { JavaType contentType = type.getContentType(); // Very first thing: is deserializer hard-coded for elements? JsonDeserializer contentDeser = contentType.getValueHandler(); final DeserializationConfig config = ctxt.getConfig(); // Then optional type info: if type has been resolved, we may already know type deserializer: TypeDeserializer contentTypeDeser = contentType.getTypeHandler(); if (contentTypeDeser == null) { // or if not, may be able to find: contentTypeDeser = findTypeDeserializer(config, contentType); } JsonDeserializer deser = _findCustomReferenceDeserializer(type, config, beanDesc, contentTypeDeser, contentDeser); if (deser == null) { // Just one referential type as of JDK 1.7 / Java 7: AtomicReference (Java 8 adds Optional) if (type.isTypeOrSubTypeOf(AtomicReference.class)) { Class rawType = type.getRawClass(); ValueInstantiator inst; if (rawType == AtomicReference.class) { inst = null; } else { /* 23-Oct-2016, tatu: Note that subtypes are probably not supportable * without either forcing merging (to avoid having to create instance) * or something else... */ inst = findValueInstantiator(ctxt, beanDesc); } return new AtomicReferenceDeserializer(type, inst, contentTypeDeser, contentDeser); } } if (deser != null) { // and then post-process if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deser = mod.modifyReferenceDeserializer(config, type, beanDesc, deser); } } } return deser; } /* /********************************************************** /* JsonDeserializerFactory impl (partial): type deserializers /********************************************************** */ @Override public TypeDeserializer findTypeDeserializer(DeserializationConfig config, JavaType baseType) throws JsonMappingException { BeanDescription bean = config.introspectClassAnnotations(baseType.getRawClass()); AnnotatedClass ac = bean.getClassInfo(); AnnotationIntrospector ai = config.getAnnotationIntrospector(); TypeResolverBuilder b = ai.findTypeResolver(config, ac, baseType); /* Ok: if there is no explicit type info handler, we may want to * use a default. If so, config object knows what to use. */ Collection subtypes = null; if (b == null) { b = config.getDefaultTyper(baseType); if (b == null) { return null; } } else { subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByTypeId(config, ac); } // May need to figure out default implementation, if none found yet // (note: check for abstract type is not 100% mandatory, more of an optimization) if ((b.getDefaultImpl() == null) && baseType.isAbstract()) { JavaType defaultType = mapAbstractType(config, baseType); if ((defaultType != null) && !defaultType.hasRawClass(baseType.getRawClass())) { b = b.defaultImpl(defaultType.getRawClass()); } } return b.buildTypeDeserializer(config, baseType, subtypes); } /** * Overridable method called after checking all other types. * * @since 2.2 */ protected JsonDeserializer findOptionalStdDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { return OptionalHandlerFactory.instance.findDeserializer(type, ctxt.getConfig(), beanDesc); } /* /********************************************************** /* JsonDeserializerFactory impl (partial): key deserializers /********************************************************** */ @Override public KeyDeserializer createKeyDeserializer(DeserializationContext ctxt, JavaType type) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); KeyDeserializer deser = null; if (_factoryConfig.hasKeyDeserializers()) { BeanDescription beanDesc = config.introspectClassAnnotations(type.getRawClass()); for (KeyDeserializers d : _factoryConfig.keyDeserializers()) { deser = d.findKeyDeserializer(type, config, beanDesc); if (deser != null) { break; } } } // the only non-standard thing is this: if (deser == null) { if (type.isEnumType()) { deser = _createEnumKeyDeserializer(ctxt, type); } else { deser = StdKeyDeserializers.findStringBasedKeyDeserializer(config, type); } } // and then post-processing if (deser != null) { if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deser = mod.modifyKeyDeserializer(config, type, deser); } } } return deser; } private KeyDeserializer _createEnumKeyDeserializer(DeserializationContext ctxt, JavaType type) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); Class enumClass = type.getRawClass(); BeanDescription beanDesc = config.introspect(type); // 24-Sep-2015, bim: a key deserializer is the preferred thing. KeyDeserializer des = findKeyDeserializerFromAnnotation(ctxt, beanDesc.getClassInfo()); if (des != null) { return des; } else { // 24-Sep-2015, bim: if no key deser, look for enum deserializer first, then a plain deser. JsonDeserializer custom = _findCustomEnumDeserializer(enumClass, config, beanDesc); if (custom != null) { return StdKeyDeserializers.constructDelegatingKeyDeserializer(config, type, custom); } JsonDeserializer valueDesForKey = findDeserializerFromAnnotation(ctxt, beanDesc.getClassInfo()); if (valueDesForKey != null) { return StdKeyDeserializers.constructDelegatingKeyDeserializer(config, type, valueDesForKey); } } EnumResolver enumRes = constructEnumResolver(enumClass, config, beanDesc.findJsonValueAccessor()); // May have @JsonCreator for static factory method: for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) { if (_hasCreatorAnnotation(ctxt, factory)) { int argCount = factory.getParameterCount(); if (argCount == 1) { Class returnType = factory.getRawReturnType(); // usually should be class, but may be just plain Enum (for Enum.valueOf()?) if (returnType.isAssignableFrom(enumClass)) { // note: mostly copied from 'EnumDeserializer.deserializerForCreator(...)' if (factory.getRawParameterType(0) != String.class) { throw new IllegalArgumentException("Parameter #0 type for factory method ("+factory+") not suitable, must be java.lang.String"); } if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(factory.getMember(), ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes, factory); } } throw new IllegalArgumentException("Unsuitable method ("+factory+") decorated with @JsonCreator (for Enum type " +enumClass.getName()+")"); } } // Also, need to consider @JsonValue, if one found return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes); } /* /********************************************************** /* Extended API /********************************************************** */ /** * Method called to create a type information deserializer for values of * given non-container property, if one is needed. * If not needed (no polymorphic handling configured for property), should return null. *

* Note that this method is only called for non-container bean properties, * and not for values in container types or root values (or container properties) * * @param baseType Declared base type of the value to deserializer (actual * deserializer type will be this type or its subtype) * * @return Type deserializer to use for given base type, if one is needed; null if not. */ public TypeDeserializer findPropertyTypeDeserializer(DeserializationConfig config, JavaType baseType, AnnotatedMember annotated) throws JsonMappingException { AnnotationIntrospector ai = config.getAnnotationIntrospector(); TypeResolverBuilder b = ai.findPropertyTypeResolver(config, annotated, baseType); // Defaulting: if no annotations on member, check value class if (b == null) { return findTypeDeserializer(config, baseType); } // but if annotations found, may need to resolve subtypes: Collection subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByTypeId( config, annotated, baseType); return b.buildTypeDeserializer(config, baseType, subtypes); } /** * Method called to find and create a type information deserializer for values of * given container (list, array, map) property, if one is needed. * If not needed (no polymorphic handling configured for property), should return null. *

* Note that this method is only called for container bean properties, * and not for values in container types or root values (or non-container properties) * * @param containerType Type of property; must be a container type * @param propertyEntity Field or method that contains container property */ public TypeDeserializer findPropertyContentTypeDeserializer(DeserializationConfig config, JavaType containerType, AnnotatedMember propertyEntity) throws JsonMappingException { AnnotationIntrospector ai = config.getAnnotationIntrospector(); TypeResolverBuilder b = ai.findPropertyContentTypeResolver(config, propertyEntity, containerType); JavaType contentType = containerType.getContentType(); // Defaulting: if no annotations on member, check class if (b == null) { return findTypeDeserializer(config, contentType); } // but if annotations found, may need to resolve subtypes: Collection subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByTypeId( config, propertyEntity, contentType); return b.buildTypeDeserializer(config, contentType, subtypes); } /** * Helper method called to find one of default serializers for "well-known" * platform types: JDK-provided types, and small number of public Jackson * API types. * * @since 2.2 */ public JsonDeserializer findDefaultDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { Class rawType = type.getRawClass(); // Object ("untyped"), String equivalents: if (rawType == CLASS_OBJECT) { // 11-Feb-2015, tatu: As per [databind#700] need to be careful wrt non-default Map, List. DeserializationConfig config = ctxt.getConfig(); JavaType lt, mt; if (_factoryConfig.hasAbstractTypeResolvers()) { lt = _findRemappedType(config, List.class); mt = _findRemappedType(config, Map.class); } else { lt = mt = null; } return new UntypedObjectDeserializer(lt, mt); } if (rawType == CLASS_STRING || rawType == CLASS_CHAR_SEQUENCE) { return StringDeserializer.instance; } if (rawType == CLASS_ITERABLE) { // [databind#199]: Can and should 'upgrade' to a Collection type: TypeFactory tf = ctxt.getTypeFactory(); JavaType[] tps = tf.findTypeParameters(type, CLASS_ITERABLE); JavaType elemType = (tps == null || tps.length != 1) ? TypeFactory.unknownType() : tps[0]; CollectionType ct = tf.constructCollectionType(Collection.class, elemType); // Should we re-introspect beanDesc? For now let's not... return createCollectionDeserializer(ctxt, ct, beanDesc); } if (rawType == CLASS_MAP_ENTRY) { // 28-Apr-2015, tatu: TypeFactory does it all for us already so JavaType kt = type.containedTypeOrUnknown(0); JavaType vt = type.containedTypeOrUnknown(1); TypeDeserializer vts = (TypeDeserializer) vt.getTypeHandler(); if (vts == null) { vts = findTypeDeserializer(ctxt.getConfig(), vt); } JsonDeserializer valueDeser = vt.getValueHandler(); KeyDeserializer keyDes = (KeyDeserializer) kt.getValueHandler(); return new MapEntryDeserializer(type, keyDes, valueDeser, vts); } String clsName = rawType.getName(); if (rawType.isPrimitive() || clsName.startsWith("java.")) { // Primitives/wrappers, other Numbers: JsonDeserializer deser = NumberDeserializers.find(rawType, clsName); if (deser == null) { deser = DateDeserializers.find(rawType, clsName); } if (deser != null) { return deser; } } // and a few Jackson types as well: if (rawType == TokenBuffer.class) { return new TokenBufferDeserializer(); } JsonDeserializer deser = findOptionalStdDeserializer(ctxt, type, beanDesc); if (deser != null) { return deser; } return JdkDeserializers.find(rawType, clsName); } protected JavaType _findRemappedType(DeserializationConfig config, Class rawType) throws JsonMappingException { JavaType type = mapAbstractType(config, config.constructType(rawType)); return (type == null || type.hasRawClass(rawType)) ? null : type; } /* /********************************************************** /* Helper methods, finding custom deserializers /********************************************************** */ protected JsonDeserializer _findCustomTreeNodeDeserializer(Class type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { for (Deserializers d : _factoryConfig.deserializers()) { JsonDeserializer deser = d.findTreeNodeDeserializer(type, config, beanDesc); if (deser != null) { return deser; } } return null; } protected JsonDeserializer _findCustomReferenceDeserializer(ReferenceType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer contentTypeDeserializer, JsonDeserializer contentDeserializer) throws JsonMappingException { for (Deserializers d : _factoryConfig.deserializers()) { JsonDeserializer deser = d.findReferenceDeserializer(type, config, beanDesc, contentTypeDeserializer, contentDeserializer); if (deser != null) { return deser; } } return null; } @SuppressWarnings("unchecked") protected JsonDeserializer _findCustomBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { for (Deserializers d : _factoryConfig.deserializers()) { JsonDeserializer deser = d.findBeanDeserializer(type, config, beanDesc); if (deser != null) { return (JsonDeserializer) deser; } } return null; } protected JsonDeserializer _findCustomArrayDeserializer(ArrayType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { for (Deserializers d : _factoryConfig.deserializers()) { JsonDeserializer deser = d.findArrayDeserializer(type, config, beanDesc, elementTypeDeserializer, elementDeserializer); if (deser != null) { return deser; } } return null; } protected JsonDeserializer _findCustomCollectionDeserializer(CollectionType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { for (Deserializers d : _factoryConfig.deserializers()) { JsonDeserializer deser = d.findCollectionDeserializer(type, config, beanDesc, elementTypeDeserializer, elementDeserializer); if (deser != null) { return deser; } } return null; } protected JsonDeserializer _findCustomCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { for (Deserializers d : _factoryConfig.deserializers()) { JsonDeserializer deser = d.findCollectionLikeDeserializer(type, config, beanDesc, elementTypeDeserializer, elementDeserializer); if (deser != null) { return deser; } } return null; } protected JsonDeserializer _findCustomEnumDeserializer(Class type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { for (Deserializers d : _factoryConfig.deserializers()) { JsonDeserializer deser = d.findEnumDeserializer(type, config, beanDesc); if (deser != null) { return deser; } } return null; } protected JsonDeserializer _findCustomMapDeserializer(MapType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { for (Deserializers d : _factoryConfig.deserializers()) { JsonDeserializer deser = d.findMapDeserializer(type, config, beanDesc, keyDeserializer, elementTypeDeserializer, elementDeserializer); if (deser != null) { return deser; } } return null; } protected JsonDeserializer _findCustomMapLikeDeserializer(MapLikeType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { for (Deserializers d : _factoryConfig.deserializers()) { JsonDeserializer deser = d.findMapLikeDeserializer(type, config, beanDesc, keyDeserializer, elementTypeDeserializer, elementDeserializer); if (deser != null) { return deser; } } return null; } /* /********************************************************** /* Helper methods, value/content/key type introspection /********************************************************** */ /** * Helper method called to check if a class or method * has annotation that tells which class to use for deserialization; and if * so, to instantiate, that deserializer to use. * Note that deserializer will NOT yet be contextualized so caller needs to * take care to call contextualization appropriately. * Returns null if no such annotation found. */ protected JsonDeserializer findDeserializerFromAnnotation(DeserializationContext ctxt, Annotated ann) throws JsonMappingException { AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (intr != null) { Object deserDef = intr.findDeserializer(ann); if (deserDef != null) { return ctxt.deserializerInstance(ann, deserDef); } } return null; } /** * Helper method called to check if a class or method * has annotation that tells which class to use for deserialization. * Returns null if no such annotation found. */ protected KeyDeserializer findKeyDeserializerFromAnnotation(DeserializationContext ctxt, Annotated ann) throws JsonMappingException { AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (intr != null) { Object deserDef = intr.findKeyDeserializer(ann); if (deserDef != null) { return ctxt.keyDeserializerInstance(ann, deserDef); } } return null; } /** * @since 2.9 */ protected JsonDeserializer findContentDeserializerFromAnnotation(DeserializationContext ctxt, Annotated ann) throws JsonMappingException { AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (intr != null) { Object deserDef = intr.findContentDeserializer(ann); if (deserDef != null) { return ctxt.deserializerInstance(ann, deserDef); } } return null; } /** * Helper method used to resolve additional type-related annotation information * like type overrides, or handler (serializer, deserializer) overrides, * so that from declared field, property or constructor parameter type * is used as the base and modified based on annotations, if any. * * @since 2.8 Combines functionality of modifyTypeByAnnotation * and resolveType */ protected JavaType resolveMemberAndTypeAnnotations(DeserializationContext ctxt, AnnotatedMember member, JavaType type) throws JsonMappingException { AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (intr == null) { return type; } // First things first: see if we can find annotations on declared // type if (type.isMapLikeType()) { JavaType keyType = type.getKeyType(); if (keyType != null) { Object kdDef = intr.findKeyDeserializer(member); KeyDeserializer kd = ctxt.keyDeserializerInstance(member, kdDef); if (kd != null) { type = ((MapLikeType) type).withKeyValueHandler(kd); keyType = type.getKeyType(); // just in case it's used below } } } if (type.hasContentType()) { // that is, is either container- or reference-type Object cdDef = intr.findContentDeserializer(member); JsonDeserializer cd = ctxt.deserializerInstance(member, cdDef); if (cd != null) { type = type.withContentValueHandler(cd); } TypeDeserializer contentTypeDeser = findPropertyContentTypeDeserializer( ctxt.getConfig(), type, (AnnotatedMember) member); if (contentTypeDeser != null) { type = type.withContentTypeHandler(contentTypeDeser); } } TypeDeserializer valueTypeDeser = findPropertyTypeDeserializer(ctxt.getConfig(), type, (AnnotatedMember) member); if (valueTypeDeser != null) { type = type.withTypeHandler(valueTypeDeser); } // Second part: find actual type-override annotations on member, if any // 18-Jun-2016, tatu: Should we re-do checks for annotations on refined // subtypes as well? Code pre-2.8 did not do this, but if we get bug // reports may need to consider type = intr.refineDeserializationType(ctxt.getConfig(), member, type); return type; } protected EnumResolver constructEnumResolver(Class enumClass, DeserializationConfig config, AnnotatedMember jsonValueAccessor) { if (jsonValueAccessor != null) { if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(jsonValueAccessor.getMember(), config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } return EnumResolver.constructUnsafeUsingMethod(enumClass, jsonValueAccessor, config.getAnnotationIntrospector()); } // 14-Mar-2016, tatu: We used to check `DeserializationFeature.READ_ENUMS_USING_TO_STRING` // here, but that won't do: it must be dynamically changeable... return EnumResolver.constructUnsafe(enumClass, config.getAnnotationIntrospector()); } /** * @since 2.9 */ protected boolean _hasCreatorAnnotation(DeserializationContext ctxt, Annotated ann) { AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (intr != null) { JsonCreator.Mode mode = intr.findCreatorAnnotation(ctxt.getConfig(), ann); return (mode != null) && (mode != JsonCreator.Mode.DISABLED); } return false; } /* /********************************************************** /* Deprecated helper methods /********************************************************** */ /** * Method called to see if given method has annotations that indicate * a more specific type than what the argument specifies. * * @deprecated Since 2.8; call {@link #resolveMemberAndTypeAnnotations} instead */ @Deprecated protected JavaType modifyTypeByAnnotation(DeserializationContext ctxt, Annotated a, JavaType type) throws JsonMappingException { AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (intr == null) { return type; } // First, deserializers for key/value types? /* if (type.isMapLikeType()) { JavaType keyType = type.getKeyType(); // 21-Mar-2011, tatu: ... and associated deserializer too (unless already assigned) // (not 100% why or how, but this does seem to get called more than once, which // is not good: for now, let's just avoid errors) if (keyType != null && keyType.getValueHandler() == null) { Object kdDef = intr.findKeyDeserializer(a); KeyDeserializer kd = ctxt.keyDeserializerInstance(a, kdDef); if (kd != null) { type = (T) ((MapLikeType) type).withKeyValueHandler(kd); keyType = type.getKeyType(); // just in case it's used below } } } JavaType contentType = type.getContentType(); if (contentType != null) { // ... as well as deserializer for contents: if (contentType.getValueHandler() == null) { // as with above, avoid resetting (which would trigger exception) Object cdDef = intr.findContentDeserializer(a); JsonDeserializer cd = ctxt.deserializerInstance(a, cdDef); if (cd != null) { type = (T) type.withContentValueHandler(cd); } } } */ // then: type refinement(s)? return intr.refineDeserializationType(ctxt.getConfig(), a, type); } /** * @deprecated since 2.8 call {@link #resolveMemberAndTypeAnnotations} instead. */ @Deprecated // since 2.8 protected JavaType resolveType(DeserializationContext ctxt, BeanDescription beanDesc, JavaType type, AnnotatedMember member) throws JsonMappingException { return resolveMemberAndTypeAnnotations(ctxt, member, type); } /** * @deprecated since 2.8 call findJsonValueMethod on {@link BeanDescription} instead */ @Deprecated // not used, possibly remove as early as 2.9 protected AnnotatedMethod _findJsonValueFor(DeserializationConfig config, JavaType enumType) { if (enumType == null) { return null; } BeanDescription beanDesc = config.introspect(enumType); return beanDesc.findJsonValueMethod(); } } BeanDeserializer.java000066400000000000000000001231021325620701100356240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.impl.*; import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring; import com.fasterxml.jackson.databind.util.NameTransformer; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Deserializer class that can deserialize instances of * arbitrary bean objects, usually from JSON Object structs, */ public class BeanDeserializer extends BeanDeserializerBase implements java.io.Serializable { /* TODOs for future versions: * * For 2.9? * * - New method in JsonDeserializer (deserializeNext()) to allow use of more * efficient 'nextXxx()' method `JsonParser` provides. * * Also: need to ensure efficient impl of those methods for Smile, CBOR * at least (in addition to JSON) */ private static final long serialVersionUID = 1L; /** * Lazily constructed exception used as root cause if reporting problem * with creator method that returns null (which is not allowed) * * @since 2.8 */ protected transient Exception _nullFromCreator; /** * State marker we need in order to avoid infinite recursion for some cases * (not very clean, alas, but has to do for now) * * @since 2.9 */ private volatile transient NameTransformer _currentlyTransforming; /* /********************************************************** /* Life-cycle, construction, initialization /********************************************************** */ /** * Constructor used by {@link BeanDeserializerBuilder}. */ public BeanDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, BeanPropertyMap properties, Map backRefs, HashSet ignorableProps, boolean ignoreAllUnknown, boolean hasViews) { super(builder, beanDesc, properties, backRefs, ignorableProps, ignoreAllUnknown, hasViews); } /** * Copy-constructor that can be used by sub-classes to allow * copy-on-write style copying of settings of an existing instance. */ protected BeanDeserializer(BeanDeserializerBase src) { super(src, src._ignoreAllUnknown); } protected BeanDeserializer(BeanDeserializerBase src, boolean ignoreAllUnknown) { super(src, ignoreAllUnknown); } protected BeanDeserializer(BeanDeserializerBase src, NameTransformer unwrapper) { super(src, unwrapper); } public BeanDeserializer(BeanDeserializerBase src, ObjectIdReader oir) { super(src, oir); } public BeanDeserializer(BeanDeserializerBase src, Set ignorableProps) { super(src, ignorableProps); } public BeanDeserializer(BeanDeserializerBase src, BeanPropertyMap props) { super(src, props); } @Override public JsonDeserializer unwrappingDeserializer(NameTransformer transformer) { // bit kludgy but we don't want to accidentally change type; sub-classes // MUST override this method to support unwrapped properties... if (getClass() != BeanDeserializer.class) { return this; } // 25-Mar-2017, tatu: Not clean at all, but for [databind#383] we do need // to keep track of accidental recursion... if (_currentlyTransforming == transformer) { return this; } _currentlyTransforming = transformer; try { return new BeanDeserializer(this, transformer); } finally { _currentlyTransforming = null; } } @Override public BeanDeserializer withObjectIdReader(ObjectIdReader oir) { return new BeanDeserializer(this, oir); } @Override public BeanDeserializer withIgnorableProperties(Set ignorableProps) { return new BeanDeserializer(this, ignorableProps); } @Override public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) { return new BeanDeserializer(this, props); } @Override protected BeanDeserializerBase asArrayDeserializer() { SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder(); return new BeanAsArrayDeserializer(this, props); } /* /********************************************************** /* JsonDeserializer implementation /********************************************************** */ /** * Main deserialization method for bean-based objects (POJOs). */ @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // common case first if (p.isExpectedStartObjectToken()) { if (_vanillaProcessing) { return vanillaDeserialize(p, ctxt, p.nextToken()); } // 23-Sep-2015, tatu: This is wrong at some many levels, but for now... it is // what it is, including "expected behavior". p.nextToken(); if (_objectIdReader != null) { return deserializeWithObjectId(p, ctxt); } return deserializeFromObject(p, ctxt); } return _deserializeOther(p, ctxt, p.getCurrentToken()); } protected final Object _deserializeOther(JsonParser p, DeserializationContext ctxt, JsonToken t) throws IOException { // and then others, generally requiring use of @JsonCreator if (t != null) { switch (t) { case VALUE_STRING: return deserializeFromString(p, ctxt); case VALUE_NUMBER_INT: return deserializeFromNumber(p, ctxt); case VALUE_NUMBER_FLOAT: return deserializeFromDouble(p, ctxt); case VALUE_EMBEDDED_OBJECT: return deserializeFromEmbedded(p, ctxt); case VALUE_TRUE: case VALUE_FALSE: return deserializeFromBoolean(p, ctxt); case VALUE_NULL: return deserializeFromNull(p, ctxt); case START_ARRAY: // these only work if there's a (delegating) creator... return deserializeFromArray(p, ctxt); case FIELD_NAME: case END_OBJECT: // added to resolve [JACKSON-319], possible related issues if (_vanillaProcessing) { return vanillaDeserialize(p, ctxt, t); } if (_objectIdReader != null) { return deserializeWithObjectId(p, ctxt); } return deserializeFromObject(p, ctxt); default: } } return ctxt.handleUnexpectedToken(handledType(), p); } @Deprecated // since 2.8; remove unless getting used protected Object _missingToken(JsonParser p, DeserializationContext ctxt) throws IOException { throw ctxt.endOfInputException(handledType()); } /** * Secondary deserialization method, called in cases where POJO * instance is created as part of deserialization, potentially * after collecting some or all of the properties to set. */ @Override public Object deserialize(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException { // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(bean); if (_injectables != null) { injectValues(ctxt, bean); } if (_unwrappedPropertyHandler != null) { return deserializeWithUnwrapped(p, ctxt, bean); } if (_externalTypeIdHandler != null) { return deserializeWithExternalTypeId(p, ctxt, bean); } String propName; // 23-Mar-2010, tatu: In some cases, we start with full JSON object too... if (p.isExpectedStartObjectToken()) { propName = p.nextFieldName(); if (propName == null) { return bean; } } else { if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) { propName = p.getCurrentName(); } else { return bean; } } if (_needViewProcesing) { Class view = ctxt.getActiveView(); if (view != null) { return deserializeWithView(p, ctxt, bean, view); } } do { p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { // normal case try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } handleUnknownVanilla(p, ctxt, bean, propName); } while ((propName = p.nextFieldName()) != null); return bean; } /* /********************************************************** /* Concrete deserialization methods /********************************************************** */ /** * Streamlined version that is only used when no "special" * features are enabled. */ private final Object vanillaDeserialize(JsonParser p, DeserializationContext ctxt, JsonToken t) throws IOException { final Object bean = _valueInstantiator.createUsingDefault(ctxt); // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(bean); if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) { String propName = p.getCurrentName(); do { p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { // normal case try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } handleUnknownVanilla(p, ctxt, bean, propName); } while ((propName = p.nextFieldName()) != null); } return bean; } /** * General version used when handling needs more advanced features. */ @Override public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException { /* 09-Dec-2014, tatu: As per [databind#622], we need to allow Object Id references * to come in as JSON Objects as well; but for now assume they will * be simple, single-property references, which means that we can * recognize them without having to buffer anything. * Once again, if we must, we can do more complex handling with buffering, * but let's only do that if and when that becomes necessary. */ if ((_objectIdReader != null) && _objectIdReader.maySerializeAsObject()) { if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME) && _objectIdReader.isValidReferencePropertyName(p.getCurrentName(), p)) { return deserializeFromObjectId(p, ctxt); } } if (_nonStandardCreation) { if (_unwrappedPropertyHandler != null) { return deserializeWithUnwrapped(p, ctxt); } if (_externalTypeIdHandler != null) { return deserializeWithExternalTypeId(p, ctxt); } Object bean = deserializeFromObjectUsingNonDefault(p, ctxt); if (_injectables != null) { injectValues(ctxt, bean); } /* 27-May-2014, tatu: I don't think view processing would work * at this point, so commenting it out; but leaving in place * just in case I forgot something fundamental... */ /* if (_needViewProcesing) { Class view = ctxt.getActiveView(); if (view != null) { return deserializeWithView(p, ctxt, bean, view); } } */ return bean; } final Object bean = _valueInstantiator.createUsingDefault(ctxt); // [databind#631]: Assign current value, to be accessible by custom deserializers p.setCurrentValue(bean); if (p.canReadObjectId()) { Object id = p.getObjectId(); if (id != null) { _handleTypedObjectId(p, ctxt, bean, id); } } if (_injectables != null) { injectValues(ctxt, bean); } if (_needViewProcesing) { Class view = ctxt.getActiveView(); if (view != null) { return deserializeWithView(p, ctxt, bean, view); } } if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) { String propName = p.getCurrentName(); do { p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { // normal case try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } handleUnknownVanilla(p, ctxt, bean, propName); } while ((propName = p.nextFieldName()) != null); } return bean; } /** * Method called to deserialize bean using "property-based creator": * this means that a non-default constructor or factory method is * called, and then possibly other setters. The trick is that * values for creator method need to be buffered, first; and * due to non-guaranteed ordering possibly some other properties * as well. */ @Override @SuppressWarnings("resource") protected Object _deserializeUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt) throws IOException { final PropertyBasedCreator creator = _propertyBasedCreator; PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); TokenBuffer unknown = null; final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; JsonToken t = p.getCurrentToken(); List referrings = null; for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); p.nextToken(); // to point to value // Object Id property? if (buffer.readIdProperty(propName)) { continue; } // creator property? SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); if (creatorProp != null) { // Last creator property to set? Object value; if ((activeView != null) && !creatorProp.visibleInView(activeView)) { p.skipChildren(); continue; } value = _deserializeWithErrorWrapping(p, ctxt, creatorProp); if (buffer.assignParameter(creatorProp, value)) { p.nextToken(); // to move to following FIELD_NAME/END_OBJECT Object bean; try { bean = creator.build(ctxt, buffer); } catch (Exception e) { bean = wrapInstantiationProblem(e, ctxt); } if (bean == null) { return ctxt.handleInstantiationProblem(handledType(), null, _creatorReturnedNullException()); } // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(bean); // polymorphic? if (bean.getClass() != _beanType.getRawClass()) { return handlePolymorphic(p, ctxt, bean, unknown); } if (unknown != null) { // nope, just extra unknown stuff... bean = handleUnknownProperties(ctxt, bean, unknown); } // or just clean? return deserialize(p, ctxt, bean); } continue; } // regular property? needs buffering SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { try { buffer.bufferProperty(prop, _deserializeWithErrorWrapping(p, ctxt, prop)); } catch (UnresolvedForwardReference reference) { // 14-Jun-2016, tatu: As per [databind#1261], looks like we need additional // handling of forward references here. Not exactly sure why existing // facilities did not cover, but this does appear to solve the problem BeanReferring referring = handleUnresolvedReference(ctxt, prop, buffer, reference); if (referrings == null) { referrings = new ArrayList(); } referrings.add(referring); } continue; } // Things marked as ignorable should not be passed to any setter if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, handledType(), propName); continue; } // "any property"? if (_anySetter != null) { try { buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt)); } catch (Exception e) { wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); } continue; } // Ok then, let's collect the whole field; name and value if (unknown == null) { unknown = new TokenBuffer(p, ctxt); } unknown.writeFieldName(propName); unknown.copyCurrentStructure(p); } // We hit END_OBJECT, so: Object bean; try { bean = creator.build(ctxt, buffer); } catch (Exception e) { wrapInstantiationProblem(e, ctxt); bean = null; // never gets here } if (referrings != null) { for (BeanReferring referring : referrings) { referring.setBean(bean); } } if (unknown != null) { // polymorphic? if (bean.getClass() != _beanType.getRawClass()) { return handlePolymorphic(null, ctxt, bean, unknown); } // no, just some extra unknown properties return handleUnknownProperties(ctxt, bean, unknown); } return bean; } /** * @since 2.8 */ private BeanReferring handleUnresolvedReference(DeserializationContext ctxt, SettableBeanProperty prop, PropertyValueBuffer buffer, UnresolvedForwardReference reference) throws JsonMappingException { BeanReferring referring = new BeanReferring(ctxt, reference, prop.getType(), buffer, prop); reference.getRoid().appendReferring(referring); return referring; } protected final Object _deserializeWithErrorWrapping(JsonParser p, DeserializationContext ctxt, SettableBeanProperty prop) throws IOException { try { return prop.deserialize(p, ctxt); } catch (Exception e) { wrapAndThrow(e, _beanType.getRawClass(), prop.getName(), ctxt); // never gets here, unless caller declines to throw an exception return null; } } /** * Helper method called for rare case of pointing to {@link JsonToken#VALUE_NULL} * token. While this is most often an erroneous condition, there is one specific * case with XML handling where polymorphic type with no properties is exposed * as such, and should be handled same as empty Object. * * @since 2.7 */ protected Object deserializeFromNull(JsonParser p, DeserializationContext ctxt) throws IOException { // 17-Dec-2015, tatu: Highly specialized case, mainly to support polymorphic // "empty" POJOs deserialized from XML, where empty XML tag synthesizes a // `VALUE_NULL` token. if (p.requiresCustomCodec()) { // not only XML module, but mostly it... @SuppressWarnings("resource") TokenBuffer tb = new TokenBuffer(p, ctxt); tb.writeEndObject(); JsonParser p2 = tb.asParser(p); p2.nextToken(); // to point to END_OBJECT // note: don't have ObjectId to consider at this point, so: Object ob = _vanillaProcessing ? vanillaDeserialize(p2, ctxt, JsonToken.END_OBJECT) : deserializeFromObject(p2, ctxt); p2.close(); return ob; } return ctxt.handleUnexpectedToken(handledType(), p); } /* /********************************************************** /* Deserializing when we have to consider an active View /********************************************************** */ protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt, Object bean, Class activeView) throws IOException { if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) { String propName = p.getCurrentName(); do { p.nextToken(); // TODO: 06-Jan-2015, tatu: try streamlining call sequences here as well SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { if (!prop.visibleInView(activeView)) { p.skipChildren(); continue; } try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } handleUnknownVanilla(p, ctxt, bean, propName); } while ((propName = p.nextFieldName()) != null); } return bean; } /* /********************************************************** /* Handling for cases where we have "unwrapped" values /********************************************************** */ /** * Method called when there are declared "unwrapped" properties * which need special handling */ @SuppressWarnings("resource") protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { if (_delegateDeserializer != null) { return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt)); } if (_propertyBasedCreator != null) { return deserializeUsingPropertyBasedWithUnwrapped(p, ctxt); } TokenBuffer tokens = new TokenBuffer(p, ctxt); tokens.writeStartObject(); final Object bean = _valueInstantiator.createUsingDefault(ctxt); // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(bean); if (_injectables != null) { injectValues(ctxt, bean); } final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; String propName = p.hasTokenId(JsonTokenId.ID_FIELD_NAME) ? p.getCurrentName() : null; for (; propName != null; propName = p.nextFieldName()) { p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { // normal case if ((activeView != null) && !prop.visibleInView(activeView)) { p.skipChildren(); continue; } try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } // Things marked as ignorable should not be passed to any setter if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, bean, propName); continue; } // 29-Nov-2016, tatu: probably should try to avoid sending content // both to any setter AND buffer... but, for now, the only thing // we can do. // how about any setter? We'll get copies but... if (_anySetter == null) { // but... others should be passed to unwrapped property deserializers tokens.writeFieldName(propName); tokens.copyCurrentStructure(p); continue; } // Need to copy to a separate buffer first TokenBuffer b2 = TokenBuffer.asCopyOfValue(p); tokens.writeFieldName(propName); tokens.append(b2); try { _anySetter.deserializeAndSet(b2.asParserOnFirstToken(), ctxt, bean, propName); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } } tokens.writeEndObject(); _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens); return bean; } @SuppressWarnings("resource") protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.START_OBJECT) { t = p.nextToken(); } TokenBuffer tokens = new TokenBuffer(p, ctxt); tokens.writeStartObject(); final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); SettableBeanProperty prop = _beanProperties.find(propName); p.nextToken(); if (prop != null) { // normal case if (activeView != null && !prop.visibleInView(activeView)) { p.skipChildren(); continue; } try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, bean, propName); continue; } // 29-Nov-2016, tatu: probably should try to avoid sending content // both to any setter AND buffer... but, for now, the only thing // we can do. // how about any setter? We'll get copies but... if (_anySetter == null) { // but... others should be passed to unwrapped property deserializers tokens.writeFieldName(propName); tokens.copyCurrentStructure(p); } else { // Need to copy to a separate buffer first TokenBuffer b2 = TokenBuffer.asCopyOfValue(p); tokens.writeFieldName(propName); tokens.append(b2); try { _anySetter.deserializeAndSet(b2.asParserOnFirstToken(), ctxt, bean, propName); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } } tokens.writeEndObject(); _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens); return bean; } @SuppressWarnings("resource") protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { // 01-Dec-2016, tatu: Note: This IS legal to call, but only when unwrapped // value itself is NOT passed via `CreatorProperty` (which isn't supported). // Ok however to pass via setter or field. final PropertyBasedCreator creator = _propertyBasedCreator; PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); TokenBuffer tokens = new TokenBuffer(p, ctxt); tokens.writeStartObject(); JsonToken t = p.getCurrentToken(); for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); p.nextToken(); // to point to value // creator property? SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); if (creatorProp != null) { // Last creator property to set? if (buffer.assignParameter(creatorProp, _deserializeWithErrorWrapping(p, ctxt, creatorProp))) { t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT Object bean; try { bean = creator.build(ctxt, buffer); } catch (Exception e) { bean = wrapInstantiationProblem(e, ctxt); } // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(bean); // if so, need to copy all remaining tokens into buffer while (t == JsonToken.FIELD_NAME) { p.nextToken(); // to skip name tokens.copyCurrentStructure(p); t = p.nextToken(); } tokens.writeEndObject(); if (bean.getClass() != _beanType.getRawClass()) { // !!! 08-Jul-2011, tatu: Could probably support; but for now // it's too complicated, so bail out ctxt.reportInputMismatch(creatorProp, "Cannot create polymorphic instances with unwrapped values"); return null; } return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens); } continue; } // Object Id property? if (buffer.readIdProperty(propName)) { continue; } // regular property? needs buffering SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { buffer.bufferProperty(prop, _deserializeWithErrorWrapping(p, ctxt, prop)); continue; } // Things marked as ignorable should not be passed to any setter if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, handledType(), propName); continue; } // 29-Nov-2016, tatu: probably should try to avoid sending content // both to any setter AND buffer... but, for now, the only thing // we can do. // how about any setter? We'll get copies but... if (_anySetter == null) { // but... others should be passed to unwrapped property deserializers tokens.writeFieldName(propName); tokens.copyCurrentStructure(p); } else { // Need to copy to a separate buffer first TokenBuffer b2 = TokenBuffer.asCopyOfValue(p); tokens.writeFieldName(propName); tokens.append(b2); try { buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(b2.asParserOnFirstToken(), ctxt)); } catch (Exception e) { wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); } continue; } } // We hit END_OBJECT, so: Object bean; try { bean = creator.build(ctxt, buffer); } catch (Exception e) { wrapInstantiationProblem(e, ctxt); return null; // never gets here } return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens); } /* /********************************************************** /* Handling for cases where we have property/-ies with /* external type id /********************************************************** */ protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt) throws IOException { if (_propertyBasedCreator != null) { return deserializeUsingPropertyBasedWithExternalTypeId(p, ctxt); } if (_delegateDeserializer != null) { /* 24-Nov-2015, tatu: Use of delegating creator needs to have precedence, and basically * external type id handling just has to be ignored, as they would relate to target * type and not delegate type. Whether this works as expected is another story, but * there's no other way to really mix these conflicting features. */ return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt)); } return deserializeWithExternalTypeId(p, ctxt, _valueInstantiator.createUsingDefault(ctxt)); } protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException { final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; final ExternalTypeHandler ext = _externalTypeIdHandler.start(); for (JsonToken t = p.getCurrentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); t = p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { // normal case // [JACKSON-831]: may have property AND be used as external type id: if (t.isScalarValue()) { ext.handleTypePropertyValue(p, ctxt, propName, bean); } if (activeView != null && !prop.visibleInView(activeView)) { p.skipChildren(); continue; } try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } // ignorable things should be ignored if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, bean, propName); continue; } // but others are likely to be part of external type id thingy... if (ext.handlePropertyValue(p, ctxt, propName, bean)) { continue; } // if not, the usual fallback handling: if (_anySetter != null) { try { _anySetter.deserializeAndSet(p, ctxt, bean, propName); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } // Unknown: let's call handler method handleUnknownProperty(p, ctxt, bean, propName); } // and when we get this far, let's try finalizing the deal: return ext.complete(p, ctxt, bean); } @SuppressWarnings("resource") protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, DeserializationContext ctxt) throws IOException { final ExternalTypeHandler ext = _externalTypeIdHandler.start(); final PropertyBasedCreator creator = _propertyBasedCreator; PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); TokenBuffer tokens = new TokenBuffer(p, ctxt); tokens.writeStartObject(); JsonToken t = p.getCurrentToken(); for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); p.nextToken(); // to point to value // creator property? SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); if (creatorProp != null) { // first: let's check to see if this might be part of value with external type id: // 11-Sep-2015, tatu: Important; do NOT pass buffer as last arg, but null, // since it is not the bean if (ext.handlePropertyValue(p, ctxt, propName, null)) { ; } else { // Last creator property to set? if (buffer.assignParameter(creatorProp, _deserializeWithErrorWrapping(p, ctxt, creatorProp))) { t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT Object bean; try { bean = creator.build(ctxt, buffer); } catch (Exception e) { wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); continue; // never gets here } // if so, need to copy all remaining tokens into buffer while (t == JsonToken.FIELD_NAME) { p.nextToken(); // to skip name tokens.copyCurrentStructure(p); t = p.nextToken(); } if (bean.getClass() != _beanType.getRawClass()) { // !!! 08-Jul-2011, tatu: Could theoretically support; but for now // it's too complicated, so bail out return ctxt.reportBadDefinition(_beanType, String.format( "Cannot create polymorphic instances with external type ids (%s -> %s)", _beanType, bean.getClass())); } return ext.complete(p, ctxt, bean); } } continue; } // Object Id property? if (buffer.readIdProperty(propName)) { continue; } // regular property? needs buffering SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { buffer.bufferProperty(prop, prop.deserialize(p, ctxt)); continue; } // external type id (or property that depends on it)? if (ext.handlePropertyValue(p, ctxt, propName, null)) { continue; } // Things marked as ignorable should not be passed to any setter if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, handledType(), propName); continue; } // "any property"? if (_anySetter != null) { buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt)); } } tokens.writeEndObject(); // We hit END_OBJECT; resolve the pieces: try { return ext.complete(p, ctxt, buffer, creator); } catch (Exception e) { return wrapInstantiationProblem(e, ctxt); } } /** * Helper method for getting a lazily construct exception to be reported * to {@link DeserializationContext#handleInstantiationProblem(Class, Object, Throwable)}. * * @since 2.8 */ protected Exception _creatorReturnedNullException() { if (_nullFromCreator == null) { _nullFromCreator = new NullPointerException("JSON Creator returned null"); } return _nullFromCreator; } /** * @since 2.8 */ static class BeanReferring extends Referring { private final DeserializationContext _context; private final SettableBeanProperty _prop; private Object _bean; BeanReferring(DeserializationContext ctxt, UnresolvedForwardReference ref, JavaType valueType, PropertyValueBuffer buffer, SettableBeanProperty prop) { super(ref, valueType); _context = ctxt; _prop = prop; } public void setBean(Object bean) { _bean = bean; } @Override public void handleResolvedForwardReference(Object id, Object value) throws IOException { if (_bean == null) { _context.reportInputMismatch(_prop, "Cannot resolve ObjectId forward reference using property '%s' (of type %s): Bean not yet resolved", _prop.getName(), _prop.getDeclaringClass().getName()); } _prop.set(_bean, value); } } } BeanDeserializerBase.java000066400000000000000000002143111325620701100364220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.JsonParser.NumberType; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.impl.*; import com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.exc.IgnoredPropertyException; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.type.ClassKey; import com.fasterxml.jackson.databind.util.*; /** * Base class for BeanDeserializer. */ public abstract class BeanDeserializerBase extends StdDeserializer implements ContextualDeserializer, ResolvableDeserializer, ValueInstantiator.Gettable, // since 2.9 java.io.Serializable // since 2.1 { private static final long serialVersionUID = 1; protected final static PropertyName TEMP_PROPERTY_NAME = new PropertyName("#temporary-name"); /* /********************************************************** /* Information regarding type being deserialized /********************************************************** */ /** * Declared type of the bean this deserializer handles. */ final protected JavaType _beanType; /** * Requested shape from bean class annotations. */ final protected JsonFormat.Shape _serializationShape; /* /********************************************************** /* Configuration for creating value instance /********************************************************** */ /** * Object that handles details of constructing initial * bean value (to which bind data to), unless instance * is passed (via updateValue()) */ protected final ValueInstantiator _valueInstantiator; /** * Deserializer that is used iff delegate-based creator is * to be used for deserializing from JSON Object. */ protected JsonDeserializer _delegateDeserializer; /** * Deserializer that is used iff array-delegate-based creator * is to be used for deserializing from JSON Object. */ protected JsonDeserializer _arrayDelegateDeserializer; /** * If the bean needs to be instantiated using constructor * or factory method * that takes one or more named properties as argument(s), * this creator is used for instantiation. * This value gets resolved during general resolution. */ protected PropertyBasedCreator _propertyBasedCreator; /** * Flag that is set to mark "non-standard" cases; where either * we use one of non-default creators, or there are unwrapped * values to consider. */ protected boolean _nonStandardCreation; /** * Flag that indicates that no "special features" whatsoever * are enabled, so the simplest processing is possible. */ protected boolean _vanillaProcessing; /* /********************************************************** /* Property information, setters /********************************************************** */ /** * Mapping of property names to properties, built when all properties * to use have been successfully resolved. */ final protected BeanPropertyMap _beanProperties; /** * List of {@link ValueInjector}s, if any injectable values are * expected by the bean; otherwise null. * This includes injectors used for injecting values via setters * and fields, but not ones passed through constructor parameters. */ final protected ValueInjector[] _injectables; /** * Fallback setter used for handling any properties that are not * mapped to regular setters. If setter is not null, it will be * called once for each such property. */ protected SettableAnyProperty _anySetter; /** * In addition to properties that are set, we will also keep * track of recognized but ignorable properties: these will * be skipped without errors or warnings. */ final protected Set _ignorableProps; /** * Flag that can be set to ignore and skip unknown properties. * If set, will not throw an exception for unknown properties. */ final protected boolean _ignoreAllUnknown; /** * Flag that indicates that some aspect of deserialization depends * on active view used (if any) */ final protected boolean _needViewProcesing; /** * We may also have one or more back reference fields (usually * zero or one). */ final protected Map _backRefs; /* /********************************************************** /* Related handlers /********************************************************** */ /** * Lazily constructed map used to contain deserializers needed * for polymorphic subtypes. * Note that this is only needed for polymorphic types, * that is, when the actual type is not statically known. * For other types this remains null. */ protected transient HashMap> _subDeserializers; /** * If one of properties has "unwrapped" value, we need separate * helper object */ protected UnwrappedPropertyHandler _unwrappedPropertyHandler; /** * Handler that we need iff any of properties uses external * type id. */ protected ExternalTypeHandler _externalTypeIdHandler; /** * If an Object Id is to be used for value handled by this * deserializer, this reader is used for handling. */ protected final ObjectIdReader _objectIdReader; /* /********************************************************** /* Life-cycle, construction, initialization /********************************************************** */ /** * Constructor used when initially building a deserializer * instance, given a {@link BeanDeserializerBuilder} that * contains configuration. */ protected BeanDeserializerBase(BeanDeserializerBuilder builder, BeanDescription beanDesc, BeanPropertyMap properties, Map backRefs, Set ignorableProps, boolean ignoreAllUnknown, boolean hasViews) { super(beanDesc.getType()); _beanType = beanDesc.getType(); _valueInstantiator = builder.getValueInstantiator(); _beanProperties = properties; _backRefs = backRefs; _ignorableProps = ignorableProps; _ignoreAllUnknown = ignoreAllUnknown; _anySetter = builder.getAnySetter(); List injectables = builder.getInjectables(); _injectables = (injectables == null || injectables.isEmpty()) ? null : injectables.toArray(new ValueInjector[injectables.size()]); _objectIdReader = builder.getObjectIdReader(); _nonStandardCreation = (_unwrappedPropertyHandler != null) || _valueInstantiator.canCreateUsingDelegate() || _valueInstantiator.canCreateUsingArrayDelegate() // new in 2.7 || _valueInstantiator.canCreateFromObjectWith() || !_valueInstantiator.canCreateUsingDefault() ; // Any transformation we may need to apply? JsonFormat.Value format = beanDesc.findExpectedFormat(null); _serializationShape = (format == null) ? null : format.getShape(); _needViewProcesing = hasViews; _vanillaProcessing = !_nonStandardCreation && (_injectables == null) && !_needViewProcesing // also, may need to reorder stuff if we expect Object Id: && (_objectIdReader == null) ; } protected BeanDeserializerBase(BeanDeserializerBase src) { this(src, src._ignoreAllUnknown); } protected BeanDeserializerBase(BeanDeserializerBase src, boolean ignoreAllUnknown) { super(src._beanType); _beanType = src._beanType; _valueInstantiator = src._valueInstantiator; _delegateDeserializer = src._delegateDeserializer; _propertyBasedCreator = src._propertyBasedCreator; _beanProperties = src._beanProperties; _backRefs = src._backRefs; _ignorableProps = src._ignorableProps; _ignoreAllUnknown = ignoreAllUnknown; _anySetter = src._anySetter; _injectables = src._injectables; _objectIdReader = src._objectIdReader; _nonStandardCreation = src._nonStandardCreation; _unwrappedPropertyHandler = src._unwrappedPropertyHandler; _needViewProcesing = src._needViewProcesing; _serializationShape = src._serializationShape; _vanillaProcessing = src._vanillaProcessing; } protected BeanDeserializerBase(BeanDeserializerBase src, NameTransformer unwrapper) { super(src._beanType); _beanType = src._beanType; _valueInstantiator = src._valueInstantiator; _delegateDeserializer = src._delegateDeserializer; _propertyBasedCreator = src._propertyBasedCreator; _backRefs = src._backRefs; _ignorableProps = src._ignorableProps; _ignoreAllUnknown = (unwrapper != null) || src._ignoreAllUnknown; _anySetter = src._anySetter; _injectables = src._injectables; _objectIdReader = src._objectIdReader; _nonStandardCreation = src._nonStandardCreation; UnwrappedPropertyHandler uph = src._unwrappedPropertyHandler; if (unwrapper != null) { // delegate further unwraps, if any if (uph != null) { // got handler, delegate uph = uph.renameAll(unwrapper); } // and handle direct unwrapping as well: _beanProperties = src._beanProperties.renameAll(unwrapper); } else { _beanProperties = src._beanProperties; } _unwrappedPropertyHandler = uph; _needViewProcesing = src._needViewProcesing; _serializationShape = src._serializationShape; // probably adds a twist, so: _vanillaProcessing = false; } public BeanDeserializerBase(BeanDeserializerBase src, ObjectIdReader oir) { super(src._beanType); _beanType = src._beanType; _valueInstantiator = src._valueInstantiator; _delegateDeserializer = src._delegateDeserializer; _propertyBasedCreator = src._propertyBasedCreator; _backRefs = src._backRefs; _ignorableProps = src._ignorableProps; _ignoreAllUnknown = src._ignoreAllUnknown; _anySetter = src._anySetter; _injectables = src._injectables; _nonStandardCreation = src._nonStandardCreation; _unwrappedPropertyHandler = src._unwrappedPropertyHandler; _needViewProcesing = src._needViewProcesing; _serializationShape = src._serializationShape; // then actual changes: _objectIdReader = oir; if (oir == null) { _beanProperties = src._beanProperties; _vanillaProcessing = src._vanillaProcessing; } else { /* 18-Nov-2012, tatu: May or may not have annotations for id property; * but no easy access. But hard to see id property being optional, * so let's consider required at this point. */ ObjectIdValueProperty idProp = new ObjectIdValueProperty(oir, PropertyMetadata.STD_REQUIRED); _beanProperties = src._beanProperties.withProperty(idProp); _vanillaProcessing = false; } } public BeanDeserializerBase(BeanDeserializerBase src, Set ignorableProps) { super(src._beanType); _beanType = src._beanType; _valueInstantiator = src._valueInstantiator; _delegateDeserializer = src._delegateDeserializer; _propertyBasedCreator = src._propertyBasedCreator; _backRefs = src._backRefs; _ignorableProps = ignorableProps; _ignoreAllUnknown = src._ignoreAllUnknown; _anySetter = src._anySetter; _injectables = src._injectables; _nonStandardCreation = src._nonStandardCreation; _unwrappedPropertyHandler = src._unwrappedPropertyHandler; _needViewProcesing = src._needViewProcesing; _serializationShape = src._serializationShape; _vanillaProcessing = src._vanillaProcessing; _objectIdReader = src._objectIdReader; // 01-May-2016, tatu: [databind#1217]: Remove properties from mapping, // to avoid them being deserialized _beanProperties = src._beanProperties.withoutProperties(ignorableProps); } /** * @since 2.8 */ protected BeanDeserializerBase(BeanDeserializerBase src, BeanPropertyMap beanProps) { super(src._beanType); _beanType = src._beanType; _valueInstantiator = src._valueInstantiator; _delegateDeserializer = src._delegateDeserializer; _propertyBasedCreator = src._propertyBasedCreator; _beanProperties = beanProps; _backRefs = src._backRefs; _ignorableProps = src._ignorableProps; _ignoreAllUnknown = src._ignoreAllUnknown; _anySetter = src._anySetter; _injectables = src._injectables; _objectIdReader = src._objectIdReader; _nonStandardCreation = src._nonStandardCreation; _unwrappedPropertyHandler = src._unwrappedPropertyHandler; _needViewProcesing = src._needViewProcesing; _serializationShape = src._serializationShape; _vanillaProcessing = src._vanillaProcessing; } @Override public abstract JsonDeserializer unwrappingDeserializer(NameTransformer unwrapper); public abstract BeanDeserializerBase withObjectIdReader(ObjectIdReader oir); public abstract BeanDeserializerBase withIgnorableProperties(Set ignorableProps); /** * Mutant factory method that custom sub-classes must override; not left as * abstract to prevent more drastic backwards compatibility problems. * * @since 2.8 */ public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) { throw new UnsupportedOperationException("Class "+getClass().getName() +" does not override `withBeanProperties()`, needs to"); } /** * Fluent factory for creating a variant that can handle * POJO output as a JSON Array. Implementations may ignore this request * if no such input is possible. * * @since 2.1 */ protected abstract BeanDeserializerBase asArrayDeserializer(); /* /********************************************************** /* Validation, post-processing /********************************************************** */ /** * Method called to finalize setup of this deserializer, * after deserializer itself has been registered. * This is needed to handle recursive and transitive dependencies. */ @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException { ExternalTypeHandler.Builder extTypes = null; // if ValueInstantiator can use "creator" approach, need to resolve it here... SettableBeanProperty[] creatorProps; if (_valueInstantiator.canCreateFromObjectWith()) { creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig()); // 22-Jan-2018, tatu: May need to propagate "ignorable" status (from `Access.READ_ONLY` // or perhaps class-ignorables) into Creator properties too. Can not just delete, // at this point, but is needed for further processing down the line if (_ignorableProps != null) { for (int i = 0, end = creatorProps.length; i < end; ++i) { SettableBeanProperty prop = creatorProps[i]; if (_ignorableProps.contains(prop.getName())) { creatorProps[i].markAsIgnorable(); } } } } else { creatorProps = null; } UnwrappedPropertyHandler unwrapped = null; // 24-Mar-2017, tatu: Looks like we may have to iterate over // properties twice, to handle potential issues with recursive // types (see [databind#1575] f.ex). // First loop: find deserializer if not yet known, but do not yet // contextualize (since that can lead to problems with self-references) // 22-Jan-2018, tatu: NOTE! Need not check for `isIgnorable` as that can // only happen for props in `creatorProps` for (SettableBeanProperty prop : _beanProperties) { if (!prop.hasValueDeserializer()) { // [databind#125]: allow use of converters JsonDeserializer deser = findConvertingDeserializer(ctxt, prop); if (deser == null) { deser = ctxt.findNonContextualValueDeserializer(prop.getType()); } SettableBeanProperty newProp = prop.withValueDeserializer(deser); _replaceProperty(_beanProperties, creatorProps, prop, newProp); } } // Second loop: contextualize, find other pieces for (SettableBeanProperty origProp : _beanProperties) { SettableBeanProperty prop = origProp; JsonDeserializer deser = prop.getValueDeserializer(); deser = ctxt.handlePrimaryContextualization(deser, prop, prop.getType()); prop = prop.withValueDeserializer(deser); // Need to link managed references with matching back references prop = _resolveManagedReferenceProperty(ctxt, prop); // [databind#351]: need to wrap properties that require object id resolution. if (!(prop instanceof ManagedReferenceProperty)) { prop = _resolvedObjectIdProperty(ctxt, prop); } // Support unwrapped values (via @JsonUnwrapped) NameTransformer xform = _findPropertyUnwrapper(ctxt, prop); if (xform != null) { JsonDeserializer orig = prop.getValueDeserializer(); JsonDeserializer unwrapping = orig.unwrappingDeserializer(xform); if (unwrapping != orig && unwrapping != null) { prop = prop.withValueDeserializer(unwrapping); if (unwrapped == null) { unwrapped = new UnwrappedPropertyHandler(); } unwrapped.addProperty(prop); // 12-Dec-2014, tatu: As per [databind#647], we will have problems if // the original property is left in place. So let's remove it now. // 25-Mar-2017, tatu: Wonder if this could be problematic wrt creators? // (that is, should be remove it from creator too) _beanProperties.remove(prop); continue; } } // 26-Oct-2016, tatu: Need to have access to value deserializer to know if // merging needed, and now seems to be reasonable time to do that. final PropertyMetadata md = prop.getMetadata(); prop = _resolveMergeAndNullSettings(ctxt, prop, md); // non-static inner classes too: prop = _resolveInnerClassValuedProperty(ctxt, prop); if (prop != origProp) { _replaceProperty(_beanProperties, creatorProps, origProp, prop); } // one more thing: if this property uses "external property" type inclusion, // it needs different handling altogether if (prop.hasValueTypeDeserializer()) { TypeDeserializer typeDeser = prop.getValueTypeDeserializer(); if (typeDeser.getTypeInclusion() == JsonTypeInfo.As.EXTERNAL_PROPERTY) { if (extTypes == null) { extTypes = ExternalTypeHandler.builder(_beanType); } extTypes.addExternal(prop, typeDeser); // In fact, remove from list of known properties to simplify later handling _beanProperties.remove(prop); continue; } } } // "any setter" may also need to be resolved now if ((_anySetter != null) && !_anySetter.hasValueDeserializer()) { _anySetter = _anySetter.withValueDeserializer(findDeserializer(ctxt, _anySetter.getType(), _anySetter.getProperty())); } // as well as delegate-based constructor: if (_valueInstantiator.canCreateUsingDelegate()) { JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig()); if (delegateType == null) { ctxt.reportBadDefinition(_beanType, String.format( "Invalid delegate-creator definition for %s: value instantiator (%s) returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'", _beanType, _valueInstantiator.getClass().getName())); } _delegateDeserializer = _findDelegateDeserializer(ctxt, delegateType, _valueInstantiator.getDelegateCreator()); } // and array-delegate-based constructor: if (_valueInstantiator.canCreateUsingArrayDelegate()) { JavaType delegateType = _valueInstantiator.getArrayDelegateType(ctxt.getConfig()); if (delegateType == null) { ctxt.reportBadDefinition(_beanType, String.format( "Invalid delegate-creator definition for %s: value instantiator (%s) returned true for 'canCreateUsingArrayDelegate()', but null for 'getArrayDelegateType()'", _beanType, _valueInstantiator.getClass().getName())); } _arrayDelegateDeserializer = _findDelegateDeserializer(ctxt, delegateType, _valueInstantiator.getArrayDelegateCreator()); } // And now that we know CreatorProperty instances are also resolved can finally create the creator: if (creatorProps != null) { _propertyBasedCreator = PropertyBasedCreator.construct(ctxt, _valueInstantiator, creatorProps, _beanProperties); } if (extTypes != null) { // 21-Jun-2016, tatu: related to [databind#999], may need to link type ids too, // so need to pass collected properties _externalTypeIdHandler = extTypes.build(_beanProperties); // we consider this non-standard, to offline handling _nonStandardCreation = true; } _unwrappedPropertyHandler = unwrapped; if (unwrapped != null) { // we consider this non-standard, to offline handling _nonStandardCreation = true; } // may need to disable vanilla processing, if unwrapped handling was enabled... _vanillaProcessing = _vanillaProcessing && !_nonStandardCreation; } /** * @since 2.8.8 */ protected void _replaceProperty(BeanPropertyMap props, SettableBeanProperty[] creatorProps, SettableBeanProperty origProp, SettableBeanProperty newProp) { props.replace(origProp, newProp); // [databind#795]: Make sure PropertyBasedCreator's properties stay in sync if (creatorProps != null) { // 18-May-2015, tatu: _Should_ start with consistent set. But can we really // fully count on this? May need to revisit in future; seems to hold for now. for (int i = 0, len = creatorProps.length; i < len; ++i) { if (creatorProps[i] == origProp) { creatorProps[i] = newProp; return; } } /* // ... as per above, it is possible we'd need to add this as fallback // if (but only if) identity check fails? for (int i = 0, len = creatorProps.length; i < len; ++i) { if (creatorProps[i].getName().equals(origProp.getName())) { creatorProps[i] = newProp; return; } } */ } } private JsonDeserializer _findDelegateDeserializer(DeserializationContext ctxt, JavaType delegateType, AnnotatedWithParams delegateCreator) throws JsonMappingException { // Need to create a temporary property to allow contextual deserializers: BeanProperty.Std property = new BeanProperty.Std(TEMP_PROPERTY_NAME, delegateType, null, delegateCreator, PropertyMetadata.STD_OPTIONAL); TypeDeserializer td = delegateType.getTypeHandler(); if (td == null) { td = ctxt.getConfig().findTypeDeserializer(delegateType); } JsonDeserializer dd = findDeserializer(ctxt, delegateType, property); if (td != null) { td = td.forProperty(property); return new TypeWrappedDeserializer(td, dd); } return dd; } /** * Helper method that can be used to see if specified property is annotated * to indicate use of a converter for property value (in case of container types, * it is container type itself, not key or content type). *

* NOTE: returned deserializer is NOT yet contextualized, caller needs to take * care to do that. * * @since 2.2 */ protected JsonDeserializer findConvertingDeserializer(DeserializationContext ctxt, SettableBeanProperty prop) throws JsonMappingException { final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (intr != null) { Object convDef = intr.findDeserializationConverter(prop.getMember()); if (convDef != null) { Converter conv = ctxt.converterInstance(prop.getMember(), convDef); JavaType delegateType = conv.getInputType(ctxt.getTypeFactory()); // 25-Mar-2017, tatu: should not yet contextualize // JsonDeserializer deser = ctxt.findContextualValueDeserializer(delegateType, prop); JsonDeserializer deser = ctxt.findNonContextualValueDeserializer(delegateType); return new StdDelegatingDeserializer(conv, delegateType, deser); } } return null; } /** * Although most of post-processing is done in resolve(), we only get * access to referring property's annotations here; and this is needed * to support per-property ObjectIds. * We will also consider Shape transformations (read from Array) at this * point, since it may come from either Class definition or property. */ @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { ObjectIdReader oir = _objectIdReader; // First: may have an override for Object Id: final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); final AnnotatedMember accessor = _neitherNull(property, intr) ? property.getMember() : null; if (accessor != null) { ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor); if (objectIdInfo != null) { // some code duplication here as well (from BeanDeserializerFactory) // 2.1: allow modifications by "id ref" annotations as well: objectIdInfo = intr.findObjectReferenceInfo(accessor, objectIdInfo); Class implClass = objectIdInfo.getGeneratorType(); // Property-based generator is trickier JavaType idType; SettableBeanProperty idProp; ObjectIdGenerator idGen; ObjectIdResolver resolver = ctxt.objectIdResolverInstance(accessor, objectIdInfo); if (implClass == ObjectIdGenerators.PropertyGenerator.class) { PropertyName propName = objectIdInfo.getPropertyName(); idProp = findProperty(propName); if (idProp == null) { ctxt.reportBadDefinition(_beanType, String.format( "Invalid Object Id definition for %s: cannot find property with name '%s'", handledType().getName(), propName)); } idType = idProp.getType(); idGen = new PropertyBasedObjectIdGenerator(objectIdInfo.getScope()); } else { // other types are to be simpler JavaType type = ctxt.constructType(implClass); idType = ctxt.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0]; idProp = null; idGen = ctxt.objectIdGeneratorInstance(accessor, objectIdInfo); } JsonDeserializer deser = ctxt.findRootValueDeserializer(idType); oir = ObjectIdReader.construct(idType, objectIdInfo.getPropertyName(), idGen, deser, idProp, resolver); } } // either way, need to resolve serializer: BeanDeserializerBase contextual = this; if (oir != null && oir != _objectIdReader) { contextual = contextual.withObjectIdReader(oir); } // And possibly add more properties to ignore if (accessor != null) { JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnorals(accessor); if (ignorals != null) { Set ignored = ignorals.findIgnoredForDeserialization(); if (!ignored.isEmpty()) { Set prev = contextual._ignorableProps; if ((prev != null) && !prev.isEmpty()) { ignored = new HashSet(ignored); ignored.addAll(prev); } contextual = contextual.withIgnorableProperties(ignored); } } } // One more thing: are we asked to serialize POJO as array? JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType()); JsonFormat.Shape shape = null; if (format != null) { if (format.hasShape()) { shape = format.getShape(); } // 16-May-2016, tatu: How about per-property case-insensitivity? Boolean B = format.getFeature(JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); if (B != null) { BeanPropertyMap propsOrig = _beanProperties; BeanPropertyMap props = propsOrig.withCaseInsensitivity(B.booleanValue()); if (props != propsOrig) { contextual = contextual.withBeanProperties(props); } } } if (shape == null) { shape = _serializationShape; } if (shape == JsonFormat.Shape.ARRAY) { contextual = contextual.asArrayDeserializer(); } return contextual; } /** * Helper method called to see if given property is part of 'managed' property * pair (managed + back reference), and if so, handle resolution details. */ protected SettableBeanProperty _resolveManagedReferenceProperty(DeserializationContext ctxt, SettableBeanProperty prop) throws JsonMappingException { String refName = prop.getManagedReferenceName(); if (refName == null) { return prop; } JsonDeserializer valueDeser = prop.getValueDeserializer(); SettableBeanProperty backProp = valueDeser.findBackReference(refName); if (backProp == null) { ctxt.reportBadDefinition(_beanType, String.format( "Cannot handle managed/back reference '%s': no back reference property found from type %s", refName, prop.getType())); } // also: verify that type is compatible JavaType referredType = _beanType; JavaType backRefType = backProp.getType(); boolean isContainer = prop.getType().isContainerType(); if (!backRefType.getRawClass().isAssignableFrom(referredType.getRawClass())) { ctxt.reportBadDefinition(_beanType, String.format( "Cannot handle managed/back reference '%s': back reference type (%s) not compatible with managed type (%s)", refName, backRefType.getRawClass().getName(), referredType.getRawClass().getName())); } return new ManagedReferenceProperty(prop, refName, backProp, isContainer); } /** * Method that wraps given property with {@link ObjectIdReferenceProperty} * in case where object id resolution is required. */ protected SettableBeanProperty _resolvedObjectIdProperty(DeserializationContext ctxt, SettableBeanProperty prop) throws JsonMappingException { ObjectIdInfo objectIdInfo = prop.getObjectIdInfo(); JsonDeserializer valueDeser = prop.getValueDeserializer(); ObjectIdReader objectIdReader = (valueDeser == null) ? null : valueDeser.getObjectIdReader(); if (objectIdInfo == null && objectIdReader == null) { return prop; } return new ObjectIdReferenceProperty(prop, objectIdInfo); } /** * Helper method called to see if given property might be so-called unwrapped * property: these require special handling. */ protected NameTransformer _findPropertyUnwrapper(DeserializationContext ctxt, SettableBeanProperty prop) throws JsonMappingException { AnnotatedMember am = prop.getMember(); if (am != null) { NameTransformer unwrapper = ctxt.getAnnotationIntrospector().findUnwrappingNameTransformer(am); if (unwrapper != null) { // 01-Dec-2016, tatu: As per [databind#265] we cannot yet support passing // of unwrapped values through creator properties, so fail fast if (prop instanceof CreatorProperty) { ctxt.reportBadDefinition(getValueType(), String.format( "Cannot define Creator property \"%s\" as `@JsonUnwrapped`: combination not yet supported", prop.getName())); } return unwrapper; } } return null; } /** * Helper method that will handle gruesome details of dealing with properties * that have non-static inner class as value... */ protected SettableBeanProperty _resolveInnerClassValuedProperty(DeserializationContext ctxt, SettableBeanProperty prop) { /* Should we encounter a property that has non-static inner-class * as value, we need to add some more magic to find the "hidden" constructor... */ JsonDeserializer deser = prop.getValueDeserializer(); // ideally wouldn't rely on it being BeanDeserializerBase; but for now it'll have to do if (deser instanceof BeanDeserializerBase) { BeanDeserializerBase bd = (BeanDeserializerBase) deser; ValueInstantiator vi = bd.getValueInstantiator(); if (!vi.canCreateUsingDefault()) { // no default constructor Class valueClass = prop.getType().getRawClass(); // NOTE: almost same as `isNonStaticInnerClass()` but need to know enclosing... Class enclosing = ClassUtil.getOuterClass(valueClass); // and is inner class of the bean class... if ((enclosing != null) && (enclosing == _beanType.getRawClass())) { for (Constructor ctor : valueClass.getConstructors()) { Class[] paramTypes = ctor.getParameterTypes(); if (paramTypes.length == 1) { if (enclosing.equals(paramTypes[0])) { if (ctxt.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(ctor, ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } return new InnerClassProperty(prop, ctor); } } } } } } return prop; } // @since 2.9 protected SettableBeanProperty _resolveMergeAndNullSettings(DeserializationContext ctxt, SettableBeanProperty prop, PropertyMetadata propMetadata) throws JsonMappingException { PropertyMetadata.MergeInfo merge = propMetadata.getMergeInfo(); // First mergeability if (merge != null) { JsonDeserializer valueDeser = prop.getValueDeserializer(); Boolean mayMerge = valueDeser.supportsUpdate(ctxt.getConfig()); if (mayMerge == null) { // we don't really know if it's ok; so only use if explicitly specified if (merge.fromDefaults) { return prop; } } else if (!mayMerge.booleanValue()) { // prevented if (!merge.fromDefaults) { // If attempts was made via explicit annotation/per-type config override, // should be reported; may or may not result in exception ctxt.reportBadMerge(valueDeser); } return prop; } // Anyway; if we get this far, do enable merging AnnotatedMember accessor = merge.getter; accessor.fixAccess(ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); if (!(prop instanceof SetterlessProperty)) { prop = MergingSettableBeanProperty.construct(prop, accessor); } } // And after this, see if we require non-standard null handling NullValueProvider nuller = findValueNullProvider(ctxt, prop, propMetadata); if (nuller != null) { prop = prop.withNullProvider(nuller); } return prop; } /* /********************************************************** /* Public accessors; null/empty value providers /********************************************************** */ @Override public AccessPattern getNullAccessPattern() { // POJO types do not have custom `null` values return AccessPattern.ALWAYS_NULL; } @Override public AccessPattern getEmptyAccessPattern() { // Empty values cannot be shared return AccessPattern.DYNAMIC; } @Override // since 2.9 public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { // alas, need to promote exception, if any: try { return _valueInstantiator.createUsingDefault(ctxt); } catch (IOException e) { return ClassUtil.throwAsMappingException(ctxt, e); } } /* /********************************************************** /* Public accessors; other /********************************************************** */ @Override public boolean isCachable() { return true; } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { // although with possible caveats, yes, values can be updated // 23-Oct-2016, tatu: Perhaps in future could and should verify from // bean settings... return Boolean.TRUE; } @Override public Class handledType() { return _beanType.getRawClass(); } /** * Overridden to return true for those instances that are * handling value for which Object Identity handling is enabled * (either via value type or referring property). */ @Override public ObjectIdReader getObjectIdReader() { return _objectIdReader; } public boolean hasProperty(String propertyName) { return _beanProperties.find(propertyName) != null; } public boolean hasViews() { return _needViewProcesing; } /** * Accessor for checking number of deserialized properties. */ public int getPropertyCount() { return _beanProperties.size(); } @Override public Collection getKnownPropertyNames() { ArrayList names = new ArrayList(); for (SettableBeanProperty prop : _beanProperties) { names.add(prop.getName()); } return names; } /** * @deprecated Since 2.3, use {@link #handledType()} instead */ @Deprecated public final Class getBeanClass() { return _beanType.getRawClass(); } @Override public JavaType getValueType() { return _beanType; } /** * Accessor for iterating over properties this deserializer uses; with * the exception that properties passed via Creator methods * (specifically, "property-based constructor") are not included, * but can be accessed separate by calling * {@link #creatorProperties} */ public Iterator properties() { if (_beanProperties == null) { throw new IllegalStateException("Can only call after BeanDeserializer has been resolved"); } return _beanProperties.iterator(); } /** * Accessor for finding properties that represents values to pass * through property-based creator method (constructor or * factory method) * * @since 2.0 */ public Iterator creatorProperties() { if (_propertyBasedCreator == null) { return Collections.emptyList().iterator(); } return _propertyBasedCreator.properties().iterator(); } public SettableBeanProperty findProperty(PropertyName propertyName) { // TODO: start matching full name? return findProperty(propertyName.getSimpleName()); } /** * Accessor for finding the property with given name, if POJO * has one. Name used is the external name, i.e. name used * in external data representation (JSON). * * @since 2.0 */ public SettableBeanProperty findProperty(String propertyName) { SettableBeanProperty prop = (_beanProperties == null) ? null : _beanProperties.find(propertyName); if (prop == null && _propertyBasedCreator != null) { prop = _propertyBasedCreator.findCreatorProperty(propertyName); } return prop; } /** * Alternate find method that tries to locate a property with given * property index. * Note that access by index is not necessarily faster than by name, * since properties are not directly indexable; however, for most * instances difference is not significant as number of properties * is low. * * @since 2.3 */ public SettableBeanProperty findProperty(int propertyIndex) { SettableBeanProperty prop = (_beanProperties == null) ? null : _beanProperties.find(propertyIndex); if (prop == null && _propertyBasedCreator != null) { prop = _propertyBasedCreator.findCreatorProperty(propertyIndex); } return prop; } /** * Method needed by {@link BeanDeserializerFactory} to properly link * managed- and back-reference pairs. */ @Override public SettableBeanProperty findBackReference(String logicalName) { if (_backRefs == null) { return null; } return _backRefs.get(logicalName); } @Override // ValueInstantiator.Gettable public ValueInstantiator getValueInstantiator() { return _valueInstantiator; } /* /********************************************************** /* Mutators /********************************************************** */ /** * Method that can be used to replace an existing property with * a modified one. *

* NOTE: only ever use this method if you know what you are doing; * incorrect usage can break deserializer. * * @param original Property to replace * @param replacement Property to replace it with * * @since 2.1 */ public void replaceProperty(SettableBeanProperty original, SettableBeanProperty replacement) { _beanProperties.replace(original, replacement); } /* /********************************************************** /* Partial deserializer implementation /********************************************************** */ /** * General version used when handling needs more advanced * features. */ public abstract Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException; @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // 16-Feb-2012, tatu: ObjectId may be used as well... need to check that first if (_objectIdReader != null) { // 05-Aug-2013, tatu: May use native Object Id if (p.canReadObjectId()) { Object id = p.getObjectId(); if (id != null) { Object ob = typeDeserializer.deserializeTypedFromObject(p, ctxt); return _handleTypedObjectId(p, ctxt, ob, id); } } // or, Object Ids Jackson explicitly sets JsonToken t = p.getCurrentToken(); if (t != null) { // Most commonly, a scalar (int id, uuid String, ...) if (t.isScalarValue()) { return deserializeFromObjectId(p, ctxt); } // but, with 2.5+, a simple Object-wrapped value also legal: if (t == JsonToken.START_OBJECT) { t = p.nextToken(); } if ((t == JsonToken.FIELD_NAME) && _objectIdReader.maySerializeAsObject() && _objectIdReader.isValidReferencePropertyName(p.getCurrentName(), p)) { return deserializeFromObjectId(p, ctxt); } } } // In future could check current token... for now this should be enough: return typeDeserializer.deserializeTypedFromObject(p, ctxt); } /** * Offlined method called to handle "native" Object Id that has been read * and known to be associated with given deserialized POJO. * * @since 2.3 */ protected Object _handleTypedObjectId(JsonParser p, DeserializationContext ctxt, Object pojo, Object rawId) throws IOException { // One more challenge: type of id may not be type of property we are expecting // later on; specifically, numeric ids vs Strings. JsonDeserializer idDeser = _objectIdReader.getDeserializer(); final Object id; // Ok, this is bit ridiculous; let's see if conversion is needed: if (idDeser.handledType() == rawId.getClass()) { // nope: already same type id = rawId; } else { id = _convertObjectId(p, ctxt, rawId, idDeser); } ReadableObjectId roid = ctxt.findObjectId(id, _objectIdReader.generator, _objectIdReader.resolver); roid.bindItem(pojo); // also: may need to set a property value as well SettableBeanProperty idProp = _objectIdReader.idProperty; if (idProp != null) { return idProp.setAndReturn(pojo, id); } return pojo; } /** * Helper method we need to do necessary conversion from whatever native object id * type is, into declared type that Jackson internals expect. This may be * simple cast (for String ids), or something more complicated; in latter * case we may need to create bogus content buffer to allow use of * id deserializer. * * @since 2.3 */ @SuppressWarnings("resource") // TokenBuffers don't need close, nor parser thereof protected Object _convertObjectId(JsonParser p, DeserializationContext ctxt, Object rawId, JsonDeserializer idDeser) throws IOException { TokenBuffer buf = new TokenBuffer(p, ctxt); if (rawId instanceof String) { buf.writeString((String) rawId); } else if (rawId instanceof Long) { buf.writeNumber(((Long) rawId).longValue()); } else if (rawId instanceof Integer) { buf.writeNumber(((Integer) rawId).intValue()); } else { // should we worry about UUIDs? They should be fine, right? // 07-Aug-2014, tatu: Maybe, but not necessarily; had issues with // Smile format; [dataformat-smile#19], possibly related. // 01-Sep-2016, tatu: For non-JSON, might want to consider `writeEmbeddedObject` // but that won't work for default impl (JSON and most dataformats) buf.writeObject(rawId); } JsonParser bufParser = buf.asParser(); bufParser.nextToken(); return idDeser.deserialize(bufParser, ctxt); } // NOTE: currently only used by standard BeanDeserializer (not Builder-based) /** * Alternative deserialization method used when we expect to see Object Id; * if so, we will need to ensure that the Id is seen before anything * else, to ensure that it is available for solving references, * even if JSON itself is not ordered that way. This may require * buffering in some cases, but usually just a simple lookup to ensure * that ordering is correct. */ protected Object deserializeWithObjectId(JsonParser p, DeserializationContext ctxt) throws IOException { return deserializeFromObject(p, ctxt); } /** * Method called in cases where it looks like we got an Object Id * to parse and use as a reference. */ protected Object deserializeFromObjectId(JsonParser p, DeserializationContext ctxt) throws IOException { Object id = _objectIdReader.readObjectReference(p, ctxt); ReadableObjectId roid = ctxt.findObjectId(id, _objectIdReader.generator, _objectIdReader.resolver); // do we have it resolved? Object pojo = roid.resolve(); if (pojo == null) { // not yet; should wait... throw new UnresolvedForwardReference(p, "Could not resolve Object Id ["+id+"] (for "+_beanType+").", p.getCurrentLocation(), roid); } return pojo; } protected Object deserializeFromObjectUsingNonDefault(JsonParser p, DeserializationContext ctxt) throws IOException { final JsonDeserializer delegateDeser = _delegateDeserializer(); if (delegateDeser != null) { return _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt)); } if (_propertyBasedCreator != null) { return _deserializeUsingPropertyBased(p, ctxt); } // 25-Jan-2017, tatu: We do not actually support use of Creators for non-static // inner classes -- with one and only one exception; that of default constructor! // -- so let's indicate it Class raw = _beanType.getRawClass(); if (ClassUtil.isNonStaticInnerClass(raw)) { return ctxt.handleMissingInstantiator(raw, null, p, "can only instantiate non-static inner class by using default, no-argument constructor"); } return ctxt.handleMissingInstantiator(raw, getValueInstantiator(), p, "cannot deserialize from Object value (no delegate- or property-based Creator)"); } protected abstract Object _deserializeUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt) throws IOException; public Object deserializeFromNumber(JsonParser p, DeserializationContext ctxt) throws IOException { // First things first: id Object Id is used, most likely that's it if (_objectIdReader != null) { return deserializeFromObjectId(p, ctxt); } final JsonDeserializer delegateDeser = _delegateDeserializer(); NumberType nt = p.getNumberType(); if (nt == NumberType.INT) { if (delegateDeser != null) { if (!_valueInstantiator.canCreateFromInt()) { Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt)); if (_injectables != null) { injectValues(ctxt, bean); } return bean; } } return _valueInstantiator.createFromInt(ctxt, p.getIntValue()); } if (nt == NumberType.LONG) { if (delegateDeser != null) { if (!_valueInstantiator.canCreateFromInt()) { Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt)); if (_injectables != null) { injectValues(ctxt, bean); } return bean; } } return _valueInstantiator.createFromLong(ctxt, p.getLongValue()); } // actually, could also be BigInteger, so: if (delegateDeser != null) { Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt)); if (_injectables != null) { injectValues(ctxt, bean); } return bean; } return ctxt.handleMissingInstantiator(handledType(), getValueInstantiator(), p, "no suitable creator method found to deserialize from Number value (%s)", p.getNumberValue()); } public Object deserializeFromString(JsonParser p, DeserializationContext ctxt) throws IOException { // First things first: id Object Id is used, most likely that's it if (_objectIdReader != null) { return deserializeFromObjectId(p, ctxt); } // Bit complicated if we have delegating creator; may need to use it, // or might not... JsonDeserializer delegateDeser = _delegateDeserializer(); if (delegateDeser != null) { if (!_valueInstantiator.canCreateFromString()) { Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt)); if (_injectables != null) { injectValues(ctxt, bean); } return bean; } } return _valueInstantiator.createFromString(ctxt, p.getText()); } /** * Method called to deserialize POJO value from a JSON floating-point * number. */ public Object deserializeFromDouble(JsonParser p, DeserializationContext ctxt) throws IOException { NumberType t = p.getNumberType(); // no separate methods for taking float... if ((t == NumberType.DOUBLE) || (t == NumberType.FLOAT)) { JsonDeserializer delegateDeser = _delegateDeserializer(); if (delegateDeser != null) { if (!_valueInstantiator.canCreateFromDouble()) { Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt)); if (_injectables != null) { injectValues(ctxt, bean); } return bean; } } return _valueInstantiator.createFromDouble(ctxt, p.getDoubleValue()); } // actually, could also be BigDecimal, so: JsonDeserializer delegateDeser = _delegateDeserializer(); if (delegateDeser != null) { return _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt)); } return ctxt.handleMissingInstantiator(handledType(), getValueInstantiator(), p, "no suitable creator method found to deserialize from Number value (%s)", p.getNumberValue()); } /** * Method called to deserialize POJO value from a JSON boolean value (true, false) */ public Object deserializeFromBoolean(JsonParser p, DeserializationContext ctxt) throws IOException { JsonDeserializer delegateDeser = _delegateDeserializer(); if (delegateDeser != null) { if (!_valueInstantiator.canCreateFromBoolean()) { Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt)); if (_injectables != null) { injectValues(ctxt, bean); } return bean; } } boolean value = (p.getCurrentToken() == JsonToken.VALUE_TRUE); return _valueInstantiator.createFromBoolean(ctxt, value); } public Object deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException { // note: cannot call `_delegateDeserializer()` since order reversed here: JsonDeserializer delegateDeser = _arrayDelegateDeserializer; // fallback to non-array delegate if ((delegateDeser != null) || ((delegateDeser = _delegateDeserializer) != null)) { Object bean = _valueInstantiator.createUsingArrayDelegate(ctxt, delegateDeser.deserialize(p, ctxt)); if (_injectables != null) { injectValues(ctxt, bean); } return bean; } if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { JsonToken t = p.nextToken(); if (t == JsonToken.END_ARRAY && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) { return null; } final Object value = deserialize(p, ctxt); if (p.nextToken() != JsonToken.END_ARRAY) { handleMissingEndArrayForSingle(p, ctxt); } return value; } if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) { JsonToken t = p.nextToken(); if (t == JsonToken.END_ARRAY) { return null; } return ctxt.handleUnexpectedToken(handledType(), JsonToken.START_ARRAY, p, null); } return ctxt.handleUnexpectedToken(handledType(), p); } public Object deserializeFromEmbedded(JsonParser p, DeserializationContext ctxt) throws IOException { // First things first: id Object Id is used, most likely that's it; specifically, // true for UUIDs when written as binary (with Smile, other binary formats) if (_objectIdReader != null) { return deserializeFromObjectId(p, ctxt); } // 26-Jul-2017, tatu: as per [databind#1711] need to support delegating case too JsonDeserializer delegateDeser = _delegateDeserializer(); if (delegateDeser != null) { if (!_valueInstantiator.canCreateFromString()) { Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt)); if (_injectables != null) { injectValues(ctxt, bean); } return bean; } } // TODO: maybe add support for ValueInstantiator, embedded? // 26-Jul-2017, tatu: related to [databind#1711], let's actually verify assignment // compatibility before returning. Bound to catch misconfigured cases and produce // more meaningful exceptions. Object value = p.getEmbeddedObject(); if (value != null) { if (!_beanType.isTypeOrSuperTypeOf(value.getClass())) { // allow this to be handled... value = ctxt.handleWeirdNativeValue(_beanType, value, p); } } return value; } /** * @since 2.9 */ private final JsonDeserializer _delegateDeserializer() { JsonDeserializer deser = _delegateDeserializer; if (deser == null) { deser = _arrayDelegateDeserializer; } return deser; } /* /********************************************************** /* Overridable helper methods /********************************************************** */ protected void injectValues(DeserializationContext ctxt, Object bean) throws IOException { for (ValueInjector injector : _injectables) { injector.inject(ctxt, bean); } } /** * Method called to handle set of one or more unknown properties, * stored in their entirety in given {@link TokenBuffer} * (as field entries, name and value). */ @SuppressWarnings("resource") protected Object handleUnknownProperties(DeserializationContext ctxt, Object bean, TokenBuffer unknownTokens) throws IOException { // First: add closing END_OBJECT as marker unknownTokens.writeEndObject(); // note: buffer does NOT have starting START_OBJECT JsonParser bufferParser = unknownTokens.asParser(); while (bufferParser.nextToken() != JsonToken.END_OBJECT) { String propName = bufferParser.getCurrentName(); // Unknown: let's call handler method bufferParser.nextToken(); handleUnknownProperty(bufferParser, ctxt, bean, propName); } return bean; } /** * Helper method called for an unknown property, when using "vanilla" * processing. */ protected void handleUnknownVanilla(JsonParser p, DeserializationContext ctxt, Object bean, String propName) throws IOException { if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, bean, propName); } else if (_anySetter != null) { try { // should we consider return type of any setter? _anySetter.deserializeAndSet(p, ctxt, bean, propName); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } } else { // Unknown: let's call handler method handleUnknownProperty(p, ctxt, bean, propName); } } /** * Method called when a JSON property is encountered that has not matching * setter, any-setter or field, and thus cannot be assigned. */ @Override protected void handleUnknownProperty(JsonParser p, DeserializationContext ctxt, Object beanOrClass, String propName) throws IOException { if (_ignoreAllUnknown) { p.skipChildren(); return; } if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, beanOrClass, propName); } // Otherwise use default handling (call handler(s); if not // handled, throw exception or skip depending on settings) super.handleUnknownProperty(p, ctxt, beanOrClass, propName); } /** * Method called when an explicitly ignored property (one specified with a * name to match, either by property annotation or class annotation) is encountered. * * @since 2.3 */ protected void handleIgnoredProperty(JsonParser p, DeserializationContext ctxt, Object beanOrClass, String propName) throws IOException { if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)) { throw IgnoredPropertyException.from(p, beanOrClass, propName, getKnownPropertyNames()); } p.skipChildren(); } /** * Method called in cases where we may have polymorphic deserialization * case: that is, type of Creator-constructed bean is not the type * of deserializer itself. It should be a sub-class or implementation * class; either way, we may have more specific deserializer to use * for handling it. * * @param p (optional) If not null, parser that has more properties to handle * (in addition to buffered properties); if null, all properties are passed * in buffer */ @SuppressWarnings("resource") protected Object handlePolymorphic(JsonParser p, DeserializationContext ctxt, Object bean, TokenBuffer unknownTokens) throws IOException { // First things first: maybe there is a more specific deserializer available? JsonDeserializer subDeser = _findSubclassDeserializer(ctxt, bean, unknownTokens); if (subDeser != null) { if (unknownTokens != null) { // need to add END_OBJECT marker first unknownTokens.writeEndObject(); JsonParser p2 = unknownTokens.asParser(); p2.nextToken(); // to get to first data field bean = subDeser.deserialize(p2, ctxt, bean); } // Original parser may also have some leftovers if (p != null) { bean = subDeser.deserialize(p, ctxt, bean); } return bean; } // nope; need to use this deserializer. Unknowns we've seen so far? if (unknownTokens != null) { bean = handleUnknownProperties(ctxt, bean, unknownTokens); } // and/or things left to process via main parser? if (p != null) { bean = deserialize(p, ctxt, bean); } return bean; } /** * Helper method called to (try to) locate deserializer for given sub-type of * type that this deserializer handles. */ protected JsonDeserializer _findSubclassDeserializer(DeserializationContext ctxt, Object bean, TokenBuffer unknownTokens) throws IOException { JsonDeserializer subDeser; // First: maybe we have already created sub-type deserializer? synchronized (this) { subDeser = (_subDeserializers == null) ? null : _subDeserializers.get(new ClassKey(bean.getClass())); } if (subDeser != null) { return subDeser; } // If not, maybe we can locate one. First, need provider JavaType type = ctxt.constructType(bean.getClass()); /* 30-Jan-2012, tatu: Ideally we would be passing referring * property; which in theory we could keep track of via * ResolvableDeserializer (if we absolutely must...). * But for now, let's not bother. */ // subDeser = ctxt.findValueDeserializer(type, _property); subDeser = ctxt.findRootValueDeserializer(type); // Also, need to cache it if (subDeser != null) { synchronized (this) { if (_subDeserializers == null) { _subDeserializers = new HashMap>();; } _subDeserializers.put(new ClassKey(bean.getClass()), subDeser); } } return subDeser; } /* /********************************************************** /* Helper methods for error reporting /********************************************************** */ /** * Method that will modify caught exception (passed in as argument) * as necessary to include reference information, and to ensure it * is a subtype of {@link IOException}, or an unchecked exception. *

* Rules for wrapping and unwrapping are bit complicated; essentially: *

    *
  • Errors are to be passed as is (if uncovered via unwrapping) *
  • "Plain" IOExceptions (ones that are not of type * {@link JsonMappingException} are to be passed as is *
*/ public void wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt) throws IOException { // Need to add reference information throw JsonMappingException.wrapWithPath(throwOrReturnThrowable(t, ctxt), bean, fieldName); } private Throwable throwOrReturnThrowable(Throwable t, DeserializationContext ctxt) throws IOException { /* 05-Mar-2009, tatu: But one nasty edge is when we get * StackOverflow: usually due to infinite loop. But that * often gets hidden within an InvocationTargetException... */ while (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } // Errors to be passed as is ClassUtil.throwIfError(t); boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS); // Ditto for IOExceptions; except we may want to wrap JSON exceptions if (t instanceof IOException) { if (!wrap || !(t instanceof JsonProcessingException)) { throw (IOException) t; } } else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions ClassUtil.throwIfRTE(t); } return t; } protected Object wrapInstantiationProblem(Throwable t, DeserializationContext ctxt) throws IOException { while (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } // Errors and "plain" IOExceptions to be passed as is ClassUtil.throwIfError(t); if (t instanceof IOException) { // Since we have no more information to add, let's not actually wrap.. throw (IOException) t; } boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS); if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions ClassUtil.throwIfRTE(t); } return ctxt.handleInstantiationProblem(_beanType.getRawClass(), null, t); } } BeanDeserializerBuilder.java000066400000000000000000000442621325620701100371440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap; import com.fasterxml.jackson.databind.deser.impl.ObjectIdValueProperty; import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader; import com.fasterxml.jackson.databind.deser.impl.ValueInjector; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.util.Annotations; /** * Builder class used for aggregating deserialization information about * a POJO, in order to build a {@link JsonDeserializer} for deserializing * instances. */ public class BeanDeserializerBuilder { /* /********************************************************** /* Configuration /********************************************************** */ final protected DeserializationConfig _config; /** * @since 2.9 */ final protected DeserializationContext _context; /* /********************************************************** /* General information about POJO /********************************************************** */ /** * Introspected information about POJO for deserializer to handle */ final protected BeanDescription _beanDesc; /* /********************************************************** /* Accumulated information about properties /********************************************************** */ /** * Properties to deserialize collected so far. */ final protected Map _properties = new LinkedHashMap(); /** * Value injectors for deserialization */ protected List _injectables; /** * Back-reference properties this bean contains (if any) */ protected HashMap _backRefProperties; /** * Set of names of properties that are recognized but are to be ignored for deserialization * purposes (meaning no exception is thrown, value is just skipped). */ protected HashSet _ignorableProps; /** * Object that will handle value instantiation for the bean type. */ protected ValueInstantiator _valueInstantiator; /** * Handler for Object Id values, if Object Ids are enabled for the * bean type. */ protected ObjectIdReader _objectIdReader; /** * Fallback setter used for handling any properties that are not * mapped to regular setters. If setter is not null, it will be * called once for each such property. */ protected SettableAnyProperty _anySetter; /** * Flag that can be set to ignore and skip unknown properties. * If set, will not throw an exception for unknown properties. */ protected boolean _ignoreAllUnknown; /** * When creating Builder-based deserializers, this indicates * method to call on builder to finalize value. */ protected AnnotatedMethod _buildMethod; /** * In addition, Builder may have additional configuration */ protected JsonPOJOBuilder.Value _builderConfig; /* /********************************************************** /* Life-cycle: construction /********************************************************** */ public BeanDeserializerBuilder(BeanDescription beanDesc, DeserializationContext ctxt) { _beanDesc = beanDesc; _context = ctxt; _config = ctxt.getConfig(); } /** * Copy constructor for sub-classes to use, when constructing * custom builder instances */ protected BeanDeserializerBuilder(BeanDeserializerBuilder src) { _beanDesc = src._beanDesc; _context = src._context; _config = src._config; // let's make copy of properties _properties.putAll(src._properties); _injectables = _copy(src._injectables); _backRefProperties = _copy(src._backRefProperties); // Hmmh. Should we create defensive copies here? For now, not yet _ignorableProps = src._ignorableProps; _valueInstantiator = src._valueInstantiator; _objectIdReader = src._objectIdReader; _anySetter = src._anySetter; _ignoreAllUnknown = src._ignoreAllUnknown; _buildMethod = src._buildMethod; _builderConfig = src._builderConfig; } private static HashMap _copy(HashMap src) { return (src == null) ? null : new HashMap(src); } private static List _copy(List src) { return (src == null) ? null : new ArrayList(src); } /* /********************************************************** /* Life-cycle: state modification (adders, setters) /********************************************************** */ /** * Method for adding a new property or replacing a property. */ public void addOrReplaceProperty(SettableBeanProperty prop, boolean allowOverride) { _properties.put(prop.getName(), prop); } /** * Method to add a property setter. Will ensure that there is no * unexpected override; if one is found will throw a * {@link IllegalArgumentException}. */ public void addProperty(SettableBeanProperty prop) { SettableBeanProperty old = _properties.put(prop.getName(), prop); if (old != null && old != prop) { // should never occur... throw new IllegalArgumentException("Duplicate property '"+prop.getName()+"' for "+_beanDesc.getType()); } } /** * Method called to add a property that represents so-called back reference; * reference that "points back" to object that has forward reference to * currently built bean. */ public void addBackReferenceProperty(String referenceName, SettableBeanProperty prop) { if (_backRefProperties == null) { _backRefProperties = new HashMap(4); } // 15-Sep-2016, tatu: For some reason fixing access at point of `build()` does // NOT work (2 failing unit tests). Not 100% clear why, but for now force // access set early; unfortunate, but since it works.... prop.fixAccess(_config); _backRefProperties.put(referenceName, prop); // 16-Jan-2018, tatu: As per [databind#1878] we may want to leave it as is, to allow // population for cases of "wrong direction", traversing parent first // If this causes problems should probably instead include in "ignored properties" list // Alternatively could also extend annotation to allow/disallow explicit value from input /* if (_properties != null) { _properties.remove(prop.getName()); } */ } public void addInjectable(PropertyName propName, JavaType propType, Annotations contextAnnotations, AnnotatedMember member, Object valueId) { if (_injectables == null) { _injectables = new ArrayList(); } boolean fixAccess = _config.canOverrideAccessModifiers(); boolean forceAccess = fixAccess && _config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS); if (fixAccess) { member.fixAccess(forceAccess); } _injectables.add(new ValueInjector(propName, propType, member, valueId)); } /** * Method that will add property name as one of properties that can * be ignored if not recognized. */ public void addIgnorable(String propName) { if (_ignorableProps == null) { _ignorableProps = new HashSet(); } _ignorableProps.add(propName); } /** * Method called by deserializer factory, when a "creator property" * (something that is passed via constructor- or factory method argument; * instead of setter or field). *

* Default implementation does not do anything; we may need to revisit this * decision if these properties need to be available through accessors. * For now, however, we just have to ensure that we don't try to resolve * types that masked setter/field has (see [JACKSON-700] for details). */ public void addCreatorProperty(SettableBeanProperty prop) { addProperty(prop); } public void setAnySetter(SettableAnyProperty s) { if (_anySetter != null && s != null) { throw new IllegalStateException("_anySetter already set to non-null"); } _anySetter = s; } public void setIgnoreUnknownProperties(boolean ignore) { _ignoreAllUnknown = ignore; } public void setValueInstantiator(ValueInstantiator inst) { _valueInstantiator = inst; } public void setObjectIdReader(ObjectIdReader r) { _objectIdReader = r; } public void setPOJOBuilder(AnnotatedMethod buildMethod, JsonPOJOBuilder.Value config) { _buildMethod = buildMethod; _builderConfig = config; } /* /********************************************************** /* Public accessors /********************************************************** */ /** * Method that allows accessing all properties that this * builder currently contains. *

* Note that properties are returned in order that properties * are ordered (explictly, or by rule), which is the serialization * order. */ public Iterator getProperties() { return _properties.values().iterator(); } public SettableBeanProperty findProperty(PropertyName propertyName) { return _properties.get(propertyName.getSimpleName()); } public boolean hasProperty(PropertyName propertyName) { return findProperty(propertyName) != null; } public SettableBeanProperty removeProperty(PropertyName name) { return _properties.remove(name.getSimpleName()); } public SettableAnyProperty getAnySetter() { return _anySetter; } public ValueInstantiator getValueInstantiator() { return _valueInstantiator; } public List getInjectables() { return _injectables; } public ObjectIdReader getObjectIdReader() { return _objectIdReader; } public AnnotatedMethod getBuildMethod() { return _buildMethod; } public JsonPOJOBuilder.Value getBuilderConfig() { return _builderConfig; } /** * @since 2.9.4 */ public boolean hasIgnorable(String name) { return (_ignorableProps != null) && _ignorableProps.contains(name); } /* /********************************************************** /* Build method(s) /********************************************************** */ /** * Method for constructing a {@link BeanDeserializer}, given all * information collected. */ public JsonDeserializer build() { Collection props = _properties.values(); _fixAccess(props); BeanPropertyMap propertyMap = BeanPropertyMap.construct(props, _config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES), _collectAliases(props)); propertyMap.assignIndexes(); // view processing must be enabled if: // (a) fields are not included by default (when deserializing with view), OR // (b) one of properties has view(s) to included in defined boolean anyViews = !_config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION); if (!anyViews) { for (SettableBeanProperty prop : props) { if (prop.hasViews()) { anyViews = true; break; } } } // one more thing: may need to create virtual ObjectId property: if (_objectIdReader != null) { /* 18-Nov-2012, tatu: May or may not have annotations for id property; * but no easy access. But hard to see id property being optional, * so let's consider required at this point. */ ObjectIdValueProperty prop = new ObjectIdValueProperty(_objectIdReader, PropertyMetadata.STD_REQUIRED); propertyMap = propertyMap.withProperty(prop); } return new BeanDeserializer(this, _beanDesc, propertyMap, _backRefProperties, _ignorableProps, _ignoreAllUnknown, anyViews); } /** * Alternate build method used when we must be using some form of * abstract resolution, usually by using addition Type Id * ("polymorphic deserialization") * * @since 2.0 */ public AbstractDeserializer buildAbstract() { return new AbstractDeserializer(this, _beanDesc, _backRefProperties, _properties); } /** * Method for constructing a specialized deserializer that uses * additional external Builder object during data binding. */ public JsonDeserializer buildBuilderBased(JavaType valueType, String expBuildMethodName) throws JsonMappingException { // First: validation; must have build method that returns compatible type if (_buildMethod == null) { // as per [databind#777], allow empty name if (!expBuildMethodName.isEmpty()) { _context.reportBadDefinition(_beanDesc.getType(), String.format("Builder class %s does not have build method (name: '%s')", _beanDesc.getBeanClass().getName(), expBuildMethodName)); } } else { // also: type of the method must be compatible Class rawBuildType = _buildMethod.getRawReturnType(); Class rawValueType = valueType.getRawClass(); if ((rawBuildType != rawValueType) && !rawBuildType.isAssignableFrom(rawValueType) && !rawValueType.isAssignableFrom(rawBuildType)) { _context.reportBadDefinition(_beanDesc.getType(), String.format("Build method '%s' has wrong return type (%s), not compatible with POJO type (%s)", _buildMethod.getFullName(), rawBuildType.getName(), valueType.getRawClass().getName())); } } // And if so, we can try building the deserializer Collection props = _properties.values(); _fixAccess(props); BeanPropertyMap propertyMap = BeanPropertyMap.construct(props, _config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES), _collectAliases(props)); propertyMap.assignIndexes(); boolean anyViews = !_config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION); if (!anyViews) { for (SettableBeanProperty prop : props) { if (prop.hasViews()) { anyViews = true; break; } } } if (_objectIdReader != null) { // May or may not have annotations for id property; but no easy access. // But hard to see id property being optional, so let's consider required at this point. ObjectIdValueProperty prop = new ObjectIdValueProperty(_objectIdReader, PropertyMetadata.STD_REQUIRED); propertyMap = propertyMap.withProperty(prop); } return new BuilderBasedDeserializer(this, _beanDesc, valueType, propertyMap, _backRefProperties, _ignorableProps, _ignoreAllUnknown, anyViews); } /* /********************************************************** /* Internal helper method(s) /********************************************************** */ protected void _fixAccess(Collection mainProps) { /* 07-Sep-2016, tatu: Ideally we should be able to avoid forcing * access to properties that are likely ignored, but due to * renaming it seems this is not a safe thing to do (there was * at least one failing test). May need to dig deeper in future; * for now let's just play it safe. */ /* Set ignorable = _ignorableProps; if (ignorable == null) { ignorable = Collections.emptySet(); } */ for (SettableBeanProperty prop : mainProps) { /* // first: no point forcing access on to-be-ignored properties if (ignorable.contains(prop.getName())) { continue; } */ prop.fixAccess(_config); } // 15-Sep-2016, tatu: Access via back-ref properties has been done earlier // as it has to, for some reason, so not repeated here. /* if (_backRefProperties != null) { for (SettableBeanProperty prop : _backRefProperties.values()) { prop.fixAccess(_config); } } */ if (_anySetter != null) { _anySetter.fixAccess(_config); } if (_buildMethod != null) { _buildMethod.fixAccess(_config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } } protected Map> _collectAliases(Collection props) { Map> mapping = null; AnnotationIntrospector intr = _config.getAnnotationIntrospector(); if (intr != null) { for (SettableBeanProperty prop : props) { List aliases = intr.findPropertyAliases(prop.getMember()); if ((aliases == null) || aliases.isEmpty()) { continue; } if (mapping == null) { mapping = new HashMap<>(); } mapping.put(prop.getName(), aliases); } } if (mapping == null) { return Collections.emptyMap(); } return mapping; } } BeanDeserializerFactory.java000066400000000000000000001231561325620701100371650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig; import com.fasterxml.jackson.databind.deser.impl.*; import com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.jsontype.impl.SubTypeValidator; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition; /** * Concrete deserializer factory class that adds full Bean deserializer * construction logic using class introspection. * Note that factories specifically do not implement any form of caching: * aside from configuration they are stateless; caching is implemented * by other components. *

* Instances of this class are fully immutable as all configuration is * done by using "fluent factories" (methods that construct new factory * instances with different configuration, instead of modifying instance). */ public class BeanDeserializerFactory extends BasicDeserializerFactory implements java.io.Serializable // since 2.1 { private static final long serialVersionUID = 1; /** * Signature of Throwable.initCause method. */ private final static Class[] INIT_CAUSE_PARAMS = new Class[] { Throwable.class }; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * Globally shareable thread-safe instance which has no additional custom deserializers * registered */ public final static BeanDeserializerFactory instance = new BeanDeserializerFactory( new DeserializerFactoryConfig()); public BeanDeserializerFactory(DeserializerFactoryConfig config) { super(config); } /** * Method used by module registration functionality, to construct a new bean * deserializer factory * with different configuration settings. */ @Override public DeserializerFactory withConfig(DeserializerFactoryConfig config) { if (_factoryConfig == config) { return this; } /* 22-Nov-2010, tatu: Handling of subtypes is tricky if we do immutable-with-copy-ctor; * and we pretty much have to here either choose between losing subtype instance * when registering additional deserializers, or losing deserializers. * Instead, let's actually just throw an error if this method is called when subtype * has not properly overridden this method; this to indicate problem as soon as possible. */ ClassUtil.verifyMustOverride(BeanDeserializerFactory.class, this, "withConfig"); return new BeanDeserializerFactory(config); } /* /********************************************************** /* DeserializerFactory API implementation /********************************************************** */ /** * Method that {@link DeserializerCache}s call to create a new * deserializer for types other than Collections, Maps, arrays and * enums. */ @Override public JsonDeserializer createBeanDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); // We may also have custom overrides: JsonDeserializer custom = _findCustomBeanDeserializer(type, config, beanDesc); if (custom != null) { return custom; } /* One more thing to check: do we have an exception type * (Throwable or its sub-classes)? If so, need slightly * different handling. */ if (type.isThrowable()) { return buildThrowableDeserializer(ctxt, type, beanDesc); } // Or, for abstract types, may have alternate means for resolution // (defaulting, materialization) // 29-Nov-2015, tatu: Also, filter out calls to primitive types, they are // not something we could materialize anything for if (type.isAbstract() && !type.isPrimitive() && !type.isEnumType()) { // Let's make it possible to materialize abstract types. JavaType concreteType = materializeAbstractType(ctxt, type, beanDesc); if (concreteType != null) { /* important: introspect actual implementation (abstract class or * interface doesn't have constructors, for one) */ beanDesc = config.introspect(concreteType); return buildBeanDeserializer(ctxt, concreteType, beanDesc); } } // Otherwise, may want to check handlers for standard types, from superclass: @SuppressWarnings("unchecked") JsonDeserializer deser = (JsonDeserializer) findStdDeserializer(ctxt, type, beanDesc); if (deser != null) { return deser; } // Otherwise: could the class be a Bean class? If not, bail out if (!isPotentialBeanType(type.getRawClass())) { return null; } // For checks like [databind#1599] _validateSubType(ctxt, type, beanDesc); // Use generic bean introspection to build deserializer return buildBeanDeserializer(ctxt, type, beanDesc); } @Override public JsonDeserializer createBuilderBasedDeserializer(DeserializationContext ctxt, JavaType valueType, BeanDescription beanDesc, Class builderClass) throws JsonMappingException { // First: need a BeanDescription for builder class JavaType builderType = ctxt.constructType(builderClass); BeanDescription builderDesc = ctxt.getConfig().introspectForBuilder(builderType); return buildBuilderBasedDeserializer(ctxt, valueType, builderDesc); } /** * Method called by {@link BeanDeserializerFactory} to see if there might be a standard * deserializer registered for given type. */ protected JsonDeserializer findStdDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { // note: we do NOT check for custom deserializers here, caller has already // done that JsonDeserializer deser = findDefaultDeserializer(ctxt, type, beanDesc); // Also: better ensure these are post-processable? if (deser != null) { if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deser = mod.modifyDeserializer(ctxt.getConfig(), beanDesc, deser); } } } return deser; } protected JavaType materializeAbstractType(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { // May have multiple resolvers, call in precedence order until one returns non-null for (AbstractTypeResolver r : _factoryConfig.abstractTypeResolvers()) { JavaType concrete = r.resolveAbstractType(ctxt.getConfig(), beanDesc); if (concrete != null) { return concrete; } } return null; } /* /********************************************************** /* Public construction method beyond DeserializerFactory API: /* can be called from outside as well as overridden by /* sub-classes /********************************************************** */ /** * Method that is to actually build a bean deserializer instance. * All basic sanity checks have been done to know that what we have * may be a valid bean type, and that there are no default simple * deserializers. */ @SuppressWarnings("unchecked") public JsonDeserializer buildBeanDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { // First: check what creators we can use, if any ValueInstantiator valueInstantiator; /* 04-Jun-2015, tatu: To work around [databind#636], need to catch the * issue, defer; this seems like a reasonable good place for now. * Note, however, that for non-Bean types (Collections, Maps) this * probably won't work and needs to be added elsewhere. */ try { valueInstantiator = findValueInstantiator(ctxt, beanDesc); } catch (NoClassDefFoundError error) { return new ErrorThrowingDeserializer(error); } catch (IllegalArgumentException e) { // 05-Apr-2017, tatu: Although it might appear cleaner to require collector // to throw proper exception, it doesn't actually have reference to this // instance so... throw InvalidDefinitionException.from(ctxt.getParser(), e.getMessage(), beanDesc, null); } BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(ctxt, beanDesc); builder.setValueInstantiator(valueInstantiator); // And then setters for deserializing from JSON Object addBeanProps(ctxt, beanDesc, builder); addObjectIdReader(ctxt, beanDesc, builder); // managed/back reference fields/setters need special handling... first part addBackReferenceProperties(ctxt, beanDesc, builder); addInjectables(ctxt, beanDesc, builder); final DeserializationConfig config = ctxt.getConfig(); if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { builder = mod.updateBuilder(config, beanDesc, builder); } } JsonDeserializer deserializer; if (type.isAbstract() && !valueInstantiator.canInstantiate()) { deserializer = builder.buildAbstract(); } else { deserializer = builder.build(); } // may have modifier(s) that wants to modify or replace serializer we just built // (note that `resolve()` and `createContextual()` called later on) if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deserializer = mod.modifyDeserializer(config, beanDesc, deserializer); } } return (JsonDeserializer) deserializer; } /** * Method for constructing a bean deserializer that uses specified * intermediate Builder for binding data, and construction of the * value instance. * Note that implementation is mostly copied from the regular * BeanDeserializer build method. */ @SuppressWarnings("unchecked") protected JsonDeserializer buildBuilderBasedDeserializer( DeserializationContext ctxt, JavaType valueType, BeanDescription builderDesc) throws JsonMappingException { // Creators, anyone? (to create builder itself) ValueInstantiator valueInstantiator; try { valueInstantiator = findValueInstantiator(ctxt, builderDesc); } catch (NoClassDefFoundError error) { return new ErrorThrowingDeserializer(error); } catch (IllegalArgumentException e) { // 05-Apr-2017, tatu: Although it might appear cleaner to require collector // to throw proper exception, it doesn't actually have reference to this // instance so... throw InvalidDefinitionException.from(ctxt.getParser(), e.getMessage(), builderDesc, null); } final DeserializationConfig config = ctxt.getConfig(); BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(ctxt, builderDesc); builder.setValueInstantiator(valueInstantiator); // And then "with methods" for deserializing from JSON Object addBeanProps(ctxt, builderDesc, builder); addObjectIdReader(ctxt, builderDesc, builder); // managed/back reference fields/setters need special handling... first part addBackReferenceProperties(ctxt, builderDesc, builder); addInjectables(ctxt, builderDesc, builder); JsonPOJOBuilder.Value builderConfig = builderDesc.findPOJOBuilderConfig(); final String buildMethodName = (builderConfig == null) ? JsonPOJOBuilder.DEFAULT_BUILD_METHOD : builderConfig.buildMethodName; // and lastly, find build method to use: AnnotatedMethod buildMethod = builderDesc.findMethod(buildMethodName, null); if (buildMethod != null) { // note: can't yet throw error; may be given build method if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(buildMethod.getMember(), config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } } builder.setPOJOBuilder(buildMethod, builderConfig); // this may give us more information... if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { builder = mod.updateBuilder(config, builderDesc, builder); } } JsonDeserializer deserializer = builder.buildBuilderBased( valueType, buildMethodName); // [JACKSON-440]: may have modifier(s) that wants to modify or replace serializer we just built: if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deserializer = mod.modifyDeserializer(config, builderDesc, deserializer); } } return (JsonDeserializer) deserializer; } protected void addObjectIdReader(DeserializationContext ctxt, BeanDescription beanDesc, BeanDeserializerBuilder builder) throws JsonMappingException { ObjectIdInfo objectIdInfo = beanDesc.getObjectIdInfo(); if (objectIdInfo == null) { return; } Class implClass = objectIdInfo.getGeneratorType(); JavaType idType; SettableBeanProperty idProp; ObjectIdGenerator gen; ObjectIdResolver resolver = ctxt.objectIdResolverInstance(beanDesc.getClassInfo(), objectIdInfo); // Just one special case: Property-based generator is trickier if (implClass == ObjectIdGenerators.PropertyGenerator.class) { // most special one, needs extra work PropertyName propName = objectIdInfo.getPropertyName(); idProp = builder.findProperty(propName); if (idProp == null) { throw new IllegalArgumentException("Invalid Object Id definition for " +beanDesc.getBeanClass().getName()+": cannot find property with name '"+propName+"'"); } idType = idProp.getType(); gen = new PropertyBasedObjectIdGenerator(objectIdInfo.getScope()); } else { JavaType type = ctxt.constructType(implClass); idType = ctxt.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0]; idProp = null; gen = ctxt.objectIdGeneratorInstance(beanDesc.getClassInfo(), objectIdInfo); } // also: unlike with value deserializers, let's just resolve one we need here JsonDeserializer deser = ctxt.findRootValueDeserializer(idType); builder.setObjectIdReader(ObjectIdReader.construct(idType, objectIdInfo.getPropertyName(), gen, deser, idProp, resolver)); } @SuppressWarnings("unchecked") public JsonDeserializer buildThrowableDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); // first: construct like a regular bean deserializer... BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(ctxt, beanDesc); builder.setValueInstantiator(findValueInstantiator(ctxt, beanDesc)); addBeanProps(ctxt, beanDesc, builder); // (and assume there won't be any back references) // But then let's decorate things a bit // Need to add "initCause" as setter for exceptions (sub-classes of Throwable). AnnotatedMethod am = beanDesc.findMethod("initCause", INIT_CAUSE_PARAMS); if (am != null) { // should never be null SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(ctxt.getConfig(), am, new PropertyName("cause")); SettableBeanProperty prop = constructSettableProperty(ctxt, beanDesc, propDef, am.getParameterType(0)); if (prop != null) { // 21-Aug-2011, tatus: We may actually have found 'cause' property // to set... but let's replace it just in case, otherwise can end up with odd errors. builder.addOrReplaceProperty(prop, true); } } // And also need to ignore "localizedMessage" builder.addIgnorable("localizedMessage"); // Java 7 also added "getSuppressed", skip if we have such data: builder.addIgnorable("suppressed"); // As well as "message": it will be passed via constructor, // as there's no 'setMessage()' method // 23-Jan-2018, tatu: ... although there MAY be Creator Property... which is problematic // builder.addIgnorable("message"); // update builder now that all information is in? if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { builder = mod.updateBuilder(config, beanDesc, builder); } } JsonDeserializer deserializer = builder.build(); /* At this point it ought to be a BeanDeserializer; if not, must assume * it's some other thing that can handle deserialization ok... */ if (deserializer instanceof BeanDeserializer) { deserializer = new ThrowableDeserializer((BeanDeserializer) deserializer); } // may have modifier(s) that wants to modify or replace serializer we just built: if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { deserializer = mod.modifyDeserializer(config, beanDesc, deserializer); } } return (JsonDeserializer) deserializer; } /* /********************************************************** /* Helper methods for Bean deserializer construction, /* overridable by sub-classes /********************************************************** */ /** * Overridable method that constructs a {@link BeanDeserializerBuilder} * which is used to accumulate information needed to create deserializer * instance. */ protected BeanDeserializerBuilder constructBeanDeserializerBuilder(DeserializationContext ctxt, BeanDescription beanDesc) { return new BeanDeserializerBuilder(beanDesc, ctxt); } /** * Method called to figure out settable properties for the * bean deserializer to use. *

* Note: designed to be overridable, and effort is made to keep interface * similar between versions. */ protected void addBeanProps(DeserializationContext ctxt, BeanDescription beanDesc, BeanDeserializerBuilder builder) throws JsonMappingException { final boolean isConcrete = !beanDesc.getType().isAbstract(); final SettableBeanProperty[] creatorProps = isConcrete ? builder.getValueInstantiator().getFromObjectArguments(ctxt.getConfig()) : null; final boolean hasCreatorProps = (creatorProps != null); // 01-May-2016, tatu: Which base type to use here gets tricky, since // it may often make most sense to use general type for overrides, // but what we have here may be more specific impl type. But for now // just use it as is. JsonIgnoreProperties.Value ignorals = ctxt.getConfig() .getDefaultPropertyIgnorals(beanDesc.getBeanClass(), beanDesc.getClassInfo()); Set ignored; if (ignorals != null) { boolean ignoreAny = ignorals.getIgnoreUnknown(); builder.setIgnoreUnknownProperties(ignoreAny); // Or explicit/implicit definitions? ignored = ignorals.findIgnoredForDeserialization(); for (String propName : ignored) { builder.addIgnorable(propName); } } else { ignored = Collections.emptySet(); } // Also, do we have a fallback "any" setter? AnnotatedMember anySetter = beanDesc.findAnySetterAccessor(); if (anySetter != null) { builder.setAnySetter(constructAnySetter(ctxt, beanDesc, anySetter)); } else { // 23-Jan-2018, tatu: although [databind#1805] would suggest we should block // properties regardless, for now only consider unless there's any setter... Collection ignored2 = beanDesc.getIgnoredPropertyNames(); if (ignored2 != null) { for (String propName : ignored2) { // allow ignoral of similarly named JSON property, but do not force; // latter means NOT adding this to 'ignored': builder.addIgnorable(propName); } } } final boolean useGettersAsSetters = ctxt.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS) && ctxt.isEnabled(MapperFeature.AUTO_DETECT_GETTERS); // Ok: let's then filter out property definitions List propDefs = filterBeanProps(ctxt, beanDesc, builder, beanDesc.findProperties(), ignored); // After which we can let custom code change the set if (_factoryConfig.hasDeserializerModifiers()) { for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { propDefs = mod.updateProperties(ctxt.getConfig(), beanDesc, propDefs); } } // At which point we still have all kinds of properties; not all with mutators: for (BeanPropertyDefinition propDef : propDefs) { SettableBeanProperty prop = null; // 18-Oct-2013, tatu: Although constructor parameters have highest precedence, // we need to do linkage (as per [databind#318]), and so need to start with // other types, and only then create constructor parameter, if any. if (propDef.hasSetter()) { AnnotatedMethod setter = propDef.getSetter(); JavaType propertyType = setter.getParameterType(0); prop = constructSettableProperty(ctxt, beanDesc, propDef, propertyType); } else if (propDef.hasField()) { AnnotatedField field = propDef.getField(); JavaType propertyType = field.getType(); prop = constructSettableProperty(ctxt, beanDesc, propDef, propertyType); } else { // NOTE: specifically getter, since field was already checked above AnnotatedMethod getter = propDef.getGetter(); if (getter != null) { if (useGettersAsSetters && _isSetterlessType(getter.getRawType())) { // 23-Jan-2018, tatu: As per [databind#1805], need to ensure we don't // accidentally sneak in getter-as-setter for `READ_ONLY` properties if (builder.hasIgnorable(propDef.getName())) { ; } else { prop = constructSetterlessProperty(ctxt, beanDesc, propDef); } } else if (!propDef.hasConstructorParameter()) { PropertyMetadata md = propDef.getMetadata(); // 25-Oct-2016, tatu: If merging enabled, might not need setter. // We cannot quite support this with creator parameters; in theory // possibly, but right not not due to complexities of routing, so // just prevent if (md.getMergeInfo() != null) { prop = constructSetterlessProperty(ctxt, beanDesc, propDef); } } } } // 25-Sep-2014, tatu: No point in finding constructor parameters for abstract types // (since they are never used anyway) if (hasCreatorProps && propDef.hasConstructorParameter()) { /* If property is passed via constructor parameter, we must * handle things in special way. Not sure what is the most optimal way... * for now, let's just call a (new) method in builder, which does nothing. */ // but let's call a method just to allow custom builders to be aware... final String name = propDef.getName(); CreatorProperty cprop = null; if (creatorProps != null) { for (SettableBeanProperty cp : creatorProps) { if (name.equals(cp.getName()) && (cp instanceof CreatorProperty)) { cprop = (CreatorProperty) cp; break; } } } if (cprop == null) { List n = new ArrayList<>(); for (SettableBeanProperty cp : creatorProps) { n.add(cp.getName()); } ctxt.reportBadPropertyDefinition(beanDesc, propDef, "Could not find creator property with name '%s' (known Creator properties: %s)", name, n); continue; } if (prop != null) { cprop.setFallbackSetter(prop); } Class[] views = propDef.findViews(); if (views == null) { views = beanDesc.findDefaultViews(); } cprop.setViews(views); builder.addCreatorProperty(cprop); continue; } if (prop != null) { // one more thing before adding to builder: copy any metadata Class[] views = propDef.findViews(); if (views == null) { views = beanDesc.findDefaultViews(); } prop.setViews(views); builder.addProperty(prop); } } } private boolean _isSetterlessType(Class rawType) { // May also need to consider getters // for Map/Collection properties; but with lowest precedence // should only consider Collections and Maps, for now? return Collection.class.isAssignableFrom(rawType) || Map.class.isAssignableFrom(rawType); } /** * Helper method called to filter out explicit ignored properties, * as well as properties that have "ignorable types". * Note that this will not remove properties that have no * setters. */ protected List filterBeanProps(DeserializationContext ctxt, BeanDescription beanDesc, BeanDeserializerBuilder builder, List propDefsIn, Set ignored) throws JsonMappingException { ArrayList result = new ArrayList( Math.max(4, propDefsIn.size())); HashMap,Boolean> ignoredTypes = new HashMap,Boolean>(); // These are all valid setters, but we do need to introspect bit more for (BeanPropertyDefinition property : propDefsIn) { String name = property.getName(); if (ignored.contains(name)) { // explicit ignoral using @JsonIgnoreProperties needs to block entries continue; } if (!property.hasConstructorParameter()) { // never skip constructor params Class rawPropertyType = property.getRawPrimaryType(); // Some types are declared as ignorable as well if ((rawPropertyType != null) && isIgnorableType(ctxt.getConfig(), property, rawPropertyType, ignoredTypes)) { // important: make ignorable, to avoid errors if value is actually seen builder.addIgnorable(name); continue; } } result.add(property); } return result; } /** * Method that will find if bean has any managed- or back-reference properties, * and if so add them to bean, to be linked during resolution phase. * * @since 2.9 */ protected void addBackReferenceProperties(DeserializationContext ctxt, BeanDescription beanDesc, BeanDeserializerBuilder builder) throws JsonMappingException { // and then back references, not necessarily found as regular properties List refProps = beanDesc.findBackReferences(); if (refProps != null) { for (BeanPropertyDefinition refProp : refProps) { /* AnnotatedMember m = refProp.getMutator(); JavaType type; if (m instanceof AnnotatedMethod) { type = ((AnnotatedMethod) m).getParameterType(0); } else { type = m.getType(); // 30-Mar-2017, tatu: Unfortunately it is not yet possible to make back-refs // work through constructors; but let's at least indicate the issue for now if (m instanceof AnnotatedParameter) { ctxt.reportBadTypeDefinition(beanDesc, "Cannot bind back reference using Creator parameter (reference '%s', parameter index #%d)", name, ((AnnotatedParameter) m).getIndex()); } } */ String refName = refProp.findReferenceName(); builder.addBackReferenceProperty(refName, constructSettableProperty(ctxt, beanDesc, refProp, refProp.getPrimaryType())); } } } @Deprecated // since 2.9 (rename) protected void addReferenceProperties(DeserializationContext ctxt, BeanDescription beanDesc, BeanDeserializerBuilder builder) throws JsonMappingException { addBackReferenceProperties(ctxt, beanDesc, builder); } /** * Method called locate all members used for value injection (if any), * constructor {@link com.fasterxml.jackson.databind.deser.impl.ValueInjector} instances, and add them to builder. */ protected void addInjectables(DeserializationContext ctxt, BeanDescription beanDesc, BeanDeserializerBuilder builder) throws JsonMappingException { Map raw = beanDesc.findInjectables(); if (raw != null) { for (Map.Entry entry : raw.entrySet()) { AnnotatedMember m = entry.getValue(); builder.addInjectable(PropertyName.construct(m.getName()), m.getType(), beanDesc.getClassAnnotations(), m, entry.getKey()); } } } /** * Method called to construct fallback {@link SettableAnyProperty} * for handling unknown bean properties, given a method that * has been designated as such setter. * * @param mutator Either 2-argument method (setter, with key and value), or Field * that contains Map; either way accessor used for passing "any values" */ @SuppressWarnings("unchecked") protected SettableAnyProperty constructAnySetter(DeserializationContext ctxt, BeanDescription beanDesc, AnnotatedMember mutator) throws JsonMappingException { //find the java type based on the annotated setter method or setter field BeanProperty prop; JavaType keyType; JavaType valueType; if (mutator instanceof AnnotatedMethod) { // we know it's a 2-arg method, second arg is the value AnnotatedMethod am = (AnnotatedMethod) mutator; keyType = am.getParameterType(0); valueType = am.getParameterType(1); valueType = resolveMemberAndTypeAnnotations(ctxt, mutator, valueType); prop = new BeanProperty.Std(PropertyName.construct(mutator.getName()), valueType, null, mutator, PropertyMetadata.STD_OPTIONAL); } else if (mutator instanceof AnnotatedField) { AnnotatedField af = (AnnotatedField) mutator; // get the type from the content type of the map object JavaType mapType = af.getType(); mapType = resolveMemberAndTypeAnnotations(ctxt, mutator, mapType); keyType = mapType.getKeyType(); valueType = mapType.getContentType(); prop = new BeanProperty.Std(PropertyName.construct(mutator.getName()), mapType, null, mutator, PropertyMetadata.STD_OPTIONAL); } else { return ctxt.reportBadDefinition(beanDesc.getType(), String.format( "Unrecognized mutator type for any setter: %s", mutator.getClass())); } // First: see if there are explicitly specified // and then possible direct deserializer override on accessor KeyDeserializer keyDeser = findKeyDeserializerFromAnnotation(ctxt, mutator); if (keyDeser == null) { keyDeser = keyType.getValueHandler(); } if (keyDeser == null) { keyDeser = ctxt.findKeyDeserializer(keyType, prop); } else { if (keyDeser instanceof ContextualKeyDeserializer) { keyDeser = ((ContextualKeyDeserializer) keyDeser) .createContextual(ctxt, prop); } } JsonDeserializer deser = findContentDeserializerFromAnnotation(ctxt, mutator); if (deser == null) { deser = valueType.getValueHandler(); } if (deser != null) { // As per [databind#462] need to ensure we contextualize deserializer before passing it on deser = (JsonDeserializer) ctxt.handlePrimaryContextualization(deser, prop, valueType); } TypeDeserializer typeDeser = valueType.getTypeHandler(); return new SettableAnyProperty(prop, mutator, valueType, keyDeser, deser, typeDeser); } /** * Method that will construct a regular bean property setter using * the given setter method. * * @return Property constructed, if any; or null to indicate that * there should be no property based on given definitions. */ protected SettableBeanProperty constructSettableProperty(DeserializationContext ctxt, BeanDescription beanDesc, BeanPropertyDefinition propDef, JavaType propType0) throws JsonMappingException { // need to ensure method is callable (for non-public) AnnotatedMember mutator = propDef.getNonConstructorMutator(); // 08-Sep-2016, tatu: issues like [databind#1342] suggest something fishy // going on; add sanity checks to try to pin down actual problem... // Possibly passing creator parameter? if (mutator == null) { ctxt.reportBadPropertyDefinition(beanDesc, propDef, "No non-constructor mutator available"); } JavaType type = resolveMemberAndTypeAnnotations(ctxt, mutator, propType0); // Does the Method specify the deserializer to use? If so, let's use it. TypeDeserializer typeDeser = type.getTypeHandler(); SettableBeanProperty prop; if (mutator instanceof AnnotatedMethod) { prop = new MethodProperty(propDef, type, typeDeser, beanDesc.getClassAnnotations(), (AnnotatedMethod) mutator); } else { // 08-Sep-2016, tatu: wonder if we should verify it is `AnnotatedField` to be safe? prop = new FieldProperty(propDef, type, typeDeser, beanDesc.getClassAnnotations(), (AnnotatedField) mutator); } JsonDeserializer deser = findDeserializerFromAnnotation(ctxt, mutator); if (deser == null) { deser = type.getValueHandler(); } if (deser != null) { deser = ctxt.handlePrimaryContextualization(deser, prop, type); prop = prop.withValueDeserializer(deser); } // need to retain name of managed forward references: AnnotationIntrospector.ReferenceProperty ref = propDef.findReferenceType(); if (ref != null && ref.isManagedReference()) { prop.setManagedReferenceName(ref.getName()); } ObjectIdInfo objectIdInfo = propDef.findObjectIdInfo(); if (objectIdInfo != null){ prop.setObjectIdInfo(objectIdInfo); } return prop; } /** * Method that will construct a regular bean property setter using * the given setter method. */ protected SettableBeanProperty constructSetterlessProperty(DeserializationContext ctxt, BeanDescription beanDesc, BeanPropertyDefinition propDef) throws JsonMappingException { final AnnotatedMethod getter = propDef.getGetter(); JavaType type = resolveMemberAndTypeAnnotations(ctxt, getter, getter.getType()); TypeDeserializer typeDeser = type.getTypeHandler(); SettableBeanProperty prop = new SetterlessProperty(propDef, type, typeDeser, beanDesc.getClassAnnotations(), getter); JsonDeserializer deser = findDeserializerFromAnnotation(ctxt, getter); if (deser == null) { deser = type.getValueHandler(); } if (deser != null) { deser = ctxt.handlePrimaryContextualization(deser, prop, type); prop = prop.withValueDeserializer(deser); } return prop; } /* /********************************************************** /* Helper methods for Bean deserializer, other /********************************************************** */ /** * Helper method used to skip processing for types that we know * cannot be (i.e. are never consider to be) beans: * things like primitives, Arrays, Enums, and proxy types. *

* Note that usually we shouldn't really be getting these sort of * types anyway; but better safe than sorry. */ protected boolean isPotentialBeanType(Class type) { String typeStr = ClassUtil.canBeABeanType(type); if (typeStr != null) { throw new IllegalArgumentException("Cannot deserialize Class "+type.getName()+" (of type "+typeStr+") as a Bean"); } if (ClassUtil.isProxyType(type)) { throw new IllegalArgumentException("Cannot deserialize Proxy class "+type.getName()+" as a Bean"); } /* also: can't deserialize some local classes: static are ok; in-method not; * other non-static inner classes are ok */ typeStr = ClassUtil.isLocalType(type, true); if (typeStr != null) { throw new IllegalArgumentException("Cannot deserialize Class "+type.getName()+" (of type "+typeStr+") as a Bean"); } return true; } /** * Helper method that will check whether given raw type is marked as always ignorable * (for purpose of ignoring properties with type) */ protected boolean isIgnorableType(DeserializationConfig config, BeanPropertyDefinition propDef, Class type, Map,Boolean> ignoredTypes) { Boolean status = ignoredTypes.get(type); if (status != null) { return status.booleanValue(); } // 22-Oct-2016, tatu: Slight check to skip primitives, String if ((type == String.class) || type.isPrimitive()) { status = Boolean.FALSE; } else { // 21-Apr-2016, tatu: For 2.8, can specify config overrides status = config.getConfigOverride(type).getIsIgnoredType(); if (status == null) { BeanDescription desc = config.introspectClassAnnotations(type); status = config.getAnnotationIntrospector().isIgnorableType(desc.getClassInfo()); // We default to 'false', i.e. not ignorable if (status == null) { status = Boolean.FALSE; } } } ignoredTypes.put(type, status); return status.booleanValue(); } /** * @since 2.8.11 */ protected void _validateSubType(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { SubTypeValidator.instance().validateSubType(ctxt, type, beanDesc); } } BeanDeserializerModifier.java000066400000000000000000000164161325620701100373140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.List; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.BeanDeserializer; import com.fasterxml.jackson.databind.deser.BeanDeserializerFactory; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.type.ArrayType; import com.fasterxml.jackson.databind.type.CollectionLikeType; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.MapLikeType; import com.fasterxml.jackson.databind.type.MapType; import com.fasterxml.jackson.databind.type.ReferenceType; /** * Abstract class that defines API for objects that can be registered * to participate in constructing {@link JsonDeserializer} instances * (via {@link DeserializerFactory}). * This is typically done by modules that want alter some aspects of deserialization * process; and is preferable to sub-classing of {@link BeanDeserializerFactory}. *

* Note that Jackson 2.2 adds more methods for customization; with earlier versions * only {@link BeanDeserializer} instances could be modified, but with 2.2 all types * of deserializers can be changed. *

* Sequence in which callback methods are called for {@link BeanDeserializer} is: *

    *
  1. {@link #updateProperties} is called once all property definitions are * collected, and initial filtering (by ignorable type and explicit ignoral-by-bean) * has been performed. *
  2. *
  3. {@link #updateBuilder} is called once all initial pieces for building deserializer * have been collected *
  4. *
  5. {@link #modifyDeserializer} is called after deserializer has been built * by {@link BeanDeserializerBuilder} * but before it is returned to be used *
  6. *
*

* For other types of deserializers, methods called depend on type of values for * which deserializer is being constructed; and only a single method is called * since the process does not involve builders (unlike that of {@link BeanDeserializer}. *

* Default method implementations are "no-op"s, meaning that methods are implemented * but have no effect; this is mostly so that new methods can be added in later * versions. */ public abstract class BeanDeserializerModifier { /** * Method called by {@link BeanDeserializerFactory} when it has collected * initial list of {@link BeanPropertyDefinition}s, and done basic by-name * and by-type filtering, but before constructing builder or actual * property handlers; or arranging order. * * The most common changes to make at this point are to completely remove * specified properties, or rename then: other modifications are easier * to make at later points. */ public List updateProperties(DeserializationConfig config, BeanDescription beanDesc, List propDefs) { return propDefs; } /** * Method called by {@link BeanDeserializerFactory} when it has collected * basic information such as tentative list of properties to deserialize. * * Implementations may choose to modify state of builder (to affect deserializer being * built), or even completely replace it (if they want to build different kind of * deserializer). Typically changes mostly concern set of properties to deserialize. */ public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) { return builder; } /** * Method called by {@link BeanDeserializerFactory} after constructing default * bean deserializer instance with properties collected and ordered earlier. * Implementations can modify or replace given deserializer and return deserializer * to use. Note that although initial deserializer being passed is of type * {@link BeanDeserializer}, modifiers may return deserializers of other types; * and this is why implementations must check for type before casting. */ public JsonDeserializer modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer deserializer) { return deserializer; } /* /********************************************************** /* Callback methods for other types (since 2.2) /********************************************************** */ /** * @since 2.2 */ public JsonDeserializer modifyEnumDeserializer(DeserializationConfig config, JavaType type, BeanDescription beanDesc, JsonDeserializer deserializer) { return deserializer; } /** * @since 2.7 */ public JsonDeserializer modifyReferenceDeserializer(DeserializationConfig config, ReferenceType type, BeanDescription beanDesc, JsonDeserializer deserializer) { return deserializer; } /** * Method called by {@link DeserializerFactory} after it has constructed the * standard deserializer for given * {@link ArrayType} * to make it possible to either replace or augment this deserializer with * additional functionality. * * @param config Configuration in use * @param valueType Type of the value deserializer is used for. * @param beanDesc Description f * @param deserializer Default deserializer that would be used. * * @return Deserializer to use; either deserializer that was passed * in, or an instance method constructed. * * @since 2.2 */ public JsonDeserializer modifyArrayDeserializer(DeserializationConfig config, ArrayType valueType, BeanDescription beanDesc, JsonDeserializer deserializer) { return deserializer; } /** * @since 2.2 */ public JsonDeserializer modifyCollectionDeserializer(DeserializationConfig config, CollectionType type, BeanDescription beanDesc, JsonDeserializer deserializer) { return deserializer; } /** * @since 2.2 */ public JsonDeserializer modifyCollectionLikeDeserializer(DeserializationConfig config, CollectionLikeType type, BeanDescription beanDesc, JsonDeserializer deserializer) { return deserializer; } /** * @since 2.2 */ public JsonDeserializer modifyMapDeserializer(DeserializationConfig config, MapType type, BeanDescription beanDesc, JsonDeserializer deserializer) { return deserializer; } /** * @since 2.2 */ public JsonDeserializer modifyMapLikeDeserializer(DeserializationConfig config, MapLikeType type, BeanDescription beanDesc, JsonDeserializer deserializer) { return deserializer; } /** * Method called by {@link DeserializerFactory} after it has constructed the * standard key deserializer for given key type. * This make it possible to replace the default key deserializer, or augment * it somehow (including optional use of default deserializer with occasional * override). * * @since 2.2 */ public KeyDeserializer modifyKeyDeserializer(DeserializationConfig config, JavaType type, KeyDeserializer deserializer) { return deserializer; } }BuilderBasedDeserializer.java000066400000000000000000000721131325620701100373110ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.impl.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.util.NameTransformer; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Class that handles deserialization using a separate * Builder class, which is used for data binding and * produces actual deserialized value at the end * of data binding. *

* Note on implementation: much of code has been copied from * {@link BeanDeserializer}; there may be opportunities to * refactor this in future. */ public class BuilderBasedDeserializer extends BeanDeserializerBase { private static final long serialVersionUID = 1L; protected final AnnotatedMethod _buildMethod; /** * Type that the builder will produce, target type; as opposed to * `handledType()` which refers to Builder class. * * @since 2.9 */ protected final JavaType _targetType; /* /********************************************************** /* Life-cycle, construction, initialization /********************************************************** */ /** * Constructor used by {@link BeanDeserializerBuilder}. */ public BuilderBasedDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, JavaType targetType, BeanPropertyMap properties, Map backRefs, Set ignorableProps, boolean ignoreAllUnknown, boolean hasViews) { super(builder, beanDesc, properties, backRefs, ignorableProps, ignoreAllUnknown, hasViews); _targetType = targetType; _buildMethod = builder.getBuildMethod(); // 05-Mar-2012, tatu: Cannot really make Object Ids work with builders, not yet anyway if (_objectIdReader != null) { throw new IllegalArgumentException("Cannot use Object Id with Builder-based deserialization (type " +beanDesc.getType()+")"); } } /** * @deprecated Since 2.9 */ @Deprecated public BuilderBasedDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, BeanPropertyMap properties, Map backRefs, Set ignorableProps, boolean ignoreAllUnknown, boolean hasViews) { this(builder, beanDesc, beanDesc.getType(), // Wrong! But got no access via `BeanDeserializerBuilder` properties, backRefs, ignorableProps, ignoreAllUnknown, hasViews); } /** * Copy-constructor that can be used by sub-classes to allow * copy-on-write styling copying of settings of an existing instance. */ protected BuilderBasedDeserializer(BuilderBasedDeserializer src) { this(src, src._ignoreAllUnknown); } protected BuilderBasedDeserializer(BuilderBasedDeserializer src, boolean ignoreAllUnknown) { super(src, ignoreAllUnknown); _buildMethod = src._buildMethod; _targetType = src._targetType; } protected BuilderBasedDeserializer(BuilderBasedDeserializer src, NameTransformer unwrapper) { super(src, unwrapper); _buildMethod = src._buildMethod; _targetType = src._targetType; } public BuilderBasedDeserializer(BuilderBasedDeserializer src, ObjectIdReader oir) { super(src, oir); _buildMethod = src._buildMethod; _targetType = src._targetType; } public BuilderBasedDeserializer(BuilderBasedDeserializer src, Set ignorableProps) { super(src, ignorableProps); _buildMethod = src._buildMethod; _targetType = src._targetType; } public BuilderBasedDeserializer(BuilderBasedDeserializer src, BeanPropertyMap props) { super(src, props); _buildMethod = src._buildMethod; _targetType = src._targetType; } @Override public JsonDeserializer unwrappingDeserializer(NameTransformer unwrapper) { /* main thing really is to just enforce ignoring of unknown * properties; since there may be multiple unwrapped values * and properties for all may be interleaved... */ return new BuilderBasedDeserializer(this, unwrapper); } @Override public BeanDeserializerBase withObjectIdReader(ObjectIdReader oir) { return new BuilderBasedDeserializer(this, oir); } @Override public BeanDeserializerBase withIgnorableProperties(Set ignorableProps) { return new BuilderBasedDeserializer(this, ignorableProps); } @Override public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) { return new BuilderBasedDeserializer(this, props); } @Override protected BeanDeserializerBase asArrayDeserializer() { SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder(); return new BeanAsArrayBuilderDeserializer(this, _targetType, props, _buildMethod); } /* /********************************************************** /* JsonDeserializer implementation /********************************************************** */ @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { // 26-Oct-2016, tatu: No, we can't merge Builder-based POJOs as of now return Boolean.FALSE; } /* /********************************************************** /* JsonDeserializer implementation /********************************************************** */ protected Object finishBuild(DeserializationContext ctxt, Object builder) throws IOException { // As per [databind#777], allow returning builder itself if (null == _buildMethod) { return builder; } try { return _buildMethod.getMember().invoke(builder, (Object[]) null); } catch (Exception e) { return wrapInstantiationProblem(e, ctxt); } } /** * Main deserialization method for bean-based objects (POJOs). */ @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // common case first: if (p.isExpectedStartObjectToken()) { JsonToken t = p.nextToken(); if (_vanillaProcessing) { return finishBuild(ctxt, vanillaDeserialize(p, ctxt, t)); } Object builder = deserializeFromObject(p, ctxt); return finishBuild(ctxt, builder); } // and then others, generally requiring use of @JsonCreator switch (p.getCurrentTokenId()) { case JsonTokenId.ID_STRING: return finishBuild(ctxt, deserializeFromString(p, ctxt)); case JsonTokenId.ID_NUMBER_INT: return finishBuild(ctxt, deserializeFromNumber(p, ctxt)); case JsonTokenId.ID_NUMBER_FLOAT: return finishBuild(ctxt, deserializeFromDouble(p, ctxt)); case JsonTokenId.ID_EMBEDDED_OBJECT: return p.getEmbeddedObject(); case JsonTokenId.ID_TRUE: case JsonTokenId.ID_FALSE: return finishBuild(ctxt, deserializeFromBoolean(p, ctxt)); case JsonTokenId.ID_START_ARRAY: // these only work if there's a (delegating) creator... return finishBuild(ctxt, deserializeFromArray(p, ctxt)); case JsonTokenId.ID_FIELD_NAME: case JsonTokenId.ID_END_OBJECT: return finishBuild(ctxt, deserializeFromObject(p, ctxt)); default: } return ctxt.handleUnexpectedToken(handledType(), p); } /** * Secondary deserialization method, called in cases where POJO * instance is created as part of deserialization, potentially * after collecting some or all of the properties to set. */ @Override public Object deserialize(JsonParser p, DeserializationContext ctxt, Object value) throws IOException { // 26-Oct-2016, tatu: I cannot see any of making this actually // work correctly, so let's indicate problem right away JavaType valueType = _targetType; // Did they try to give us builder? Class builderRawType = handledType(); Class instRawType = value.getClass(); if (builderRawType.isAssignableFrom(instRawType)) { return ctxt.reportBadDefinition(valueType, String.format( "Deserialization of %s by passing existing Builder (%s) instance not supported", valueType, builderRawType.getName())); } return ctxt.reportBadDefinition(valueType, String.format( "Deserialization of %s by passing existing instance (of %s) not supported", valueType, instRawType.getName())); } /* /********************************************************** /* Concrete deserialization methods /********************************************************** */ /** * Streamlined version that is only used when no "special" * features are enabled. */ private final Object vanillaDeserialize(JsonParser p, DeserializationContext ctxt, JsonToken t) throws IOException { Object bean = _valueInstantiator.createUsingDefault(ctxt); for (; p.getCurrentToken() == JsonToken.FIELD_NAME; p.nextToken()) { String propName = p.getCurrentName(); // Skip field name: p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { // normal case try { bean = prop.deserializeSetAndReturn(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } } else { handleUnknownVanilla(p, ctxt, bean, propName); } } return bean; } /** * General version used when handling needs more advanced * features. */ @Override public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException { if (_nonStandardCreation) { if (_unwrappedPropertyHandler != null) { return deserializeWithUnwrapped(p, ctxt); } if (_externalTypeIdHandler != null) { return deserializeWithExternalTypeId(p, ctxt); } return deserializeFromObjectUsingNonDefault(p, ctxt); } Object bean = _valueInstantiator.createUsingDefault(ctxt); if (_injectables != null) { injectValues(ctxt, bean); } if (_needViewProcesing) { Class view = ctxt.getActiveView(); if (view != null) { return deserializeWithView(p, ctxt, bean, view); } } for (; p.getCurrentToken() == JsonToken.FIELD_NAME; p.nextToken()) { String propName = p.getCurrentName(); // Skip field name: p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { // normal case try { bean = prop.deserializeSetAndReturn(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } handleUnknownVanilla(p, ctxt, bean, propName); } return bean; } /** * Method called to deserialize bean using "property-based creator": * this means that a non-default constructor or factory method is * called, and then possibly other setters. The trick is that * values for creator method need to be buffered, first; and * due to non-guaranteed ordering possibly some other properties * as well. * * @return Builder instance constructed */ @Override @SuppressWarnings("resource") protected Object _deserializeUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt) throws IOException { final PropertyBasedCreator creator = _propertyBasedCreator; PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; // 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases TokenBuffer unknown = null; JsonToken t = p.getCurrentToken(); for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); p.nextToken(); // to point to value // creator property? SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); if (creatorProp != null) { if ((activeView != null) && !creatorProp.visibleInView(activeView)) { p.skipChildren(); continue; } // Last creator property to set? if (buffer.assignParameter(creatorProp, creatorProp.deserialize(p, ctxt))) { p.nextToken(); // to move to following FIELD_NAME/END_OBJECT Object builder; try { builder = creator.build(ctxt, buffer); } catch (Exception e) { wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); continue; // never gets here } // polymorphic? if (builder.getClass() != _beanType.getRawClass()) { return handlePolymorphic(p, ctxt, builder, unknown); } if (unknown != null) { // nope, just extra unknown stuff... builder = handleUnknownProperties(ctxt, builder, unknown); } // or just clean? return _deserialize(p, ctxt, builder); } continue; } // Object Id property? if (buffer.readIdProperty(propName)) { continue; } // regular property? needs buffering SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { buffer.bufferProperty(prop, prop.deserialize(p, ctxt)); continue; } // As per [JACKSON-313], things marked as ignorable should not be // passed to any setter if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, handledType(), propName); continue; } // "any property"? if (_anySetter != null) { buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt)); continue; } // Ok then, let's collect the whole field; name and value if (unknown == null) { unknown = new TokenBuffer(p, ctxt); } unknown.writeFieldName(propName); unknown.copyCurrentStructure(p); } // We hit END_OBJECT, so: Object builder; try { builder = creator.build(ctxt, buffer); } catch (Exception e) { builder = wrapInstantiationProblem(e, ctxt); } if (unknown != null) { // polymorphic? if (builder.getClass() != _beanType.getRawClass()) { return handlePolymorphic(null, ctxt, builder, unknown); } // no, just some extra unknown properties return handleUnknownProperties(ctxt, builder, unknown); } return builder; } @SuppressWarnings("resource") protected final Object _deserialize(JsonParser p, DeserializationContext ctxt, Object builder) throws IOException { if (_injectables != null) { injectValues(ctxt, builder); } if (_unwrappedPropertyHandler != null) { if (p.hasToken(JsonToken.START_OBJECT)) { p.nextToken(); } TokenBuffer tokens = new TokenBuffer(p, ctxt); tokens.writeStartObject(); return deserializeWithUnwrapped(p, ctxt, builder, tokens); } if (_externalTypeIdHandler != null) { return deserializeWithExternalTypeId(p, ctxt, builder); } if (_needViewProcesing) { Class view = ctxt.getActiveView(); if (view != null) { return deserializeWithView(p, ctxt, builder, view); } } JsonToken t = p.getCurrentToken(); // 23-Mar-2010, tatu: In some cases, we start with full JSON object too... if (t == JsonToken.START_OBJECT) { t = p.nextToken(); } for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); // Skip field name: p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { // normal case try { builder = prop.deserializeSetAndReturn(p, ctxt, builder); } catch (Exception e) { wrapAndThrow(e, builder, propName, ctxt); } continue; } handleUnknownVanilla(p, ctxt, handledType(), propName); } return builder; } /* /********************************************************** /* Deserializing when we have to consider an active View /********************************************************** */ protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt, Object bean, Class activeView) throws IOException { JsonToken t = p.getCurrentToken(); for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); // Skip field name: p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { if (!prop.visibleInView(activeView)) { p.skipChildren(); continue; } try { bean = prop.deserializeSetAndReturn(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } handleUnknownVanilla(p, ctxt, bean, propName); } return bean; } /* /********************************************************** /* Handling for cases where we have "unwrapped" values /********************************************************** */ /** * Method called when there are declared "unwrapped" properties * which need special handling */ @SuppressWarnings("resource") protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { if (_delegateDeserializer != null) { return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt)); } if (_propertyBasedCreator != null) { return deserializeUsingPropertyBasedWithUnwrapped(p, ctxt); } TokenBuffer tokens = new TokenBuffer(p, ctxt); tokens.writeStartObject(); Object bean = _valueInstantiator.createUsingDefault(ctxt); if (_injectables != null) { injectValues(ctxt, bean); } final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; for (; p.getCurrentToken() == JsonToken.FIELD_NAME; p.nextToken()) { String propName = p.getCurrentName(); p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { // normal case if (activeView != null && !prop.visibleInView(activeView)) { p.skipChildren(); continue; } try { bean = prop.deserializeSetAndReturn(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } // ignorable things should be ignored if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, bean, propName); continue; } // but... others should be passed to unwrapped property deserializers tokens.writeFieldName(propName); tokens.copyCurrentStructure(p); // how about any setter? We'll get copies but... if (_anySetter != null) { try { _anySetter.deserializeAndSet(p, ctxt, bean, propName); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } } tokens.writeEndObject(); return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens); } @SuppressWarnings("resource") protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { final PropertyBasedCreator creator = _propertyBasedCreator; PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); TokenBuffer tokens = new TokenBuffer(p, ctxt); tokens.writeStartObject(); Object builder = null; JsonToken t = p.getCurrentToken(); for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); p.nextToken(); // to point to value // creator property? SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); if (creatorProp != null) { // Last creator property to set? if (buffer.assignParameter(creatorProp, creatorProp.deserialize(p, ctxt))) { t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT try { builder = creator.build(ctxt, buffer); } catch (Exception e) { wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); continue; // never gets here } if (builder.getClass() != _beanType.getRawClass()) { return handlePolymorphic(p, ctxt, builder, tokens); } return deserializeWithUnwrapped(p, ctxt, builder, tokens); } continue; } // Object Id property? if (buffer.readIdProperty(propName)) { continue; } // regular property? needs buffering SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { buffer.bufferProperty(prop, prop.deserialize(p, ctxt)); continue; } if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, handledType(), propName); continue; } tokens.writeFieldName(propName); tokens.copyCurrentStructure(p); // "any property"? if (_anySetter != null) { buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt)); } } tokens.writeEndObject(); // We hit END_OBJECT, so: if (builder == null) { try { builder = creator.build(ctxt, buffer); } catch (Exception e) { return wrapInstantiationProblem(e, ctxt); } } return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, builder, tokens); } protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt, Object builder, TokenBuffer tokens) throws IOException { final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; for (JsonToken t = p.getCurrentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); SettableBeanProperty prop = _beanProperties.find(propName); p.nextToken(); if (prop != null) { // normal case if (activeView != null && !prop.visibleInView(activeView)) { p.skipChildren(); continue; } try { builder = prop.deserializeSetAndReturn(p, ctxt, builder); } catch (Exception e) { wrapAndThrow(e, builder, propName, ctxt); } continue; } if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, builder, propName); continue; } // but... others should be passed to unwrapped property deserializers tokens.writeFieldName(propName); tokens.copyCurrentStructure(p); // how about any setter? We'll get copies but... if (_anySetter != null) { _anySetter.deserializeAndSet(p, ctxt, builder, propName); } } tokens.writeEndObject(); return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, builder, tokens); } /* /********************************************************** /* Handling for cases where we have property/-ies with /* external type id /********************************************************** */ protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt) throws IOException { if (_propertyBasedCreator != null) { return deserializeUsingPropertyBasedWithExternalTypeId(p, ctxt); } return deserializeWithExternalTypeId(p, ctxt, _valueInstantiator.createUsingDefault(ctxt)); } protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException { final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; final ExternalTypeHandler ext = _externalTypeIdHandler.start(); for (JsonToken t = p.getCurrentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); t = p.nextToken(); SettableBeanProperty prop = _beanProperties.find(propName); if (prop != null) { // normal case // May have property AND be used as external type id: if (t.isScalarValue()) { ext.handleTypePropertyValue(p, ctxt, propName, bean); } if (activeView != null && !prop.visibleInView(activeView)) { p.skipChildren(); continue; } try { bean = prop.deserializeSetAndReturn(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } // ignorable things should be ignored if (_ignorableProps != null && _ignorableProps.contains(propName)) { handleIgnoredProperty(p, ctxt, bean, propName); continue; } // but others are likely to be part of external type id thingy... if (ext.handlePropertyValue(p, ctxt, propName, bean)) { continue; } // if not, the usual fallback handling: if (_anySetter != null) { try { _anySetter.deserializeAndSet(p, ctxt, bean, propName); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } continue; } else { // Unknown: let's call handler method handleUnknownProperty(p, ctxt, bean, propName); } } // and when we get this far, let's try finalizing the deal: return ext.complete(p, ctxt, bean); } protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, DeserializationContext ctxt) throws IOException { // !!! 04-Mar-2012, TODO: Need to fix -- will not work as is... JavaType t = _targetType; return ctxt.reportBadDefinition(t, String.format( "Deserialization (of %s) with Builder, External type id, @JsonCreator not yet implemented", t)); } } ContextualDeserializer.java000066400000000000000000000041061325620701100371070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.databind.*; /** * Add-on interface that {@link JsonDeserializer}s can implement to get a callback * that can be used to create contextual (context-dependent) instances of * deserializer to use for handling properties of supported type. * This can be useful * for deserializers that can be configured by annotations, or should otherwise * have differing behavior depending on what kind of property is being deserialized. *

* Note that in cases where deserializer needs both contextualization and * resolution -- that is, implements both this interface and {@link ResolvableDeserializer} * -- resolution via {@link ResolvableDeserializer} occurs first, and contextual * resolution (via this interface) later on. */ public interface ContextualDeserializer { /** * Method called to see if a different (or differently configured) deserializer * is needed to deserialize values of specified property. * Note that instance that this method is called on is typically shared one and * as a result method should NOT modify this instance but rather construct * and return a new instance. This instance should only be returned as-is, in case * it is already suitable for use. * * @param ctxt Deserialization context to access configuration, additional * deserializers that may be needed by this deserializer * @param property Method, field or constructor parameter that represents the property * (and is used to assign deserialized value). * Should be available; but there may be cases where caller cannot provide it and * null is passed instead (in which case impls usually pass 'this' deserializer as is) * * @return Deserializer to use for deserializing values of specified property; * may be this instance or a new instance. * * @throws JsonMappingException */ public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException; } ContextualKeyDeserializer.java000066400000000000000000000032251325620701100375610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.databind.*; /** * Add-on interface that {@link KeyDeserializer}s can implement to get a callback * that can be used to create contextual instances of key deserializer to use for * handling Map keys of supported type. This can be useful * for key deserializers that can be configured by annotations, or should otherwise * have differing behavior depending on what kind of Map property keys are being deserialized. */ public interface ContextualKeyDeserializer { /** * Method called to see if a different (or differently configured) key deserializer * is needed to deserialize keys of specified Map property. * Note that instance that this method is called on is typically shared one and * as a result method should NOT modify this instance but rather construct * and return a new instance. This instance should only be returned as-is, in case * it is already suitable for use. * * @param ctxt Deserialization context to access configuration, additional * deserializers that may be needed by this deserializer * @param property Method, field or constructor parameter that declared Map for which * contextual instance will be used. Will not be available when deserializing root-level * Map value; otherwise should not be null. * * @return Key deserializer to use for deserializing keys specified Map property, * may be this instance or a new instance. */ public KeyDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException; } CreatorProperty.java000066400000000000000000000223431325620701100355650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.lang.annotation.Annotation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.Annotations; import com.fasterxml.jackson.databind.util.ClassUtil; /** * This concrete sub-class implements property that is passed * via Creator (constructor or static factory method). * It is not a full-featured implementation in that its set method * should usually not be called for primary mutation -- instead, value must separately passed -- * but some aspects are still needed (specifically, injection). *

* Note on injectable values: unlike with other mutators, where * deserializer and injecting are separate, here we treat the two as related * things. This is necessary to add proper priority, as well as to simplify * coordination. */ public class CreatorProperty extends SettableBeanProperty { private static final long serialVersionUID = 1L; /** * Placeholder that represents constructor parameter, when it is created * from actual constructor. * May be null when a synthetic instance is created. */ protected final AnnotatedParameter _annotated; /** * Id of value to inject, if value injection should be used for this parameter * (in addition to, or instead of, regular deserialization). */ protected final Object _injectableValueId; /** * In special cases, when implementing "updateValue", we cannot use * constructors or factory methods, but have to fall back on using a * setter (or mutable field property). If so, this refers to that fallback * accessor. *

* Mutable only to allow setting after construction, but must be strictly * set before any use. * * @since 2.3 */ protected SettableBeanProperty _fallbackSetter; /** * @since 2.1 */ protected final int _creatorIndex; /** * Marker flag that may have to be set during construction, to indicate that * although property may have been constructed and added as a placeholder, * it represents something that should be ignored during deserialization. * This mostly concerns Creator properties which may not be easily deleted * during processing. * * @since 2.9.4 */ protected boolean _ignorable; /** * @param name Name of the logical property * @param type Type of the property, used to find deserializer * @param typeDeser Type deserializer to use for handling polymorphic type * information, if one is needed * @param contextAnnotations Contextual annotations (usually by class that * declares creator [constructor, factory method] that includes * this property) * @param param Representation of property, constructor or factory * method parameter; used for accessing annotations of the property * @param index Index of this property within creator invocation * * @since 2.3 */ public CreatorProperty(PropertyName name, JavaType type, PropertyName wrapperName, TypeDeserializer typeDeser, Annotations contextAnnotations, AnnotatedParameter param, int index, Object injectableValueId, PropertyMetadata metadata) { super(name, type, wrapperName, typeDeser, contextAnnotations, metadata); _annotated = param; _creatorIndex = index; _injectableValueId = injectableValueId; _fallbackSetter = null; } /** * @since 2.3 */ protected CreatorProperty(CreatorProperty src, PropertyName newName) { super(src, newName); _annotated = src._annotated; _injectableValueId = src._injectableValueId; _fallbackSetter = src._fallbackSetter; _creatorIndex = src._creatorIndex; _ignorable = src._ignorable; } protected CreatorProperty(CreatorProperty src, JsonDeserializer deser, NullValueProvider nva) { super(src, deser, nva); _annotated = src._annotated; _injectableValueId = src._injectableValueId; _fallbackSetter = src._fallbackSetter; _creatorIndex = src._creatorIndex; _ignorable = src._ignorable; } @Override public SettableBeanProperty withName(PropertyName newName) { return new CreatorProperty(this, newName); } @Override public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } return new CreatorProperty(this, deser, _nullProvider); } @Override public SettableBeanProperty withNullProvider(NullValueProvider nva) { return new CreatorProperty(this, _valueDeserializer, nva); } @Override public void fixAccess(DeserializationConfig config) { if (_fallbackSetter != null) { _fallbackSetter.fixAccess(config); } } /** * NOTE: one exception to immutability, due to problems with CreatorProperty instances * being shared between Bean, separate PropertyBasedCreator * * @since 2.6 */ public void setFallbackSetter(SettableBeanProperty fallbackSetter) { _fallbackSetter = fallbackSetter; } @Override public void markAsIgnorable() { _ignorable = true; } @Override public boolean isIgnorable() { return _ignorable; } /* /********************************************************** /* Injection support /********************************************************** */ /** * Method that can be called to locate value to be injected for this * property, if it is configured for this. */ public Object findInjectableValue(DeserializationContext context, Object beanInstance) throws JsonMappingException { if (_injectableValueId == null) { context.reportBadDefinition(ClassUtil.classOf(beanInstance), String.format("Property '%s' (type %s) has no injectable value id configured", getName(), getClass().getName())); } return context.findInjectableValue(_injectableValueId, this, beanInstance); } /** * Method to find value to inject, and inject it to this property. */ public void inject(DeserializationContext context, Object beanInstance) throws IOException { set(beanInstance, findInjectableValue(context, beanInstance)); } /* /********************************************************** /* BeanProperty impl /********************************************************** */ @Override public A getAnnotation(Class acls) { if (_annotated == null) { return null; } return _annotated.getAnnotation(acls); } @Override public AnnotatedMember getMember() { return _annotated; } @Override public int getCreatorIndex() { return _creatorIndex; } /* /********************************************************** /* Overridden methods /********************************************************** */ @Override public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { _verifySetter(); _fallbackSetter.set(instance, deserialize(p, ctxt)); } @Override public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { _verifySetter(); return _fallbackSetter.setAndReturn(instance, deserialize(p, ctxt)); } @Override public void set(Object instance, Object value) throws IOException { _verifySetter(); _fallbackSetter.set(instance, value); } @Override public Object setAndReturn(Object instance, Object value) throws IOException { _verifySetter(); return _fallbackSetter.setAndReturn(instance, value); } @Override public Object getInjectableValueId() { return _injectableValueId; } @Override public String toString() { return "[creator property, name '"+getName()+"'; inject id '"+_injectableValueId+"']"; } // since 2.9 private final void _verifySetter() throws IOException { if (_fallbackSetter == null) { _reportMissingSetter(null, null); } } // since 2.9 private void _reportMissingSetter(JsonParser p, DeserializationContext ctxt) throws IOException { final String msg = "No fallback setter/field defined for creator property '"+getName()+"'"; // Hmmmh. Should we return quietly (NOP), or error? // Perhaps better to throw an exception, since it's generally an error. if (ctxt != null ) { ctxt.reportBadDefinition(getType(), msg); } else { throw InvalidDefinitionException.from(p, msg, getType()); } } } DataFormatReaders.java000066400000000000000000000314301325620701100357460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.format.*; import com.fasterxml.jackson.core.io.MergedStream; import com.fasterxml.jackson.databind.*; /** * Alternative to {@link DataFormatDetector} that needs to be used when * using data-binding. * * @since 2.1 */ public class DataFormatReaders { /** * By default we will look ahead at most 64 bytes; in most cases, * much less (4 bytes or so) is needed, but we will allow bit more * leniency to support data formats that need more complex heuristics. */ public final static int DEFAULT_MAX_INPUT_LOOKAHEAD = 64; /** * Ordered list of readers which both represent data formats to * detect (in precedence order, starting with highest) and contain * factories used for actual detection. */ protected final ObjectReader[] _readers; /** * Strength of match we consider to be good enough to be used * without checking any other formats. * Default value is {@link MatchStrength#SOLID_MATCH}, */ protected final MatchStrength _optimalMatch; /** * Strength of minimal match we accept as the answer, unless * better matches are found. * Default value is {@link MatchStrength#WEAK_MATCH}, */ protected final MatchStrength _minimalMatch; /** * Maximum number of leading bytes of the input that we can read * to determine data format. *

* Default value is {@link #DEFAULT_MAX_INPUT_LOOKAHEAD}. */ protected final int _maxInputLookahead; /* /********************************************************** /* Construction /********************************************************** */ public DataFormatReaders(ObjectReader... detectors) { this(detectors, MatchStrength.SOLID_MATCH, MatchStrength.WEAK_MATCH, DEFAULT_MAX_INPUT_LOOKAHEAD); } public DataFormatReaders(Collection detectors) { this(detectors.toArray(new ObjectReader[detectors.size()])); } private DataFormatReaders(ObjectReader[] detectors, MatchStrength optMatch, MatchStrength minMatch, int maxInputLookahead) { _readers = detectors; _optimalMatch = optMatch; _minimalMatch = minMatch; _maxInputLookahead = maxInputLookahead; } /* /********************************************************** /* Fluent factories for changing match settings /********************************************************** */ public DataFormatReaders withOptimalMatch(MatchStrength optMatch) { if (optMatch == _optimalMatch) { return this; } return new DataFormatReaders(_readers, optMatch, _minimalMatch, _maxInputLookahead); } public DataFormatReaders withMinimalMatch(MatchStrength minMatch) { if (minMatch == _minimalMatch) { return this; } return new DataFormatReaders(_readers, _optimalMatch, minMatch, _maxInputLookahead); } public DataFormatReaders with(ObjectReader[] readers) { return new DataFormatReaders(readers, _optimalMatch, _minimalMatch, _maxInputLookahead); } public DataFormatReaders withMaxInputLookahead(int lookaheadBytes) { if (lookaheadBytes == _maxInputLookahead) { return this; } return new DataFormatReaders(_readers, _optimalMatch, _minimalMatch, lookaheadBytes); } /* /********************************************************** /* Fluent factories for changing underlying readers /********************************************************** */ public DataFormatReaders with(DeserializationConfig config) { final int len = _readers.length; ObjectReader[] r = new ObjectReader[len]; for (int i = 0; i < len; ++i) { r[i] = _readers[i].with(config); } return new DataFormatReaders(r, _optimalMatch, _minimalMatch, _maxInputLookahead); } public DataFormatReaders withType(JavaType type) { final int len = _readers.length; ObjectReader[] r = new ObjectReader[len]; for (int i = 0; i < len; ++i) { r[i] = _readers[i].forType(type); } return new DataFormatReaders(r, _optimalMatch, _minimalMatch, _maxInputLookahead); } /* /********************************************************** /* Public API /********************************************************** */ /** * Method to call to find format that content (accessible via given * {@link InputStream}) given has, as per configuration of this detector * instance. * * @return Matcher object which contains result; never null, even in cases * where no match (with specified minimal match strength) is found. */ public Match findFormat(InputStream in) throws IOException { return _findFormat(new AccessorForReader(in, new byte[_maxInputLookahead])); } /** * Method to call to find format that given content (full document) * has, as per configuration of this detector instance. * * @return Matcher object which contains result; never null, even in cases * where no match (with specified minimal match strength) is found. */ public Match findFormat(byte[] fullInputData) throws IOException { return _findFormat(new AccessorForReader(fullInputData)); } /** * Method to call to find format that given content (full document) * has, as per configuration of this detector instance. * * @return Matcher object which contains result; never null, even in cases * where no match (with specified minimal match strength) is found. * * @since 2.1 */ public Match findFormat(byte[] fullInputData, int offset, int len) throws IOException { return _findFormat(new AccessorForReader(fullInputData, offset, len)); } /* /********************************************************** /* Overrides /********************************************************** */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append('['); final int len = _readers.length; if (len > 0) { sb.append(_readers[0].getFactory().getFormatName()); for (int i = 1; i < len; ++i) { sb.append(", "); sb.append(_readers[i].getFactory().getFormatName()); } } sb.append(']'); return sb.toString(); } /* /********************************************************** /* Internal methods /********************************************************** */ private Match _findFormat(AccessorForReader acc) throws IOException { ObjectReader bestMatch = null; MatchStrength bestMatchStrength = null; for (ObjectReader f : _readers) { acc.reset(); MatchStrength strength = f.getFactory().hasFormat(acc); // if not better than what we have so far (including minimal level limit), skip if (strength == null || strength.ordinal() < _minimalMatch.ordinal()) { continue; } // also, needs to better match than before if (bestMatch != null) { if (bestMatchStrength.ordinal() >= strength.ordinal()) { continue; } } // finally: if it's good enough match, we are done bestMatch = f; bestMatchStrength = strength; if (strength.ordinal() >= _optimalMatch.ordinal()) { break; } } return acc.createMatcher(bestMatch, bestMatchStrength); } /* /********************************************************** /* Helper classes /********************************************************** */ /** * We need sub-class here as well, to be able to access efficiently. */ protected class AccessorForReader extends InputAccessor.Std { public AccessorForReader(InputStream in, byte[] buffer) { super(in, buffer); } public AccessorForReader(byte[] inputDocument) { super(inputDocument); } public AccessorForReader(byte[] inputDocument, int start, int len) { super(inputDocument, start, len); } public Match createMatcher(ObjectReader match, MatchStrength matchStrength) { return new Match(_in, _buffer, _bufferedStart, (_bufferedEnd - _bufferedStart), match, matchStrength); } } /** * Result class, similar to {@link DataFormatMatcher} */ public static class Match { protected final InputStream _originalStream; /** * Content read during format matching process */ protected final byte[] _bufferedData; /** * Pointer to the first byte in buffer available for reading */ protected final int _bufferedStart; /** * Number of bytes available in buffer. */ protected final int _bufferedLength; /** * Factory that produced sufficient match (if any) */ protected final ObjectReader _match; /** * Strength of match with {@link #_match} */ protected final MatchStrength _matchStrength; protected Match(InputStream in, byte[] buffered, int bufferedStart, int bufferedLength, ObjectReader match, MatchStrength strength) { _originalStream = in; _bufferedData = buffered; _bufferedStart = bufferedStart; _bufferedLength = bufferedLength; _match = match; _matchStrength = strength; } /* /********************************************************** /* Public API, simple accessors /********************************************************** */ /** * Accessor to use to see if any formats matched well enough with * the input data. */ public boolean hasMatch() { return _match != null; } /** * Method for accessing strength of the match, if any; if no match, * will return {@link MatchStrength#INCONCLUSIVE}. */ public MatchStrength getMatchStrength() { return (_matchStrength == null) ? MatchStrength.INCONCLUSIVE : _matchStrength; } /** * Accessor for {@link JsonFactory} that represents format that data matched. */ public ObjectReader getReader() { return _match; } /** * Accessor for getting brief textual name of matched format if any (null * if none). Equivalent to: *

         *   return hasMatch() ? getMatch().getFormatName() : null;
         *
*/ public String getMatchedFormatName() { return _match.getFactory().getFormatName(); } /* /********************************************************** /* Public API, factory methods /********************************************************** */ /** * Convenience method for trying to construct a {@link JsonParser} for * parsing content which is assumed to be in detected data format. * If no match was found, returns null. */ public JsonParser createParserWithMatch() throws IOException { if (_match == null) { return null; } JsonFactory jf = _match.getFactory(); if (_originalStream == null) { return jf.createParser(_bufferedData, _bufferedStart, _bufferedLength); } return jf.createParser(getDataStream()); } /** * Method to use for accessing input for which format detection has been done. * This must be used instead of using stream passed to detector * unless given stream itself can do buffering. * Stream will return all content that was read during matching process, as well * as remaining contents of the underlying stream. */ public InputStream getDataStream() { if (_originalStream == null) { return new ByteArrayInputStream(_bufferedData, _bufferedStart, _bufferedLength); } return new MergedStream(null, _originalStream, _bufferedData, _bufferedStart, _bufferedLength); } } } DefaultDeserializationContext.java000066400000000000000000000313661325620701100404260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import java.util.Map.Entry; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdResolver; import com.fasterxml.jackson.annotation.ObjectIdGenerator.IdKey; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId; import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Complete {@link DeserializationContext} implementation that adds * extended API for {@link ObjectMapper} (and {@link ObjectReader}) * to call, as well as implements certain parts that base class * has left abstract. * The remaining abstract methods ({@link #createInstance}, {@link #with}) * are left so that custom implementations will properly implement them * to return intended subtype. */ public abstract class DefaultDeserializationContext extends DeserializationContext implements java.io.Serializable // since 2.1 { private static final long serialVersionUID = 1L; protected transient LinkedHashMap _objectIds; private List _objectIdResolvers; /** * Constructor that will pass specified deserializer factory and * cache: cache may be null (in which case default implementation * will be used), factory cannot be null */ protected DefaultDeserializationContext(DeserializerFactory df, DeserializerCache cache) { super(df, cache); } protected DefaultDeserializationContext(DefaultDeserializationContext src, DeserializationConfig config, JsonParser jp, InjectableValues values) { super(src, config, jp, values); } protected DefaultDeserializationContext(DefaultDeserializationContext src, DeserializerFactory factory) { super(src, factory); } /** * @since 2.4.4 */ protected DefaultDeserializationContext(DefaultDeserializationContext src) { super(src); } /** * Method needed to ensure that {@link ObjectMapper#copy} will work * properly; specifically, that caches are cleared, but settings * will otherwise remain identical; and that no sharing of state * occurs. * * @since 2.4.4 */ public DefaultDeserializationContext copy() { throw new IllegalStateException("DefaultDeserializationContext sub-class not overriding copy()"); } /* /********************************************************** /* Abstract methods impls, Object Id /********************************************************** */ @Override public ReadableObjectId findObjectId(Object id, ObjectIdGenerator gen, ObjectIdResolver resolverType) { /* 02-Apr-2015, tatu: As per [databind#742] should allow 'null', similar to how * missing id already works. */ if (id == null) { return null; } final ObjectIdGenerator.IdKey key = gen.key(id); if (_objectIds == null) { _objectIds = new LinkedHashMap(); } else { ReadableObjectId entry = _objectIds.get(key); if (entry != null) { return entry; } } // Not seen yet, must create entry and configure resolver. ObjectIdResolver resolver = null; if (_objectIdResolvers == null) { _objectIdResolvers = new ArrayList(8); } else { for (ObjectIdResolver res : _objectIdResolvers) { if (res.canUseFor(resolverType)) { resolver = res; break; } } } if (resolver == null) { resolver = resolverType.newForDeserialization(this); _objectIdResolvers.add(resolver); } ReadableObjectId entry = createReadableObjectId(key); entry.setResolver(resolver); _objectIds.put(key, entry); return entry; } /** * Overridable factory method to create a new instance of ReadableObjectId or its * subclass. It is meant to be overridden when custom ReadableObjectId is * needed for {@link #tryToResolveUnresolvedObjectId}. * Default implementation simply constructs default {@link ReadableObjectId} with * given key. * * @param key The key to associate with the new ReadableObjectId * @return New ReadableObjectId instance * * @since 2.7 */ protected ReadableObjectId createReadableObjectId(IdKey key) { return new ReadableObjectId(key); } @Override public void checkUnresolvedObjectId() throws UnresolvedForwardReference { if (_objectIds == null) { return; } // 29-Dec-2014, tatu: As per [databind#299], may also just let unresolved refs be... if (!isEnabled(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS)) { return; } UnresolvedForwardReference exception = null; for (Entry entry : _objectIds.entrySet()) { ReadableObjectId roid = entry.getValue(); if (!roid.hasReferringProperties()) { continue; } // as per [databind#675], allow resolution at this point if (tryToResolveUnresolvedObjectId(roid)) { continue; } if (exception == null) { exception = new UnresolvedForwardReference(getParser(), "Unresolved forward references for: "); } Object key = roid.getKey().key; for (Iterator iterator = roid.referringProperties(); iterator.hasNext(); ) { Referring referring = iterator.next(); exception.addUnresolvedId(key, referring.getBeanType(), referring.getLocation()); } } if (exception != null) { throw exception; } } /** * Overridable helper method called to try to resolve otherwise unresolvable {@link ReadableObjectId}; * and if this succeeds, return true to indicate problem has been resolved in * some way, so that caller can avoid reporting it as an error. *

* Default implementation simply calls {@link ReadableObjectId#tryToResolveUnresolved} and * returns whatever it returns. * * @since 2.6 */ protected boolean tryToResolveUnresolvedObjectId(ReadableObjectId roid) { return roid.tryToResolveUnresolved(this); } /* /********************************************************** /* Abstract methods impls, other factory methods /********************************************************** */ @SuppressWarnings("unchecked") @Override public JsonDeserializer deserializerInstance(Annotated ann, Object deserDef) throws JsonMappingException { if (deserDef == null) { return null; } JsonDeserializer deser; if (deserDef instanceof JsonDeserializer) { deser = (JsonDeserializer) deserDef; } else { /* Alas, there's no way to force return type of "either class * X or Y" -- need to throw an exception after the fact */ if (!(deserDef instanceof Class)) { throw new IllegalStateException("AnnotationIntrospector returned deserializer definition of type "+deserDef.getClass().getName()+"; expected type JsonDeserializer or Class instead"); } Class deserClass = (Class)deserDef; // there are some known "no class" markers to consider too: if (deserClass == JsonDeserializer.None.class || ClassUtil.isBogusClass(deserClass)) { return null; } if (!JsonDeserializer.class.isAssignableFrom(deserClass)) { throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()+"; expected Class"); } HandlerInstantiator hi = _config.getHandlerInstantiator(); deser = (hi == null) ? null : hi.deserializerInstance(_config, ann, deserClass); if (deser == null) { deser = (JsonDeserializer) ClassUtil.createInstance(deserClass, _config.canOverrideAccessModifiers()); } } // First: need to resolve if (deser instanceof ResolvableDeserializer) { ((ResolvableDeserializer) deser).resolve(this); } return (JsonDeserializer) deser; } @Override public final KeyDeserializer keyDeserializerInstance(Annotated ann, Object deserDef) throws JsonMappingException { if (deserDef == null) { return null; } KeyDeserializer deser; if (deserDef instanceof KeyDeserializer) { deser = (KeyDeserializer) deserDef; } else { if (!(deserDef instanceof Class)) { throw new IllegalStateException("AnnotationIntrospector returned key deserializer definition of type " +deserDef.getClass().getName() +"; expected type KeyDeserializer or Class instead"); } Class deserClass = (Class)deserDef; // there are some known "no class" markers to consider too: if (deserClass == KeyDeserializer.None.class || ClassUtil.isBogusClass(deserClass)) { return null; } if (!KeyDeserializer.class.isAssignableFrom(deserClass)) { throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName() +"; expected Class"); } HandlerInstantiator hi = _config.getHandlerInstantiator(); deser = (hi == null) ? null : hi.keyDeserializerInstance(_config, ann, deserClass); if (deser == null) { deser = (KeyDeserializer) ClassUtil.createInstance(deserClass, _config.canOverrideAccessModifiers()); } } // First: need to resolve if (deser instanceof ResolvableDeserializer) { ((ResolvableDeserializer) deser).resolve(this); } return deser; } /* /********************************************************** /* Extended API /********************************************************** */ /** * Fluent factory method used for constructing a blueprint instance * with different factory */ public abstract DefaultDeserializationContext with(DeserializerFactory factory); /** * Method called to create actual usable per-deserialization * context instance. */ public abstract DefaultDeserializationContext createInstance( DeserializationConfig config, JsonParser jp, InjectableValues values); /* /********************************************************** /* And then the concrete implementation class /********************************************************** */ /** * Actual full concrete implementation */ public final static class Impl extends DefaultDeserializationContext { private static final long serialVersionUID = 1L; /** * Default constructor for a blueprint object, which will use the standard * {@link DeserializerCache}, given factory. */ public Impl(DeserializerFactory df) { super(df, null); } protected Impl(Impl src, DeserializationConfig config, JsonParser jp, InjectableValues values) { super(src, config, jp, values); } protected Impl(Impl src) { super(src); } protected Impl(Impl src, DeserializerFactory factory) { super(src, factory); } @Override public DefaultDeserializationContext copy() { ClassUtil.verifyMustOverride(Impl.class, this, "copy"); return new Impl(this); } @Override public DefaultDeserializationContext createInstance(DeserializationConfig config, JsonParser p, InjectableValues values) { return new Impl(this, config, p, values); } @Override public DefaultDeserializationContext with(DeserializerFactory factory) { return new Impl(this, factory); } } } DeserializationProblemHandler.java000066400000000000000000000377131325620701100403750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; /** * This is the class that can be registered (via * {@link DeserializationConfig} object owner by * {@link ObjectMapper}) to get called when a potentially * recoverable problem is encountered during deserialization * process. Handlers can try to resolve the problem, throw * an exception or just skip the content. *

* Default implementations for all methods implemented minimal * "do nothing" functionality, which is roughly equivalent to * not having a registered listener at all. This allows for * only implemented handler methods one is interested in, without * handling other cases. *

* NOTE: it is typically NOT acceptable to simply do nothing, * because this will result in unprocessed tokens being left in * token stream (read via {@link JsonParser}, in case a structured * (JSON Object or JSON Array) value is being pointed to by parser. */ public abstract class DeserializationProblemHandler { /** * Marker value returned by some handler methods to indicate that * they could not handle problem and produce replacement value. * * @since 2.7 */ public final static Object NOT_HANDLED = new Object(); /** * Method called when a JSON Object property with an unrecognized * name is encountered. * Content (supposedly) matching the property are accessible via * parser that can be obtained from passed deserialization context. * Handler can also choose to skip the content; if so, it MUST return * true to indicate it did handle property successfully. * Skipping is usually done like so: *

     *  parser.skipChildren();
     *
*

* Note: {@link com.fasterxml.jackson.databind.DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIES}) * takes effect only after handler is called, and only * if handler did not handle the problem. * * @param beanOrClass Either bean instance being deserialized (if one * has been instantiated so far); or Class that indicates type that * will be instantiated (if no instantiation done yet: for example * when bean uses non-default constructors) * @param p Parser to use for handling problematic content * * @return True if the problem is resolved (and content available used or skipped); * false if the handler did not anything and the problem is unresolved. Note that in * latter case caller will either throw an exception or explicitly skip the content, * depending on configuration. */ public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer deserializer, Object beanOrClass, String propertyName) throws IOException { return false; } /** * Method called when a property name from input cannot be converted to a * non-Java-String key type (passed as rawKeyType) due to format problem. * Handler may choose to do one of 3 things: *

    *
  • Indicate it does not know what to do by returning {@link #NOT_HANDLED} *
  • *
  • Throw a {@link IOException} to indicate specific fail message (instead of * standard exception caller would throw *
  • *
  • Return actual key value to use as replacement, and continue processing. *
  • *
* * @param failureMsg Message that will be used by caller (by calling * {@link DeserializationContext#weirdKeyException(Class, String, String)}) * to indicate type of failure unless handler produces key to use * * @return Either {@link #NOT_HANDLED} to indicate that handler does not know * what to do (and exception may be thrown), or value to use as key (possibly * null * * @since 2.8 */ public Object handleWeirdKey(DeserializationContext ctxt, Class rawKeyType, String keyValue, String failureMsg) throws IOException { return NOT_HANDLED; } /** * Method called when a String value * cannot be converted to a non-String value type due to specific problem * (as opposed to String values never being usable). * Handler may choose to do one of 3 things: *
    *
  • Indicate it does not know what to do by returning {@link #NOT_HANDLED} *
  • *
  • Throw a {@link IOException} to indicate specific fail message (instead of * standard exception caller would throw *
  • *
  • Return actual converted value (of type targetType) to use as * replacement, and continue processing. *
  • *
* * @param failureMsg Message that will be used by caller (by calling * {@link DeserializationContext#weirdNumberException}) * to indicate type of failure unless handler produces key to use * * @return Either {@link #NOT_HANDLED} to indicate that handler does not know * what to do (and exception may be thrown), or value to use as (possibly * null) * * @since 2.8 */ public Object handleWeirdStringValue(DeserializationContext ctxt, Class targetType, String valueToConvert, String failureMsg) throws IOException { return NOT_HANDLED; } /** * Method called when a numeric value (integral or floating-point from input * cannot be converted to a non-numeric value type due to specific problem * (as opposed to numeric values never being usable). * Handler may choose to do one of 3 things: *
    *
  • Indicate it does not know what to do by returning {@link #NOT_HANDLED} *
  • *
  • Throw a {@link IOException} to indicate specific fail message (instead of * standard exception caller would throw *
  • *
  • Return actual converted value (of type targetType) to use as * replacement, and continue processing. *
  • *
* * @param failureMsg Message that will be used by caller (by calling * {@link DeserializationContext#weirdNumberException}) * to indicate type of failure unless handler produces key to use * * @return Either {@link #NOT_HANDLED} to indicate that handler does not know * what to do (and exception may be thrown), or value to use as (possibly * null) * * @since 2.8 */ public Object handleWeirdNumberValue(DeserializationContext ctxt, Class targetType, Number valueToConvert, String failureMsg) throws IOException { return NOT_HANDLED; } /** * Method called when an embedded (native) value ({@link JsonToken#VALUE_EMBEDDED_OBJECT}) * cannot be converted directly into expected value type (usually POJO). * Handler may choose to do one of 3 things: *
    *
  • Indicate it does not know what to do by returning {@link #NOT_HANDLED} *
  • *
  • Throw a {@link IOException} to indicate specific fail message (instead of * standard exception caller would throw *
  • *
  • Return actual converted value (of type targetType) to use as * replacement, and continue processing. *
  • *
* * @return Either {@link #NOT_HANDLED} to indicate that handler does not know * what to do (and exception may be thrown), or value to use (possibly * null) * * @since 2.9 */ public Object handleWeirdNativeValue(DeserializationContext ctxt, JavaType targetType, Object valueToConvert, JsonParser p) throws IOException { return NOT_HANDLED; } /** * Method that deserializers should call if the first token of the value to * deserialize is of unexpected type (that is, type of token that deserializer * cannot handle). This could occur, for example, if a Number deserializer * encounter {@link JsonToken#START_ARRAY} instead of * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}. *
    *
  • Indicate it does not know what to do by returning {@link #NOT_HANDLED} *
  • *
  • Throw a {@link IOException} to indicate specific fail message (instead of * standard exception caller would throw *
  • *
  • Handle content to match (by consuming or skipping it), and return actual * instantiated value (of type targetType) to use as replacement; * value may be `null` as well as expected target type. *
  • *
* * @param failureMsg Message that will be used by caller * to indicate type of failure unless handler produces value to use * * @return Either {@link #NOT_HANDLED} to indicate that handler does not know * what to do (and exception may be thrown), or value to use (possibly * null * * @since 2.8 */ public Object handleUnexpectedToken(DeserializationContext ctxt, Class targetType, JsonToken t, JsonParser p, String failureMsg) throws IOException { return NOT_HANDLED; } /** * Method called when instance creation for a type fails due to an exception. * Handler may choose to do one of following things: *
    *
  • Indicate it does not know what to do by returning {@link #NOT_HANDLED} *
  • *
  • Throw a {@link IOException} to indicate specific fail message (instead of * standard exception caller would throw *
  • *
  • Return actual instantiated value (of type targetType) to use as * replacement, and continue processing. *
  • *
  • Return null to use null as value but not to try further * processing (in cases where properties would otherwise be bound) *
  • *
* * @param instClass Type that was to be instantiated * @param argument (optional) Additional argument that was passed to creator, if any * @param t Exception that caused instantiation failure * * @return Either {@link #NOT_HANDLED} to indicate that handler does not know * what to do (and exception may be thrown), or value to use (possibly * null * * @since 2.8 */ public Object handleInstantiationProblem(DeserializationContext ctxt, Class instClass, Object argument, Throwable t) throws IOException { return NOT_HANDLED; } /** * Method called when instance creation for a type fails due to lack of an * instantiator. Method is called before actual deserialization from input * is attempted, so handler may do one of following things: *
    *
  • Indicate it does not know what to do by returning {@link #NOT_HANDLED} *
  • *
  • Throw a {@link IOException} to indicate specific fail message (instead of * standard exception caller would throw *
  • *
  • Handle content to match (by consuming or skipping it), and return actual * instantiated value (of type targetType) to use as replacement; * value may be `null` as well as expected target type. *
  • *
* * @param instClass Type that was to be instantiated * @param p Parser to use for accessing content that needs handling, to either * use it or skip it (latter with {@link JsonParser#skipChildren()}. * * @return Either {@link #NOT_HANDLED} to indicate that handler does not know * what to do (and exception may be thrown), or value to use (possibly * null * * @since 2.9 */ public Object handleMissingInstantiator(DeserializationContext ctxt, Class instClass, ValueInstantiator valueInsta, JsonParser p, String msg) throws IOException { // 16-Oct-2016, tatu: Need to delegate to deprecated method from 2.8; // remove redirect from later versions (post-2.9) return handleMissingInstantiator(ctxt, instClass, p, msg); } /** * Handler method called if resolution of type id from given String failed * to produce a subtype; usually because logical id is not mapped to actual * implementation class. * Handler may choose to do one of following things: *
    *
  • Indicate it does not know what to do by returning `null` *
  • *
  • Indicate that nothing should be deserialized, by return `Void.class` *
  • *
  • Throw a {@link IOException} to indicate specific fail message (instead of * standard exception caller would throw *
  • *
  • Return actual resolved type to use for type id. *
  • *
* * @param ctxt Deserialization context to use for accessing information or * constructing exception to throw * @param baseType Base type to use for resolving subtype id * @param subTypeId Subtype id that failed to resolve * @param failureMsg Informational message that would be thrown as part of * exception, if resolution still fails * * @return Actual type to use, if resolved; `null` if handler does not know what * to do; or `Void.class` to indicate that nothing should be deserialized for * type with the id (which caller may choose to do... or not) * * @since 2.8 */ public JavaType handleUnknownTypeId(DeserializationContext ctxt, JavaType baseType, String subTypeId, TypeIdResolver idResolver, String failureMsg) throws IOException { return null; } /** * Handler method called if an expected type id for a polymorphic value is * not found and no "default type" is specified or allowed. * Handler may choose to do one of following things: *
    *
  • Indicate it does not know what to do by returning `null` *
  • *
  • Indicate that nothing should be deserialized, by return `Void.class` *
  • *
  • Throw a {@link IOException} to indicate specific fail message (instead of * standard exception caller would throw *
  • *
  • Return actual resolved type to use for this particular case. *
  • *
* * @param ctxt Deserialization context to use for accessing information or * constructing exception to throw * @param baseType Base type to use for resolving subtype id * @param failureMsg Informational message that would be thrown as part of * exception, if resolution still fails * * @return Actual type to use, if resolved; `null` if handler does not know what * to do; or `Void.class` to indicate that nothing should be deserialized for * type with the id (which caller may choose to do... or not) * * @since 2.9 */ public JavaType handleMissingTypeId(DeserializationContext ctxt, JavaType baseType, TypeIdResolver idResolver, String failureMsg) throws IOException { return null; } /* /********************************************************** /* Deprecated /********************************************************** */ /** * @since 2.8 * @deprecated Since 2.9: use variant that takes {@link ValueInstantiator} */ @Deprecated public Object handleMissingInstantiator(DeserializationContext ctxt, Class instClass, JsonParser p, String msg) throws IOException { return NOT_HANDLED; } } DeserializerCache.java000066400000000000000000000614251325620701100357730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.type.*; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.Converter; /** * Class that defines caching layer between callers (like * {@link ObjectMapper}, * {@link com.fasterxml.jackson.databind.DeserializationContext}) * and classes that construct deserializers * ({@link com.fasterxml.jackson.databind.deser.DeserializerFactory}). */ public final class DeserializerCache implements java.io.Serializable // since 2.1 -- needs to be careful tho { private static final long serialVersionUID = 1L; /* /********************************************************** /* Caching /********************************************************** */ /** * We will also cache some dynamically constructed deserializers; * specifically, ones that are expensive to construct. * This currently means bean and Enum deserializers; starting with * 2.5, container deserializers will also be cached. *

* Given that we don't expect much concurrency for additions * (should very quickly converge to zero after startup), let's * define a relatively low concurrency setting. */ final protected ConcurrentHashMap> _cachedDeserializers = new ConcurrentHashMap>(64, 0.75f, 4); /** * During deserializer construction process we may need to keep track of partially * completed deserializers, to resolve cyclic dependencies. This is the * map used for storing deserializers before they are fully complete. */ final protected HashMap> _incompleteDeserializers = new HashMap>(8); /* /********************************************************** /* Life-cycle /********************************************************** */ public DeserializerCache() { } /* /********************************************************** /* JDK serialization handling /********************************************************** */ Object writeReplace() { // instead of making this transient, just clear it: _incompleteDeserializers.clear(); // TODO: clear out "cheap" cached deserializers? return this; } /* /********************************************************** /* Access to caching aspects /********************************************************** */ /** * Method that can be used to determine how many deserializers this * provider is caching currently * (if it does caching: default implementation does) * Exact count depends on what kind of deserializers get cached; * default implementation caches only dynamically constructed deserializers, * but not eagerly constructed standard deserializers (which is different * from how serializer provider works). *

* The main use case for this method is to allow conditional flushing of * deserializer cache, if certain number of entries is reached. */ public int cachedDeserializersCount() { return _cachedDeserializers.size(); } /** * Method that will drop all dynamically constructed deserializers (ones that * are counted as result value for {@link #cachedDeserializersCount}). * This can be used to remove memory usage (in case some deserializers are * only used once or so), or to force re-construction of deserializers after * configuration changes for mapper than owns the provider. */ public void flushCachedDeserializers() { _cachedDeserializers.clear(); } /* /********************************************************** /* General deserializer locating method /********************************************************** */ /** * Method called to get hold of a deserializer for a value of given type; * or if no such deserializer can be found, a default handler (which * may do a best-effort generic serialization or just simply * throw an exception when invoked). *

* Note: this method is only called for value types; not for keys. * Key deserializers can be accessed using {@link #findKeyDeserializer}. *

* Note also that deserializer returned is guaranteed to be resolved * (if it is of type {@link ResolvableDeserializer}), but * not contextualized (wrt {@link ContextualDeserializer}): caller * has to handle latter if necessary. * * @param ctxt Deserialization context * @param propertyType Declared type of the value to deserializer (obtained using * 'setter' method signature and/or type annotations * * @throws JsonMappingException if there are fatal problems with * accessing suitable deserializer; including that of not * finding any serializer */ public JsonDeserializer findValueDeserializer(DeserializationContext ctxt, DeserializerFactory factory, JavaType propertyType) throws JsonMappingException { JsonDeserializer deser = _findCachedDeserializer(propertyType); if (deser == null) { // If not, need to request factory to construct (or recycle) deser = _createAndCacheValueDeserializer(ctxt, factory, propertyType); if (deser == null) { /* Should we let caller handle it? Let's have a helper method * decide it; can throw an exception, or return a valid * deserializer */ deser = _handleUnknownValueDeserializer(ctxt, propertyType); } } return deser; } /** * Method called to get hold of a deserializer to use for deserializing * keys for {@link java.util.Map}. * * @throws JsonMappingException if there are fatal problems with * accessing suitable key deserializer; including that of not * finding any serializer */ public KeyDeserializer findKeyDeserializer(DeserializationContext ctxt, DeserializerFactory factory, JavaType type) throws JsonMappingException { KeyDeserializer kd = factory.createKeyDeserializer(ctxt, type); if (kd == null) { // if none found, need to use a placeholder that'll fail return _handleUnknownKeyDeserializer(ctxt, type); } // First: need to resolve? if (kd instanceof ResolvableDeserializer) { ((ResolvableDeserializer) kd).resolve(ctxt); } return kd; } /** * Method called to find out whether provider would be able to find * a deserializer for given type, using a root reference (i.e. not * through fields or membership in an array or collection) */ public boolean hasValueDeserializerFor(DeserializationContext ctxt, DeserializerFactory factory, JavaType type) throws JsonMappingException { /* Note: mostly copied from findValueDeserializer, except for * handling of unknown types */ JsonDeserializer deser = _findCachedDeserializer(type); if (deser == null) { deser = _createAndCacheValueDeserializer(ctxt, factory, type); } return (deser != null); } /* /********************************************************** /* Helper methods that handle cache lookups /********************************************************** */ protected JsonDeserializer _findCachedDeserializer(JavaType type) { if (type == null) { throw new IllegalArgumentException("Null JavaType passed"); } if (_hasCustomHandlers(type)) { return null; } return _cachedDeserializers.get(type); } /** * Method that will try to create a deserializer for given type, * and resolve and cache it if necessary * * @param ctxt Currently active deserialization context * @param type Type of property to deserialize */ protected JsonDeserializer _createAndCacheValueDeserializer(DeserializationContext ctxt, DeserializerFactory factory, JavaType type) throws JsonMappingException { /* Only one thread to construct deserializers at any given point in time; * limitations necessary to ensure that only completely initialized ones * are visible and used. */ synchronized (_incompleteDeserializers) { // Ok, then: could it be that due to a race condition, deserializer can now be found? JsonDeserializer deser = _findCachedDeserializer(type); if (deser != null) { return deser; } int count = _incompleteDeserializers.size(); // Or perhaps being resolved right now? if (count > 0) { deser = _incompleteDeserializers.get(type); if (deser != null) { return deser; } } // Nope: need to create and possibly cache try { return _createAndCache2(ctxt, factory, type); } finally { // also: any deserializers that have been created are complete by now if (count == 0 && _incompleteDeserializers.size() > 0) { _incompleteDeserializers.clear(); } } } } /** * Method that handles actual construction (via factory) and caching (both * intermediate and eventual) */ protected JsonDeserializer _createAndCache2(DeserializationContext ctxt, DeserializerFactory factory, JavaType type) throws JsonMappingException { JsonDeserializer deser; try { deser = _createDeserializer(ctxt, factory, type); } catch (IllegalArgumentException iae) { // We better only expose checked exceptions, since those // are what caller is expected to handle throw JsonMappingException.from(ctxt, iae.getMessage(), iae); } if (deser == null) { return null; } /* cache resulting deserializer? always true for "plain" BeanDeserializer * (but can be re-defined for sub-classes by using @JsonCachable!) */ // 27-Mar-2015, tatu: As per [databind#735], avoid caching types with custom value desers boolean addToCache = !_hasCustomHandlers(type) && deser.isCachable(); /* we will temporarily hold on to all created deserializers (to * handle cyclic references, and possibly reuse non-cached * deserializers (list, map)) */ /* 07-Jun-2010, tatu: Danger: [JACKSON-296] was caused by accidental * resolution of a reference -- couple of ways to prevent this; * either not add Lists or Maps, or clear references eagerly. * Let's actually do both; since both seem reasonable. */ /* Need to resolve? Mostly done for bean deserializers; required for * resolving cyclic references. */ if (deser instanceof ResolvableDeserializer) { _incompleteDeserializers.put(type, deser); ((ResolvableDeserializer)deser).resolve(ctxt); _incompleteDeserializers.remove(type); } if (addToCache) { _cachedDeserializers.put(type, deser); } return deser; } /* /********************************************************** /* Helper methods for actual construction of deserializers /********************************************************** */ /** * Method that does the heavy lifting of checking for per-type annotations, * find out full type, and figure out which actual factory method * to call. */ @SuppressWarnings("unchecked") protected JsonDeserializer _createDeserializer(DeserializationContext ctxt, DeserializerFactory factory, JavaType type) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); // First things first: do we need to use abstract type mapping? if (type.isAbstract() || type.isMapLikeType() || type.isCollectionLikeType()) { type = factory.mapAbstractType(config, type); } BeanDescription beanDesc = config.introspect(type); // Then: does type define explicit deserializer to use, with annotation(s)? JsonDeserializer deser = findDeserializerFromAnnotation(ctxt, beanDesc.getClassInfo()); if (deser != null) { return deser; } // If not, may have further type-modification annotations to check: JavaType newType = modifyTypeByAnnotation(ctxt, beanDesc.getClassInfo(), type); if (newType != type) { type = newType; beanDesc = config.introspect(newType); } // We may also have a Builder type to consider... Class builder = beanDesc.findPOJOBuilder(); if (builder != null) { return (JsonDeserializer) factory.createBuilderBasedDeserializer( ctxt, type, beanDesc, builder); } // Or perhaps a Converter? Converter conv = beanDesc.findDeserializationConverter(); if (conv == null) { // nope, just construct in normal way return (JsonDeserializer) _createDeserializer2(ctxt, factory, type, beanDesc); } // otherwise need to do bit of introspection JavaType delegateType = conv.getInputType(ctxt.getTypeFactory()); // One more twist, as per [databind#288]; probably need to get new BeanDesc if (!delegateType.hasRawClass(type.getRawClass())) { beanDesc = config.introspect(delegateType); } return new StdDelegatingDeserializer(conv, delegateType, _createDeserializer2(ctxt, factory, delegateType, beanDesc)); } protected JsonDeserializer _createDeserializer2(DeserializationContext ctxt, DeserializerFactory factory, JavaType type, BeanDescription beanDesc) throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); // If not, let's see which factory method to use: if (type.isEnumType()) { return factory.createEnumDeserializer(ctxt, type, beanDesc); } if (type.isContainerType()) { if (type.isArrayType()) { return factory.createArrayDeserializer(ctxt, (ArrayType) type, beanDesc); } if (type.isMapLikeType()) { // 11-Mar-2017, tatu: As per [databind#1554], also need to block // handling as Map if overriden with "as POJO" option. // Ideally we'd determine it bit later on (to allow custom handler checks) // but that won't work for other reasons. So do it here. // (read: rewrite for 3.0) JsonFormat.Value format = beanDesc.findExpectedFormat(null); if ((format == null) || format.getShape() != JsonFormat.Shape.OBJECT) { MapLikeType mlt = (MapLikeType) type; if (mlt.isTrueMapType()) { return factory.createMapDeserializer(ctxt,(MapType) mlt, beanDesc); } return factory.createMapLikeDeserializer(ctxt, mlt, beanDesc); } } if (type.isCollectionLikeType()) { /* 03-Aug-2012, tatu: As per [databind#40], one exception is if shape * is to be Shape.OBJECT. Ideally we'd determine it bit later on * (to allow custom handler checks), but that won't work for other * reasons. So do it here. */ JsonFormat.Value format = beanDesc.findExpectedFormat(null); if ((format == null) || format.getShape() != JsonFormat.Shape.OBJECT) { CollectionLikeType clt = (CollectionLikeType) type; if (clt.isTrueCollectionType()) { return factory.createCollectionDeserializer(ctxt, (CollectionType) clt, beanDesc); } return factory.createCollectionLikeDeserializer(ctxt, clt, beanDesc); } } } if (type.isReferenceType()) { return factory.createReferenceDeserializer(ctxt, (ReferenceType) type, beanDesc); } if (JsonNode.class.isAssignableFrom(type.getRawClass())) { return factory.createTreeDeserializer(config, type, beanDesc); } return factory.createBeanDeserializer(ctxt, type, beanDesc); } /** * Helper method called to check if a class or method * has annotation that tells which class to use for deserialization. * Returns null if no such annotation found. */ protected JsonDeserializer findDeserializerFromAnnotation(DeserializationContext ctxt, Annotated ann) throws JsonMappingException { Object deserDef = ctxt.getAnnotationIntrospector().findDeserializer(ann); if (deserDef == null) { return null; } JsonDeserializer deser = ctxt.deserializerInstance(ann, deserDef); // One more thing however: may need to also apply a converter: return findConvertingDeserializer(ctxt, ann, deser); } /** * Helper method that will check whether given annotated entity (usually class, * but may also be a property accessor) indicates that a {@link Converter} is to * be used; and if so, to construct and return suitable serializer for it. * If not, will simply return given serializer as is. */ protected JsonDeserializer findConvertingDeserializer(DeserializationContext ctxt, Annotated a, JsonDeserializer deser) throws JsonMappingException { Converter conv = findConverter(ctxt, a); if (conv == null) { return deser; } JavaType delegateType = conv.getInputType(ctxt.getTypeFactory()); return (JsonDeserializer) new StdDelegatingDeserializer(conv, delegateType, deser); } protected Converter findConverter(DeserializationContext ctxt, Annotated a) throws JsonMappingException { Object convDef = ctxt.getAnnotationIntrospector().findDeserializationConverter(a); if (convDef == null) { return null; } return ctxt.converterInstance(a, convDef); } /** * Method called to see if given method has annotations that indicate * a more specific type than what the argument specifies. * If annotations are present, they must specify compatible Class; * instance of which can be assigned using the method. This means * that the Class has to be raw class of type, or its sub-class * (or, implementing class if original Class instance is an interface). * * @param a Method or field that the type is associated with * @param type Type derived from the setter argument * * @return Original type if no annotations are present; or a more * specific type derived from it if type annotation(s) was found * * @throws JsonMappingException if invalid annotation is found */ private JavaType modifyTypeByAnnotation(DeserializationContext ctxt, Annotated a, JavaType type) throws JsonMappingException { AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (intr == null) { return type; } // First things first: find explicitly annotated deserializer(s) // then key/value handlers (annotated deserializers)? if (type.isMapLikeType()) { JavaType keyType = type.getKeyType(); // 21-Mar-2011, tatu: ... and associated deserializer too (unless already assigned) // (not 100% why or how, but this does seem to get called more than once, which // is not good: for now, let's just avoid errors) if (keyType != null && keyType.getValueHandler() == null) { Object kdDef = intr.findKeyDeserializer(a); if (kdDef != null) { KeyDeserializer kd = ctxt.keyDeserializerInstance(a, kdDef); if (kd != null) { type = ((MapLikeType) type).withKeyValueHandler(kd); keyType = type.getKeyType(); // just in case it's used below } } } } JavaType contentType = type.getContentType(); if (contentType != null) { if (contentType.getValueHandler() == null) { // as with above, avoid resetting (which would trigger exception) Object cdDef = intr.findContentDeserializer(a); if (cdDef != null) { JsonDeserializer cd = null; if (cdDef instanceof JsonDeserializer) { cdDef = (JsonDeserializer) cdDef; } else { Class cdClass = _verifyAsClass(cdDef, "findContentDeserializer", JsonDeserializer.None.class); if (cdClass != null) { cd = ctxt.deserializerInstance(a, cdClass); } } if (cd != null) { type = type.withContentValueHandler(cd); } } } } // And after handlers, possible type refinements // (note: could possibly avoid this if explicit deserializer was invoked?) type = intr.refineDeserializationType(ctxt.getConfig(), a, type); return type; } /* /********************************************************** /* Helper methods, other /********************************************************** */ /** * Helper method used to prevent both caching and cache lookups for structured * types that have custom value handlers * * @since 2.8.11 */ private boolean _hasCustomHandlers(JavaType t) { if (t.isContainerType()) { // First: value types may have both value and type handlers JavaType ct = t.getContentType(); if (ct != null) { if ((ct.getValueHandler() != null) || (ct.getTypeHandler() != null)) { return true; } } // Second: map(-like) types may have value handler for key (but not type; keys are untyped) if (t.isMapLikeType()) { JavaType kt = t.getKeyType(); if (kt.getValueHandler() != null) { return true; } } } return false; } private Class _verifyAsClass(Object src, String methodName, Class noneClass) { if (src == null) { return null; } if (!(src instanceof Class)) { throw new IllegalStateException("AnnotationIntrospector."+methodName+"() returned value of type "+src.getClass().getName()+": expected type JsonSerializer or Class instead"); } Class cls = (Class) src; if (cls == noneClass || ClassUtil.isBogusClass(cls)) { return null; } return cls; } /* /********************************************************** /* Overridable error reporting methods /********************************************************** */ protected JsonDeserializer _handleUnknownValueDeserializer(DeserializationContext ctxt, JavaType type) throws JsonMappingException { // Let's try to figure out the reason, to give better error messages Class rawClass = type.getRawClass(); if (!ClassUtil.isConcrete(rawClass)) { return ctxt.reportBadDefinition(type, "Cannot find a Value deserializer for abstract type "+type); } return ctxt.reportBadDefinition(type, "Cannot find a Value deserializer for type "+type); } protected KeyDeserializer _handleUnknownKeyDeserializer(DeserializationContext ctxt, JavaType type) throws JsonMappingException { return ctxt.reportBadDefinition(type, "Cannot find a (Map) Key deserializer for type "+type); } } DeserializerFactory.java000066400000000000000000000204251325620701100363720ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.type.*; /** * Abstract class that defines API used by {@link DeserializationContext} * to construct actual * {@link JsonDeserializer} instances (which are then cached by * context and/or dedicated cache). *

* Since there are multiple broad categories of deserializers, there are * multiple factory methods: *

    *
  • For JSON "Array" type, we need 2 methods: one to deal with expected * Java arrays ({@link #createArrayDeserializer}) * and the other for other Java containers like {@link java.util.List}s * and {@link java.util.Set}s ({@link #createCollectionDeserializer}). * Actually there is also a third method for "Collection-like" types; * things like Scala collections that act like JDK collections but do not * implement same interfaces. *
  • *
  • For JSON "Object" type, we need 2 methods: one to deal with * expected Java {@link java.util.Map}s * ({@link #createMapDeserializer}), and another for POJOs * ({@link #createBeanDeserializer}. * As an additional twist there is also a callback for "Map-like" types, * mostly to make it possible to support Scala Maps (which are NOT JDK * Map compatible). *
  • *
  • For Tree Model ({@link com.fasterxml.jackson.databind.JsonNode}) properties there is * {@link #createTreeDeserializer} *
  • For enumerated types ({@link java.lang.Enum}) there is * {@link #createEnumDeserializer} *
  • *
  • For all other types, {@link #createBeanDeserializer} is used. *
*

*/ public abstract class DeserializerFactory { protected final static Deserializers[] NO_DESERIALIZERS = new Deserializers[0]; /* /******************************************************** /* Configuration handling /******************************************************** */ /** * Convenience method for creating a new factory instance with additional deserializer * provider. */ public abstract DeserializerFactory withAdditionalDeserializers(Deserializers additional); /** * Convenience method for creating a new factory instance with additional * {@link KeyDeserializers}. */ public abstract DeserializerFactory withAdditionalKeyDeserializers(KeyDeserializers additional); /** * Convenience method for creating a new factory instance with additional * {@link BeanDeserializerModifier}. */ public abstract DeserializerFactory withDeserializerModifier(BeanDeserializerModifier modifier); /** * Convenience method for creating a new factory instance with additional * {@link AbstractTypeResolver}. */ public abstract DeserializerFactory withAbstractTypeResolver(AbstractTypeResolver resolver); /** * Convenience method for creating a new factory instance with additional * {@link ValueInstantiators}. */ public abstract DeserializerFactory withValueInstantiators(ValueInstantiators instantiators); /* /********************************************************** /* Basic DeserializerFactory API: /********************************************************** */ /** * Method that can be called to try to resolve an abstract type * (interface, abstract class) into a concrete type, or at least * something "more concrete" (abstract class instead of interface). * Will either return passed type, or a more specific type. */ public abstract JavaType mapAbstractType(DeserializationConfig config, JavaType type) throws JsonMappingException; /** * Method that is to find all creators (constructors, factory methods) * for the bean type to deserialize. */ public abstract ValueInstantiator findValueInstantiator(DeserializationContext ctxt, BeanDescription beanDesc) throws JsonMappingException; /** * Method called to create (or, for completely immutable deserializers, * reuse) a deserializer that can convert JSON content into values of * specified Java "bean" (POJO) type. * At this point it is known that the type is not otherwise recognized * as one of structured types (array, Collection, Map) or a well-known * JDK type (enum, primitives/wrappers, String); this method only * gets called if other options are exhausted. This also means that * this method can be overridden to add support for custom types. * * @param type Type to be deserialized */ public abstract JsonDeserializer createBeanDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException; /** * Method called to create a deserializer that will use specified Builder * class for building value instances. */ public abstract JsonDeserializer createBuilderBasedDeserializer( DeserializationContext ctxt, JavaType type, BeanDescription beanDesc, Class builderClass) throws JsonMappingException; public abstract JsonDeserializer createEnumDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException; /** * @since 2.7 */ public abstract JsonDeserializer createReferenceDeserializer(DeserializationContext ctxt, ReferenceType type, BeanDescription beanDesc) throws JsonMappingException; /** * Method called to create and return a deserializer that can construct * JsonNode(s) from JSON content. */ public abstract JsonDeserializer createTreeDeserializer(DeserializationConfig config, JavaType type, BeanDescription beanDesc) throws JsonMappingException; /** * Method called to create (or, for completely immutable deserializers, * reuse) a deserializer that can convert JSON content into values of * specified Java type. * * @param type Type to be deserialized */ public abstract JsonDeserializer createArrayDeserializer(DeserializationContext ctxt, ArrayType type, BeanDescription beanDesc) throws JsonMappingException; public abstract JsonDeserializer createCollectionDeserializer(DeserializationContext ctxt, CollectionType type, BeanDescription beanDesc) throws JsonMappingException; public abstract JsonDeserializer createCollectionLikeDeserializer(DeserializationContext ctxt, CollectionLikeType type, BeanDescription beanDesc) throws JsonMappingException; public abstract JsonDeserializer createMapDeserializer(DeserializationContext ctxt, MapType type, BeanDescription beanDesc) throws JsonMappingException; public abstract JsonDeserializer createMapLikeDeserializer(DeserializationContext ctxt, MapLikeType type, BeanDescription beanDesc) throws JsonMappingException; /** * Method called to find if factory knows how to create a key deserializer * for specified type; currently this means checking if a module has registered * possible deserializers. * * @return Key deserializer to use for specified type, if one found; null if not * (and default key deserializer should be used) */ public abstract KeyDeserializer createKeyDeserializer(DeserializationContext ctxt, JavaType type) throws JsonMappingException; /** * Method called to find and create a type information deserializer for given base type, * if one is needed. If not needed (no polymorphic handling configured for type), * should return null. *

* Note that this method is usually only directly called for values of container (Collection, * array, Map) types and root values, but not for bean property values. * * @param baseType Declared base type of the value to deserializer (actual * deserializer type will be this type or its subtype) * * @return Type deserializer to use for given base type, if one is needed; null if not. */ public abstract TypeDeserializer findTypeDeserializer(DeserializationConfig config, JavaType baseType) throws JsonMappingException; } Deserializers.java000066400000000000000000000414121325620701100352240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.type.*; /** * Interface that defines API for simple extensions that can provide additional deserializers * for various types. Access is by a single callback method; instance is to either return * a configured {@link JsonDeserializer} for specified type, or null to indicate that it * does not support handling of the type. In latter case, further calls can be made * for other providers; in former case returned deserializer is used for handling of * instances of specified type. *

* It is strongly recommended that implementations always extend {@link Deserializers.Base} * and NOT just implement {@link Deserializers}. */ public interface Deserializers { // // // Scalar types first: /** * Method called to locate deserializer for specified {@link java.lang.Enum} type. * * @param type Type of {@link java.lang.Enum} instances to deserialize * @param config Configuration in effect * @param beanDesc Definition of the enumeration type that contains class annotations and * other information typically needed for building deserializers * * @return Deserializer to use for the type; or null if this provider does not know how to construct it */ public JsonDeserializer findEnumDeserializer(Class type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException; /** * Method called to locate deserializer for specified JSON tree node type. * * @param nodeType Specific type of JSON tree nodes to deserialize * (subtype of {@link com.fasterxml.jackson.databind.JsonNode}) * @param config Configuration in effect * * @return Deserializer to use for the type; or null if this provider does not know how to construct it */ public JsonDeserializer findTreeNodeDeserializer(Class nodeType, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException; /** * Method called to locate deserializer for specified value type which does not belong to any other * category (not an Enum, Collection, Map, Array, reference value or tree node) * * @param type Bean type to deserialize * @param config Configuration in effect * @param beanDesc Definition of the enumeration type that contains class annotations and * other information typically needed for building deserializers * * @return Deserializer to use for the type; or null if this provider does not know how to construct it */ public JsonDeserializer findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException; // // // Then container types /** * Method called to locate deserializer for value that is of referential * type, * * @param refType Specific referential type to deserialize * @param config Configuration in effect * @param beanDesc Definition of the reference type that contains class annotations and * other information typically needed for building deserializers * @param contentTypeDeserializer Possible type deserializer for referenced value * @param contentDeserializer Value deserializer to use for referenced value, if indicated * by property annotation * * @return Deserializer to use for the type; or null if this provider does not know how to construct it * * @since 2.7 */ public JsonDeserializer findReferenceDeserializer(ReferenceType refType, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer contentTypeDeserializer, JsonDeserializer contentDeserializer) throws JsonMappingException; /** * Method called to locate serializer for specified array type. *

* Deserializer for element type may be passed, if configured explicitly at higher level (by * annotations, typically), but usually are not. * Type deserializer for element is passed if one is needed based on contextual information * (annotations on declared element class; or on field or method type is associated with). * * @param type Type of array instances to deserialize * @param config Configuration in effect * @param beanDesc Definition of the enumeration type that contains class annotations and * other information typically needed for building deserializers * @param elementTypeDeserializer If element type needs polymorphic type handling, this is * the type information deserializer to use; should usually be used as is when constructing * array deserializer. * @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using * annotations, for exmple). May be null, in which case it should be resolved here (or using * {@link ResolvableDeserializer} callback) * * @return Deserializer to use for the type; or null if this provider does not know how to construct it */ public JsonDeserializer findArrayDeserializer(ArrayType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException; /** * Method called to locate serializer for specified {@link java.util.Collection} (List, Set etc) type. *

* Deserializer for element type may be passed, if configured explicitly at higher level (by * annotations, typically), but usually are not. * Type deserializer for element is passed if one is needed based on contextual information * (annotations on declared element class; or on field or method type is associated with). * * @param type Type of collection instances to deserialize * @param config Configuration in effect * @param beanDesc Definition of the enumeration type that contains class annotations and * other information typically needed for building deserializers * @param elementTypeDeserializer If element type needs polymorphic type handling, this is * the type information deserializer to use; should usually be used as is when constructing * array deserializer. * @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using * annotations, for exmple). May be null, in which case it should be resolved here (or using * {@link ResolvableDeserializer} callback) * * @return Deserializer to use for the type; or null if this provider does not know how to construct it */ public JsonDeserializer findCollectionDeserializer(CollectionType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException; /** * Method called to locate serializer for specified * "Collection-like" type (one that acts * like {@link java.util.Collection} but does not implement it). *

* Deserializer for element type may be passed, if configured explicitly at higher level (by * annotations, typically), but usually are not. * Type deserializer for element is passed if one is needed based on contextual information * (annotations on declared element class; or on field or method type is associated with). * * @param type Type of instances to deserialize * @param config Configuration in effect * @param beanDesc Definition of the enumeration type that contains class annotations and * other information typically needed for building deserializers * @param elementTypeDeserializer If element type needs polymorphic type handling, this is * the type information deserializer to use; should usually be used as is when constructing * array deserializer. * @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using * annotations, for exmple). May be null, in which case it should be resolved here (or using * {@link ResolvableDeserializer} callback) * * @return Deserializer to use for the type; or null if this provider does not know how to construct it */ public JsonDeserializer findCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException; /** * Method called to locate deserializer for specified {@link java.util.Map} type. *

* Deserializer for element type may be passed, if configured explicitly at higher level (by * annotations, typically), but usually are not. * Type deserializer for element is passed if one is needed based on contextual information * (annotations on declared element class; or on field or method type is associated with). *

* Similarly, a {@link KeyDeserializer} may be passed, but this is only done if there is * a specific configuration override (annotations) to indicate instance to use. * Otherwise null is passed, and key deserializer needs to be obtained later during * resolution (using {@link ResolvableDeserializer#resolve}). * * @param type Type of {@link java.util.Map} instances to deserialize * @param config Configuration in effect * @param beanDesc Definition of the enumeration type that contains class annotations and * other information typically needed for building deserializers * @param keyDeserializer Key deserializer use, if it is defined via annotations or other configuration; * null if default key deserializer for key type can be used. * @param elementTypeDeserializer If element type needs polymorphic type handling, this is * the type information deserializer to use; should usually be used as is when constructing * array deserializer. * @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using * annotations, for exmple). May be null, in which case it should be resolved here (or using * {@link ResolvableDeserializer} callback) * * @return Deserializer to use for the type; or null if this provider does not know how to construct it */ public JsonDeserializer findMapDeserializer(MapType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException; /** * Method called to locate serializer for specified * "Map-like" type (one that acts * like {@link java.util.Map} but does not implement it). *

* Deserializer for element type may be passed, if configured explicitly at higher level (by * annotations, typically), but usually are not. * Type deserializer for element is passed if one is needed based on contextual information * (annotations on declared element class; or on field or method type is associated with). *

* Similarly, a {@link KeyDeserializer} may be passed, but this is only done if there is * a specific configuration override (annotations) to indicate instance to use. * Otherwise null is passed, and key deserializer needs to be obtained later during * resolution (using {@link ResolvableDeserializer#resolve}). * * @param type Type of {@link java.util.Map} instances to deserialize * @param config Configuration in effect * @param beanDesc Definition of the enumeration type that contains class annotations and * other information typically needed for building deserializers * @param keyDeserializer Key deserializer use, if it is defined via annotations or other configuration; * null if default key deserializer for key type can be used. * @param elementTypeDeserializer If element type needs polymorphic type handling, this is * the type information deserializer to use; should usually be used as is when constructing * array deserializer. * @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using * annotations, for exmple). May be null, in which case it should be resolved here (or using * {@link ResolvableDeserializer} callback) * * @return Deserializer to use for the type; or null if this provider does not know how to construct it */ public JsonDeserializer findMapLikeDeserializer(MapLikeType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException; /* /********************************************************** /* Helper classes /********************************************************** */ /** * Basic {@link Deserializers} implementation that implements all methods but provides * no deserializers. Its main purpose is to serve as a base class so that * sub-classes only need to override methods they need, as most of the time some * of methods are not needed (especially enumeration and array deserializers are * very rarely overridden). */ public static class Base implements Deserializers { @Override public JsonDeserializer findEnumDeserializer(Class type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { return null; } @Override public JsonDeserializer findTreeNodeDeserializer(Class nodeType, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { return null; } @Override // since 2.7 public JsonDeserializer findReferenceDeserializer(ReferenceType refType, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer contentTypeDeserializer, JsonDeserializer contentDeserializer) throws JsonMappingException { // 21-Oct-2015, tatu: For backwards compatibility, let's delegate to "bean" variant, // for 2.7 -- remove work-around from 2.8 or later return findBeanDeserializer(refType, config, beanDesc); } @Override public JsonDeserializer findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { return null; } @Override public JsonDeserializer findArrayDeserializer(ArrayType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { return null; } @Override public JsonDeserializer findCollectionDeserializer(CollectionType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { return null; } @Override public JsonDeserializer findCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { return null; } @Override public JsonDeserializer findMapDeserializer(MapType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { return null; } @Override public JsonDeserializer findMapLikeDeserializer(MapLikeType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { return null; } } } KeyDeserializers.java000066400000000000000000000014611325620701100356750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.databind.*; /** * Interface that defines API for simple extensions that can provide additional deserializers * for deserializer Map keys of various types, from JSON property names. * Access is by a single callback method; instance is to either return * a configured {@link KeyDeserializer} for specified type, or null to indicate that it * does not support handling of the type. In latter case, further calls can be made * for other providers; in former case returned key deserializer is used for handling of * key instances of specified type. */ public interface KeyDeserializers { public KeyDeserializer findKeyDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException; } NullValueProvider.java000066400000000000000000000024271325620701100360440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.util.AccessPattern; /** * Helper interface implemented by classes that are to be used as * null providers during deserialization. Most importantly implemented by * {@link com.fasterxml.jackson.databind.JsonDeserializer} (as a mix-in * interface), but also by converters used to support more configurable * null replacement. * * @since 2.9 */ public interface NullValueProvider { /** * Method called to possibly convert incoming `null` token (read via * underlying streaming input source) into other value of type accessor * supports. May return `null`, or value compatible with type binding. *

* NOTE: if {@link #getNullAccessPattern()} returns `ALWAYS_NULL` or * `CONSTANT`, this method WILL NOT use provided `ctxt` and it may thus * be passed as `null`. */ public Object getNullValue(DeserializationContext ctxt) throws JsonMappingException; /** * Accessor that may be used to determine if and when provider must be called to * access null replacement value. */ public AccessPattern getNullAccessPattern(); } ResolvableDeserializer.java000066400000000000000000000041571325620701100370650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonMappingException; /** * Interface used to indicate deserializers that want to do post-processing * after construction but before being returned to caller (and possibly cached) * and used. * This is typically used to resolve references * to other contained types; for example, bean deserializers use this callback * to locate deserializers for contained field types. * Main reason for using a callback (instead of trying to resolve dependencies * immediately) is to make it possible to cleanly handle self-references; * otherwise it would be easy to get into infinite recursion. *

* Note that {@link #resolve} method does NOT allow returning anything * (specifically, a new deserializer instance): reason for this is that * allowing this would not work with proper handling of cyclic dependencies, * which are resolved by two-phase processing, where initially constructed * deserializer is added as known deserializer, and only after this * resolution is done. Resolution is the part that results in lookups for * dependant deserializers, which may include handling references to * deserializer itself. *

* Note that in cases where deserializer needs both contextualization and * resolution -- that is, implements both this interface and {@link ContextualDeserializer} * -- resolution via this interface occurs first, and contextual * resolution (using {@link ContextualDeserializer}) later on. */ public interface ResolvableDeserializer { /** * Method called after deserializer instance has been constructed * (and registered as necessary by provider objects), * but before it has returned it to the caller. * Called object can then resolve its dependencies to other types, * including self-references (direct or indirect). * * @param ctxt Context to use for accessing configuration, resolving * secondary deserializers */ public abstract void resolve(DeserializationContext ctxt) throws JsonMappingException; } SettableAnyProperty.java000066400000000000000000000217071325620701100364040ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.util.Map; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring; import com.fasterxml.jackson.databind.introspect.AnnotatedField; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Class that represents a "wildcard" set method which can be used * to generically set values of otherwise unmapped (aka "unknown") * properties read from Json content. *

* !!! Note: might make sense to refactor to share some code * with {@link SettableBeanProperty}? */ public class SettableAnyProperty implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Method used for setting "any" properties, along with annotation * information. Retained to allow contextualization of any properties. */ protected final BeanProperty _property; /** * Annotated variant is needed for JDK serialization only */ final protected AnnotatedMember _setter; final boolean _setterIsField; protected final JavaType _type; protected JsonDeserializer _valueDeserializer; protected final TypeDeserializer _valueTypeDeserializer; /** * @since 2.9 */ protected final KeyDeserializer _keyDeserializer; /* /********************************************************** /* Life-cycle /********************************************************** */ public SettableAnyProperty(BeanProperty property, AnnotatedMember setter, JavaType type, KeyDeserializer keyDeser, JsonDeserializer valueDeser, TypeDeserializer typeDeser) { _property = property; _setter = setter; _type = type; _valueDeserializer = valueDeser; _valueTypeDeserializer = typeDeser; _keyDeserializer = keyDeser; _setterIsField = setter instanceof AnnotatedField; } @Deprecated // since 2.9 public SettableAnyProperty(BeanProperty property, AnnotatedMember setter, JavaType type, JsonDeserializer valueDeser, TypeDeserializer typeDeser) { this(property, setter, type, null, valueDeser, typeDeser); } public SettableAnyProperty withValueDeserializer(JsonDeserializer deser) { return new SettableAnyProperty(_property, _setter, _type, _keyDeserializer, deser, _valueTypeDeserializer); } public void fixAccess(DeserializationConfig config) { _setter.fixAccess( config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } /* /********************************************************** /* JDK serialization handling /********************************************************** */ /** * Need to define this to verify that we retain actual Method reference */ Object readResolve() { // sanity check... if (_setter == null || _setter.getAnnotated() == null) { throw new IllegalArgumentException("Missing method (broken JDK (de)serialization?)"); } return this; } /* /********************************************************** /* Public API, accessors /********************************************************** */ public BeanProperty getProperty() { return _property; } public boolean hasValueDeserializer() { return (_valueDeserializer != null); } public JavaType getType() { return _type; } /* /********************************************************** /* Public API, deserialization /********************************************************** */ /** * Method called to deserialize appropriate value, given parser (and * context), and set it using appropriate method (a setter method). */ public final void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance, String propName) throws IOException { try { Object key = (_keyDeserializer == null) ? propName : _keyDeserializer.deserializeKey(propName, ctxt); set(instance, key, deserialize(p, ctxt)); } catch (UnresolvedForwardReference reference) { if (!(_valueDeserializer.getObjectIdReader() != null)) { throw JsonMappingException.from(p, "Unresolved forward reference but no identity info.", reference); } AnySetterReferring referring = new AnySetterReferring(this, reference, _type.getRawClass(), instance, propName); reference.getRoid().appendReferring(referring); } } public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_NULL) { return _valueDeserializer.getNullValue(ctxt); } if (_valueTypeDeserializer != null) { return _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } return _valueDeserializer.deserialize(p, ctxt); } @SuppressWarnings("unchecked") public void set(Object instance, Object propName, Object value) throws IOException { try { // if annotation in the field (only map is supported now) if (_setterIsField) { AnnotatedField field = (AnnotatedField) _setter; Map val = (Map) field.getValue(instance); /* 01-Jun-2016, tatu: At this point it is not quite clear what to do if * field is `null` -- we cannot necessarily count on zero-args * constructor except for a small set of types, so for now just * ignore if null. May need to figure out something better in future. */ if (val != null) { // add the property key and value val.put(propName, value); } } else { // note: cannot use 'setValue()' due to taking 2 args ((AnnotatedMethod) _setter).callOnWith(instance, propName, value); } } catch (Exception e) { _throwAsIOE(e, propName, value); } } /* /********************************************************** /* Helper methods /********************************************************** */ /** * @param e Exception to re-throw or wrap * @param propName Name of property (from Json input) to set * @param value Value of the property */ protected void _throwAsIOE(Exception e, Object propName, Object value) throws IOException { if (e instanceof IllegalArgumentException) { String actType = ClassUtil.classNameOf(value); StringBuilder msg = new StringBuilder("Problem deserializing \"any\" property '").append(propName); msg.append("' of class "+getClassName()+" (expected type: ").append(_type); msg.append("; actual type: ").append(actType).append(")"); String origMsg = e.getMessage(); if (origMsg != null) { msg.append(", problem: ").append(origMsg); } else { msg.append(" (no error message provided)"); } throw new JsonMappingException(null, msg.toString(), e); } ClassUtil.throwIfIOE(e); ClassUtil.throwIfRTE(e); // let's wrap the innermost problem Throwable t = ClassUtil.getRootCause(e); throw new JsonMappingException(null, t.getMessage(), t); } private String getClassName() { return _setter.getDeclaringClass().getName(); } @Override public String toString() { return "[any property on class "+getClassName()+"]"; } private static class AnySetterReferring extends Referring { private final SettableAnyProperty _parent; private final Object _pojo; private final String _propName; public AnySetterReferring(SettableAnyProperty parent, UnresolvedForwardReference reference, Class type, Object instance, String propName) { super(reference, type); _parent = parent; _pojo = instance; _propName = propName; } @Override public void handleResolvedForwardReference(Object id, Object value) throws IOException { if (!hasId(id)) { throw new IllegalArgumentException("Trying to resolve a forward reference with id [" + id.toString() + "] that wasn't previously registered."); } _parent.set(_pojo, _propName, value); } } } SettableBeanProperty.java000066400000000000000000000627631325620701100365310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.lang.annotation.Annotation; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.impl.FailingDeserializer; import com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.Annotations; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.ViewMatcher; /** * Base class for deserializable properties of a bean: contains * both type and name definitions, and reflection-based set functionality. * Concrete sub-classes implement details, so that field- and * setter-backed properties, as well as a few more esoteric variations, * can be handled. */ @SuppressWarnings("serial") public abstract class SettableBeanProperty extends ConcreteBeanPropertyBase implements java.io.Serializable { /** * To avoid nasty NPEs, let's use a placeholder for _valueDeserializer, * if real deserializer is not (yet) available. * * @since 2.2 */ protected static final JsonDeserializer MISSING_VALUE_DESERIALIZER = new FailingDeserializer( "No _valueDeserializer assigned"); /** * Logical name of the property (often but not always derived * from the setter method name) */ protected final PropertyName _propName; /** * Base type for property; may be a supertype of actual value. */ protected final JavaType _type; /** * @since 2.2 */ protected final PropertyName _wrapperName; /** * Class that contains this property (either class that declares * the property or one of its subclasses), class that is * deserialized using deserializer that contains this property. */ protected final transient Annotations _contextAnnotations; /** * Deserializer used for handling property value. *

* NOTE: has been immutable since 2.3 */ protected final JsonDeserializer _valueDeserializer; /** * If value will contain type information (to support * polymorphic handling), this is the type deserializer * used to handle type resolution. */ protected final TypeDeserializer _valueTypeDeserializer; /** * Entity used for possible translation from `null` into non-null * value of type of this property. * Often same as _valueDeserializer, but not always. * * @since 2.9 */ protected final NullValueProvider _nullProvider; /* /********************************************************** /* Configuration that is not yet immutable; generally assigned /* during initialization process but cannot be passed to /* constructor. /********************************************************** */ /** * If property represents a managed (forward) reference, we will need * the name of reference for later linking. *

* TODO: should try to make immutable. */ protected String _managedReferenceName; /** * This is the information for object identity associated with the property. *

* TODO: should try to make immutable. */ protected ObjectIdInfo _objectIdInfo; /** * Helper object used for checking whether this property is to * be included in the active view, if property is view-specific; * null otherwise. *

* TODO: should try to make immutable. */ protected ViewMatcher _viewMatcher; /** * Index of property (within all property of a bean); assigned * when all properties have been collected. Order of entries * is arbitrary, but once indexes are assigned they are not * changed. *

* TODO: should try to make immutable if at all possible */ protected int _propertyIndex = -1; /* /********************************************************** /* Life-cycle (construct & configure) /********************************************************** */ protected SettableBeanProperty(BeanPropertyDefinition propDef, JavaType type, TypeDeserializer typeDeser, Annotations contextAnnotations) { this(propDef.getFullName(), type, propDef.getWrapperName(), typeDeser, contextAnnotations, propDef.getMetadata()); } protected SettableBeanProperty(PropertyName propName, JavaType type, PropertyName wrapper, TypeDeserializer typeDeser, Annotations contextAnnotations, PropertyMetadata metadata) { super(metadata); // 09-Jan-2009, tatu: Intern()ing makes sense since Jackson parsed // field names are (usually) interned too, hence lookups will be faster. // 23-Oct-2009, tatu: should this be disabled wrt [JACKSON-180]? // Probably need not, given that namespace of field/method names // is not unbounded, unlike potential JSON names. if (propName == null) { _propName = PropertyName.NO_NAME; } else { _propName = propName.internSimpleName(); } _type = type; _wrapperName = wrapper; _contextAnnotations = contextAnnotations; _viewMatcher = null; // 30-Jan-2012, tatu: Important: contextualize TypeDeserializer now... if (typeDeser != null) { typeDeser = typeDeser.forProperty(this); } _valueTypeDeserializer = typeDeser; _valueDeserializer = MISSING_VALUE_DESERIALIZER; _nullProvider = MISSING_VALUE_DESERIALIZER; } /** * Constructor only used by {@link com.fasterxml.jackson.databind.deser.impl.ObjectIdValueProperty}. * * @since 2.3 */ protected SettableBeanProperty(PropertyName propName, JavaType type, PropertyMetadata metadata, JsonDeserializer valueDeser) { super(metadata); // as with above ctor, intern()ing probably fine if (propName == null) { _propName = PropertyName.NO_NAME; } else { _propName = propName.internSimpleName(); } _type = type; _wrapperName = null; _contextAnnotations = null; _viewMatcher = null; _valueTypeDeserializer = null; _valueDeserializer = valueDeser; // 29-Jan-2017, tatu: Presumed to be irrelevant for ObjectId values... _nullProvider = valueDeser; } /** * Basic copy-constructor for sub-classes to use. */ protected SettableBeanProperty(SettableBeanProperty src) { super(src); _propName = src._propName; _type = src._type; _wrapperName = src._wrapperName; _contextAnnotations = src._contextAnnotations; _valueDeserializer = src._valueDeserializer; _valueTypeDeserializer = src._valueTypeDeserializer; _managedReferenceName = src._managedReferenceName; _propertyIndex = src._propertyIndex; _viewMatcher = src._viewMatcher; _nullProvider = src._nullProvider; } /** * Copy-with-deserializer-change constructor for sub-classes to use. */ @SuppressWarnings("unchecked") protected SettableBeanProperty(SettableBeanProperty src, JsonDeserializer deser, NullValueProvider nuller) { super(src); _propName = src._propName; _type = src._type; _wrapperName = src._wrapperName; _contextAnnotations = src._contextAnnotations; _valueTypeDeserializer = src._valueTypeDeserializer; _managedReferenceName = src._managedReferenceName; _propertyIndex = src._propertyIndex; if (deser == null) { _valueDeserializer = MISSING_VALUE_DESERIALIZER; } else { _valueDeserializer = (JsonDeserializer) deser; } _viewMatcher = src._viewMatcher; // 29-Jan-2017, tatu: Bit messy, but for now has to do... if (nuller == MISSING_VALUE_DESERIALIZER) { nuller = _valueDeserializer; } _nullProvider = nuller; } /** * Copy-with-deserializer-change constructor for sub-classes to use. */ protected SettableBeanProperty(SettableBeanProperty src, PropertyName newName) { super(src); _propName = newName; _type = src._type; _wrapperName = src._wrapperName; _contextAnnotations = src._contextAnnotations; _valueDeserializer = src._valueDeserializer; _valueTypeDeserializer = src._valueTypeDeserializer; _managedReferenceName = src._managedReferenceName; _propertyIndex = src._propertyIndex; _viewMatcher = src._viewMatcher; _nullProvider = src._nullProvider; } /** * Fluent factory method for constructing and returning a new instance * with specified value deserializer. * Note that this method should NOT change configuration of this instance. * * @param deser Deserializer to assign to the new property instance * * @return Newly constructed instance, if value deserializer differs from the * one used for this instance; or 'this' if not. */ public abstract SettableBeanProperty withValueDeserializer(JsonDeserializer deser); /** * Fluent factory method for constructing and returning a new instance * with specified property name. * Note that this method should NOT change configuration of this instance. * * @param newName Name to use for the new instance. * * @return Newly constructed instance, if property name differs from the * one used for this instance; or 'this' if not. */ public abstract SettableBeanProperty withName(PropertyName newName); /** * @since 2.3 */ public SettableBeanProperty withSimpleName(String simpleName) { PropertyName n = (_propName == null) ? new PropertyName(simpleName) : _propName.withSimpleName(simpleName); return (n == _propName) ? this : withName(n); } /** * @since 2.9 */ public abstract SettableBeanProperty withNullProvider(NullValueProvider nva); public void setManagedReferenceName(String n) { _managedReferenceName = n; } public void setObjectIdInfo(ObjectIdInfo objectIdInfo) { _objectIdInfo = objectIdInfo; } public void setViews(Class[] views) { if (views == null) { _viewMatcher = null; } else { _viewMatcher = ViewMatcher.construct(views); } } /** * Method used to assign index for property. */ public void assignIndex(int index) { if (_propertyIndex != -1) { throw new IllegalStateException("Property '"+getName()+"' already had index ("+_propertyIndex+"), trying to assign "+index); } _propertyIndex = index; } /** * Method called to ensure that the mutator has proper access rights to * be called, as per configuration. Overridden by implementations that * have mutators that require access, fields and setters. * * @since 2.8.3 */ public void fixAccess(DeserializationConfig config) { ; } /** * @since 2.9.4 */ public void markAsIgnorable() { } /** * @since 2.9.4 */ public boolean isIgnorable() { return false; } /* /********************************************************** /* BeanProperty impl /********************************************************** */ @Override public final String getName() { return _propName.getSimpleName(); } @Override public PropertyName getFullName() { return _propName; } @Override public JavaType getType() { return _type; } @Override public PropertyName getWrapperName() { return _wrapperName; } @Override public abstract AnnotatedMember getMember(); @Override public abstract A getAnnotation(Class acls); @Override public A getContextAnnotation(Class acls) { return _contextAnnotations.get(acls); } @Override public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException { if (isRequired()) { objectVisitor.property(this); } else { objectVisitor.optionalProperty(this); } } /* /********************************************************** /* Accessors /********************************************************** */ protected Class getDeclaringClass() { return getMember().getDeclaringClass(); } public String getManagedReferenceName() { return _managedReferenceName; } public ObjectIdInfo getObjectIdInfo() { return _objectIdInfo; } public boolean hasValueDeserializer() { return (_valueDeserializer != null) && (_valueDeserializer != MISSING_VALUE_DESERIALIZER); } public boolean hasValueTypeDeserializer() { return (_valueTypeDeserializer != null); } public JsonDeserializer getValueDeserializer() { JsonDeserializer deser = _valueDeserializer; if (deser == MISSING_VALUE_DESERIALIZER) { return null; } return deser; } public TypeDeserializer getValueTypeDeserializer() { return _valueTypeDeserializer; } /** * @since 2.9 */ public NullValueProvider getNullValueProvider() { return _nullProvider; } public boolean visibleInView(Class activeView) { return (_viewMatcher == null) || _viewMatcher.isVisibleForView(activeView); } public boolean hasViews() { return _viewMatcher != null; } /** * Method for accessing unique index of this property; indexes are * assigned once all properties of a {@link BeanDeserializer} have * been collected. * * @return Index of this property */ public int getPropertyIndex() { return _propertyIndex; } /** * Method for accessing index of the creator property: for other * types of properties will simply return -1. * * @since 2.1 */ public int getCreatorIndex() { // changed from 'return -1' in 2.7.9 / 2.8.7 throw new IllegalStateException(String.format( "Internal error: no creator index for property '%s' (of type %s)", this.getName(), getClass().getName())); } /** * Accessor for id of injectable value, if this bean property supports * value injection. */ public Object getInjectableValueId() { return null; } /* /********************************************************** /* Public API /********************************************************** */ /** * Method called to deserialize appropriate value, given parser (and * context), and set it using appropriate mechanism. * Pre-condition is that passed parser must point to the first token * that should be consumed to produce the value (the only value for * scalars, multiple for Objects and Arrays). */ public abstract void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException; /** * Alternative to {@link #deserializeAndSet} that returns * either return value of setter method called (if one is), * or null to indicate that no return value is available. * Mostly used to support Builder style deserialization. * * @since 2.0 */ public abstract Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException; /** * Method called to assign given value to this property, on * specified Object. *

* Note: this is an optional operation, not supported by all * implementations, creator-backed properties for example do not * support this method. */ public abstract void set(Object instance, Object value) throws IOException; /** * Method called to assign given value to this property, on * specified Object, and return whatever delegating accessor * returned (if anything) *

* Note: this is an optional operation, not supported by all * implementations, creator-backed properties for example do not * support this method. */ public abstract Object setAndReturn(Object instance, Object value) throws IOException; /** * This method is needed by some specialized bean deserializers, * and also called by some {@link #deserializeAndSet} implementations. *

* Pre-condition is that passed parser must point to the first token * that should be consumed to produce the value (the only value for * scalars, multiple for Objects and Arrays). *

* Note that this method is final for performance reasons: to override * functionality you must override other methods that call this method; * this method should also not be called directly unless you really know * what you are doing (and probably not even then). */ public final Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_NULL)) { return _nullProvider.getNullValue(ctxt); } if (_valueTypeDeserializer != null) { return _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } return _valueDeserializer.deserialize(p, ctxt); } /** * @since 2.9 */ public final Object deserializeWith(JsonParser p, DeserializationContext ctxt, Object toUpdate) throws IOException { // 20-Oct-2016, tatu: Not 100% sure what to do; probably best to simply return // null value and let caller decide what to do. if (p.hasToken(JsonToken.VALUE_NULL)) { // ... except for "skip nulls" case which should just do that: if (NullsConstantProvider.isSkipper(_nullProvider)) { return toUpdate; } return _nullProvider.getNullValue(ctxt); } // 20-Oct-2016, tatu: Also tricky -- for now, report an error if (_valueTypeDeserializer != null) { ctxt.reportBadDefinition(getType(), String.format("Cannot merge polymorphic property '%s'", getName())); // return _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } return _valueDeserializer.deserialize(p, ctxt, toUpdate); } /* /********************************************************** /* Helper methods /********************************************************** */ /** * Method that takes in exception of any type, and casts or wraps it * to an IOException or its subclass. */ protected void _throwAsIOE(JsonParser p, Exception e, Object value) throws IOException { if (e instanceof IllegalArgumentException) { String actType = ClassUtil.classNameOf(value); StringBuilder msg = new StringBuilder("Problem deserializing property '") .append(getName()) .append("' (expected type: ") .append(getType()) .append("; actual type: ") .append(actType).append(")"); String origMsg = e.getMessage(); if (origMsg != null) { msg.append(", problem: ") .append(origMsg); } else { msg.append(" (no error message provided)"); } throw JsonMappingException.from(p, msg.toString(), e); } _throwAsIOE(p, e); } /** * @since 2.7 */ protected IOException _throwAsIOE(JsonParser p, Exception e) throws IOException { ClassUtil.throwIfIOE(e); ClassUtil.throwIfRTE(e); // let's wrap the innermost problem Throwable th = ClassUtil.getRootCause(e); throw JsonMappingException.from(p, th.getMessage(), th); } @Deprecated // since 2.7 protected IOException _throwAsIOE(Exception e) throws IOException { return _throwAsIOE((JsonParser) null, e); } // 10-Oct-2015, tatu: _Should_ be deprecated, too, but its remaining // callers cannot actually provide a JsonParser protected void _throwAsIOE(Exception e, Object value) throws IOException { _throwAsIOE((JsonParser) null, e, value); } @Override public String toString() { return "[property '"+getName()+"']"; } /* /********************************************************** /* Helper classes /********************************************************** */ /** * Helper class that is designed to both make it easier to sub-class * delegating subtypes and to reduce likelihood of breakage when * new methods are added. *

* Class was specifically added to help with {@code Afterburner} * module, but its use is not limited to only support it. * * @since 2.9 */ public static abstract class Delegating extends SettableBeanProperty { protected final SettableBeanProperty delegate; protected Delegating(SettableBeanProperty d) { super(d); delegate = d; } /** * Method sub-classes must implement, to construct a new instance * with given delegate. */ protected abstract SettableBeanProperty withDelegate(SettableBeanProperty d); protected SettableBeanProperty _with(SettableBeanProperty newDelegate) { if (newDelegate == delegate) { return this; } return withDelegate(newDelegate); } @Override public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { return _with(delegate.withValueDeserializer(deser)); } @Override public SettableBeanProperty withName(PropertyName newName) { return _with(delegate.withName(newName)); } @Override public SettableBeanProperty withNullProvider(NullValueProvider nva) { return _with(delegate.withNullProvider(nva)); } @Override public void assignIndex(int index) { delegate.assignIndex(index); } @Override public void fixAccess(DeserializationConfig config) { delegate.fixAccess(config); } /* /********************************************************** /* Accessors /********************************************************** */ @Override protected Class getDeclaringClass() { return delegate.getDeclaringClass(); } @Override public String getManagedReferenceName() { return delegate.getManagedReferenceName(); } @Override public ObjectIdInfo getObjectIdInfo() { return delegate.getObjectIdInfo(); } @Override public boolean hasValueDeserializer() { return delegate.hasValueDeserializer(); } @Override public boolean hasValueTypeDeserializer() { return delegate.hasValueTypeDeserializer(); } @Override public JsonDeserializer getValueDeserializer() { return delegate.getValueDeserializer(); } @Override public TypeDeserializer getValueTypeDeserializer() { return delegate.getValueTypeDeserializer(); } @Override public boolean visibleInView(Class activeView) { return delegate.visibleInView(activeView); } @Override public boolean hasViews() { return delegate.hasViews(); } @Override public int getPropertyIndex() { return delegate.getPropertyIndex(); } @Override public int getCreatorIndex() { return delegate.getCreatorIndex(); } @Override public Object getInjectableValueId() { return delegate.getInjectableValueId(); } @Override public AnnotatedMember getMember() { return delegate.getMember(); } @Override public A getAnnotation(Class acls) { return delegate.getAnnotation(acls); } /* /********************************************************** /* Extended API /********************************************************** */ public SettableBeanProperty getDelegate() { return delegate; } /* /********************************************************** /* Actual mutators /********************************************************** */ @Override public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { delegate.deserializeAndSet(p, ctxt, instance); } @Override public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { return delegate.deserializeSetAndReturn(p, ctxt, instance); } @Override public void set(Object instance, Object value) throws IOException { delegate.set(instance, value); } @Override public Object setAndReturn(Object instance, Object value) throws IOException { return delegate.setAndReturn(instance, value); } } } UnresolvedForwardReference.java000066400000000000000000000051211325620701100377060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId; /** * Exception thrown during deserialization when there are object id that can't * be resolved. * * @author pgelinas */ public class UnresolvedForwardReference extends JsonMappingException { private static final long serialVersionUID = 1L; private ReadableObjectId _roid; private List _unresolvedIds; /** * @since 2.7 */ public UnresolvedForwardReference(JsonParser p, String msg, JsonLocation loc, ReadableObjectId roid) { super(p, msg, loc); _roid = roid; } /** * @since 2.7 */ public UnresolvedForwardReference(JsonParser p, String msg) { super(p, msg); _unresolvedIds = new ArrayList(); } /** * @deprecated Since 2.7 */ @Deprecated // since 2.7 public UnresolvedForwardReference(String msg, JsonLocation loc, ReadableObjectId roid) { super(msg, loc); _roid = roid; } /** * @deprecated Since 2.7 */ @Deprecated // since 2.7 public UnresolvedForwardReference(String msg) { super(msg); _unresolvedIds = new ArrayList(); } /* /********************************************************** /* Accessor methods /********************************************************** */ public ReadableObjectId getRoid() { return _roid; } public Object getUnresolvedId() { return _roid.getKey().key; } public void addUnresolvedId(Object id, Class type, JsonLocation where) { _unresolvedIds.add(new UnresolvedId(id, type, where)); } public List getUnresolvedIds(){ return _unresolvedIds; } @Override public String getMessage() { String msg = super.getMessage(); if (_unresolvedIds == null) { return msg; } StringBuilder sb = new StringBuilder(msg); Iterator iterator = _unresolvedIds.iterator(); while (iterator.hasNext()) { UnresolvedId unresolvedId = iterator.next(); sb.append(unresolvedId.toString()); if (iterator.hasNext()) { sb.append(", "); } } sb.append('.'); return sb.toString(); } } UnresolvedId.java000066400000000000000000000017561325620701100350310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Helper class for {@link UnresolvedForwardReference}, to contain information about unresolved ids. * * @author pgelinas */ public class UnresolvedId { private final Object _id; private final JsonLocation _location; private final Class _type; public UnresolvedId(Object id, Class type, JsonLocation where) { _id = id; _type = type; _location = where; } /** * The id which is unresolved. */ public Object getId() { return _id; } /** * The type of object which was expected. */ public Class getType() { return _type; } public JsonLocation getLocation() { return _location; } @Override public String toString() { return String.format("Object id [%s] (for %s) at %s", _id, ClassUtil.nameOf(_type), _location); } } ValueInstantiator.java000066400000000000000000000406231325620701100360760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams; /** * Class that defines simple API implemented by objects that create value * instances. Some or all of properties of value instances may * be initialized by instantiator, rest being populated by deserializer, * to which value instance is passed. * Since different kinds of JSON values (structured and scalar) * may be bound to Java values, in some cases instantiator * fully defines resulting value; this is the case when JSON value * is a scalar value (String, number, boolean). *

* Note that this type is not parameterized (even though it would seemingly * make sense), because such type information cannot be use effectively * during runtime: access is always using either wildcard type, or just * basic {@link java.lang.Object}; and so adding type parameter seems * like unnecessary extra work. *

* Actual implementations are strongly recommended to be based on * {@link com.fasterxml.jackson.databind.deser.std.StdValueInstantiator} * which implements all methods, and as such will be compatible * across versions even if new methods were added to this interface. */ public abstract class ValueInstantiator { /* /********************************************************** /* Metadata accessors /********************************************************** */ /** * Accessor for raw (type-erased) type of instances to create. *

* NOTE: since this method has not existed since beginning of * Jackson 2.0 series, default implementation will just return * Object.class; implementations are expected * to override it with real value. * * @since 2.8 */ public Class getValueClass() { return Object.class; } /** * Method that returns description of the value type this instantiator * handles. Used for error messages, diagnostics. */ public String getValueTypeDesc() { Class cls = getValueClass(); if (cls == null) { return "UNKNOWN"; } return cls.getName(); } /** * Method that will return true if any of canCreateXxx method * returns true: that is, if there is any way that an instance could * be created. */ public boolean canInstantiate() { return canCreateUsingDefault() || canCreateUsingDelegate() || canCreateUsingArrayDelegate() || canCreateFromObjectWith() || canCreateFromString() || canCreateFromInt() || canCreateFromLong() || canCreateFromDouble() || canCreateFromBoolean(); } /** * Method that can be called to check whether a String-based creator * is available for this instantiator */ public boolean canCreateFromString() { return false; } /** * Method that can be called to check whether an integer (int, Integer) based * creator is available to use (to call {@link #createFromInt}). */ public boolean canCreateFromInt() { return false; } /** * Method that can be called to check whether a long (long, Long) based * creator is available to use (to call {@link #createFromLong}). */ public boolean canCreateFromLong() { return false; } /** * Method that can be called to check whether a double (double / Double) based * creator is available to use (to call {@link #createFromDouble}). */ public boolean canCreateFromDouble() { return false; } /** * Method that can be called to check whether a double (boolean / Boolean) based * creator is available to use (to call {@link #createFromDouble}). */ public boolean canCreateFromBoolean() { return false; } /** * Method that can be called to check whether a default creator (constructor, * or no-arg static factory method) * is available for this instantiator */ public boolean canCreateUsingDefault() { return getDefaultCreator() != null; } /** * Method that can be called to check whether a delegate-based creator (single-arg * constructor or factory method) * is available for this instantiator */ public boolean canCreateUsingDelegate() { return false; } /** * Method that can be called to check whether a array-delegate-based creator * (single-arg constructor or factory method) * is available for this instantiator * * @since 2.7 */ public boolean canCreateUsingArrayDelegate() { return false; } /** * Method that can be called to check whether a property-based creator * (argument-taking constructor or factory method) * is available to instantiate values from JSON Object */ public boolean canCreateFromObjectWith() { return false; } /** * Method called to determine types of instantiation arguments * to use when creating instances with creator arguments * (when {@link #canCreateFromObjectWith()} returns true). * These arguments are bound from JSON, using specified * property types to locate deserializers. *

* NOTE: all properties will be of type * {@link com.fasterxml.jackson.databind.deser.CreatorProperty}. */ public SettableBeanProperty[] getFromObjectArguments(DeserializationConfig config) { return null; } /** * Method that can be used to determine what is the type of delegate * type to use, if any; if no delegates are used, will return null. * If non-null type is returned, deserializer will bind JSON into * specified type (using standard deserializer for that type), and * pass that to instantiator. */ public JavaType getDelegateType(DeserializationConfig config) { return null; } /** * Method that can be used to determine what is the type of array delegate * type to use, if any; if no delegates are used, will return null. If * non-null type is returned, deserializer will bind JSON into specified * type (using standard deserializer for that type), and pass that to * instantiator. * * @since 2.7 */ public JavaType getArrayDelegateType(DeserializationConfig config) { return null; } /* /********************************************************** /* Instantiation methods for JSON Object /********************************************************** */ /** * Method called to create value instance from a JSON value when * no data needs to passed to creator (constructor, factory method); * typically this will call the default constructor of the value object. * It will only be used if more specific creator methods are not * applicable; hence "default". *

* This method is called if {@link #getFromObjectArguments} returns * null or empty List. */ public Object createUsingDefault(DeserializationContext ctxt) throws IOException { return ctxt.handleMissingInstantiator(getValueClass(), this, null, "no default no-arguments constructor found"); } /** * Method called to create value instance from JSON Object when * instantiation arguments are passed; this is done, for example when passing information * specified with "Creator" annotations. *

* This method is called if {@link #getFromObjectArguments} returns * a non-empty List of arguments. */ public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) throws IOException { // sanity check; shouldn't really get called if no Creator specified return ctxt.handleMissingInstantiator(getValueClass(), this, null, "no creator with arguments specified"); } /** * Method that delegates to * {@link #createFromObjectWith(DeserializationContext, Object[])} by * default, but can be overridden if the application should have customized * behavior with respect to missing properties. *

* The default implementation of this method uses * {@link PropertyValueBuffer#getParameters(SettableBeanProperty[])} to read * and validate all properties in bulk, possibly substituting defaults for * missing properties or throwing exceptions for missing properties. An * overridden implementation of this method could, for example, use * {@link PropertyValueBuffer#hasParameter(SettableBeanProperty)} and * {@link PropertyValueBuffer#getParameter(SettableBeanProperty)} to safely * read the present properties only, and to have some other behavior for the * missing properties. * * @since 2.8 */ public Object createFromObjectWith(DeserializationContext ctxt, SettableBeanProperty[] props, PropertyValueBuffer buffer) throws IOException { return createFromObjectWith(ctxt, buffer.getParameters(props)); } /** * Method to called to create value instance from JSON Object using * an intermediate "delegate" value to pass to createor method */ public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) throws IOException { return ctxt.handleMissingInstantiator(getValueClass(), this, null, "no delegate creator specified"); } /** * Method to called to create value instance from JSON Array using * an intermediate "delegate" value to pass to createor method */ public Object createUsingArrayDelegate(DeserializationContext ctxt, Object delegate) throws IOException { return ctxt.handleMissingInstantiator(getValueClass(), this, null, "no array delegate creator specified"); } /* /********************************************************** /* Instantiation methods for JSON scalar types /* (String, Number, Boolean) /********************************************************** */ public Object createFromString(DeserializationContext ctxt, String value) throws IOException { return _createFromStringFallbacks(ctxt, value); } public Object createFromInt(DeserializationContext ctxt, int value) throws IOException { return ctxt.handleMissingInstantiator(getValueClass(), this, null, "no int/Int-argument constructor/factory method to deserialize from Number value (%s)", value); } public Object createFromLong(DeserializationContext ctxt, long value) throws IOException { return ctxt.handleMissingInstantiator(getValueClass(), this, null, "no long/Long-argument constructor/factory method to deserialize from Number value (%s)", value); } public Object createFromDouble(DeserializationContext ctxt, double value) throws IOException { return ctxt.handleMissingInstantiator(getValueClass(), this, null, "no double/Double-argument constructor/factory method to deserialize from Number value (%s)", value); } public Object createFromBoolean(DeserializationContext ctxt, boolean value) throws IOException { return ctxt.handleMissingInstantiator(getValueClass(), this, null, "no boolean/Boolean-argument constructor/factory method to deserialize from boolean value (%s)", value); } /* /********************************************************** /* Accessors for underlying creator objects (optional) /********************************************************** */ /** * Method that can be called to try to access member (constructor, * static factory method) that is used as the "default creator" * (creator that is called without arguments; typically default * [zero-argument] constructor of the type). * Note that implementations not required to return actual object * they use (or, they may use some other instantiation) method. * That is, even if {@link #canCreateUsingDefault()} returns true, * this method may return null . */ public AnnotatedWithParams getDefaultCreator() { return null; } /** * Method that can be called to try to access member (constructor, * static factory method) that is used as the "delegate creator". * Note that implementations not required to return actual object * they use (or, they may use some other instantiation) method. * That is, even if {@link #canCreateUsingDelegate()} returns true, * this method may return null . */ public AnnotatedWithParams getDelegateCreator() { return null; } /** * Method that can be called to try to access member (constructor, * static factory method) that is used as the "array delegate creator". * Note that implementations not required to return actual object * they use (or, they may use some other instantiation) method. * That is, even if {@link #canCreateUsingArrayDelegate()} returns true, * this method may return null . */ public AnnotatedWithParams getArrayDelegateCreator() { return null; } /** * Method that can be called to try to access member (constructor, * static factory method) that is used as the "non-default creator" * (constructor or factory method that takes one or more arguments). * Note that implementations not required to return actual object * they use (or, they may use some other instantiation) method. * That is, even if {@link #canCreateFromObjectWith()} returns true, * this method may return null . */ public AnnotatedWithParams getWithArgsCreator() { return null; } /** * If an incomplete creator was found, this is the first parameter that * needs further annotation to help make the creator complete. */ public AnnotatedParameter getIncompleteParameter() { return null; } /* /********************************************************** /* Helper methods /********************************************************** */ /** * @since 2.4 (demoted from StdValueInstantiator) */ protected Object _createFromStringFallbacks(DeserializationContext ctxt, String value) throws IOException { /* 28-Sep-2011, tatu: Ok this is not clean at all; but since there are legacy * systems that expect conversions in some cases, let's just add a minimal * patch (note: same could conceivably be used for numbers too). */ if (canCreateFromBoolean()) { String str = value.trim(); if ("true".equals(str)) { return createFromBoolean(ctxt, true); } if ("false".equals(str)) { return createFromBoolean(ctxt, false); } } // also, empty Strings might be accepted as null Object... if (value.length() == 0) { if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { return null; } } return ctxt.handleMissingInstantiator(getValueClass(), this, ctxt.getParser(), "no String-argument constructor/factory method to deserialize from String value ('%s')", value); } /* /********************************************************** /* Introspection /********************************************************** */ /** * @since 2.9 */ public interface Gettable { public ValueInstantiator getValueInstantiator(); } /* /********************************************************** /* Standard Base implementation (since 2.8) /********************************************************** */ /** * Partial {@link ValueInstantiator} implementation that is strongly recommended * to be used instead of directly extending {@link ValueInstantiator} itself. */ public static class Base extends ValueInstantiator { protected final Class _valueType; public Base(Class type) { _valueType = type; } public Base(JavaType type) { _valueType = type.getRawClass(); } @Override public String getValueTypeDesc() { return _valueType.getName(); } @Override public Class getValueClass() { return _valueType; } } } ValueInstantiators.java000066400000000000000000000041341325620701100362560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.databind.*; /** * Interface for providers of {@link ValueInstantiator} instances. * Implemented when an object wants to provide custom value instantiators, * usually to support custom value types with alternate constructors, or * which need specified post-processing after construction but before * binding data. */ public interface ValueInstantiators { /** * Method called to find the {@link ValueInstantiator} to use for creating * instances of specified type during deserialization. * Note that a default value instantiator is always created first and passed; * if an implementation does not want to modify or replace it, it has to return * passed instance as is (returning null is an error) * * @param config Deserialization configuration in use * @param beanDesc Additional information about POJO type to be instantiated * @param defaultInstantiator Instantiator that will be used if no changes are made; * passed to allow custom instances to use annotation-provided information * (note, however, that earlier {@link ValueInstantiators} may have changed it to * a custom instantiator already) * * @return Instantiator to use; either defaultInstantiator that was passed, * or a custom variant; cannot be null. */ public ValueInstantiator findValueInstantiator(DeserializationConfig config, BeanDescription beanDesc, ValueInstantiator defaultInstantiator); /** * Basic "NOP" implementation that can be used as the base class for custom implementations. * Safer to extend (instead of implementing {@link ValueInstantiators}) in case later * Jackson versions add new methods in base interface. */ public static class Base implements ValueInstantiators { @Override public ValueInstantiator findValueInstantiator(DeserializationConfig config, BeanDescription beanDesc, ValueInstantiator defaultInstantiator) { return defaultInstantiator; } } } jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/impl/000077500000000000000000000000001325620701100325725ustar00rootroot00000000000000BeanAsArrayBuilderDeserializer.java000066400000000000000000000321631325620701100413650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.util.Set; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.util.NameTransformer; public class BeanAsArrayBuilderDeserializer extends BeanDeserializerBase { private static final long serialVersionUID = 1L; /** * Deserializer we delegate operations that we cannot handle. */ final protected BeanDeserializerBase _delegate; /** * Properties in order expected to be found in JSON array. */ final protected SettableBeanProperty[] _orderedProperties; final protected AnnotatedMethod _buildMethod; /** * Type that the builder will produce, target type; as opposed to * `handledType()` which refers to Builder class. * * @since 2.9 */ protected final JavaType _targetType; /* /********************************************************** /* Life-cycle, construction, initialization /********************************************************** */ /** * Main constructor used both for creating new instances (by * {@link BeanDeserializer#asArrayDeserializer}) and for * creating copies with different delegate. * * @since 2.9 */ public BeanAsArrayBuilderDeserializer(BeanDeserializerBase delegate, JavaType targetType, SettableBeanProperty[] ordered, AnnotatedMethod buildMethod) { super(delegate); _delegate = delegate; _targetType = targetType; _orderedProperties = ordered; _buildMethod = buildMethod; } @Override public JsonDeserializer unwrappingDeserializer(NameTransformer unwrapper) { /* We can't do much about this; could either replace _delegate * with unwrapping instance, or just replace this one. Latter seems * more sensible. */ return _delegate.unwrappingDeserializer(unwrapper); } @Override public BeanDeserializerBase withObjectIdReader(ObjectIdReader oir) { return new BeanAsArrayBuilderDeserializer(_delegate.withObjectIdReader(oir), _targetType, _orderedProperties, _buildMethod); } @Override public BeanDeserializerBase withIgnorableProperties(Set ignorableProps) { return new BeanAsArrayBuilderDeserializer(_delegate.withIgnorableProperties(ignorableProps), _targetType, _orderedProperties, _buildMethod); } @Override public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) { return new BeanAsArrayBuilderDeserializer(_delegate.withBeanProperties(props), _targetType, _orderedProperties, _buildMethod); } @Override protected BeanDeserializerBase asArrayDeserializer() { return this; } /* /********************************************************** /* Overrides /********************************************************** */ @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { // 26-Oct-2016, tatu: No, we can't merge Builder-based POJOs as of now return Boolean.FALSE; } /* /********************************************************** /* JsonDeserializer implementation /********************************************************** */ protected final Object finishBuild(DeserializationContext ctxt, Object builder) throws IOException { try { return _buildMethod.getMember().invoke(builder, (Object[]) null); } catch (Exception e) { return wrapInstantiationProblem(e, ctxt); } } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // Let's delegate just in case we got a JSON Object (could error out, alternatively?) if (!p.isExpectedStartArrayToken()) { return finishBuild(ctxt, _deserializeFromNonArray(p, ctxt)); } if (!_vanillaProcessing) { return finishBuild(ctxt, _deserializeNonVanilla(p, ctxt)); } Object builder = _valueInstantiator.createUsingDefault(ctxt); final SettableBeanProperty[] props = _orderedProperties; int i = 0; final int propCount = props.length; while (true) { if (p.nextToken() == JsonToken.END_ARRAY) { return finishBuild(ctxt, builder); } if (i == propCount) { break; } SettableBeanProperty prop = props[i]; if (prop != null) { // normal case try { builder = prop.deserializeSetAndReturn(p, ctxt, builder); } catch (Exception e) { wrapAndThrow(e, builder, prop.getName(), ctxt); } } else { // just skip? p.skipChildren(); } ++i; } // 09-Nov-2016, tatu: Should call `handleUnknownProperty()` in Context, but it'd give // non-optimal exception message so... if (!_ignoreAllUnknown && ctxt.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) { ctxt.reportInputMismatch(handledType(), "Unexpected JSON values; expected at most %d properties (in JSON Array)", propCount); // fall through } // otherwise, skip until end while (p.nextToken() != JsonToken.END_ARRAY) { p.skipChildren(); } return finishBuild(ctxt, builder); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt, Object value) throws IOException { // 26-Oct-2016, tatu: Will fail, but let the original deserializer provide message return _delegate.deserialize(p, ctxt, value); } // needed since 2.1 @Override public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException { return _deserializeFromNonArray(p, ctxt); } /* /********************************************************** /* Helper methods, non-standard creation /********************************************************** */ /** * Alternate deserialization method that has to check many more configuration * aspects than the "vanilla" processing. * Note: should NOT resolve builder; caller will do that * * @return Builder object in use. */ protected Object _deserializeNonVanilla(JsonParser p, DeserializationContext ctxt) throws IOException { if (_nonStandardCreation) { return deserializeFromObjectUsingNonDefault(p, ctxt); } Object builder = _valueInstantiator.createUsingDefault(ctxt); if (_injectables != null) { injectValues(ctxt, builder); } Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; final SettableBeanProperty[] props = _orderedProperties; int i = 0; final int propCount = props.length; while (true) { if (p.nextToken() == JsonToken.END_ARRAY) { return builder; } if (i == propCount) { break; } SettableBeanProperty prop = props[i]; ++i; if (prop != null) { // normal case if (activeView == null || prop.visibleInView(activeView)) { try { prop.deserializeSetAndReturn(p, ctxt, builder); } catch (Exception e) { wrapAndThrow(e, builder, prop.getName(), ctxt); } continue; } } // otherwise, skip it (view-filtered, no prop etc) p.skipChildren(); } // Ok; extra fields? Let's fail, unless ignoring extra props is fine if (!_ignoreAllUnknown && ctxt.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) { ctxt.reportWrongTokenException(this, JsonToken.END_ARRAY, "Unexpected JSON value(s); expected at most %d properties (in JSON Array)", propCount); // will never reach here as exception has been thrown } // otherwise, skip until end while (p.nextToken() != JsonToken.END_ARRAY) { p.skipChildren(); } return builder; } /** * Method called to deserialize bean using "property-based creator": * this means that a non-default constructor or factory method is * called, and then possibly other setters. The trick is that * values for creator method need to be buffered, first; and * due to non-guaranteed ordering possibly some other properties * as well. */ @Override protected final Object _deserializeUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt) throws IOException { final PropertyBasedCreator creator = _propertyBasedCreator; PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); final SettableBeanProperty[] props = _orderedProperties; final int propCount = props.length; final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; int i = 0; Object builder = null; for (; p.nextToken() != JsonToken.END_ARRAY; ++i) { SettableBeanProperty prop = (i < propCount) ? props[i] : null; if (prop == null) { // we get null if there are extra elements; maybe otherwise too? p.skipChildren(); continue; } if ((activeView != null) && !prop.visibleInView(activeView)) { p.skipChildren(); continue; } // if we have already constructed POJO, things are simple: if (builder != null) { try { builder = prop.deserializeSetAndReturn(p, ctxt, builder); } catch (Exception e) { wrapAndThrow(e, builder, prop.getName(), ctxt); } continue; } final String propName = prop.getName(); // if not yet, maybe we got a creator property? SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); if (creatorProp != null) { // Last creator property to set? if (buffer.assignParameter(creatorProp, creatorProp.deserialize(p, ctxt))) { try { builder = creator.build(ctxt, buffer); } catch (Exception e) { wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); continue; // never gets here } // polymorphic? if (builder.getClass() != _beanType.getRawClass()) { /* 23-Jul-2012, tatu: Not sure if these could ever be properly * supported (since ordering of elements may not be guaranteed); * but make explicitly non-supported for now. */ return ctxt.reportBadDefinition(_beanType, String.format( "Cannot support implicit polymorphic deserialization for POJOs-as-Arrays style: nominal type %s, actual type %s", _beanType.getRawClass().getName(), builder.getClass().getName())); } } continue; } // Object Id property? if (buffer.readIdProperty(propName)) { continue; } // regular property? needs buffering buffer.bufferProperty(prop, prop.deserialize(p, ctxt)); } // In case we didn't quite get all the creator properties, we may have to do this: if (builder == null) { try { builder = creator.build(ctxt, buffer); } catch (Exception e) { return wrapInstantiationProblem(e, ctxt); } } return builder; } /* /********************************************************** /* Helper methods, error reporting /********************************************************** */ protected Object _deserializeFromNonArray(JsonParser p, DeserializationContext ctxt) throws IOException { // Let's start with failure return ctxt.handleUnexpectedToken(handledType(), p.getCurrentToken(), p, "Cannot deserialize a POJO (of type %s) from non-Array representation (token: %s): " +"type/property designed to be serialized as JSON Array", _beanType.getRawClass().getName(), p.getCurrentToken()); // in future, may allow use of "standard" POJO serialization as well; if so, do: //return _delegate.deserialize(p, ctxt); } } BeanAsArrayDeserializer.java000066400000000000000000000333721325620701100400610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.util.Set; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Variant of {@link BeanDeserializer} used for handling deserialization * of POJOs when serialized as JSON Arrays, instead of JSON Objects. * * @since 2.1 */ public class BeanAsArrayDeserializer extends BeanDeserializerBase { private static final long serialVersionUID = 1L; /** * Deserializer we delegate operations that we cannot handle. */ protected final BeanDeserializerBase _delegate; /** * Properties in order expected to be found in JSON array. */ protected final SettableBeanProperty[] _orderedProperties; /* /********************************************************** /* Life-cycle, construction, initialization /********************************************************** */ /** * Main constructor used both for creating new instances (by * {@link BeanDeserializer#asArrayDeserializer}) and for * creating copies with different delegate. */ public BeanAsArrayDeserializer(BeanDeserializerBase delegate, SettableBeanProperty[] ordered) { super(delegate); _delegate = delegate; _orderedProperties = ordered; } @Override public JsonDeserializer unwrappingDeserializer(NameTransformer unwrapper) { /* We can't do much about this; could either replace _delegate * with unwrapping instance, or just replace this one. Latter seems * more sensible. */ return _delegate.unwrappingDeserializer(unwrapper); } @Override public BeanDeserializerBase withObjectIdReader(ObjectIdReader oir) { return new BeanAsArrayDeserializer(_delegate.withObjectIdReader(oir), _orderedProperties); } @Override public BeanDeserializerBase withIgnorableProperties(Set ignorableProps) { return new BeanAsArrayDeserializer(_delegate.withIgnorableProperties(ignorableProps), _orderedProperties); } @Override public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) { return new BeanAsArrayDeserializer(_delegate.withBeanProperties(props), _orderedProperties); } @Override protected BeanDeserializerBase asArrayDeserializer() { return this; } /* /********************************************************** /* JsonDeserializer implementation /********************************************************** */ @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // Let's delegate just in case we got a JSON Object (could error out, alternatively?) if (!p.isExpectedStartArrayToken()) { return _deserializeFromNonArray(p, ctxt); } if (!_vanillaProcessing) { return _deserializeNonVanilla(p, ctxt); } final Object bean = _valueInstantiator.createUsingDefault(ctxt); // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(bean); final SettableBeanProperty[] props = _orderedProperties; int i = 0; final int propCount = props.length; while (true) { if (p.nextToken() == JsonToken.END_ARRAY) { return bean; } if (i == propCount) { break; } SettableBeanProperty prop = props[i]; if (prop != null) { // normal case try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, prop.getName(), ctxt); } } else { // just skip? p.skipChildren(); } ++i; } // Ok; extra fields? Let's fail, unless ignoring extra props is fine if (!_ignoreAllUnknown && ctxt.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) { ctxt.reportWrongTokenException(this, JsonToken.END_ARRAY, "Unexpected JSON values; expected at most %d properties (in JSON Array)", propCount); // never gets here } // otherwise, skip until end do { p.skipChildren(); } while (p.nextToken() != JsonToken.END_ARRAY); return bean; } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException { // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(bean); if (!p.isExpectedStartArrayToken()) { return _deserializeFromNonArray(p, ctxt); } /* No good way to verify that we have an array... although could I guess * check via JsonParser. So let's assume everything is working fine, for now. */ if (_injectables != null) { injectValues(ctxt, bean); } final SettableBeanProperty[] props = _orderedProperties; int i = 0; final int propCount = props.length; while (true) { if (p.nextToken() == JsonToken.END_ARRAY) { return bean; } if (i == propCount) { break; } SettableBeanProperty prop = props[i]; if (prop != null) { // normal case try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, prop.getName(), ctxt); } } else { // just skip? p.skipChildren(); } ++i; } // Ok; extra fields? Let's fail, unless ignoring extra props is fine if (!_ignoreAllUnknown && ctxt.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) { ctxt.reportWrongTokenException(this, JsonToken.END_ARRAY, "Unexpected JSON values; expected at most %d properties (in JSON Array)", propCount); // never gets here } // otherwise, skip until end do { p.skipChildren(); } while (p.nextToken() != JsonToken.END_ARRAY); return bean; } // needed since 2.1 @Override public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException { return _deserializeFromNonArray(p, ctxt); } /* /********************************************************** /* Helper methods, non-standard creation /********************************************************** */ /** * Alternate deserialization method that has to check many more configuration * aspects than the "vanilla" processing. */ protected Object _deserializeNonVanilla(JsonParser p, DeserializationContext ctxt) throws IOException { if (_nonStandardCreation) { return deserializeFromObjectUsingNonDefault(p, ctxt); } final Object bean = _valueInstantiator.createUsingDefault(ctxt); // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(bean); if (_injectables != null) { injectValues(ctxt, bean); } Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; final SettableBeanProperty[] props = _orderedProperties; int i = 0; final int propCount = props.length; while (true) { if (p.nextToken() == JsonToken.END_ARRAY) { return bean; } if (i == propCount) { break; } SettableBeanProperty prop = props[i]; ++i; if (prop != null) { // normal case if (activeView == null || prop.visibleInView(activeView)) { try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, prop.getName(), ctxt); } continue; } } // otherwise, skip it (view-filtered, no prop etc) p.skipChildren(); } // Ok; extra fields? Let's fail, unless ignoring extra props is fine if (!_ignoreAllUnknown) { ctxt.reportWrongTokenException(this, JsonToken.END_ARRAY, "Unexpected JSON values; expected at most %d properties (in JSON Array)", propCount); // will never reach here as exception has been thrown } // otherwise, skip until end do { p.skipChildren(); } while (p.nextToken() != JsonToken.END_ARRAY); return bean; } /** * Method called to deserialize bean using "property-based creator": * this means that a non-default constructor or factory method is * called, and then possibly other setters. The trick is that * values for creator method need to be buffered, first; and * due to non-guaranteed ordering possibly some other properties * as well. */ @Override protected final Object _deserializeUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt) throws IOException { final PropertyBasedCreator creator = _propertyBasedCreator; PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); final SettableBeanProperty[] props = _orderedProperties; final int propCount = props.length; int i = 0; Object bean = null; final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; for (; p.nextToken() != JsonToken.END_ARRAY; ++i) { SettableBeanProperty prop = (i < propCount) ? props[i] : null; if (prop == null) { // we get null if there are extra elements; maybe otherwise too? p.skipChildren(); continue; } if ((activeView != null) && !prop.visibleInView(activeView)) { p.skipChildren(); continue; } // if we have already constructed POJO, things are simple: if (bean != null) { try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, prop.getName(), ctxt); } continue; } final String propName = prop.getName(); // if not yet, maybe we got a creator property? SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); if (creatorProp != null) { // Last creator property to set? if (buffer.assignParameter(creatorProp, creatorProp.deserialize(p, ctxt))) { try { bean = creator.build(ctxt, buffer); } catch (Exception e) { wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); continue; // never gets here } // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(bean); // polymorphic? if (bean.getClass() != _beanType.getRawClass()) { /* 23-Jul-2012, tatu: Not sure if these could ever be properly * supported (since ordering of elements may not be guaranteed); * but make explicitly non-supported for now. */ ctxt.reportBadDefinition(_beanType, String.format( "Cannot support implicit polymorphic deserialization for POJOs-as-Arrays style: " +"nominal type %s, actual type %s", _beanType.getRawClass().getName(), bean.getClass().getName())); } } continue; } // Object Id property? if (buffer.readIdProperty(propName)) { continue; } // regular property? needs buffering buffer.bufferProperty(prop, prop.deserialize(p, ctxt)); } // In case we didn't quite get all the creator properties, we may have to do this: if (bean == null) { try { bean = creator.build(ctxt, buffer); } catch (Exception e) { return wrapInstantiationProblem(e, ctxt); } } return bean; } /* /********************************************************** /* Helper methods, error reporting /********************************************************** */ protected Object _deserializeFromNonArray(JsonParser p, DeserializationContext ctxt) throws IOException { return ctxt.handleUnexpectedToken(handledType(), p.getCurrentToken(), p, "Cannot deserialize a POJO (of type %s) from non-Array representation (token: %s): " +"type/property designed to be serialized as JSON Array", _beanType.getRawClass().getName(), p.getCurrentToken()); // in future, may allow use of "standard" POJO serialization as well; if so, do: //return _delegate.deserialize(p, ctxt); } } BeanPropertyMap.java000066400000000000000000000625711325620701100364410ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.*; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.PropertyName; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Helper class used for storing mapping from property name to * {@link SettableBeanProperty} instances. *

* Note that this class is used instead of generic {@link java.util.HashMap} * for bit of performance gain (and some memory savings): although default * implementation is very good for generic use cases, it can be streamlined * a bit for specific use case we have. Even relatively small improvements * matter since this is directly on the critical path during deserialization, * as it is done for each and every POJO property deserialized. */ public class BeanPropertyMap implements Iterable, java.io.Serializable { private static final long serialVersionUID = 2L; /** * @since 2.5 */ protected final boolean _caseInsensitive; private int _hashMask; /** * Number of entries stored in the hash area. */ private int _size; private int _spillCount; /** * Hash area that contains key/property pairs in adjacent elements. */ private Object[] _hashArea; /** * Array of properties in the exact order they were handed in. This is * used by as-array serialization, deserialization. */ private SettableBeanProperty[] _propsInOrder; /** * Configuration of alias mappings, indexed by unmodified property name * to unmodified aliases, if any; entries only included for properties * that do have aliases. * This is is used for constructing actual reverse lookup mapping, if * needed, taking into account possible case-insensitivity, as well * as possibility of name prefixes. * * @since 2.9 */ private final Map> _aliasDefs; /** * Mapping from secondary names (aliases) to primary names. * * @since 2.9 */ private final Map _aliasMapping; /** * @since 2.9 */ public BeanPropertyMap(boolean caseInsensitive, Collection props, Map> aliasDefs) { _caseInsensitive = caseInsensitive; _propsInOrder = props.toArray(new SettableBeanProperty[props.size()]); _aliasDefs = aliasDefs; _aliasMapping = _buildAliasMapping(aliasDefs); init(props); } @Deprecated // since 2.8 public BeanPropertyMap(boolean caseInsensitive, Collection props) { this(caseInsensitive, props, Collections.>emptyMap()); } /** * @since 2.8 */ protected BeanPropertyMap(BeanPropertyMap base, boolean caseInsensitive) { _caseInsensitive = caseInsensitive; _aliasDefs = base._aliasDefs; _aliasMapping = base._aliasMapping; // 16-May-2016, tatu: Alas, not enough to just change flag, need to re-init as well. _propsInOrder = Arrays.copyOf(base._propsInOrder, base._propsInOrder.length); init(Arrays.asList(_propsInOrder)); } /** * Mutant factory method that constructs a new instance if desired case-insensitivity * state differs from the state of this instance; if states are the same, returns * this. * * @since 2.8 */ public BeanPropertyMap withCaseInsensitivity(boolean state) { if (_caseInsensitive == state) { return this; } return new BeanPropertyMap(this, state); } protected void init(Collection props) { _size = props.size(); // First: calculate size of primary hash area final int hashSize = findSize(_size); _hashMask = hashSize-1; // and allocate enough to contain primary/secondary, expand for spillovers as need be int alloc = (hashSize + (hashSize>>1)) * 2; Object[] hashed = new Object[alloc]; int spillCount = 0; for (SettableBeanProperty prop : props) { // Due to removal, renaming, theoretically possible we'll have "holes" so: if (prop == null) { continue; } String key = getPropertyName(prop); int slot = _hashCode(key); int ix = (slot<<1); // primary slot not free? if (hashed[ix] != null) { // secondary? ix = (hashSize + (slot >> 1)) << 1; if (hashed[ix] != null) { // ok, spill over. ix = ((hashSize + (hashSize >> 1) ) << 1) + spillCount; spillCount += 2; if (ix >= hashed.length) { hashed = Arrays.copyOf(hashed, hashed.length + 4); } } } //System.err.println(" add '"+key+" at #"+(ix>>1)+"/"+size+" (hashed at "+slot+")"); hashed[ix] = key; hashed[ix+1] = prop; // and aliases } //for (int i = 0; i < hashed.length; i += 2) { //System.err.printf("#%02d: %s\n", i>>1, (hashed[i] == null) ? "-" : hashed[i]); //} _hashArea = hashed; _spillCount = spillCount; } private final static int findSize(int size) { if (size <= 5) { return 8; } if (size <= 12) { return 16; } int needed = size + (size >> 2); // at most 80% full int result = 32; while (result < needed) { result += result; } return result; } /** * @since 2.6 */ public static BeanPropertyMap construct(Collection props, boolean caseInsensitive, Map> aliasMapping) { return new BeanPropertyMap(caseInsensitive, props, aliasMapping); } @Deprecated // since 2.9 public static BeanPropertyMap construct(Collection props, boolean caseInsensitive) { return construct(props, caseInsensitive, Collections.>emptyMap()); } /** * Fluent copy method that creates a new instance that is a copy * of this instance except for one additional property that is * passed as the argument. * Note that method does not modify this instance but constructs * and returns a new one. */ public BeanPropertyMap withProperty(SettableBeanProperty newProp) { // First: may be able to just replace? String key = getPropertyName(newProp); for (int i = 1, end = _hashArea.length; i < end; i += 2) { SettableBeanProperty prop = (SettableBeanProperty) _hashArea[i]; if ((prop != null) && prop.getName().equals(key)) { _hashArea[i] = newProp; _propsInOrder[_findFromOrdered(prop)] = newProp; return this; } } // If not, append final int slot = _hashCode(key); final int hashSize = _hashMask+1; int ix = (slot<<1); // primary slot not free? if (_hashArea[ix] != null) { // secondary? ix = (hashSize + (slot >> 1)) << 1; if (_hashArea[ix] != null) { // ok, spill over. ix = ((hashSize + (hashSize >> 1) ) << 1) + _spillCount; _spillCount += 2; if (ix >= _hashArea.length) { _hashArea = Arrays.copyOf(_hashArea, _hashArea.length + 4); // Uncomment for debugging only //for (int i = 0; i < _hashArea.length; i += 2) { // if (_hashArea[i] != null) { // System.err.println("Property #"+(i/2)+" '"+_hashArea[i]+"'..."); // } //} //System.err.println("And new propr #"+slot+" '"+key+"'"); } } } _hashArea[ix] = key; _hashArea[ix+1] = newProp; int last = _propsInOrder.length; _propsInOrder = Arrays.copyOf(_propsInOrder, last+1); _propsInOrder[last] = newProp; // should we just create a new one? Or is resetting ok? return this; } public BeanPropertyMap assignIndexes() { // order is arbitrary, but stable: int index = 0; for (int i = 1, end = _hashArea.length; i < end; i += 2) { SettableBeanProperty prop = (SettableBeanProperty) _hashArea[i]; if (prop != null) { prop.assignIndex(index++); } } return this; } /** * Mutant factory method for constructing a map where all entries use given * prefix */ public BeanPropertyMap renameAll(NameTransformer transformer) { if (transformer == null || (transformer == NameTransformer.NOP)) { return this; } // Try to retain insertion ordering as well final int len = _propsInOrder.length; ArrayList newProps = new ArrayList(len); for (int i = 0; i < len; ++i) { SettableBeanProperty prop = _propsInOrder[i]; // What to do with holes? For now, retain if (prop == null) { newProps.add(prop); continue; } newProps.add(_rename(prop, transformer)); } // should we try to re-index? Ordering probably changed but caller probably doesn't want changes... // 26-Feb-2017, tatu: Probably SHOULD handle renaming wrt Aliases? return new BeanPropertyMap(_caseInsensitive, newProps, _aliasDefs); } /* /********************************************************** /* Public API, mutators /********************************************************** */ /** * Mutant factory method that will use this instance as the base, and * construct an instance that is otherwise same except for excluding * properties with specified names. * * @since 2.8 */ public BeanPropertyMap withoutProperties(Collection toExclude) { if (toExclude.isEmpty()) { return this; } final int len = _propsInOrder.length; ArrayList newProps = new ArrayList(len); for (int i = 0; i < len; ++i) { SettableBeanProperty prop = _propsInOrder[i]; // 01-May-2015, tatu: Not 100% sure if existing `null`s should be retained; // or, if entries to ignore should be retained as nulls. For now just // prune them out if (prop != null) { // may contain holes, too, check. if (!toExclude.contains(prop.getName())) { newProps.add(prop); } } } // should we try to re-index? Apparently no need return new BeanPropertyMap(_caseInsensitive, newProps, _aliasDefs); } @Deprecated // in 2.9.4 -- must call method that takes old and new property to avoid mismatch public void replace(SettableBeanProperty newProp) { String key = getPropertyName(newProp); int ix = _findIndexInHash(key); if (ix < 0) { throw new NoSuchElementException("No entry '"+key+"' found, can't replace"); } SettableBeanProperty prop = (SettableBeanProperty) _hashArea[ix]; _hashArea[ix] = newProp; // also, replace in in-order _propsInOrder[_findFromOrdered(prop)] = newProp; } /** * Specialized method that can be used to replace an existing entry * (note: entry MUST exist; otherwise exception is thrown) with * specified replacement. * * @since 2.9.4 */ public void replace(SettableBeanProperty origProp, SettableBeanProperty newProp) { int i = 1; int end = _hashArea.length; for (;; i += 2) { if (i > end) { throw new NoSuchElementException("No entry '"+origProp.getName()+"' found, can't replace"); } if (_hashArea[i] == origProp) { _hashArea[i] = newProp; break; } } _propsInOrder[_findFromOrdered(origProp)] = newProp; } /** * Specialized method for removing specified existing entry. * NOTE: entry MUST exist, otherwise an exception is thrown. */ public void remove(SettableBeanProperty propToRm) { ArrayList props = new ArrayList(_size); String key = getPropertyName(propToRm); boolean found = false; for (int i = 1, end = _hashArea.length; i < end; i += 2) { SettableBeanProperty prop = (SettableBeanProperty) _hashArea[i]; if (prop == null) { continue; } if (!found) { // 09-Jan-2017, tatu: Important: must check name slot and NOT property name, // as only former is lower-case in case-insensitive case found = key.equals(_hashArea[i-1]); if (found) { // need to leave a hole here _propsInOrder[_findFromOrdered(prop)] = null; continue; } } props.add(prop); } if (!found) { throw new NoSuchElementException("No entry '"+propToRm.getName()+"' found, can't remove"); } init(props); } /* /********************************************************** /* Public API, simple accessors /********************************************************** */ public int size() { return _size; } /** * @since 2.9 */ public boolean isCaseInsensitive() { return _caseInsensitive; } /** * @since 2.9 */ public boolean hasAliases() { return !_aliasDefs.isEmpty(); } /** * Accessor for traversing over all contained properties. */ @Override public Iterator iterator() { return _properties().iterator(); } private List _properties() { ArrayList p = new ArrayList(_size); for (int i = 1, end = _hashArea.length; i < end; i += 2) { SettableBeanProperty prop = (SettableBeanProperty) _hashArea[i]; if (prop != null) { p.add(prop); } } return p; } /** * Method that will re-create initial insertion-ordering of * properties contained in this map. Note that if properties * have been removed, array may contain nulls; otherwise * it should be consecutive. * * @since 2.1 */ public SettableBeanProperty[] getPropertiesInInsertionOrder() { return _propsInOrder; } // Confining this case insensitivity to this function (and the find method) in case we want to // apply a particular locale to the lower case function. For now, using the default. protected final String getPropertyName(SettableBeanProperty prop) { return _caseInsensitive ? prop.getName().toLowerCase() : prop.getName(); } /* /********************************************************** /* Public API, property lookup /********************************************************** */ /** * @since 2.3 */ public SettableBeanProperty find(int index) { // note: will scan the whole area, including primary, secondary and // possible spill-area for (int i = 1, end = _hashArea.length; i < end; i += 2) { SettableBeanProperty prop = (SettableBeanProperty) _hashArea[i]; if ((prop != null) && (index == prop.getPropertyIndex())) { return prop; } } return null; } public SettableBeanProperty find(String key) { if (key == null) { throw new IllegalArgumentException("Cannot pass null property name"); } if (_caseInsensitive) { key = key.toLowerCase(); } // inlined `_hashCode(key)` int slot = key.hashCode() & _hashMask; // int h = key.hashCode(); // int slot = (h + (h >> 13)) & _hashMask; int ix = (slot<<1); Object match = _hashArea[ix]; if ((match == key) || key.equals(match)) { return (SettableBeanProperty) _hashArea[ix+1]; } return _find2(key, slot, match); } private final SettableBeanProperty _find2(String key, int slot, Object match) { if (match == null) { // 26-Feb-2017, tatu: Need to consider aliases return _findWithAlias(_aliasMapping.get(key)); } // no? secondary? int hashSize = _hashMask+1; int ix = hashSize + (slot>>1) << 1; match = _hashArea[ix]; if (key.equals(match)) { return (SettableBeanProperty) _hashArea[ix+1]; } if (match != null) { // _findFromSpill(...) int i = (hashSize + (hashSize>>1)) << 1; for (int end = i + _spillCount; i < end; i += 2) { match = _hashArea[i]; if ((match == key) || key.equals(match)) { return (SettableBeanProperty) _hashArea[i+1]; } } } // 26-Feb-2017, tatu: Need to consider aliases return _findWithAlias(_aliasMapping.get(key)); } private SettableBeanProperty _findWithAlias(String keyFromAlias) { if (keyFromAlias == null) { return null; } // NOTE: need to inline much of handling do avoid cyclic calls via alias // first, inlined main `find(String)` int slot = _hashCode(keyFromAlias); int ix = (slot<<1); Object match = _hashArea[ix]; if (keyFromAlias.equals(match)) { return (SettableBeanProperty) _hashArea[ix+1]; } if (match == null) { return null; } return _find2ViaAlias(keyFromAlias, slot, match); } private SettableBeanProperty _find2ViaAlias(String key, int slot, Object match) { // no? secondary? int hashSize = _hashMask+1; int ix = hashSize + (slot>>1) << 1; match = _hashArea[ix]; if (key.equals(match)) { return (SettableBeanProperty) _hashArea[ix+1]; } if (match != null) { // _findFromSpill(...) int i = (hashSize + (hashSize>>1)) << 1; for (int end = i + _spillCount; i < end; i += 2) { match = _hashArea[i]; if ((match == key) || key.equals(match)) { return (SettableBeanProperty) _hashArea[i+1]; } } } return null; } /* /********************************************************** /* Public API, deserialization support /********************************************************** */ /** * Convenience method that tries to find property with given name, and * if it is found, call {@link SettableBeanProperty#deserializeAndSet} * on it, and return true; or, if not found, return false. * Note, too, that if deserialization is attempted, possible exceptions * are wrapped if and as necessary, so caller need not handle those. * * @since 2.5 */ public boolean findDeserializeAndSet(JsonParser p, DeserializationContext ctxt, Object bean, String key) throws IOException { final SettableBeanProperty prop = find(key); if (prop == null) { return false; } try { prop.deserializeAndSet(p, ctxt, bean); } catch (Exception e) { wrapAndThrow(e, bean, key, ctxt); } return true; } /* /********************************************************** /* Std method overrides /********************************************************** */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Properties=["); int count = 0; Iterator it = iterator(); while (it.hasNext()) { SettableBeanProperty prop = it.next(); if (count++ > 0) { sb.append(", "); } sb.append(prop.getName()); sb.append('('); sb.append(prop.getType()); sb.append(')'); } sb.append(']'); if (!_aliasDefs.isEmpty()) { sb.append("(aliases: "); sb.append(_aliasDefs); sb.append(")"); } return sb.toString(); } /* /********************************************************** /* Helper methods /********************************************************** */ protected SettableBeanProperty _rename(SettableBeanProperty prop, NameTransformer xf) { if (prop == null) { return prop; } String newName = xf.transform(prop.getName()); prop = prop.withSimpleName(newName); JsonDeserializer deser = prop.getValueDeserializer(); if (deser != null) { @SuppressWarnings("unchecked") JsonDeserializer newDeser = (JsonDeserializer) deser.unwrappingDeserializer(xf); if (newDeser != deser) { prop = prop.withValueDeserializer(newDeser); } } return prop; } protected void wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt) throws IOException { // inlined 'throwOrReturnThrowable' while (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } // Errors to be passed as is ClassUtil.throwIfError(t); // StackOverflowErrors are tricky ones; need to be careful... boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS); // Ditto for IOExceptions; except we may want to wrap JSON exceptions if (t instanceof IOException) { if (!wrap || !(t instanceof JsonProcessingException)) { throw (IOException) t; } } else if (!wrap) { // allow disabling wrapping for unchecked exceptions ClassUtil.throwIfRTE(t); } throw JsonMappingException.wrapWithPath(t, bean, fieldName); } /** * Helper method used to find exact location of a property with name * given exactly, not subject to case changes, within hash area. * Expectation is that such property SHOULD exist, although no * exception is thrown. * * @since 2.7 */ private final int _findIndexInHash(String key) { final int slot = _hashCode(key); int ix = (slot<<1); // primary match? if (key.equals(_hashArea[ix])) { return ix+1; } // no? secondary? int hashSize = _hashMask+1; ix = hashSize + (slot>>1) << 1; if (key.equals(_hashArea[ix])) { return ix+1; } // perhaps spill then int i = (hashSize + (hashSize>>1)) << 1; for (int end = i + _spillCount; i < end; i += 2) { if (key.equals(_hashArea[i])) { return i+1; } } return -1; } private final int _findFromOrdered(SettableBeanProperty prop) { for (int i = 0, end = _propsInOrder.length; i < end; ++i) { if (_propsInOrder[i] == prop) { return i; } } throw new IllegalStateException("Illegal state: property '"+prop.getName()+"' missing from _propsInOrder"); } // Offlined version for convenience if we want to change hashing scheme private final int _hashCode(String key) { // This method produces better hash, fewer collisions... yet for some // reason produces slightly worse performance. Very strange. // 05-Aug-2015, tatu: ... still true? /* int h = key.hashCode(); return (h + (h >> 13)) & _hashMask; */ return key.hashCode() & _hashMask; } // @since 2.9 private Map _buildAliasMapping(Map> defs) { if ((defs == null) || defs.isEmpty()) { return Collections.emptyMap(); } Map aliases = new HashMap<>(); for (Map.Entry> entry : defs.entrySet()) { String key = entry.getKey(); if (_caseInsensitive) { key = key.toLowerCase(); } for (PropertyName pn : entry.getValue()) { String mapped = pn.getSimpleName(); if (_caseInsensitive) { mapped = mapped.toLowerCase(); } aliases.put(mapped, key); } } return aliases; } } CreatorCandidate.java000066400000000000000000000077311325620701100365620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import com.fasterxml.jackson.annotation.JacksonInject; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.PropertyName; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; public final class CreatorCandidate { protected final AnnotationIntrospector _intr; protected final AnnotatedWithParams _creator; protected final int _paramCount; protected final Param[] _params; protected CreatorCandidate(AnnotationIntrospector intr, AnnotatedWithParams ct, Param[] params, int count) { _intr = intr; _creator = ct; _params = params; _paramCount = count; } public static CreatorCandidate construct(AnnotationIntrospector intr, AnnotatedWithParams creator, BeanPropertyDefinition[] propDefs) { final int pcount = creator.getParameterCount(); Param[] params = new Param[pcount]; for (int i = 0; i < pcount; ++i) { AnnotatedParameter annParam = creator.getParameter(i); JacksonInject.Value injectId = intr.findInjectableValue(annParam); params[i] = new Param(annParam, (propDefs == null) ? null : propDefs[i], injectId); } return new CreatorCandidate(intr, creator, params, pcount); } public AnnotatedWithParams creator() { return _creator; } public int paramCount() { return _paramCount; } public JacksonInject.Value injection(int i) { return _params[i].injection; } public AnnotatedParameter parameter(int i) { return _params[i].annotated; } public BeanPropertyDefinition propertyDef(int i) { return _params[i].propDef; } public PropertyName paramName(int i) { BeanPropertyDefinition propDef = _params[i].propDef; if (propDef != null) { return propDef.getFullName(); } return null; } public PropertyName explicitParamName(int i) { BeanPropertyDefinition propDef = _params[i].propDef; if (propDef != null) { if (propDef.isExplicitlyNamed()) { return propDef.getFullName(); } } return null; } public PropertyName findImplicitParamName(int i) { String str = _intr.findImplicitPropertyName(_params[i].annotated); if (str != null && !str.isEmpty()) { return PropertyName.construct(str); } return null; } /** * Specialized accessor that finds index of the one and only parameter * with NO injection and returns that; or, if none or more than one found, * returns -1. */ public int findOnlyParamWithoutInjection() { int missing = -1; for (int i = 0; i < _paramCount; ++i) { if (_params[i].injection == null) { if (missing >= 0) { return -1; } missing = i; } } return missing; } @Override public String toString() { return _creator.toString(); } public final static class Param { public final AnnotatedParameter annotated; public final BeanPropertyDefinition propDef; public final JacksonInject.Value injection; public Param(AnnotatedParameter p, BeanPropertyDefinition pd, JacksonInject.Value i) { annotated = p; propDef = pd; injection = i; } public PropertyName fullName() { if (propDef == null) { return null; } return propDef.getFullName(); } public boolean hasFullName() { if (propDef == null) { return false; } PropertyName n = propDef.getFullName(); return n.hasSimpleName(); } } } CreatorCollector.java000066400000000000000000000410161325620701100366260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Member; import java.lang.reflect.Type; import java.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Container class for storing information on creators (based on annotations, * visibility), to be able to build actual instantiator later on. */ public class CreatorCollector { // Since 2.5 protected final static int C_DEFAULT = 0; protected final static int C_STRING = 1; protected final static int C_INT = 2; protected final static int C_LONG = 3; protected final static int C_DOUBLE = 4; protected final static int C_BOOLEAN = 5; protected final static int C_DELEGATE = 6; protected final static int C_PROPS = 7; protected final static int C_ARRAY_DELEGATE = 8; protected final static String[] TYPE_DESCS = new String[] { "default", "from-String", "from-int", "from-long", "from-double", "from-boolean", "delegate", "property-based" }; /// Type of bean being created final protected BeanDescription _beanDesc; final protected boolean _canFixAccess; /** * @since 2.7 */ final protected boolean _forceAccess; /** * Set of creators we have collected so far * * @since 2.5 */ protected final AnnotatedWithParams[] _creators = new AnnotatedWithParams[9]; /** * Bitmask of creators that were explicitly marked as creators; false for * auto-detected (ones included base on naming and/or visibility, not * annotation) * * @since 2.5 */ protected int _explicitCreators = 0; protected boolean _hasNonDefaultCreator = false; // when there are injectable values along with delegate: protected SettableBeanProperty[] _delegateArgs; protected SettableBeanProperty[] _arrayDelegateArgs; protected SettableBeanProperty[] _propertyBasedArgs; protected AnnotatedParameter _incompleteParameter; /* /********************************************************** /* Life-cycle /********************************************************** */ public CreatorCollector(BeanDescription beanDesc, MapperConfig config) { _beanDesc = beanDesc; _canFixAccess = config.canOverrideAccessModifiers(); _forceAccess = config .isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS); } public ValueInstantiator constructValueInstantiator( DeserializationConfig config) { final JavaType delegateType = _computeDelegateType( _creators[C_DELEGATE], _delegateArgs); final JavaType arrayDelegateType = _computeDelegateType( _creators[C_ARRAY_DELEGATE], _arrayDelegateArgs); final JavaType type = _beanDesc.getType(); // 11-Jul-2016, tatu: Earlier optimization by replacing the whole // instantiator did not // work well, so let's replace by lower-level check: AnnotatedWithParams defaultCtor = StdTypeConstructor .tryToOptimize(_creators[C_DEFAULT]); StdValueInstantiator inst = new StdValueInstantiator(config, type); inst.configureFromObjectSettings(defaultCtor, _creators[C_DELEGATE], delegateType, _delegateArgs, _creators[C_PROPS], _propertyBasedArgs); inst.configureFromArraySettings(_creators[C_ARRAY_DELEGATE], arrayDelegateType, _arrayDelegateArgs); inst.configureFromStringCreator(_creators[C_STRING]); inst.configureFromIntCreator(_creators[C_INT]); inst.configureFromLongCreator(_creators[C_LONG]); inst.configureFromDoubleCreator(_creators[C_DOUBLE]); inst.configureFromBooleanCreator(_creators[C_BOOLEAN]); inst.configureIncompleteParameter(_incompleteParameter); return inst; } /* /********************************************************** /* Setters /********************************************************** */ /** * Method called to indicate the default creator: no-arguments constructor * or factory method that is called to instantiate a value before populating * it with data. Default creator is only used if no other creators are * indicated. * * @param creator * Creator method; no-arguments constructor or static factory * method. */ public void setDefaultCreator(AnnotatedWithParams creator) { _creators[C_DEFAULT] = _fixAccess(creator); } public void addStringCreator(AnnotatedWithParams creator, boolean explicit) { verifyNonDup(creator, C_STRING, explicit); } public void addIntCreator(AnnotatedWithParams creator, boolean explicit) { verifyNonDup(creator, C_INT, explicit); } public void addLongCreator(AnnotatedWithParams creator, boolean explicit) { verifyNonDup(creator, C_LONG, explicit); } public void addDoubleCreator(AnnotatedWithParams creator, boolean explicit) { verifyNonDup(creator, C_DOUBLE, explicit); } public void addBooleanCreator(AnnotatedWithParams creator, boolean explicit) { verifyNonDup(creator, C_BOOLEAN, explicit); } public void addDelegatingCreator(AnnotatedWithParams creator, boolean explicit, SettableBeanProperty[] injectables, int delegateeIndex) { if (creator.getParameterType(delegateeIndex).isCollectionLikeType()) { if (verifyNonDup(creator, C_ARRAY_DELEGATE, explicit)) { _arrayDelegateArgs = injectables; } } else { if (verifyNonDup(creator, C_DELEGATE, explicit)) { _delegateArgs = injectables; } } } public void addPropertyCreator(AnnotatedWithParams creator, boolean explicit, SettableBeanProperty[] properties) { if (verifyNonDup(creator, C_PROPS, explicit)) { // Better ensure we have no duplicate names either... if (properties.length > 1) { HashMap names = new HashMap(); for (int i = 0, len = properties.length; i < len; ++i) { String name = properties[i].getName(); // Need to consider Injectables, which may not have // a name at all, and need to be skipped if (name.isEmpty() && (properties[i].getInjectableValueId() != null)) { continue; } Integer old = names.put(name, Integer.valueOf(i)); if (old != null) { throw new IllegalArgumentException(String.format( "Duplicate creator property \"%s\" (index %s vs %d)", name, old, i)); } } } _propertyBasedArgs = properties; } } public void addIncompeteParameter(AnnotatedParameter parameter) { if (_incompleteParameter == null) { _incompleteParameter = parameter; } } /* /********************************************************** /* Accessors /********************************************************** */ /** * @since 2.1 */ public boolean hasDefaultCreator() { return _creators[C_DEFAULT] != null; } /** * @since 2.6 */ public boolean hasDelegatingCreator() { return _creators[C_DELEGATE] != null; } /** * @since 2.6 */ public boolean hasPropertyBasedCreator() { return _creators[C_PROPS] != null; } /* /********************************************************** /* Helper methods /********************************************************** */ private JavaType _computeDelegateType(AnnotatedWithParams creator, SettableBeanProperty[] delegateArgs) { if (!_hasNonDefaultCreator || (creator == null)) { return null; } // need to find type... int ix = 0; if (delegateArgs != null) { for (int i = 0, len = delegateArgs.length; i < len; ++i) { if (delegateArgs[i] == null) { // marker for delegate itself ix = i; break; } } } return creator.getParameterType(ix); } private T _fixAccess(T member) { if (member != null && _canFixAccess) { ClassUtil.checkAndFixAccess((Member) member.getAnnotated(), _forceAccess); } return member; } /** * @return True if specified Creator is to be used */ protected boolean verifyNonDup(AnnotatedWithParams newOne, int typeIndex, boolean explicit) { final int mask = (1 << typeIndex); _hasNonDefaultCreator = true; AnnotatedWithParams oldOne = _creators[typeIndex]; // already had an explicitly marked one? if (oldOne != null) { boolean verify; if ((_explicitCreators & mask) != 0) { // already had explicitly annotated, leave as-is // but skip, if new one not annotated if (!explicit) { return false; } // both explicit: verify verify = true; } else { // otherwise only verify if neither explicitly annotated. verify = !explicit; } // one more thing: ok to override in sub-class if (verify && (oldOne.getClass() == newOne.getClass())) { // [databind#667]: avoid one particular class of bogus problems Class oldType = oldOne.getRawParameterType(0); Class newType = newOne.getRawParameterType(0); if (oldType == newType) { // 13-Jul-2016, tatu: One more thing to check; since Enum // classes always have // implicitly created `valueOf()`, let's resolve in favor of // other implicit // creator (`fromString()`) if (_isEnumValueOf(newOne)) { return false; // ignore } if (_isEnumValueOf(oldOne)) { ; } else { throw new IllegalArgumentException(String.format( "Conflicting %s creators: already had %s creator %s, encountered another: %s", TYPE_DESCS[typeIndex], explicit ? "explicitly marked" : "implicitly discovered", oldOne, newOne)); } } // otherwise, which one to choose? else if (newType.isAssignableFrom(oldType)) { // new type more generic, use old return false; } // new type more specific, use it } } if (explicit) { _explicitCreators |= mask; } _creators[typeIndex] = _fixAccess(newOne); return true; } /** * Helper method for recognizing `Enum.valueOf()` factory method * * @since 2.8.1 */ protected boolean _isEnumValueOf(AnnotatedWithParams creator) { return creator.getDeclaringClass().isEnum() && "valueOf".equals(creator.getName()); } /* /********************************************************** /* Helper class(es) /********************************************************** */ /** * Replacement for default constructor to use for a small set of * "well-known" types. *

* Note: replaces earlier Vanilla * ValueInstantiator implementation * * @since 2.8.1 (replacing earlier Vanilla instantiator */ protected final static class StdTypeConstructor extends AnnotatedWithParams implements java.io.Serializable { private static final long serialVersionUID = 1L; public final static int TYPE_ARRAY_LIST = 1; public final static int TYPE_HASH_MAP = 2; public final static int TYPE_LINKED_HASH_MAP = 3; private final AnnotatedWithParams _base; private final int _type; public StdTypeConstructor(AnnotatedWithParams base, int t) { super(base, null); _base = base; _type = t; } public static AnnotatedWithParams tryToOptimize( AnnotatedWithParams src) { if (src != null) { final Class rawType = src.getDeclaringClass(); if (rawType == List.class || rawType == ArrayList.class) { return new StdTypeConstructor(src, TYPE_ARRAY_LIST); } if (rawType == LinkedHashMap.class) { return new StdTypeConstructor(src, TYPE_LINKED_HASH_MAP); } if (rawType == HashMap.class) { return new StdTypeConstructor(src, TYPE_HASH_MAP); } } return src; } protected final Object _construct() { switch (_type) { case TYPE_ARRAY_LIST: return new ArrayList(); case TYPE_LINKED_HASH_MAP: return new LinkedHashMap(); case TYPE_HASH_MAP: return new HashMap(); } throw new IllegalStateException("Unknown type " + _type); } @Override public int getParameterCount() { return _base.getParameterCount(); } @Override public Class getRawParameterType(int index) { return _base.getRawParameterType(index); } @Override public JavaType getParameterType(int index) { return _base.getParameterType(index); } @Override @Deprecated public Type getGenericParameterType(int index) { return _base.getGenericParameterType(index); } @Override public Object call() throws Exception { return _construct(); } @Override public Object call(Object[] args) throws Exception { return _construct(); } @Override public Object call1(Object arg) throws Exception { return _construct(); } @Override public Class getDeclaringClass() { return _base.getDeclaringClass(); } @Override public Member getMember() { return _base.getMember(); } @Override public void setValue(Object pojo, Object value) throws UnsupportedOperationException, IllegalArgumentException { throw new UnsupportedOperationException(); } @Override public Object getValue(Object pojo) throws UnsupportedOperationException, IllegalArgumentException { throw new UnsupportedOperationException(); } @Override public Annotated withAnnotations(AnnotationMap fallback) { throw new UnsupportedOperationException(); } @Override public AnnotatedElement getAnnotated() { return _base.getAnnotated(); } @Override protected int getModifiers() { return _base.getMember().getModifiers(); } @Override public String getName() { return _base.getName(); } @Override public JavaType getType() { return _base.getType(); } @Override public Class getRawType() { return _base.getRawType(); } @Override public boolean equals(Object o) { return (o == this); } @Override public int hashCode() { return _base.hashCode(); } @Override public String toString() { return _base.toString(); } } } ErrorThrowingDeserializer.java000066400000000000000000000017021325620701100405340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; /** * A deserializer that stores an {@link Error} caught during constructing * of the deserializer, which needs to be deferred and only during actual * attempt to deserialize a value of given type. * Note that null and empty values can be deserialized without error. * * @since 2.9 Note: prior to this version was named NoClassDefFoundDeserializer */ public class ErrorThrowingDeserializer extends JsonDeserializer { private final Error _cause; public ErrorThrowingDeserializer(NoClassDefFoundError cause) { _cause = cause; } @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { throw _cause; } } ExternalTypeHandler.java000066400000000000000000000450451325620701100373100ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Helper class that is used to flatten JSON structure when using * "external type id" (see {@link com.fasterxml.jackson.annotation.JsonTypeInfo.As#EXTERNAL_PROPERTY}). * This is needed to store temporary state and buffer tokens, as the structure is * rearranged a bit so that actual type deserializer can resolve type and * finalize deserialization. */ public class ExternalTypeHandler { private final JavaType _beanType; private final ExtTypedProperty[] _properties; /** * Mapping from external property ids to one or more indexes; * in most cases single index as Integer, but * occasionally same name maps to multiple ones: if so, * List<Integer>. */ private final Map _nameToPropertyIndex; private final String[] _typeIds; private final TokenBuffer[] _tokens; protected ExternalTypeHandler(JavaType beanType, ExtTypedProperty[] properties, Map nameToPropertyIndex, String[] typeIds, TokenBuffer[] tokens) { _beanType = beanType; _properties = properties; _nameToPropertyIndex = nameToPropertyIndex; _typeIds = typeIds; _tokens = tokens; } protected ExternalTypeHandler(ExternalTypeHandler h) { _beanType = h._beanType; _properties = h._properties; _nameToPropertyIndex = h._nameToPropertyIndex; int len = _properties.length; _typeIds = new String[len]; _tokens = new TokenBuffer[len]; } /** * @since 2.9 */ public static Builder builder(JavaType beanType) { return new Builder(beanType); } /** * Method called to start collection process by creating non-blueprint * instances. */ public ExternalTypeHandler start() { return new ExternalTypeHandler(this); } /** * Method called to see if given property/value pair is an external type * id; and if so handle it. This is only to be called in case * containing POJO has similarly named property as the external type id AND * value is of scalar type: * otherwise {@link #handlePropertyValue} should be called instead. */ @SuppressWarnings("unchecked") public boolean handleTypePropertyValue(JsonParser p, DeserializationContext ctxt, String propName, Object bean) throws IOException { Object ob = _nameToPropertyIndex.get(propName); if (ob == null) { return false; } final String typeId = p.getText(); // 28-Nov-2016, tatu: For [databind#291], need separate handling if (ob instanceof List) { boolean result = false; for (Integer index : (List) ob) { if (_handleTypePropertyValue(p, ctxt, propName, bean, typeId, index.intValue())) { result = true; } } return result; } return _handleTypePropertyValue(p, ctxt, propName, bean, typeId, ((Integer) ob).intValue()); } private final boolean _handleTypePropertyValue(JsonParser p, DeserializationContext ctxt, String propName, Object bean, String typeId, int index) throws IOException { ExtTypedProperty prop = _properties[index]; if (!prop.hasTypePropertyName(propName)) { // when could/should this ever happen? return false; } // note: can NOT skip child values (should always be String anyway) boolean canDeserialize = (bean != null) && (_tokens[index] != null); // Minor optimization: deserialize properties as soon as we have all we need: if (canDeserialize) { _deserializeAndSet(p, ctxt, bean, index, typeId); // clear stored data, to avoid deserializing+setting twice: _tokens[index] = null; } else { _typeIds[index] = typeId; } return true; } /** * Method called to ask handler to handle value of given property, * at point where parser points to the first token of the value. * Handling can mean either resolving type id it contains (if it matches type * property name), or by buffering the value for further use. * * @return True, if the given property was properly handled */ @SuppressWarnings("unchecked") public boolean handlePropertyValue(JsonParser p, DeserializationContext ctxt, String propName, Object bean) throws IOException { Object ob = _nameToPropertyIndex.get(propName); if (ob == null) { return false; } // 28-Nov-2016, tatu: For [databind#291], need separate handling if (ob instanceof List) { Iterator it = ((List) ob).iterator(); Integer index = it.next(); ExtTypedProperty prop = _properties[index]; // For now, let's assume it's same type (either type id OR value) // for all mappings, so we'll only check first one if (prop.hasTypePropertyName(propName)) { String typeId = p.getText(); p.skipChildren(); _typeIds[index] = typeId; while (it.hasNext()) { _typeIds[it.next()] = typeId; } } else { @SuppressWarnings("resource") TokenBuffer tokens = new TokenBuffer(p, ctxt); tokens.copyCurrentStructure(p); _tokens[index] = tokens; while (it.hasNext()) { _tokens[it.next()] = tokens; } } return true; } // Otherwise only maps to a single value, in which case we can // handle things in bit more optimal way... int index = ((Integer) ob).intValue(); ExtTypedProperty prop = _properties[index]; boolean canDeserialize; if (prop.hasTypePropertyName(propName)) { _typeIds[index] = p.getText(); p.skipChildren(); canDeserialize = (bean != null) && (_tokens[index] != null); } else { @SuppressWarnings("resource") TokenBuffer tokens = new TokenBuffer(p, ctxt); tokens.copyCurrentStructure(p); _tokens[index] = tokens; canDeserialize = (bean != null) && (_typeIds[index] != null); } // Minor optimization: let's deserialize properties as soon as // we have all pertinent information: if (canDeserialize) { String typeId = _typeIds[index]; // clear stored data, to avoid deserializing+setting twice: _typeIds[index] = null; _deserializeAndSet(p, ctxt, bean, index, typeId); _tokens[index] = null; } return true; } /** * Method called after JSON Object closes, and has to ensure that all external * type ids have been handled. */ @SuppressWarnings("resource") public Object complete(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException { for (int i = 0, len = _properties.length; i < len; ++i) { String typeId = _typeIds[i]; if (typeId == null) { TokenBuffer tokens = _tokens[i]; // let's allow missing both type and property (may already have been set, too) // but not just one if (tokens == null) { continue; } // [databind#118]: Need to mind natural types, for which no type id // will be included. JsonToken t = tokens.firstToken(); if (t.isScalarValue()) { // can't be null as we never store empty buffers JsonParser buffered = tokens.asParser(p); buffered.nextToken(); SettableBeanProperty extProp = _properties[i].getProperty(); Object result = TypeDeserializer.deserializeIfNatural(buffered, ctxt, extProp.getType()); if (result != null) { extProp.set(bean, result); continue; } // 26-Oct-2012, tatu: As per [databind#94], must allow use of 'defaultImpl' if (!_properties[i].hasDefaultType()) { ctxt.reportInputMismatch(bean.getClass(), "Missing external type id property '%s'", _properties[i].getTypePropertyName()); } else { typeId = _properties[i].getDefaultTypeId(); } } } else if (_tokens[i] == null) { SettableBeanProperty prop = _properties[i].getProperty(); if(prop.isRequired() || ctxt.isEnabled(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY)) { ctxt.reportInputMismatch(bean.getClass(), "Missing property '%s' for external type id '%s'", prop.getName(), _properties[i].getTypePropertyName()); } return bean; } _deserializeAndSet(p, ctxt, bean, i, typeId); } return bean; } /** * Variant called when creation of the POJO involves buffering of creator properties * as well as property-based creator. */ public Object complete(JsonParser p, DeserializationContext ctxt, PropertyValueBuffer buffer, PropertyBasedCreator creator) throws IOException { // first things first: deserialize all data buffered: final int len = _properties.length; Object[] values = new Object[len]; for (int i = 0; i < len; ++i) { String typeId = _typeIds[i]; final ExtTypedProperty extProp = _properties[i]; if (typeId == null) { // let's allow missing both type and property (may already have been set, too) if (_tokens[i] == null) { continue; } // but not just one // 26-Oct-2012, tatu: As per [databind#94], must allow use of 'defaultImpl' if (!extProp.hasDefaultType()) { ctxt.reportInputMismatch(_beanType, "Missing external type id property '%s'", extProp.getTypePropertyName()); } else { typeId = extProp.getDefaultTypeId(); } } else if (_tokens[i] == null) { SettableBeanProperty prop = extProp.getProperty(); ctxt.reportInputMismatch(_beanType, "Missing property '%s' for external type id '%s'", prop.getName(), _properties[i].getTypePropertyName()); } values[i] = _deserialize(p, ctxt, i, typeId); final SettableBeanProperty prop = extProp.getProperty(); // also: if it's creator prop, fill in if (prop.getCreatorIndex() >= 0) { buffer.assignParameter(prop, values[i]); // [databind#999] And maybe there's creator property for type id too? SettableBeanProperty typeProp = extProp.getTypeProperty(); // for now, should only be needed for creator properties, too if ((typeProp != null) && (typeProp.getCreatorIndex() >= 0)) { buffer.assignParameter(typeProp, typeId); } } } Object bean = creator.build(ctxt, buffer); // third: assign non-creator properties for (int i = 0; i < len; ++i) { SettableBeanProperty prop = _properties[i].getProperty(); if (prop.getCreatorIndex() < 0) { prop.set(bean, values[i]); } } return bean; } @SuppressWarnings("resource") protected final Object _deserialize(JsonParser p, DeserializationContext ctxt, int index, String typeId) throws IOException { JsonParser p2 = _tokens[index].asParser(p); JsonToken t = p2.nextToken(); // 29-Sep-2015, tatu: As per [databind#942], nulls need special support if (t == JsonToken.VALUE_NULL) { return null; } TokenBuffer merged = new TokenBuffer(p, ctxt); merged.writeStartArray(); merged.writeString(typeId); merged.copyCurrentStructure(p2); merged.writeEndArray(); // needs to point to START_OBJECT (or whatever first token is) JsonParser mp = merged.asParser(p); mp.nextToken(); return _properties[index].getProperty().deserialize(mp, ctxt); } @SuppressWarnings("resource") protected final void _deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object bean, int index, String typeId) throws IOException { /* Ok: time to mix type id, value; and we will actually use "wrapper-array" * style to ensure we can handle all kinds of JSON constructs. */ JsonParser p2 = _tokens[index].asParser(p); JsonToken t = p2.nextToken(); // 29-Sep-2015, tatu: As per [databind#942], nulls need special support if (t == JsonToken.VALUE_NULL) { _properties[index].getProperty().set(bean, null); return; } TokenBuffer merged = new TokenBuffer(p, ctxt); merged.writeStartArray(); merged.writeString(typeId); merged.copyCurrentStructure(p2); merged.writeEndArray(); // needs to point to START_OBJECT (or whatever first token is) JsonParser mp = merged.asParser(p); mp.nextToken(); _properties[index].getProperty().deserializeAndSet(mp, ctxt, bean); } /* /********************************************************** /* Helper classes /********************************************************** */ public static class Builder { private final JavaType _beanType; private final List _properties = new ArrayList<>(); private final Map _nameToPropertyIndex = new HashMap<>(); protected Builder(JavaType t) { _beanType = t; } public void addExternal(SettableBeanProperty property, TypeDeserializer typeDeser) { Integer index = _properties.size(); _properties.add(new ExtTypedProperty(property, typeDeser)); _addPropertyIndex(property.getName(), index); _addPropertyIndex(typeDeser.getPropertyName(), index); } private void _addPropertyIndex(String name, Integer index) { Object ob = _nameToPropertyIndex.get(name); if (ob == null) { _nameToPropertyIndex.put(name, index); } else if (ob instanceof List) { @SuppressWarnings("unchecked") List list = (List) ob; list.add(index); } else { List list = new LinkedList<>(); list.add(ob); list.add(index); _nameToPropertyIndex.put(name, list); } } /** * Method called after all external properties have been assigned, to further * link property with polymorphic value with possible property for type id * itself. This is needed to support type ids as Creator properties. * * @since 2.8 */ public ExternalTypeHandler build(BeanPropertyMap otherProps) { // 21-Jun-2016, tatu: as per [databind#999], may need to link type id property also final int len = _properties.size(); ExtTypedProperty[] extProps = new ExtTypedProperty[len]; for (int i = 0; i < len; ++i) { ExtTypedProperty extProp = _properties.get(i); String typePropId = extProp.getTypePropertyName(); SettableBeanProperty typeProp = otherProps.find(typePropId); if (typeProp != null) { extProp.linkTypeProperty(typeProp); } extProps[i] = extProp; } return new ExternalTypeHandler(_beanType, extProps, _nameToPropertyIndex, null, null); } } private final static class ExtTypedProperty { private final SettableBeanProperty _property; private final TypeDeserializer _typeDeserializer; private final String _typePropertyName; /** * @since 2.8 */ private SettableBeanProperty _typeProperty; public ExtTypedProperty(SettableBeanProperty property, TypeDeserializer typeDeser) { _property = property; _typeDeserializer = typeDeser; _typePropertyName = typeDeser.getPropertyName(); } /** * @since 2.8 */ public void linkTypeProperty(SettableBeanProperty p) { _typeProperty = p; } public boolean hasTypePropertyName(String n) { return n.equals(_typePropertyName); } public boolean hasDefaultType() { return _typeDeserializer.getDefaultImpl() != null; } /** * Specialized called when we need to expose type id of `defaultImpl` when * serializing: we may need to expose it for assignment to a property, or * it may be requested as visible for some other reason. */ public String getDefaultTypeId() { Class defaultType = _typeDeserializer.getDefaultImpl(); if (defaultType == null) { return null; } return _typeDeserializer.getTypeIdResolver().idFromValueAndType(null, defaultType); } public String getTypePropertyName() { return _typePropertyName; } public SettableBeanProperty getProperty() { return _property; } /** * @since 2.8 */ public SettableBeanProperty getTypeProperty() { return _typeProperty; } } } FailingDeserializer.java000066400000000000000000000017501325620701100372750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; /** * Special bogus "serializer" that will throw * {@link JsonMappingException} if an attempt is made to deserialize * a value. This is used as placeholder to avoid NPEs for uninitialized * structured serializers or handlers. */ public class FailingDeserializer extends StdDeserializer { private static final long serialVersionUID = 1L; protected final String _message; public FailingDeserializer(String m) { super(Object.class); _message = m; } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { ctxt.reportInputMismatch(this, _message); return null; } } FieldProperty.java000066400000000000000000000143071325620701100361530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.introspect.AnnotatedField; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.Annotations; import com.fasterxml.jackson.databind.util.ClassUtil; /** * This concrete sub-class implements property that is set * directly assigning to a Field. */ public final class FieldProperty extends SettableBeanProperty { private static final long serialVersionUID = 1L; final protected AnnotatedField _annotated; /** * Actual field to set when deserializing this property. * Transient since there is no need to persist; only needed during * construction of objects. */ final protected transient Field _field; /** * @since 2.9 */ final protected boolean _skipNulls; public FieldProperty(BeanPropertyDefinition propDef, JavaType type, TypeDeserializer typeDeser, Annotations contextAnnotations, AnnotatedField field) { super(propDef, type, typeDeser, contextAnnotations); _annotated = field; _field = field.getAnnotated(); _skipNulls = NullsConstantProvider.isSkipper(_nullProvider); } protected FieldProperty(FieldProperty src, JsonDeserializer deser, NullValueProvider nva) { super(src, deser, nva); _annotated = src._annotated; _field = src._field; _skipNulls = NullsConstantProvider.isSkipper(nva); } protected FieldProperty(FieldProperty src, PropertyName newName) { super(src, newName); _annotated = src._annotated; _field = src._field; _skipNulls = src._skipNulls; } /** * Constructor used for JDK Serialization when reading persisted object */ protected FieldProperty(FieldProperty src) { super(src); _annotated = src._annotated; Field f = _annotated.getAnnotated(); if (f == null) { throw new IllegalArgumentException("Missing field (broken JDK (de)serialization?)"); } _field = f; _skipNulls = src._skipNulls; } @Override public SettableBeanProperty withName(PropertyName newName) { return new FieldProperty(this, newName); } @Override public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } return new FieldProperty(this, deser, _nullProvider); } @Override public SettableBeanProperty withNullProvider(NullValueProvider nva) { return new FieldProperty(this, _valueDeserializer, nva); } @Override public void fixAccess(DeserializationConfig config) { ClassUtil.checkAndFixAccess(_field, config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } /* /********************************************************** /* BeanProperty impl /********************************************************** */ @Override public A getAnnotation(Class acls) { return (_annotated == null) ? null : _annotated.getAnnotation(acls); } @Override public AnnotatedMember getMember() { return _annotated; } /* /********************************************************** /* Overridden methods /********************************************************** */ @Override public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { Object value; if (p.hasToken(JsonToken.VALUE_NULL)) { if (_skipNulls) { return; } value = _nullProvider.getNullValue(ctxt); } else if (_valueTypeDeserializer == null) { value = _valueDeserializer.deserialize(p, ctxt); } else { value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } try { _field.set(instance, value); } catch (Exception e) { _throwAsIOE(p, e, value); } } @Override public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { Object value; if (p.hasToken(JsonToken.VALUE_NULL)) { if (_skipNulls) { return instance; } value = _nullProvider.getNullValue(ctxt); } else if (_valueTypeDeserializer == null) { value = _valueDeserializer.deserialize(p, ctxt); } else { value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } try { _field.set(instance, value); } catch (Exception e) { _throwAsIOE(p, e, value); } return instance; } @Override public void set(Object instance, Object value) throws IOException { try { _field.set(instance, value); } catch (Exception e) { // 15-Sep-2015, tatu: How could we get a ref to JsonParser? _throwAsIOE(e, value); } } @Override public Object setAndReturn(Object instance, Object value) throws IOException { try { _field.set(instance, value); } catch (Exception e) { // 15-Sep-2015, tatu: How could we get a ref to JsonParser? _throwAsIOE(e, value); } return instance; } /* /********************************************************** /* JDK serialization handling /********************************************************** */ Object readResolve() { return new FieldProperty(this); } }InnerClassProperty.java000066400000000000000000000100021325620701100371550ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.lang.reflect.Constructor; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.util.ClassUtil; /** * This sub-class is used to handle special case of value being a * non-static inner class. If so, we will have to use a special * alternative for default constructor; but otherwise can delegate * to regular implementation. */ public final class InnerClassProperty extends SettableBeanProperty.Delegating { private static final long serialVersionUID = 1L; /** * Constructor used when deserializing this property. * Transient since there is no need to persist; only needed during * construction of objects. */ final protected transient Constructor _creator; /** * Serializable version of single-arg constructor we use for value instantiation. */ protected AnnotatedConstructor _annotated; public InnerClassProperty(SettableBeanProperty delegate, Constructor ctor) { super(delegate); _creator = ctor; } /** * Constructor used with JDK Serialization; needed to handle transient * Constructor, wrap/unwrap in/out-of Annotated variant. */ protected InnerClassProperty(SettableBeanProperty src, AnnotatedConstructor ann) { super(src); _annotated = ann; _creator = (_annotated == null) ? null : _annotated.getAnnotated(); if (_creator == null) { throw new IllegalArgumentException("Missing constructor (broken JDK (de)serialization?)"); } } @Override protected SettableBeanProperty withDelegate(SettableBeanProperty d) { if (d == this.delegate) { return this; } return new InnerClassProperty(d, _creator); } /* /********************************************************** /* Deserialization methods /********************************************************** */ @Override public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException { JsonToken t = p.getCurrentToken(); Object value; if (t == JsonToken.VALUE_NULL) { value = _valueDeserializer.getNullValue(ctxt); } else if (_valueTypeDeserializer != null) { value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } else { // the usual case try { value = _creator.newInstance(bean); } catch (Exception e) { ClassUtil.unwrapAndThrowAsIAE(e, String.format( "Failed to instantiate class %s, problem: %s", _creator.getDeclaringClass().getName(), e.getMessage())); value = null; } _valueDeserializer.deserialize(p, ctxt, value); } set(bean, value); } @Override public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { return setAndReturn(instance, deserialize(p, ctxt)); } // these are fine with defaults // public final void set(Object instance, Object value) throws IOException { } // public Object setAndReturn(Object instance, Object value) throws IOException { } /* /********************************************************** /* JDK serialization handling /********************************************************** */ // When reading things back, Object readResolve() { return new InnerClassProperty(this, _annotated); } Object writeReplace() { // need to construct a fake instance to support serialization if (_annotated == null) { return new InnerClassProperty(this, new AnnotatedConstructor(null, _creator, null, null)); } return this; } } JavaUtilCollectionsDeserializers.java000066400000000000000000000156111325620701100420260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.util.*; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.Converter; /** * Helper class used to contain logic for deserializing "special" containers * from {@code java.util.Collections} and {@code java.util.Arrays}. This is needed * because they do not have usable no-arguments constructor: however, are easy enough * to deserialize using delegating deserializer. * * @since 2.9.4 */ public abstract class JavaUtilCollectionsDeserializers { private final static int TYPE_SINGLETON_SET = 1; private final static int TYPE_SINGLETON_LIST = 2; private final static int TYPE_SINGLETON_MAP = 3; private final static int TYPE_UNMODIFIABLE_SET = 4; private final static int TYPE_UNMODIFIABLE_LIST = 5; private final static int TYPE_UNMODIFIABLE_MAP = 6; public final static int TYPE_AS_LIST = 7; // 10-Jan-2018, tatu: There are a few "well-known" special containers in JDK too: private final static Class CLASS_AS_ARRAYS_LIST = Arrays.asList(null, null).getClass(); private final static Class CLASS_SINGLETON_SET; private final static Class CLASS_SINGLETON_LIST; private final static Class CLASS_SINGLETON_MAP; private final static Class CLASS_UNMODIFIABLE_SET; private final static Class CLASS_UNMODIFIABLE_LIST; private final static Class CLASS_UNMODIFIABLE_MAP; static { Set set = Collections.singleton(Boolean.TRUE); CLASS_SINGLETON_SET = set.getClass(); CLASS_UNMODIFIABLE_SET = Collections.unmodifiableSet(set).getClass(); List list = Collections.singletonList(Boolean.TRUE); CLASS_SINGLETON_LIST = list.getClass(); CLASS_UNMODIFIABLE_LIST = Collections.unmodifiableList(list).getClass(); Map map = Collections.singletonMap("a", "b"); CLASS_SINGLETON_MAP = map.getClass(); CLASS_UNMODIFIABLE_MAP = Collections.unmodifiableMap(map).getClass(); } public static JsonDeserializer findForCollection(DeserializationContext ctxt, JavaType type) throws JsonMappingException { JavaUtilCollectionsConverter conv; // 10-Jan-2017, tatu: Some types from `java.util.Collections`/`java.util.Arrays` need bit of help... if (type.hasRawClass(CLASS_AS_ARRAYS_LIST)) { conv = converter(TYPE_AS_LIST, type, List.class); } else if (type.hasRawClass(CLASS_SINGLETON_LIST)) { conv = converter(TYPE_SINGLETON_LIST, type, List.class); } else if (type.hasRawClass(CLASS_SINGLETON_SET)) { conv = converter(TYPE_SINGLETON_SET, type, Set.class); } else if (type.hasRawClass(CLASS_UNMODIFIABLE_LIST)) { conv = converter(TYPE_UNMODIFIABLE_LIST, type, List.class); } else if (type.hasRawClass(CLASS_UNMODIFIABLE_SET)) { conv = converter(TYPE_UNMODIFIABLE_SET, type, Set.class); } else { return null; } return new StdDelegatingDeserializer(conv); } public static JsonDeserializer findForMap(DeserializationContext ctxt, JavaType type) throws JsonMappingException { JavaUtilCollectionsConverter conv; // 10-Jan-2017, tatu: Some types from `java.util.Collections`/`java.util.Arrays` need bit of help... if (type.hasRawClass(CLASS_SINGLETON_MAP)) { conv = converter(TYPE_SINGLETON_MAP, type, Map.class); } else if (type.hasRawClass(CLASS_UNMODIFIABLE_MAP)) { conv = converter(TYPE_UNMODIFIABLE_MAP, type, Map.class); } else { return null; } return new StdDelegatingDeserializer(conv); } static JavaUtilCollectionsConverter converter(int kind, JavaType concreteType, Class rawSuper) { return new JavaUtilCollectionsConverter(kind, concreteType.findSuperType(rawSuper)); } /** * Implementation used for converting from various generic container * types ({@link java.util.Set}, {@link java.util.List}, {@link java.util.Map}) * into more specific implementations accessible via {@code java.util.Collections}. */ private static class JavaUtilCollectionsConverter implements Converter { private final JavaType _inputType; private final int _kind; private JavaUtilCollectionsConverter(int kind, JavaType inputType) { _inputType = inputType; _kind = kind; } @Override public Object convert(Object value) { if (value == null) { // is this legal to get? return null; } switch (_kind) { case TYPE_SINGLETON_SET: { Set set = (Set) value; _checkSingleton(set.size()); return Collections.singleton(set.iterator().next()); } case TYPE_SINGLETON_LIST: { List list = (List) value; _checkSingleton(list.size()); return Collections.singletonList(list.get(0)); } case TYPE_SINGLETON_MAP: { Map map = (Map) value; _checkSingleton(map.size()); Map.Entry entry = map.entrySet().iterator().next(); return Collections.singletonMap(entry.getKey(), entry.getValue()); } case TYPE_UNMODIFIABLE_SET: return Collections.unmodifiableSet((Set) value); case TYPE_UNMODIFIABLE_LIST: return Collections.unmodifiableList((List) value); case TYPE_UNMODIFIABLE_MAP: return Collections.unmodifiableMap((Map) value); case TYPE_AS_LIST: default: // Here we do not actually care about impl type, just return List as-is: return value; } } @Override public JavaType getInputType(TypeFactory typeFactory) { return _inputType; } @Override public JavaType getOutputType(TypeFactory typeFactory) { // we don't actually care, so: return _inputType; } private void _checkSingleton(int size) { if (size != 1) { // not the best error ever but... has to do throw new IllegalArgumentException("Can not deserialize Singleton container from "+size+" entries"); } } } } ManagedReferenceProperty.java000066400000000000000000000073351325620701100403060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.util.Collection; import java.util.Map; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; /** * Wrapper property that is used to handle managed (forward) properties * Basically just needs to delegate first to actual forward property, and * then to back property. */ public final class ManagedReferenceProperty // Changed to extends delegating base class in 2.9 extends SettableBeanProperty.Delegating { private static final long serialVersionUID = 1L; protected final String _referenceName; /** * Flag that indicates whether property to handle is a container type * (array, Collection, Map) or not. */ protected final boolean _isContainer; protected final SettableBeanProperty _backProperty; public ManagedReferenceProperty(SettableBeanProperty forward, String refName, SettableBeanProperty backward, boolean isContainer) { super(forward); _referenceName = refName; _backProperty = backward; _isContainer = isContainer; } @Override protected SettableBeanProperty withDelegate(SettableBeanProperty d) { throw new IllegalStateException("Should never try to reset delegate"); } // need to override to ensure both get fixed @Override public void fixAccess(DeserializationConfig config) { delegate.fixAccess(config); _backProperty.fixAccess(config); } /* /********************************************************** /* Overridden methods /********************************************************** */ @Override public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { set(instance, delegate.deserialize(p, ctxt)); } @Override public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { return setAndReturn(instance, deserialize(p, ctxt)); } @Override public final void set(Object instance, Object value) throws IOException { setAndReturn(instance, value); } @Override public Object setAndReturn(Object instance, Object value) throws IOException { /* 04-Feb-2014, tatu: As per [#390], it may be necessary to switch the * ordering of forward/backward references, and start with back ref. */ if (value != null) { if (_isContainer) { // ok, this gets ugly... but has to do for now if (value instanceof Object[]) { for (Object ob : (Object[]) value) { if (ob != null) { _backProperty.set(ob, instance); } } } else if (value instanceof Collection) { for (Object ob : (Collection) value) { if (ob != null) { _backProperty.set(ob, instance); } } } else if (value instanceof Map) { for (Object ob : ((Map) value).values()) { if (ob != null) { _backProperty.set(ob, instance); } } } else { throw new IllegalStateException("Unsupported container type ("+value.getClass().getName() +") when resolving reference '"+_referenceName+"'"); } } else { _backProperty.set(value, instance); } } // and then the forward reference itself return delegate.setAndReturn(instance, value); } } MergingSettableBeanProperty.java000066400000000000000000000112621325620701100407670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; /** * {@link SettableBeanProperty} implementation that will try to access value of * the property first, and if non-null value found, pass that for update * (using {@link com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext, Object)}) * instead of constructing a new value. This is necessary to support "merging" properties. *

* Note that there are many similarities to {@link SetterlessProperty}, which predates * this variant; and that one is even used in cases where there is no mutator * available. * * @since 2.9 */ public class MergingSettableBeanProperty extends SettableBeanProperty.Delegating { private static final long serialVersionUID = 1L; /** * Member (field, method) used for accessing existing value. */ protected final AnnotatedMember _accessor; /* /********************************************************** /* Life-cycle /********************************************************** */ protected MergingSettableBeanProperty(SettableBeanProperty delegate, AnnotatedMember accessor) { super(delegate); _accessor = accessor; } protected MergingSettableBeanProperty(MergingSettableBeanProperty src, SettableBeanProperty delegate) { super(delegate); _accessor = src._accessor; } public static MergingSettableBeanProperty construct(SettableBeanProperty delegate, AnnotatedMember accessor) { return new MergingSettableBeanProperty(delegate, accessor); } @Override protected SettableBeanProperty withDelegate(SettableBeanProperty d) { return new MergingSettableBeanProperty(d, _accessor); } /* /********************************************************** /* Deserialization methods /********************************************************** */ @Override public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { Object oldValue = _accessor.getValue(instance); Object newValue; // 20-Oct-2016, tatu: Couple of possibilities of how to proceed; for // now, default to "normal" handling without merging if (oldValue == null) { newValue = delegate.deserialize(p, ctxt); } else { newValue = delegate.deserializeWith(p, ctxt, oldValue); } if (newValue != oldValue) { // 18-Apr-2017, tatu: Null handling should occur within delegate, which may // set/skip/transform it, or throw an exception. delegate.set(instance, newValue); } } @Override public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { Object oldValue = _accessor.getValue(instance); Object newValue; // 20-Oct-2016, tatu: Couple of possibilities of how to proceed; for // now, default to "normal" handling without merging if (oldValue == null) { newValue = delegate.deserialize(p, ctxt); } else { newValue = delegate.deserializeWith(p, ctxt, oldValue); } // 23-Oct-2016, tatu: One possible complication here; should we always // try calling setter on builder? Presumably should not be required, // but may need to revise if (newValue != oldValue) { // 31-Oct-2016, tatu: Basically should just ignore as null can't really // contribute to merging. if (newValue != null) { return delegate.setAndReturn(instance, newValue); } } return instance; } @Override public void set(Object instance, Object value) throws IOException { // 31-Oct-2016, tatu: Basically should just ignore as null can't really // contribute to merging. if (value != null) { delegate.set(instance, value); } } @Override public Object setAndReturn(Object instance, Object value) throws IOException { // 31-Oct-2016, tatu: Basically should just ignore as null can't really // contribute to merging. if (value != null) { return delegate.setAndReturn(instance, value); } return instance; } } MethodProperty.java000066400000000000000000000137771325620701100363620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.Annotations; /** * This concrete sub-class implements property that is set * using regular "setter" method. */ public final class MethodProperty extends SettableBeanProperty { private static final long serialVersionUID = 1; protected final AnnotatedMethod _annotated; /** * Setter method for modifying property value; used for * "regular" method-accessible properties. */ protected final transient Method _setter; /** * @since 2.9 */ final protected boolean _skipNulls; public MethodProperty(BeanPropertyDefinition propDef, JavaType type, TypeDeserializer typeDeser, Annotations contextAnnotations, AnnotatedMethod method) { super(propDef, type, typeDeser, contextAnnotations); _annotated = method; _setter = method.getAnnotated(); _skipNulls = NullsConstantProvider.isSkipper(_nullProvider); } protected MethodProperty(MethodProperty src, JsonDeserializer deser, NullValueProvider nva) { super(src, deser, nva); _annotated = src._annotated; _setter = src._setter; _skipNulls = NullsConstantProvider.isSkipper(nva); } protected MethodProperty(MethodProperty src, PropertyName newName) { super(src, newName); _annotated = src._annotated; _setter = src._setter; _skipNulls = src._skipNulls; } /** * Constructor used for JDK Serialization when reading persisted object */ protected MethodProperty(MethodProperty src, Method m) { super(src); _annotated = src._annotated; _setter = m; _skipNulls = src._skipNulls; } @Override public SettableBeanProperty withName(PropertyName newName) { return new MethodProperty(this, newName); } @Override public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } return new MethodProperty(this, deser, _nullProvider); } @Override public SettableBeanProperty withNullProvider(NullValueProvider nva) { return new MethodProperty(this, _valueDeserializer, nva); } @Override public void fixAccess(DeserializationConfig config) { _annotated.fixAccess( config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } /* /********************************************************** /* BeanProperty impl /********************************************************** */ @Override public A getAnnotation(Class acls) { return (_annotated == null) ? null : _annotated.getAnnotation(acls); } @Override public AnnotatedMember getMember() { return _annotated; } /* /********************************************************** /* Overridden methods /********************************************************** */ @Override public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { Object value; if (p.hasToken(JsonToken.VALUE_NULL)) { if (_skipNulls) { return; } value = _nullProvider.getNullValue(ctxt); } else if (_valueTypeDeserializer == null) { value = _valueDeserializer.deserialize(p, ctxt); } else { value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } try { _setter.invoke(instance, value); } catch (Exception e) { _throwAsIOE(p, e, value); } } @Override public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { Object value; if (p.hasToken(JsonToken.VALUE_NULL)) { if (_skipNulls) { return instance; } value = _nullProvider.getNullValue(ctxt); } else if (_valueTypeDeserializer == null) { value = _valueDeserializer.deserialize(p, ctxt); } else { value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } try { Object result = _setter.invoke(instance, value); return (result == null) ? instance : result; } catch (Exception e) { _throwAsIOE(p, e, value); return null; } } @Override public final void set(Object instance, Object value) throws IOException { try { _setter.invoke(instance, value); } catch (Exception e) { // 15-Sep-2015, tatu: How coud we get a ref to JsonParser? _throwAsIOE(e, value); } } @Override public Object setAndReturn(Object instance, Object value) throws IOException { try { Object result = _setter.invoke(instance, value); return (result == null) ? instance : result; } catch (Exception e) { // 15-Sep-2015, tatu: How coud we get a ref to JsonParser? _throwAsIOE(e, value); return null; } } /* /********************************************************** /* JDK serialization handling /********************************************************** */ Object readResolve() { return new MethodProperty(this, _annotated.getAnnotated()); } } NullsAsEmptyProvider.java000066400000000000000000000017371325620701100375010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.exc.InvalidNullException; import com.fasterxml.jackson.databind.util.AccessPattern; /** * Simple {@link NullValueProvider} that will always throw a * {@link InvalidNullException} when a null is encountered. */ public class NullsAsEmptyProvider implements NullValueProvider, java.io.Serializable { private static final long serialVersionUID = 1L; protected final JsonDeserializer _deserializer; public NullsAsEmptyProvider(JsonDeserializer deser) { _deserializer = deser; } @Override public AccessPattern getNullAccessPattern() { return AccessPattern.DYNAMIC; } @Override public Object getNullValue(DeserializationContext ctxt) throws JsonMappingException { return _deserializer.getEmptyValue(ctxt); } } NullsConstantProvider.java000066400000000000000000000047151325620701100377070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.exc.InvalidNullException; import com.fasterxml.jackson.databind.util.AccessPattern; /** * Simple {@link NullValueProvider} that will always throw a * {@link InvalidNullException} when a null is encountered. */ public class NullsConstantProvider implements NullValueProvider, java.io.Serializable { private static final long serialVersionUID = 1L; private final static NullsConstantProvider SKIPPER = new NullsConstantProvider(null); private final static NullsConstantProvider NULLER = new NullsConstantProvider(null); protected final Object _nullValue; protected final AccessPattern _access; protected NullsConstantProvider(Object nvl) { _nullValue = nvl; _access = (_nullValue == null) ? AccessPattern.ALWAYS_NULL : AccessPattern.CONSTANT; } /** * Static accessor for a stateless instance used as marker, to indicate * that all input `null` values should be skipped (ignored), so that * no corresponding property value is set (with POJOs), and no content * values (array/Collection elements, Map entries) are added. */ public static NullsConstantProvider skipper() { return SKIPPER; } public static NullsConstantProvider nuller() { return NULLER; } public static NullsConstantProvider forValue(Object nvl) { if (nvl == null) { return NULLER; } return new NullsConstantProvider(nvl); } /** * Utility method that can be used to check if given null value provider * is "skipper", marker provider that means that all input `null`s should * be skipped (ignored), instead of converted */ public static boolean isSkipper(NullValueProvider p) { return (p == SKIPPER); } /** * Utility method that can be used to check if given null value provider * is "nuller", no-operation provider that will always simply return * Java `null` for any and all input `null`s. */ public static boolean isNuller(NullValueProvider p) { return (p == NULLER); } @Override public AccessPattern getNullAccessPattern() { return _access; } @Override public Object getNullValue(DeserializationContext ctxt) { return _nullValue; } } NullsFailProvider.java000066400000000000000000000025551325620701100367710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.exc.InvalidNullException; import com.fasterxml.jackson.databind.util.AccessPattern; /** * Simple {@link NullValueProvider} that will always throw a * {@link InvalidNullException} when a null is encountered. */ public class NullsFailProvider implements NullValueProvider, java.io.Serializable { private static final long serialVersionUID = 1L; protected final PropertyName _name; protected final JavaType _type; protected NullsFailProvider(PropertyName name, JavaType type) { _name = name; _type = type; } public static NullsFailProvider constructForProperty(BeanProperty prop) { return new NullsFailProvider(prop.getFullName(), prop.getType()); } public static NullsFailProvider constructForRootValue(JavaType t) { return new NullsFailProvider(null, t); } @Override public AccessPattern getNullAccessPattern() { // Must be called every time to effect the exception... return AccessPattern.DYNAMIC; } @Override public Object getNullValue(DeserializationContext ctxt) throws JsonMappingException { throw InvalidNullException.from(ctxt, _name, _type); } } ObjectIdReader.java000066400000000000000000000075111325620701100361700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdResolver; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; /** * Object that knows how to deserialize Object Ids. */ public class ObjectIdReader implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final JavaType _idType; public final PropertyName propertyName; /** * Blueprint generator instance: actual instance will be * fetched from {@link SerializerProvider} using this as * the key. */ public final ObjectIdGenerator generator; public final ObjectIdResolver resolver; /** * Deserializer used for deserializing id values. */ protected final JsonDeserializer _deserializer; public final SettableBeanProperty idProperty; /* /********************************************************** /* Life-cycle /********************************************************** */ @SuppressWarnings("unchecked") protected ObjectIdReader(JavaType t, PropertyName propName, ObjectIdGenerator gen, JsonDeserializer deser, SettableBeanProperty idProp, ObjectIdResolver resolver) { _idType = t; propertyName = propName; generator = gen; this.resolver = resolver; _deserializer = (JsonDeserializer) deser; idProperty = idProp; } /** * Factory method called by {@link com.fasterxml.jackson.databind.ser.std.BeanSerializerBase} * with the initial information based on standard settings for the type * for which serializer is being built. */ public static ObjectIdReader construct(JavaType idType, PropertyName propName, ObjectIdGenerator generator, JsonDeserializer deser, SettableBeanProperty idProp, ObjectIdResolver resolver) { return new ObjectIdReader(idType, propName, generator, deser, idProp, resolver); } /* /********************************************************** /* API /********************************************************** */ public JsonDeserializer getDeserializer() { return _deserializer; } public JavaType getIdType() { return _idType; } /** * Convenience method, equivalent to calling: * * readerInstance.generator.maySerializeAsObject(); * * and used to determine whether Object Ids handled by the underlying * generator may be in form of (JSON) Objects. * Used for optimizing handling in cases where method returns false. * * @since 2.5 */ public boolean maySerializeAsObject() { return generator.maySerializeAsObject(); } /** * Convenience method, equivalent to calling: * * readerInstance.generator.isValidReferencePropertyName(name, parser); * * and used to determine whether Object Ids handled by the underlying * generator may be in form of (JSON) Objects. * Used for optimizing handling in cases where method returns false. * * @since 2.5 */ public boolean isValidReferencePropertyName(String name, JsonParser parser) { return generator.isValidReferencePropertyName(name, parser); } /** * Method called to read value that is expected to be an Object Reference * (that is, value of an Object Id used to refer to another object). * * @since 2.3 */ public Object readObjectReference(JsonParser jp, DeserializationContext ctxt) throws IOException { return _deserializer.deserialize(jp, ctxt); } } ObjectIdReferenceProperty.java000066400000000000000000000106641325620701100404340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.lang.annotation.Annotation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.UnresolvedForwardReference; import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.ObjectIdInfo; public class ObjectIdReferenceProperty extends SettableBeanProperty { private static final long serialVersionUID = 1L; private final SettableBeanProperty _forward; public ObjectIdReferenceProperty(SettableBeanProperty forward, ObjectIdInfo objectIdInfo) { super(forward); _forward = forward; _objectIdInfo = objectIdInfo; } public ObjectIdReferenceProperty(ObjectIdReferenceProperty src, JsonDeserializer deser, NullValueProvider nva) { super(src, deser, nva); _forward = src._forward; _objectIdInfo = src._objectIdInfo; } public ObjectIdReferenceProperty(ObjectIdReferenceProperty src, PropertyName newName) { super(src, newName); _forward = src._forward; _objectIdInfo = src._objectIdInfo; } @Override public SettableBeanProperty withName(PropertyName newName) { return new ObjectIdReferenceProperty(this, newName); } @Override public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } return new ObjectIdReferenceProperty(this, deser, _nullProvider); } @Override public SettableBeanProperty withNullProvider(NullValueProvider nva) { return new ObjectIdReferenceProperty(this, _valueDeserializer, nva); } @Override public void fixAccess(DeserializationConfig config) { if (_forward != null) { _forward.fixAccess(config); } } @Override public A getAnnotation(Class acls) { return _forward.getAnnotation(acls); } @Override public AnnotatedMember getMember() { return _forward.getMember(); } @Override public int getCreatorIndex() { return _forward.getCreatorIndex(); } @Override public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { deserializeSetAndReturn(p, ctxt, instance); } @Override public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { try { return setAndReturn(instance, deserialize(p, ctxt)); } catch (UnresolvedForwardReference reference) { boolean usingIdentityInfo = (_objectIdInfo != null) || (_valueDeserializer.getObjectIdReader() != null); if (!usingIdentityInfo) { throw JsonMappingException.from(p, "Unresolved forward reference but no identity info", reference); } reference.getRoid().appendReferring(new PropertyReferring(this, reference, _type.getRawClass(), instance)); return null; } } @Override public void set(Object instance, Object value) throws IOException { _forward.set(instance, value); } @Override public Object setAndReturn(Object instance, Object value) throws IOException { return _forward.setAndReturn(instance, value); } public final static class PropertyReferring extends Referring { private final ObjectIdReferenceProperty _parent; public final Object _pojo; public PropertyReferring(ObjectIdReferenceProperty parent, UnresolvedForwardReference ref, Class type, Object ob) { super(ref, type); _parent = parent; _pojo = ob; } @Override public void handleResolvedForwardReference(Object id, Object value) throws IOException { if (!hasId(id)) { throw new IllegalArgumentException("Trying to resolve a forward reference with id [" + id + "] that wasn't previously seen as unresolved."); } _parent.set(_pojo, value); } } } ObjectIdValueProperty.java000066400000000000000000000101321325620701100376000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.lang.annotation.Annotation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; /** * Specialized {@link SettableBeanProperty} implementation used * for virtual property that represents Object Id that is used * for some POJO types (or properties). */ public final class ObjectIdValueProperty extends SettableBeanProperty { private static final long serialVersionUID = 1L; protected final ObjectIdReader _objectIdReader; public ObjectIdValueProperty(ObjectIdReader objectIdReader, PropertyMetadata metadata) { super(objectIdReader.propertyName, objectIdReader.getIdType(), metadata, objectIdReader.getDeserializer()); _objectIdReader = objectIdReader; } protected ObjectIdValueProperty(ObjectIdValueProperty src, JsonDeserializer deser, NullValueProvider nva) { super(src, deser, nva); _objectIdReader = src._objectIdReader; } protected ObjectIdValueProperty(ObjectIdValueProperty src, PropertyName newName) { super(src, newName); _objectIdReader = src._objectIdReader; } @Override public SettableBeanProperty withName(PropertyName newName) { return new ObjectIdValueProperty(this, newName); } @Override public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } return new ObjectIdValueProperty(this, deser, _nullProvider); } @Override public SettableBeanProperty withNullProvider(NullValueProvider nva) { return new ObjectIdValueProperty(this, _valueDeserializer, nva); } // // // BeanProperty impl @Override public A getAnnotation(Class acls) { return null; } @Override public AnnotatedMember getMember() { return null; } /* /********************************************************** /* Deserialization methods /********************************************************** */ @Override public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { deserializeSetAndReturn(p, ctxt, instance); } @Override public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { /* 02-Apr-2015, tatu: Actually, as per [databind#742], let it be; * missing or null id is needed for some cases, such as cases where id * will be generated externally, at a later point, and is not available * quite yet. Typical use case is with DB inserts. */ // note: no null checks (unlike usually); deserializer should fail if one found if (p.hasToken(JsonToken.VALUE_NULL)) { return null; } Object id = _valueDeserializer.deserialize(p, ctxt); ReadableObjectId roid = ctxt.findObjectId(id, _objectIdReader.generator, _objectIdReader.resolver); roid.bindItem(instance); // also: may need to set a property value as well SettableBeanProperty idProp = _objectIdReader.idProperty; if (idProp != null) { return idProp.setAndReturn(instance, id); } return instance; } @Override public void set(Object instance, Object value) throws IOException { setAndReturn(instance, value); } @Override public Object setAndReturn(Object instance, Object value) throws IOException { SettableBeanProperty idProp = _objectIdReader.idProperty; if (idProp == null) { throw new UnsupportedOperationException( "Should not call set() on ObjectIdProperty that has no SettableBeanProperty"); } return idProp.setAndReturn(instance, value); } } PropertyBasedCreator.java000066400000000000000000000206411325620701100374640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; /** * Object that is used to collect arguments for non-default creator * (non-default-constructor, or argument-taking factory method) * before creator can be called. * Since ordering of JSON properties is not guaranteed, this may * require buffering of values other than ones being passed to * creator. */ public final class PropertyBasedCreator { /** * Number of properties: usually same as size of {@link #_propertyLookup}, * but not necessarily, when we have unnamed injectable properties. */ protected final int _propertyCount; /** * Helper object that knows how to actually construct the instance by * invoking creator method with buffered arguments. */ protected final ValueInstantiator _valueInstantiator; /** * Map that contains property objects for either constructor or factory * method (whichever one is null: one property for each * parameter for that one), keyed by logical property name */ protected final HashMap _propertyLookup; /** * Array that contains properties that expect value to inject, if any; * null if no injectable values are expected. */ protected final SettableBeanProperty[] _allProperties; /* /********************************************************** /* Construction, initialization /********************************************************** */ protected PropertyBasedCreator(DeserializationContext ctxt, ValueInstantiator valueInstantiator, SettableBeanProperty[] creatorProps, boolean caseInsensitive, boolean addAliases) { _valueInstantiator = valueInstantiator; if (caseInsensitive) { _propertyLookup = new CaseInsensitiveMap(); } else { _propertyLookup = new HashMap(); } final int len = creatorProps.length; _propertyCount = len; _allProperties = new SettableBeanProperty[len]; // 26-Feb-2017, tatu: Let's start by aliases, so that there is no // possibility of accidental override of primary names if (addAliases) { final DeserializationConfig config = ctxt.getConfig(); for (SettableBeanProperty prop : creatorProps) { // 22-Jan-2018, tatu: ignorable entries should be ignored, even if got aliases if (!prop.isIgnorable()) { List aliases = prop.findAliases(config); if (!aliases.isEmpty()) { for (PropertyName pn : aliases) { _propertyLookup.put(pn.getSimpleName(), prop); } } } } } for (int i = 0; i < len; ++i) { SettableBeanProperty prop = creatorProps[i]; _allProperties[i] = prop; // 22-Jan-2018, tatu: ignorable entries should be skipped if (!prop.isIgnorable()) { _propertyLookup.put(prop.getName(), prop); } } } /** * Factory method used for building actual instances to be used with POJOS: * resolves deserializers, checks for "null values". * * @since 2.9 */ public static PropertyBasedCreator construct(DeserializationContext ctxt, ValueInstantiator valueInstantiator, SettableBeanProperty[] srcCreatorProps, BeanPropertyMap allProperties) throws JsonMappingException { final int len = srcCreatorProps.length; SettableBeanProperty[] creatorProps = new SettableBeanProperty[len]; for (int i = 0; i < len; ++i) { SettableBeanProperty prop = srcCreatorProps[i]; if (!prop.hasValueDeserializer()) { prop = prop.withValueDeserializer(ctxt.findContextualValueDeserializer(prop.getType(), prop)); } creatorProps[i] = prop; } return new PropertyBasedCreator(ctxt, valueInstantiator, creatorProps, allProperties.isCaseInsensitive(), allProperties.hasAliases()); } /** * Factory method used for building actual instances to be used with types * OTHER than POJOs. * resolves deserializers and checks for "null values". * * @since 2.9 */ public static PropertyBasedCreator construct(DeserializationContext ctxt, ValueInstantiator valueInstantiator, SettableBeanProperty[] srcCreatorProps, boolean caseInsensitive) throws JsonMappingException { final int len = srcCreatorProps.length; SettableBeanProperty[] creatorProps = new SettableBeanProperty[len]; for (int i = 0; i < len; ++i) { SettableBeanProperty prop = srcCreatorProps[i]; if (!prop.hasValueDeserializer()) { prop = prop.withValueDeserializer(ctxt.findContextualValueDeserializer(prop.getType(), prop)); } creatorProps[i] = prop; } return new PropertyBasedCreator(ctxt, valueInstantiator, creatorProps, caseInsensitive, false); } @Deprecated // since 2.9 public static PropertyBasedCreator construct(DeserializationContext ctxt, ValueInstantiator valueInstantiator, SettableBeanProperty[] srcCreatorProps) throws JsonMappingException { return construct(ctxt, valueInstantiator, srcCreatorProps, ctxt.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); } /* /********************************************************** /* Accessors /********************************************************** */ public Collection properties() { return _propertyLookup.values(); } public SettableBeanProperty findCreatorProperty(String name) { return _propertyLookup.get(name); } public SettableBeanProperty findCreatorProperty(int propertyIndex) { for (SettableBeanProperty prop : _propertyLookup.values()) { if (prop.getPropertyIndex() == propertyIndex) { return prop; } } return null; } /* /********************************************************** /* Building process /********************************************************** */ /** * Method called when starting to build a bean instance. * * @since 2.1 (added ObjectIdReader parameter -- existed in previous versions without) */ public PropertyValueBuffer startBuilding(JsonParser p, DeserializationContext ctxt, ObjectIdReader oir) { return new PropertyValueBuffer(p, ctxt, _propertyCount, oir); } public Object build(DeserializationContext ctxt, PropertyValueBuffer buffer) throws IOException { Object bean = _valueInstantiator.createFromObjectWith(ctxt, _allProperties, buffer); // returning null isn't quite legal, but let's let caller deal with that if (bean != null) { // Object Id to handle? bean = buffer.handleIdValue(ctxt, bean); // Anything buffered? for (PropertyValue pv = buffer.buffered(); pv != null; pv = pv.next) { pv.assign(bean); } } return bean; } /* /********************************************************** /* Helper classes /********************************************************** */ /** * Simple override of standard {@link java.util.HashMap} to support * case-insensitive access to creator properties * * @since 2.8.5 */ static class CaseInsensitiveMap extends HashMap { private static final long serialVersionUID = 1L; @Override public SettableBeanProperty get(Object key0) { return super.get(((String) key0).toLowerCase()); } @Override public SettableBeanProperty put(String key, SettableBeanProperty value) { key = key.toLowerCase(); return super.put(key, value); } } } PropertyBasedObjectIdGenerator.java000066400000000000000000000021551325620701100414170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdGenerators; // Simple placeholder public class PropertyBasedObjectIdGenerator extends ObjectIdGenerators.PropertyGenerator { private static final long serialVersionUID = 1L; public PropertyBasedObjectIdGenerator(Class scope) { super(scope); } @Override public Object generateId(Object forPojo) { throw new UnsupportedOperationException(); } @Override public ObjectIdGenerator forScope(Class scope) { return (scope == _scope) ? this : new PropertyBasedObjectIdGenerator(scope); } @Override public ObjectIdGenerator newForSerialization(Object context) { return this; } @Override public com.fasterxml.jackson.annotation.ObjectIdGenerator.IdKey key(Object key) { if (key == null) { return null; } // should we use general type for all; or type of property itself? return new IdKey(getClass(), _scope, key); } } PropertyValue.java000066400000000000000000000061061325620701100362020ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.deser.SettableAnyProperty; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; /** * Base class for property values that need to be buffered during * deserialization. */ public abstract class PropertyValue { public final PropertyValue next; /** * Value to assign when POJO has been instantiated. */ public final Object value; protected PropertyValue(PropertyValue next, Object value) { this.next = next; this.value = value; } /** * Method called to assign stored value of this property to specified * bean instance */ public abstract void assign(Object bean) throws IOException, JsonProcessingException; /* /********************************************************** /* Concrete property value classes /********************************************************** */ /** * Property value that used when assigning value to property using * a setter method or direct field access. */ final static class Regular extends PropertyValue { final SettableBeanProperty _property; public Regular(PropertyValue next, Object value, SettableBeanProperty prop) { super(next, value); _property = prop; } @Override public void assign(Object bean) throws IOException, JsonProcessingException { _property.set(bean, value); } } /** * Property value type used when storing entries to be added * to a POJO using "any setter" (method that takes name and * value arguments, allowing setting multiple different * properties using single method). */ final static class Any extends PropertyValue { final SettableAnyProperty _property; final String _propertyName; public Any(PropertyValue next, Object value, SettableAnyProperty prop, String propName) { super(next, value); _property = prop; _propertyName = propName; } @Override public void assign(Object bean) throws IOException, JsonProcessingException { _property.set(bean, _propertyName, value); } } /** * Property value type used when storing entries to be added * to a Map. */ final static class Map extends PropertyValue { final Object _key; public Map(PropertyValue next, Object value, Object key) { super(next, value); _key = key; } @SuppressWarnings("unchecked") @Override public void assign(Object bean) throws IOException, JsonProcessingException { ((java.util.Map) bean).put(_key, value); } } } PropertyValueBuffer.java000066400000000000000000000253251325620701100373400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.util.BitSet; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.deser.SettableAnyProperty; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; /** * Simple container used for temporarily buffering a set of * PropertyValues. * Using during construction of beans (and Maps) that use Creators, * and hence need buffering before instance (that will have properties * to assign values to) is constructed. */ public class PropertyValueBuffer { /* /********************************************************** /* Configuration /********************************************************** */ protected final JsonParser _parser; protected final DeserializationContext _context; protected final ObjectIdReader _objectIdReader; /* /********************************************************** /* Accumulated properties, other stuff /********************************************************** */ /** * Buffer used for storing creator parameters for constructing * instance. */ protected final Object[] _creatorParameters; /** * Number of creator parameters for which we have not yet received * values. */ protected int _paramsNeeded; /** * Bitflag used to track parameters found from incoming data * when number of parameters is * less than 32 (fits in int). */ protected int _paramsSeen; /** * Bitflag used to track parameters found from incoming data * when number of parameters is * 32 or higher. */ protected final BitSet _paramsSeenBig; /** * If we get non-creator parameters before or between * creator parameters, those need to be buffered. Buffer * is just a simple linked list */ protected PropertyValue _buffered; /** * In case there is an Object Id property to handle, this is the value * we have for it. */ protected Object _idValue; /* /********************************************************** /* Life-cycle /********************************************************** */ public PropertyValueBuffer(JsonParser p, DeserializationContext ctxt, int paramCount, ObjectIdReader oir) { _parser = p; _context = ctxt; _paramsNeeded = paramCount; _objectIdReader = oir; _creatorParameters = new Object[paramCount]; if (paramCount < 32) { _paramsSeenBig = null; } else { _paramsSeenBig = new BitSet(); } } /** * Returns {@code true} if the given property was seen in the JSON source by * this buffer. * * @since 2.8 */ public final boolean hasParameter(SettableBeanProperty prop) { if (_paramsSeenBig == null) { return ((_paramsSeen >> prop.getCreatorIndex()) & 1) == 1; } return _paramsSeenBig.get(prop.getCreatorIndex()); } /** * A variation of {@link #getParameters(SettableBeanProperty[])} that * accepts a single property. Whereas the plural form eagerly fetches and * validates all properties, this method may be used (along with * {@link #hasParameter(SettableBeanProperty)}) to let applications only * fetch the properties defined in the JSON source itself, and to have some * other customized behavior for missing properties. * * @since 2.8 */ public Object getParameter(SettableBeanProperty prop) throws JsonMappingException { Object value; if (hasParameter(prop)) { value = _creatorParameters[prop.getCreatorIndex()]; } else { value = _creatorParameters[prop.getCreatorIndex()] = _findMissing(prop); } if (value == null && _context.isEnabled(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES)) { return _context.reportInputMismatch(prop, "Null value for creator property '%s' (index %d); `DeserializationFeature.FAIL_ON_NULL_FOR_CREATOR_PARAMETERS` enabled", prop.getName(), prop.getCreatorIndex()); } return value; } /** * Method called to do necessary post-processing such as injection of values * and verification of values for required properties, * after either {@link #assignParameter(SettableBeanProperty, Object)} * returns true (to indicate all creator properties are found), or when * then whole JSON Object has been processed, */ public Object[] getParameters(SettableBeanProperty[] props) throws JsonMappingException { // quick check to see if anything else is needed if (_paramsNeeded > 0) { if (_paramsSeenBig == null) { int mask = _paramsSeen; // not optimal, could use `Integer.trailingZeroes()`, but for now should not // really matter for common cases for (int ix = 0, len = _creatorParameters.length; ix < len; ++ix, mask >>= 1) { if ((mask & 1) == 0) { _creatorParameters[ix] = _findMissing(props[ix]); } } } else { final int len = _creatorParameters.length; for (int ix = 0; (ix = _paramsSeenBig.nextClearBit(ix)) < len; ++ix) { _creatorParameters[ix] = _findMissing(props[ix]); } } } if (_context.isEnabled(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES)) { for (int ix = 0; ix < props.length; ++ix) { if (_creatorParameters[ix] == null) { SettableBeanProperty prop = props[ix]; _context.reportInputMismatch(prop.getType(), "Null value for creator property '%s' (index %d); `DeserializationFeature.FAIL_ON_NULL_FOR_CREATOR_PARAMETERS` enabled", prop.getName(), props[ix].getCreatorIndex()); } } } return _creatorParameters; } protected Object _findMissing(SettableBeanProperty prop) throws JsonMappingException { // First: do we have injectable value? Object injectableValueId = prop.getInjectableValueId(); if (injectableValueId != null) { return _context.findInjectableValue(prop.getInjectableValueId(), prop, null); } // Second: required? if (prop.isRequired()) { _context.reportInputMismatch(prop, "Missing required creator property '%s' (index %d)", prop.getName(), prop.getCreatorIndex()); } if (_context.isEnabled(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES)) { _context.reportInputMismatch(prop, "Missing creator property '%s' (index %d); `DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES` enabled", prop.getName(), prop.getCreatorIndex()); } // Third: default value JsonDeserializer deser = prop.getValueDeserializer(); return deser.getNullValue(_context); } /* /********************************************************** /* Other methods /********************************************************** */ /** * Helper method called to see if given non-creator property is the "id property"; * and if so, handle appropriately. * * @since 2.1 */ public boolean readIdProperty(String propName) throws IOException { if ((_objectIdReader != null) && propName.equals(_objectIdReader.propertyName.getSimpleName())) { _idValue = _objectIdReader.readObjectReference(_parser, _context); return true; } return false; } /** * Helper method called to handle Object Id value collected earlier, if any */ public Object handleIdValue(final DeserializationContext ctxt, Object bean) throws IOException { if (_objectIdReader != null) { if (_idValue != null) { ReadableObjectId roid = ctxt.findObjectId(_idValue, _objectIdReader.generator, _objectIdReader.resolver); roid.bindItem(bean); // also: may need to set a property value as well SettableBeanProperty idProp = _objectIdReader.idProperty; if (idProp != null) { return idProp.setAndReturn(bean, _idValue); } } else { // 07-Jun-2016, tatu: Trying to improve error messaging here... ctxt.reportUnresolvedObjectId(_objectIdReader, bean); } } return bean; } protected PropertyValue buffered() { return _buffered; } public boolean isComplete() { return _paramsNeeded <= 0; } /** * Method called to buffer value for given property, as well as check whether * we now have values for all (creator) properties that we expect to get values for. * * @return True if we have received all creator parameters * * @since 2.6 */ public boolean assignParameter(SettableBeanProperty prop, Object value) { final int ix = prop.getCreatorIndex(); _creatorParameters[ix] = value; if (_paramsSeenBig == null) { int old = _paramsSeen; int newValue = (old | (1 << ix)); if (old != newValue) { _paramsSeen = newValue; if (--_paramsNeeded <= 0) { // 29-Nov-2016, tatu: But! May still require Object Id value return (_objectIdReader == null) || (_idValue != null); } } } else { if (!_paramsSeenBig.get(ix)) { _paramsSeenBig.set(ix); if (--_paramsNeeded <= 0) { // 29-Nov-2016, tatu: But! May still require Object Id value } } } return false; } public void bufferProperty(SettableBeanProperty prop, Object value) { _buffered = new PropertyValue.Regular(_buffered, value, prop); } public void bufferAnyProperty(SettableAnyProperty prop, String propName, Object value) { _buffered = new PropertyValue.Any(_buffered, value, prop, propName); } public void bufferMapProperty(Object key, Object value) { _buffered = new PropertyValue.Map(_buffered, value, key); } } ReadableObjectId.java000066400000000000000000000112221325620701100364570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdResolver; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.deser.UnresolvedForwardReference; /** * Simple value container for containing information about single Object Id * during deserialization */ public class ReadableObjectId { /** * @since 2.8 (with this name, formerly `public Object item`) */ protected Object _item; protected final ObjectIdGenerator.IdKey _key; protected LinkedList _referringProperties; protected ObjectIdResolver _resolver; public ReadableObjectId(ObjectIdGenerator.IdKey key) { _key = key; } public void setResolver(ObjectIdResolver resolver) { _resolver = resolver; } public ObjectIdGenerator.IdKey getKey() { return _key; } public void appendReferring(Referring currentReferring) { if (_referringProperties == null) { _referringProperties = new LinkedList(); } _referringProperties.add(currentReferring); } /** * Method called to assign actual POJO to which ObjectId refers to: will * also handle referring properties, if any, by assigning POJO. */ public void bindItem(Object ob) throws IOException { _resolver.bindItem(_key, ob); _item = ob; Object id = _key.key; if (_referringProperties != null) { Iterator it = _referringProperties.iterator(); _referringProperties = null; while (it.hasNext()) { it.next().handleResolvedForwardReference(id, ob); } } } public Object resolve(){ return (_item = _resolver.resolveId(_key)); } public boolean hasReferringProperties() { return (_referringProperties != null) && !_referringProperties.isEmpty(); } public Iterator referringProperties() { if (_referringProperties == null) { return Collections. emptyList().iterator(); } return _referringProperties.iterator(); } /** * Method called by {@link DeserializationContext} at the end of deserialization * if this Object Id was not resolved during normal processing. Call is made to * allow custom implementations to use alternative resolution strategies; currently * the only way to make use of this functionality is by sub-classing * {@link ReadableObjectId} and overriding this method. *

* Default implementation simply returns false to indicate that resolution * attempt did not succeed. * * @return True, if resolution succeeded (and no error needs to be reported); false to * indicate resolution did not succeed. * * @since 2.6 */ public boolean tryToResolveUnresolved(DeserializationContext ctxt) { return false; } /** * Allow access to the resolver in case anybody wants to use it directly, for * examples from * {@link com.fasterxml.jackson.databind.deser.DefaultDeserializationContext#tryToResolveUnresolvedObjectId}. * * @return The registered resolver * * @since 2.7 */ public ObjectIdResolver getResolver() { return _resolver; } @Override public String toString() { return String.valueOf(_key); } /* /********************************************************** /* Helper classes /********************************************************** */ public static abstract class Referring { private final UnresolvedForwardReference _reference; private final Class _beanType; public Referring(UnresolvedForwardReference ref, Class beanType) { _reference = ref; _beanType = beanType; } public Referring(UnresolvedForwardReference ref, JavaType beanType) { _reference = ref; _beanType = beanType.getRawClass(); } public JsonLocation getLocation() { return _reference.getLocation(); } public Class getBeanType() { return _beanType; } public abstract void handleResolvedForwardReference(Object id, Object value) throws IOException; public boolean hasId(Object id) { return id.equals(_reference.getUnresolvedId()); } } } SetterlessProperty.java000066400000000000000000000126631325620701100372700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.Annotations; /** * This concrete sub-class implements Collection or Map property that is * indirectly by getting the property value and directly modifying it. */ public final class SetterlessProperty extends SettableBeanProperty { private static final long serialVersionUID = 1L; protected final AnnotatedMethod _annotated; /** * Get method for accessing property value used to access property * (of Collection or Map type) to modify. */ protected final Method _getter; public SetterlessProperty(BeanPropertyDefinition propDef, JavaType type, TypeDeserializer typeDeser, Annotations contextAnnotations, AnnotatedMethod method) { super(propDef, type, typeDeser, contextAnnotations); _annotated = method; _getter = method.getAnnotated(); } protected SetterlessProperty(SetterlessProperty src, JsonDeserializer deser, NullValueProvider nva) { super(src, deser, nva); _annotated = src._annotated; _getter = src._getter; } protected SetterlessProperty(SetterlessProperty src, PropertyName newName) { super(src, newName); _annotated = src._annotated; _getter = src._getter; } @Override public SettableBeanProperty withName(PropertyName newName) { return new SetterlessProperty(this, newName); } @Override public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } return new SetterlessProperty(this, deser, _nullProvider); } @Override public SettableBeanProperty withNullProvider(NullValueProvider nva) { return new SetterlessProperty(this, _valueDeserializer, nva); } @Override public void fixAccess(DeserializationConfig config) { _annotated.fixAccess( config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } /* /********************************************************** /* BeanProperty impl /********************************************************** */ @Override public A getAnnotation(Class acls) { return _annotated.getAnnotation(acls); } @Override public AnnotatedMember getMember() { return _annotated; } /* /********************************************************** /* Overridden methods /********************************************************** */ @Override public final void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_NULL) { // Hmmh. Is this a problem? We won't be setting anything, so it's // equivalent of empty Collection/Map in this case return; } // For [databind#501] fix we need to implement this but: if (_valueTypeDeserializer != null) { ctxt.reportBadDefinition(getType(), String.format( "Problem deserializing 'setterless' property (\"%s\"): no way to handle typed deser with setterless yet", getName())); // return _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } // Ok: then, need to fetch Collection/Map to modify: Object toModify; try { toModify = _getter.invoke(instance, (Object[]) null); } catch (Exception e) { _throwAsIOE(p, e); return; // never gets here } // Note: null won't work, since we can't then inject anything in. At least // that's not good in common case. However, theoretically the case where // we get JSON null might be compatible. If so, implementation could be changed. if (toModify == null) { ctxt.reportBadDefinition(getType(), String.format( "Problem deserializing 'setterless' property '%s': get method returned null", getName())); } _valueDeserializer.deserialize(p, ctxt, toModify); } @Override public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException { deserializeAndSet(p, ctxt, instance); return instance; } @Override public final void set(Object instance, Object value) throws IOException { throw new UnsupportedOperationException("Should never call `set()` on setterless property ('"+getName()+"')"); } @Override public Object setAndReturn(Object instance, Object value) throws IOException { set(instance, value); return instance; } }TypeWrappedDeserializer.java000066400000000000000000000055361325620701100401760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.util.Collection; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; /** * Simple deserializer that will call configured type deserializer, passing * in configured data deserializer, and exposing it all as a simple * deserializer. * This is necessary when there is no "parent" deserializer which could handle * details of calling a {@link TypeDeserializer}, most commonly used with * root values. */ public final class TypeWrappedDeserializer extends JsonDeserializer implements java.io.Serializable // since 2.5 { private static final long serialVersionUID = 1L; final protected TypeDeserializer _typeDeserializer; final protected JsonDeserializer _deserializer; @SuppressWarnings("unchecked") public TypeWrappedDeserializer(TypeDeserializer typeDeser, JsonDeserializer deser) { super(); _typeDeserializer = typeDeser; _deserializer = (JsonDeserializer) deser; } @Override public Class handledType() { return _deserializer.handledType(); } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return _deserializer.supportsUpdate(config); } @Override public JsonDeserializer getDelegatee() { return _deserializer.getDelegatee(); } @Override public Collection getKnownPropertyNames() { return _deserializer.getKnownPropertyNames(); } @Override public Object getNullValue(DeserializationContext ctxt) throws JsonMappingException { return _deserializer.getNullValue(ctxt); } @Override public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { return _deserializer.getEmptyValue(ctxt); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return _deserializer.deserializeWithType(p, ctxt, _typeDeserializer); } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // should never happen? (if it can, could call on that object) throw new IllegalStateException("Type-wrapped deserializer's deserializeWithType should never get called"); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt, Object intoValue) throws IOException { /* 01-Mar-2013, tatu: Hmmh. Tough call as to what to do... need * to delegate, but will this work reliably? Let's just hope so: */ return _deserializer.deserialize(p, ctxt, intoValue); } } UnwrappedPropertyHandler.java000066400000000000000000000046261325620701100403760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.util.NameTransformer; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Object that is responsible for handling acrobatics related to * deserializing "unwrapped" values; sets of properties that are * embedded (inlined) as properties of parent JSON object. */ public class UnwrappedPropertyHandler { protected final List _properties; public UnwrappedPropertyHandler() { _properties = new ArrayList(); } protected UnwrappedPropertyHandler(List props) { _properties = props; } public void addProperty(SettableBeanProperty property) { _properties.add(property); } public UnwrappedPropertyHandler renameAll(NameTransformer transformer) { ArrayList newProps = new ArrayList(_properties.size()); for (SettableBeanProperty prop : _properties) { String newName = transformer.transform(prop.getName()); prop = prop.withSimpleName(newName); JsonDeserializer deser = prop.getValueDeserializer(); if (deser != null) { @SuppressWarnings("unchecked") JsonDeserializer newDeser = (JsonDeserializer) deser.unwrappingDeserializer(transformer); if (newDeser != deser) { prop = prop.withValueDeserializer(newDeser); } } newProps.add(prop); } return new UnwrappedPropertyHandler(newProps); } @SuppressWarnings("resource") public Object processUnwrapped(JsonParser originalParser, DeserializationContext ctxt, Object bean, TokenBuffer buffered) throws IOException { for (int i = 0, len = _properties.size(); i < len; ++i) { SettableBeanProperty prop = _properties.get(i); JsonParser p = buffered.asParser(); p.nextToken(); prop.deserializeAndSet(p, ctxt, bean); } return bean; } } ValueInjector.java000066400000000000000000000032171325620701100361330ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/implpackage com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; /** * Class that encapsulates details of value injection that occurs before * deserialization of a POJO. Details include information needed to find * injectable value (logical id) as well as method used for assigning * value (setter or field) */ public class ValueInjector extends BeanProperty.Std { private static final long serialVersionUID = 1L; /** * Identifier used for looking up value to inject */ protected final Object _valueId; public ValueInjector(PropertyName propName, JavaType type, AnnotatedMember mutator, Object valueId) { super(propName, type, null, mutator, PropertyMetadata.STD_OPTIONAL); _valueId = valueId; } /** * @deprecated in 2.9 (remove from 3.0) */ @Deprecated // see [databind#1835] public ValueInjector(PropertyName propName, JavaType type, com.fasterxml.jackson.databind.util.Annotations contextAnnotations, // removed from later versions AnnotatedMember mutator, Object valueId) { this(propName, type, mutator, valueId); } public Object findValue(DeserializationContext context, Object beanInstance) throws JsonMappingException { return context.findInjectableValue(_valueId, this, beanInstance); } public void inject(DeserializationContext context, Object beanInstance) throws IOException { _member.setValue(beanInstance, findValue(context, beanInstance)); } }package-info.java000066400000000000000000000007011325620701100357000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/impl/** * Contains those implementation classes of deserialization part of * data binding that are not considered part of public or semi-public * interfaces. Use of these classes by non-core classes is discouraged, * although occasionally this may be necessary. * Note that backwards-compatibility of these classes is not guaranteed * between minor releases (but is between patch releases). */ package com.fasterxml.jackson.databind.deser.impl; package-info.java000066400000000000000000000002061325620701100347370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/** * Contains implementation classes of deserialization part of * data binding. */ package com.fasterxml.jackson.databind.deser; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/std/000077500000000000000000000000001325620701100324235ustar00rootroot00000000000000ArrayBlockingQueueDeserializer.java000066400000000000000000000076621325620701100413210ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.*; import java.util.concurrent.ArrayBlockingQueue; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; /** * We need a custom deserializer both because {@link ArrayBlockingQueue} has no * default constructor AND because it has size limit used for constructing * underlying storage automatically. */ public class ArrayBlockingQueueDeserializer extends CollectionDeserializer { private static final long serialVersionUID = 1; /* /********************************************************** /* Life-cycle /********************************************************** */ public ArrayBlockingQueueDeserializer(JavaType containerType, JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser, ValueInstantiator valueInstantiator) { super(containerType, valueDeser, valueTypeDeser, valueInstantiator); } /** * Constructor used when creating contextualized instances. */ protected ArrayBlockingQueueDeserializer(JavaType containerType, JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser, ValueInstantiator valueInstantiator, JsonDeserializer delegateDeser, NullValueProvider nuller, Boolean unwrapSingle) { super(containerType, valueDeser, valueTypeDeser, valueInstantiator, delegateDeser, nuller, unwrapSingle); } /** * Copy-constructor that can be used by sub-classes to allow * copy-on-write styling copying of settings of an existing instance. */ protected ArrayBlockingQueueDeserializer(ArrayBlockingQueueDeserializer src) { super(src); } /** * Fluent-factory method call to construct contextual instance. */ @Override @SuppressWarnings("unchecked") protected ArrayBlockingQueueDeserializer withResolved(JsonDeserializer dd, JsonDeserializer vd, TypeDeserializer vtd, NullValueProvider nuller, Boolean unwrapSingle) { return new ArrayBlockingQueueDeserializer(_containerType, (JsonDeserializer) vd, vtd, _valueInstantiator, (JsonDeserializer) dd, nuller, unwrapSingle); } /* /********************************************************** /* JsonDeserializer API /********************************************************** */ @Override protected Collection createDefaultInstance(DeserializationContext ctxt) throws IOException { // 07-Nov-2016, tatu: Important: cannot create using default ctor (one // does not exist); and also need to know exact size. Hence, return // null from here return null; } @Override public Collection deserialize(JsonParser p, DeserializationContext ctxt, Collection result0) throws IOException { if (result0 != null) { return super.deserialize(p, ctxt, result0); } // Ok: must point to START_ARRAY (or equivalent) if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt, new ArrayBlockingQueue(1)); } result0 = super.deserialize(p, ctxt, new ArrayList()); return new ArrayBlockingQueue(result0.size(), false, result0); } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // In future could check current token... for now this should be enough: return typeDeserializer.deserializeTypedFromArray(p, ctxt); } } AtomicBooleanDeserializer.java000066400000000000000000000012021325620701100402610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; public class AtomicBooleanDeserializer extends StdScalarDeserializer { private static final long serialVersionUID = 1L; public AtomicBooleanDeserializer() { super(AtomicBoolean.class); } @Override public AtomicBoolean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { return new AtomicBoolean(_parseBooleanPrimitive(jp, ctxt)); } }AtomicReferenceDeserializer.java000066400000000000000000000042671325620701100406160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; public class AtomicReferenceDeserializer extends ReferenceTypeDeserializer> { private static final long serialVersionUID = 1L; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @since 2.9 */ public AtomicReferenceDeserializer(JavaType fullType, ValueInstantiator inst, TypeDeserializer typeDeser, JsonDeserializer deser) { super(fullType, inst, typeDeser, deser); } /* /********************************************************** /* Abstract method implementations /********************************************************** */ @Override public AtomicReferenceDeserializer withResolved(TypeDeserializer typeDeser, JsonDeserializer valueDeser) { return new AtomicReferenceDeserializer(_fullType, _valueInstantiator, typeDeser, valueDeser); } @Override public AtomicReference getNullValue(DeserializationContext ctxt) { return new AtomicReference(); } @Override public Object getEmptyValue(DeserializationContext ctxt) { return new AtomicReference(); } @Override public AtomicReference referenceValue(Object contents) { return new AtomicReference(contents); } @Override public Object getReferenced(AtomicReference reference) { return reference.get(); } @Override // since 2.9 public AtomicReference updateReference(AtomicReference reference, Object contents) { reference.set(contents); return reference; } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { // yes; regardless of value deserializer reference itself may be updated return Boolean.TRUE; } } ByteBufferDeserializer.java000066400000000000000000000020101325620701100376000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.*; import java.nio.ByteBuffer; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.util.ByteBufferBackedOutputStream; public class ByteBufferDeserializer extends StdScalarDeserializer { private static final long serialVersionUID = 1L; protected ByteBufferDeserializer() { super(ByteBuffer.class); } @Override public ByteBuffer deserialize(JsonParser parser, DeserializationContext cx) throws IOException { byte[] b = parser.getBinaryValue(); return ByteBuffer.wrap(b); } @Override public ByteBuffer deserialize(JsonParser jp, DeserializationContext ctxt, ByteBuffer intoValue) throws IOException { // Let's actually read in streaming manner... OutputStream out = new ByteBufferBackedOutputStream(intoValue); jp.readBinaryValue(ctxt.getBase64Variant(), out); out.close(); return intoValue; } } CollectionDeserializer.java000066400000000000000000000456431325620701100376610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring; import com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Basic serializer that can take JSON "Array" structure and * construct a {@link java.util.Collection} instance, with typed contents. *

* Note: for untyped content (one indicated by passing Object.class * as the type), {@link UntypedObjectDeserializer} is used instead. * It can also construct {@link java.util.List}s, but not with specific * POJO types, only other containers and primitives/wrappers. */ @JacksonStdImpl public class CollectionDeserializer extends ContainerDeserializerBase> implements ContextualDeserializer { private static final long serialVersionUID = -1L; // since 2.5 // // Configuration /** * Value deserializer. */ protected final JsonDeserializer _valueDeserializer; /** * If element instances have polymorphic type information, this * is the type deserializer that can handle it */ protected final TypeDeserializer _valueTypeDeserializer; // // Instance construction settings: protected final ValueInstantiator _valueInstantiator; /** * Deserializer that is used iff delegate-based creator is * to be used for deserializing from JSON Object. */ protected final JsonDeserializer _delegateDeserializer; // NOTE: no PropertyBasedCreator, as JSON Arrays have no properties /* /********************************************************** /* Life-cycle /********************************************************** */ /** * Constructor for context-free instances, where we do not yet know * which property is using this deserializer. */ public CollectionDeserializer(JavaType collectionType, JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser, ValueInstantiator valueInstantiator) { this(collectionType, valueDeser, valueTypeDeser, valueInstantiator, null, null, null); } /** * Constructor used when creating contextualized instances. * * @since 2.9 */ protected CollectionDeserializer(JavaType collectionType, JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser, ValueInstantiator valueInstantiator, JsonDeserializer delegateDeser, NullValueProvider nuller, Boolean unwrapSingle) { super(collectionType, nuller, unwrapSingle); _valueDeserializer = valueDeser; _valueTypeDeserializer = valueTypeDeser; _valueInstantiator = valueInstantiator; _delegateDeserializer = delegateDeser; } /** * Copy-constructor that can be used by sub-classes to allow * copy-on-write styling copying of settings of an existing instance. */ protected CollectionDeserializer(CollectionDeserializer src) { super(src); _valueDeserializer = src._valueDeserializer; _valueTypeDeserializer = src._valueTypeDeserializer; _valueInstantiator = src._valueInstantiator; _delegateDeserializer = src._delegateDeserializer; } /** * Fluent-factory method call to construct contextual instance. * * @since 2.9 */ @SuppressWarnings("unchecked") protected CollectionDeserializer withResolved(JsonDeserializer dd, JsonDeserializer vd, TypeDeserializer vtd, NullValueProvider nuller, Boolean unwrapSingle) { //if (true) throw new Error(); return new CollectionDeserializer(_containerType, (JsonDeserializer) vd, vtd, _valueInstantiator, (JsonDeserializer) dd, nuller, unwrapSingle); } // Important: do NOT cache if polymorphic values @Override // since 2.5 public boolean isCachable() { // 26-Mar-2015, tatu: As per [databind#735], need to be careful return (_valueDeserializer == null) && (_valueTypeDeserializer == null) && (_delegateDeserializer == null) ; } /* /********************************************************** /* Validation, post-processing (ResolvableDeserializer) /********************************************************** */ /** * Method called to finalize setup of this deserializer, * when it is known for which property deserializer is needed * for. */ @Override public CollectionDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { // May need to resolve types for delegate-based creators: JsonDeserializer delegateDeser = null; if (_valueInstantiator != null) { if (_valueInstantiator.canCreateUsingDelegate()) { JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig()); if (delegateType == null) { ctxt.reportBadDefinition(_containerType, String.format( "Invalid delegate-creator definition for %s: value instantiator (%s) returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'", _containerType, _valueInstantiator.getClass().getName())); } delegateDeser = findDeserializer(ctxt, delegateType, property); } else if (_valueInstantiator.canCreateUsingArrayDelegate()) { JavaType delegateType = _valueInstantiator.getArrayDelegateType(ctxt.getConfig()); if (delegateType == null) { ctxt.reportBadDefinition(_containerType, String.format( "Invalid delegate-creator definition for %s: value instantiator (%s) returned true for 'canCreateUsingArrayDelegate()', but null for 'getArrayDelegateType()'", _containerType, _valueInstantiator.getClass().getName())); } delegateDeser = findDeserializer(ctxt, delegateType, property); } } // [databind#1043]: allow per-property allow-wrapping of single overrides: // 11-Dec-2015, tatu: Should we pass basic `Collection.class`, or more refined? Mostly // comes down to "List vs Collection" I suppose... for now, pass Collection Boolean unwrapSingle = findFormatFeature(ctxt, property, Collection.class, JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); // also, often value deserializer is resolved here: JsonDeserializer valueDeser = _valueDeserializer; // May have a content converter valueDeser = findConvertingContentDeserializer(ctxt, property, valueDeser); final JavaType vt = _containerType.getContentType(); if (valueDeser == null) { valueDeser = ctxt.findContextualValueDeserializer(vt, property); } else { // if directly assigned, probably not yet contextual, so: valueDeser = ctxt.handleSecondaryContextualization(valueDeser, property, vt); } // and finally, type deserializer needs context as well TypeDeserializer valueTypeDeser = _valueTypeDeserializer; if (valueTypeDeser != null) { valueTypeDeser = valueTypeDeser.forProperty(property); } NullValueProvider nuller = findContentNullProvider(ctxt, property, valueDeser); if ( (unwrapSingle != _unwrapSingle) || (nuller != _nullProvider) || (delegateDeser != _delegateDeserializer) || (valueDeser != _valueDeserializer) || (valueTypeDeser != _valueTypeDeserializer) ) { return withResolved(delegateDeser, valueDeser, valueTypeDeser, nuller, unwrapSingle); } return this; } /* /********************************************************** /* ContainerDeserializerBase API /********************************************************** */ @Override public JsonDeserializer getContentDeserializer() { return _valueDeserializer; } @Override public ValueInstantiator getValueInstantiator() { return _valueInstantiator; } /* /********************************************************** /* JsonDeserializer API /********************************************************** */ @SuppressWarnings("unchecked") @Override public Collection deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (_delegateDeserializer != null) { return (Collection) _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt)); } // Empty String may be ok; bit tricky to check, however, since // there is also possibility of "auto-wrapping" of single-element arrays. // Hence we only accept empty String here. if (p.hasToken(JsonToken.VALUE_STRING)) { String str = p.getText(); if (str.length() == 0) { return (Collection) _valueInstantiator.createFromString(ctxt, str); } } return deserialize(p, ctxt, createDefaultInstance(ctxt)); } /** * @since 2.9 */ @SuppressWarnings("unchecked") protected Collection createDefaultInstance(DeserializationContext ctxt) throws IOException { return (Collection) _valueInstantiator.createUsingDefault(ctxt); } @Override public Collection deserialize(JsonParser p, DeserializationContext ctxt, Collection result) throws IOException { // Ok: must point to START_ARRAY (or equivalent) if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt, result); } // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(result); JsonDeserializer valueDes = _valueDeserializer; // Let's offline handling of values with Object Ids (simplifies code here) if (valueDes.getObjectIdReader() != null) { return _deserializeWithObjectId(p, ctxt, result); } final TypeDeserializer typeDeser = _valueTypeDeserializer; JsonToken t; while ((t = p.nextToken()) != JsonToken.END_ARRAY) { try { Object value; if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = _nullProvider.getNullValue(ctxt); } else if (typeDeser == null) { value = valueDes.deserialize(p, ctxt); } else { value = valueDes.deserializeWithType(p, ctxt, typeDeser); } result.add(value); /* 17-Dec-2017, tatu: should not occur at this level... } catch (UnresolvedForwardReference reference) { throw JsonMappingException .from(p, "Unresolved forward reference but no identity info", reference); */ } catch (Exception e) { boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS); if (!wrap) { ClassUtil.throwIfRTE(e); } throw JsonMappingException.wrapWithPath(e, result, result.size()); } } return result; } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // In future could check current token... for now this should be enough: return typeDeserializer.deserializeTypedFromArray(p, ctxt); } /** * Helper method called when current token is no START_ARRAY. Will either * throw an exception, or try to handle value as if member of implicit * array, depending on configuration. */ @SuppressWarnings("unchecked") protected final Collection handleNonArray(JsonParser p, DeserializationContext ctxt, Collection result) throws IOException { // Implicit arrays from single values? boolean canWrap = (_unwrapSingle == Boolean.TRUE) || ((_unwrapSingle == null) && ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); if (!canWrap) { return (Collection) ctxt.handleUnexpectedToken(_containerType.getRawClass(), p); } JsonDeserializer valueDes = _valueDeserializer; final TypeDeserializer typeDeser = _valueTypeDeserializer; JsonToken t = p.getCurrentToken(); Object value; try { if (t == JsonToken.VALUE_NULL) { // 03-Feb-2017, tatu: Hmmh. I wonder... let's try skipping here, too if (_skipNullValues) { return result; } value = _nullProvider.getNullValue(ctxt); } else if (typeDeser == null) { value = valueDes.deserialize(p, ctxt); } else { value = valueDes.deserializeWithType(p, ctxt, typeDeser); } } catch (Exception e) { // note: pass Object.class, not Object[].class, as we need element type for error info throw JsonMappingException.wrapWithPath(e, Object.class, result.size()); } result.add(value); return result; } protected Collection _deserializeWithObjectId(JsonParser p, DeserializationContext ctxt, Collection result) throws IOException { // Ok: must point to START_ARRAY (or equivalent) if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt, result); } // [databind#631]: Assign current value, to be accessible by custom serializers p.setCurrentValue(result); final JsonDeserializer valueDes = _valueDeserializer; final TypeDeserializer typeDeser = _valueTypeDeserializer; CollectionReferringAccumulator referringAccumulator = new CollectionReferringAccumulator(_containerType.getContentType().getRawClass(), result); JsonToken t; while ((t = p.nextToken()) != JsonToken.END_ARRAY) { try { Object value; if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = _nullProvider.getNullValue(ctxt); } else if (typeDeser == null) { value = valueDes.deserialize(p, ctxt); } else { value = valueDes.deserializeWithType(p, ctxt, typeDeser); } referringAccumulator.add(value); } catch (UnresolvedForwardReference reference) { Referring ref = referringAccumulator.handleUnresolvedReference(reference); reference.getRoid().appendReferring(ref); } catch (Exception e) { boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS); if (!wrap) { ClassUtil.throwIfRTE(e); } throw JsonMappingException.wrapWithPath(e, result, result.size()); } } return result; } /** * Helper class for dealing with Object Id references for values contained in * collections being deserialized. */ public static class CollectionReferringAccumulator { private final Class _elementType; private final Collection _result; /** * A list of {@link CollectionReferring} to maintain ordering. */ private List _accumulator = new ArrayList(); public CollectionReferringAccumulator(Class elementType, Collection result) { _elementType = elementType; _result = result; } public void add(Object value) { if (_accumulator.isEmpty()) { _result.add(value); } else { CollectionReferring ref = _accumulator.get(_accumulator.size() - 1); ref.next.add(value); } } public Referring handleUnresolvedReference(UnresolvedForwardReference reference) { CollectionReferring id = new CollectionReferring(this, reference, _elementType); _accumulator.add(id); return id; } public void resolveForwardReference(Object id, Object value) throws IOException { Iterator iterator = _accumulator.iterator(); // Resolve ordering after resolution of an id. This mean either: // 1- adding to the result collection in case of the first unresolved id. // 2- merge the content of the resolved id with its previous unresolved id. Collection previous = _result; while (iterator.hasNext()) { CollectionReferring ref = iterator.next(); if (ref.hasId(id)) { iterator.remove(); previous.add(value); previous.addAll(ref.next); return; } previous = ref.next; } throw new IllegalArgumentException("Trying to resolve a forward reference with id [" + id + "] that wasn't previously seen as unresolved."); } } /** * Helper class to maintain processing order of value. The resolved * object associated with {@link #_id} comes before the values in * {@link #next}. */ private final static class CollectionReferring extends Referring { private final CollectionReferringAccumulator _parent; public final List next = new ArrayList(); CollectionReferring(CollectionReferringAccumulator parent, UnresolvedForwardReference reference, Class contentType) { super(reference, contentType); _parent = parent; } @Override public void handleResolvedForwardReference(Object id, Object value) throws IOException { _parent.resolveForwardReference(id, value); } } } ContainerDeserializerBase.java000066400000000000000000000141751325620701100402770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.AccessPattern; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Intermediate base deserializer class that adds more shared accessor * so that other classes can access information about contained (value) types */ @SuppressWarnings("serial") public abstract class ContainerDeserializerBase extends StdDeserializer implements ValueInstantiator.Gettable // since 2.9 { protected final JavaType _containerType; /** * Handler we need for dealing with nulls. * * @since 2.9 */ protected final NullValueProvider _nullProvider; /** * Specific override for this instance (from proper, or global per-type overrides) * to indicate whether single value may be taken to mean an unwrapped one-element array * or not. If null, left to global defaults. * * @since 2.9 (demoted from sub-classes where added in 2.7) */ protected final Boolean _unwrapSingle; /** * Marker flag set if the _nullProvider indicates that all null * content values should be skipped (instead of being possibly converted). * * @since 2.9 */ protected final boolean _skipNullValues; protected ContainerDeserializerBase(JavaType selfType, NullValueProvider nuller, Boolean unwrapSingle) { super(selfType); _containerType = selfType; _unwrapSingle = unwrapSingle; _nullProvider = nuller; _skipNullValues = NullsConstantProvider.isSkipper(nuller); } protected ContainerDeserializerBase(JavaType selfType) { this(selfType, null, null); } /** * @since 2.9 */ protected ContainerDeserializerBase(ContainerDeserializerBase base) { this(base, base._nullProvider, base._unwrapSingle); } /** * @since 2.9 */ protected ContainerDeserializerBase(ContainerDeserializerBase base, NullValueProvider nuller, Boolean unwrapSingle) { super(base._containerType); _containerType = base._containerType; _nullProvider = nuller; _unwrapSingle = unwrapSingle; _skipNullValues = NullsConstantProvider.isSkipper(nuller); } /* /********************************************************** /* Overrides /********************************************************** */ @Override // since 2.9 public JavaType getValueType() { return _containerType; } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return Boolean.TRUE; } @Override public SettableBeanProperty findBackReference(String refName) { JsonDeserializer valueDeser = getContentDeserializer(); if (valueDeser == null) { throw new IllegalArgumentException(String.format( "Cannot handle managed/back reference '%s': type: container deserializer of type %s returned null for 'getContentDeserializer()'", refName, getClass().getName())); } return valueDeser.findBackReference(refName); } /* /********************************************************** /* Extended API /********************************************************** */ /** * Accessor for declared type of contained value elements; either exact * type, or one of its supertypes. */ public JavaType getContentType() { if (_containerType == null) { return TypeFactory.unknownType(); // should never occur but... } return _containerType.getContentType(); } /** * Accesor for deserializer use for deserializing content values. */ public abstract JsonDeserializer getContentDeserializer(); /** * @since 2.9 */ @Override public ValueInstantiator getValueInstantiator() { return null; } @Override // since 2.9 public AccessPattern getEmptyAccessPattern() { // 02-Feb-2017, tatu: Empty containers are usually constructed as needed // and may not be shared; for some deserializers this may be further refined. return AccessPattern.DYNAMIC; } @Override // since 2.9 public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { ValueInstantiator vi = getValueInstantiator(); if (vi == null || !vi.canCreateUsingDefault()) { JavaType type = getValueType(); ctxt.reportBadDefinition(type, String.format("Cannot create empty instance of %s, no default Creator", type)); } try { return vi.createUsingDefault(ctxt); } catch (IOException e) { return ClassUtil.throwAsMappingException(ctxt, e); } } /* /********************************************************** /* Shared methods for sub-classes /********************************************************** */ /** * Helper method called by various Map(-like) deserializers. */ protected BOGUS wrapAndThrow(Throwable t, Object ref, String key) throws IOException { // to handle StackOverflow: while (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } // Errors and "plain" IOExceptions to be passed as is ClassUtil.throwIfError(t); // ... except for mapping exceptions if (t instanceof IOException && !(t instanceof JsonMappingException)) { throw (IOException) t; } // for [databind#1141] throw JsonMappingException.wrapWithPath(t, ref, ClassUtil.nonNull(key, "N/A")); } } DateDeserializers.java000066400000000000000000000304561325620701100366220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.lang.reflect.Constructor; import java.sql.Timestamp; import java.text.*; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.StdDateFormat; /** * Container class for core JDK date/time type deserializers. */ @SuppressWarnings("serial") public class DateDeserializers { private final static HashSet _classNames = new HashSet(); static { Class[] numberTypes = new Class[] { Calendar.class, GregorianCalendar.class, java.sql.Date.class, java.util.Date.class, Timestamp.class, }; for (Class cls : numberTypes) { _classNames.add(cls.getName()); } } public static JsonDeserializer find(Class rawType, String clsName) { if (_classNames.contains(clsName)) { // Start with the most common type if (rawType == Calendar.class) { return new CalendarDeserializer(); } if (rawType == java.util.Date.class) { return DateDeserializer.instance; } if (rawType == java.sql.Date.class) { return new SqlDateDeserializer(); } if (rawType == Timestamp.class) { return new TimestampDeserializer(); } if (rawType == GregorianCalendar.class) { return new CalendarDeserializer(GregorianCalendar.class); } } return null; } /* /********************************************************** /* Intermediate class for Date-based ones /********************************************************** */ protected abstract static class DateBasedDeserializer extends StdScalarDeserializer implements ContextualDeserializer { /** * Specific format to use, if non-null; if null will * just use default format. */ protected final DateFormat _customFormat; /** * Let's also keep format String for reference, to use for error messages */ protected final String _formatString; protected DateBasedDeserializer(Class clz) { super(clz); _customFormat = null; _formatString = null; } protected DateBasedDeserializer(DateBasedDeserializer base, DateFormat format, String formatStr) { super(base._valueClass); _customFormat = format; _formatString = formatStr; } protected abstract DateBasedDeserializer withDateFormat(DateFormat df, String formatStr); @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { final JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType()); if (format != null) { TimeZone tz = format.getTimeZone(); final Boolean lenient = format.getLenient(); // First: fully custom pattern? if (format.hasPattern()) { final String pattern = format.getPattern(); final Locale loc = format.hasLocale() ? format.getLocale() : ctxt.getLocale(); SimpleDateFormat df = new SimpleDateFormat(pattern, loc); if (tz == null) { tz = ctxt.getTimeZone(); } df.setTimeZone(tz); if (lenient != null) { df.setLenient(lenient); } return withDateFormat(df, pattern); } // But if not, can still override timezone if (tz != null) { DateFormat df = ctxt.getConfig().getDateFormat(); // one shortcut: with our custom format, can simplify handling a bit if (df.getClass() == StdDateFormat.class) { final Locale loc = format.hasLocale() ? format.getLocale() : ctxt.getLocale(); StdDateFormat std = (StdDateFormat) df; std = std.withTimeZone(tz); std = std.withLocale(loc); if (lenient != null) { std = std.withLenient(lenient); } df = std; } else { // otherwise need to clone, re-set timezone: df = (DateFormat) df.clone(); df.setTimeZone(tz); if (lenient != null) { df.setLenient(lenient); } } return withDateFormat(df, _formatString); } // or maybe even just leniency? if (lenient != null) { DateFormat df = ctxt.getConfig().getDateFormat(); String pattern = _formatString; // one shortcut: with our custom format, can simplify handling a bit if (df.getClass() == StdDateFormat.class) { StdDateFormat std = (StdDateFormat) df; std = std.withLenient(lenient); df = std; pattern = std.toPattern(); } else { // otherwise need to clone, df = (DateFormat) df.clone(); df.setLenient(lenient); if (df instanceof SimpleDateFormat) { ((SimpleDateFormat) df).toPattern(); } } if (pattern == null) { pattern = "[unknown]"; } return withDateFormat(df, pattern); } } return this; } @Override protected java.util.Date _parseDate(JsonParser p, DeserializationContext ctxt) throws IOException { if (_customFormat != null) { if (p.hasToken(JsonToken.VALUE_STRING)) { String str = p.getText().trim(); if (str.length() == 0) { return (Date) getEmptyValue(ctxt); } synchronized (_customFormat) { try { return _customFormat.parse(str); } catch (ParseException e) { return (java.util.Date) ctxt.handleWeirdStringValue(handledType(), str, "expected format \"%s\"", _formatString); } } } } return super._parseDate(p, ctxt); } } /* /********************************************************** /* Deserializer implementations for Date types /********************************************************** */ @JacksonStdImpl public static class CalendarDeserializer extends DateBasedDeserializer { /** * We may know actual expected type; if so, it will be * used for instantiation. * * @since 2.9 */ protected final Constructor _defaultCtor; public CalendarDeserializer() { super(Calendar.class); _defaultCtor = null; } @SuppressWarnings("unchecked") public CalendarDeserializer(Class cc) { super(cc); _defaultCtor = (Constructor) ClassUtil.findConstructor(cc, false); } public CalendarDeserializer(CalendarDeserializer src, DateFormat df, String formatString) { super(src, df, formatString); _defaultCtor = src._defaultCtor; } @Override protected CalendarDeserializer withDateFormat(DateFormat df, String formatString) { return new CalendarDeserializer(this, df, formatString); } @Override public Calendar deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Date d = _parseDate(p, ctxt); if (d == null) { return null; } if (_defaultCtor == null) { return ctxt.constructCalendar(d); } try { Calendar c = _defaultCtor.newInstance(); c.setTimeInMillis(d.getTime()); TimeZone tz = ctxt.getTimeZone(); if (tz != null) { c.setTimeZone(tz); } return c; } catch (Exception e) { return (Calendar) ctxt.handleInstantiationProblem(handledType(), d, e); } } } /** * Simple deserializer for handling {@link java.util.Date} values. *

* One way to customize Date formats accepted is to override method * {@link DeserializationContext#parseDate} that this basic * deserializer calls. */ @JacksonStdImpl public static class DateDeserializer extends DateBasedDeserializer { public final static DateDeserializer instance = new DateDeserializer(); public DateDeserializer() { super(Date.class); } public DateDeserializer(DateDeserializer base, DateFormat df, String formatString) { super(base, df, formatString); } @Override protected DateDeserializer withDateFormat(DateFormat df, String formatString) { return new DateDeserializer(this, df, formatString); } @Override public java.util.Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return _parseDate(p, ctxt); } } /** * Compared to plain old {@link java.util.Date}, SQL version is easier * to deal with: mostly because it is more limited. */ public static class SqlDateDeserializer extends DateBasedDeserializer { public SqlDateDeserializer() { super(java.sql.Date.class); } public SqlDateDeserializer(SqlDateDeserializer src, DateFormat df, String formatString) { super(src, df, formatString); } @Override protected SqlDateDeserializer withDateFormat(DateFormat df, String formatString) { return new SqlDateDeserializer(this, df, formatString); } @Override public java.sql.Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Date d = _parseDate(p, ctxt); return (d == null) ? null : new java.sql.Date(d.getTime()); } } /** * Simple deserializer for handling {@link java.sql.Timestamp} values. *

* One way to customize Timestamp formats accepted is to override method * {@link DeserializationContext#parseDate} that this basic * deserializer calls. */ public static class TimestampDeserializer extends DateBasedDeserializer { public TimestampDeserializer() { super(Timestamp.class); } public TimestampDeserializer(TimestampDeserializer src, DateFormat df, String formatString) { super(src, df, formatString); } @Override protected TimestampDeserializer withDateFormat(DateFormat df, String formatString) { return new TimestampDeserializer(this, df, formatString); } @Override public java.sql.Timestamp deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Date d = _parseDate(p, ctxt); return (d == null) ? null : new Timestamp(d.getTime()); } } } DelegatingDeserializer.java000066400000000000000000000116761325620701100376300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.Collection; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.AccessPattern; /** * Base class that simplifies implementations of {@link JsonDeserializer}s * that mostly delegate functionality to another deserializer implementation * (possibly forming a chaing of deserializers delegating functionality * in some cases) * * @since 2.1 */ public abstract class DelegatingDeserializer extends StdDeserializer implements ContextualDeserializer, ResolvableDeserializer { private static final long serialVersionUID = 1L; protected final JsonDeserializer _delegatee; /* /********************************************************************** /* Construction /********************************************************************** */ public DelegatingDeserializer(JsonDeserializer d) { super(d.handledType()); _delegatee = d; } /* /********************************************************************** /* Abstract methods to implement /********************************************************************** */ protected abstract JsonDeserializer newDelegatingInstance(JsonDeserializer newDelegatee); /* /********************************************************************** /* Overridden methods for contextualization, resolving /********************************************************************** */ @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException { if (_delegatee instanceof ResolvableDeserializer) { ((ResolvableDeserializer) _delegatee).resolve(ctxt); } } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { JavaType vt = ctxt.constructType(_delegatee.handledType()); JsonDeserializer del = ctxt.handleSecondaryContextualization(_delegatee, property, vt); if (del == _delegatee) { return this; } return newDelegatingInstance(del); } @Override public JsonDeserializer replaceDelegatee(JsonDeserializer delegatee) { if (delegatee == _delegatee) { return this; } return newDelegatingInstance(delegatee); } /* /********************************************************************** /* Overridden deserialization methods /********************************************************************** */ @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return _delegatee.deserialize(p, ctxt); } @SuppressWarnings("unchecked") @Override public Object deserialize(JsonParser p, DeserializationContext ctxt, Object intoValue) throws IOException { return ((JsonDeserializer)_delegatee).deserialize(p, ctxt, intoValue); } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { return _delegatee.deserializeWithType(p, ctxt, typeDeserializer); } /* /********************************************************************** /* Overridden other methods /********************************************************************** */ @Override public boolean isCachable() { return _delegatee.isCachable(); } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return _delegatee.supportsUpdate(config); } @Override public JsonDeserializer getDelegatee() { return _delegatee; } @Override public SettableBeanProperty findBackReference(String logicalName) { // [databind#253]: Hope this works.... return _delegatee.findBackReference(logicalName); } @Override public AccessPattern getNullAccessPattern() { return _delegatee.getNullAccessPattern(); } @Override public Object getNullValue(DeserializationContext ctxt) throws JsonMappingException { return _delegatee.getNullValue(ctxt); } @Override public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { return _delegatee.getEmptyValue(ctxt); } @Override public Collection getKnownPropertyNames() { return _delegatee.getKnownPropertyNames(); } @Override public ObjectIdReader getObjectIdReader() { return _delegatee.getObjectIdReader(); } } EnumDeserializer.java000066400000000000000000000247411325620701100364660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.CompactStringObjectMap; import com.fasterxml.jackson.databind.util.EnumResolver; /** * Deserializer class that can deserialize instances of * specified Enum class from Strings and Integers. */ @JacksonStdImpl // was missing until 2.6 public class EnumDeserializer extends StdScalarDeserializer implements ContextualDeserializer { private static final long serialVersionUID = 1L; protected Object[] _enumsByIndex; /** * @since 2.8 */ private final Enum _enumDefaultValue; /** * @since 2.7.3 */ protected final CompactStringObjectMap _lookupByName; /** * Alternatively, we may need a different lookup object if "use toString" * is defined. * * @since 2.7.3 */ protected CompactStringObjectMap _lookupByToString; protected final Boolean _caseInsensitive; /** * @since 2.9 */ public EnumDeserializer(EnumResolver byNameResolver, Boolean caseInsensitive) { super(byNameResolver.getEnumClass()); _lookupByName = byNameResolver.constructLookup(); _enumsByIndex = byNameResolver.getRawEnums(); _enumDefaultValue = byNameResolver.getDefaultValue(); _caseInsensitive = caseInsensitive; } /** * @since 2.9 */ protected EnumDeserializer(EnumDeserializer base, Boolean caseInsensitive) { super(base); _lookupByName = base._lookupByName; _enumsByIndex = base._enumsByIndex; _enumDefaultValue = base._enumDefaultValue; _caseInsensitive = caseInsensitive; } /** * @deprecated Since 2.9 */ @Deprecated public EnumDeserializer(EnumResolver byNameResolver) { this(byNameResolver, null); } /** * @deprecated Since 2.8 */ @Deprecated public static JsonDeserializer deserializerForCreator(DeserializationConfig config, Class enumClass, AnnotatedMethod factory) { return deserializerForCreator(config, enumClass, factory, null, null); } /** * Factory method used when Enum instances are to be deserialized * using a creator (static factory method) * * @return Deserializer based on given factory method * * @since 2.8 */ public static JsonDeserializer deserializerForCreator(DeserializationConfig config, Class enumClass, AnnotatedMethod factory, ValueInstantiator valueInstantiator, SettableBeanProperty[] creatorProps) { if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(factory.getMember(), config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } return new FactoryBasedEnumDeserializer(enumClass, factory, factory.getParameterType(0), valueInstantiator, creatorProps); } /** * Factory method used when Enum instances are to be deserialized * using a zero-/no-args factory method * * @return Deserializer based on given no-args factory method * * @since 2.8 */ public static JsonDeserializer deserializerForNoArgsCreator(DeserializationConfig config, Class enumClass, AnnotatedMethod factory) { if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(factory.getMember(), config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } return new FactoryBasedEnumDeserializer(enumClass, factory); } /** * @since 2.9 */ public EnumDeserializer withResolved(Boolean caseInsensitive) { if (_caseInsensitive == caseInsensitive) { return this; } return new EnumDeserializer(this, caseInsensitive); } @Override // since 2.9 public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { Boolean caseInsensitive = findFormatFeature(ctxt, property, handledType(), JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); if (caseInsensitive == null) { caseInsensitive = _caseInsensitive; } return withResolved(caseInsensitive); } /* /********************************************************** /* Default JsonDeserializer implementation /********************************************************** */ /** * Because of costs associated with constructing Enum resolvers, * let's cache instances by default. */ @Override public boolean isCachable() { return true; } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken curr = p.getCurrentToken(); // Usually should just get string value: if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) { CompactStringObjectMap lookup = ctxt.isEnabled(DeserializationFeature.READ_ENUMS_USING_TO_STRING) ? _getToStringLookup(ctxt) : _lookupByName; final String name = p.getText(); Object result = lookup.find(name); if (result == null) { return _deserializeAltString(p, ctxt, lookup, name); } return result; } // But let's consider int acceptable as well (if within ordinal range) if (curr == JsonToken.VALUE_NUMBER_INT) { // ... unless told not to do that int index = p.getIntValue(); if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)) { return ctxt.handleWeirdNumberValue(_enumClass(), index, "not allowed to deserialize Enum value out of number: disable DeserializationConfig.DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS to allow" ); } if (index >= 0 && index < _enumsByIndex.length) { return _enumsByIndex[index]; } if ((_enumDefaultValue != null) && ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)) { return _enumDefaultValue; } if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { return ctxt.handleWeirdNumberValue(_enumClass(), index, "index value outside legal index range [0..%s]", _enumsByIndex.length-1); } return null; } return _deserializeOther(p, ctxt); } /* /********************************************************** /* Internal helper methods /********************************************************** */ private final Object _deserializeAltString(JsonParser p, DeserializationContext ctxt, CompactStringObjectMap lookup, String name) throws IOException { name = name.trim(); if (name.length() == 0) { if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { return getEmptyValue(ctxt); } } else { // [databind#1313]: Case insensitive enum deserialization if (Boolean.TRUE.equals(_caseInsensitive)) { Object match = lookup.findCaseInsensitive(name); if (match != null) { return match; } } else if (!ctxt.isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)) { // [databind#149]: Allow use of 'String' indexes as well -- unless prohibited (as per above) char c = name.charAt(0); if (c >= '0' && c <= '9') { try { int index = Integer.parseInt(name); if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) { return ctxt.handleWeirdStringValue(_enumClass(), name, "value looks like quoted Enum index, but `MapperFeature.ALLOW_COERCION_OF_SCALARS` prevents use" ); } if (index >= 0 && index < _enumsByIndex.length) { return _enumsByIndex[index]; } } catch (NumberFormatException e) { // fine, ignore, was not an integer } } } } if ((_enumDefaultValue != null) && ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)) { return _enumDefaultValue; } if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { return ctxt.handleWeirdStringValue(_enumClass(), name, "value not one of declared Enum instance names: %s", lookup.keys()); } return null; } protected Object _deserializeOther(JsonParser p, DeserializationContext ctxt) throws IOException { // [databind#381] if (p.hasToken(JsonToken.START_ARRAY)) { return _deserializeFromArray(p, ctxt); } return ctxt.handleUnexpectedToken(_enumClass(), p); } protected Class _enumClass() { return handledType(); } protected CompactStringObjectMap _getToStringLookup(DeserializationContext ctxt) { CompactStringObjectMap lookup = _lookupByToString; // note: exact locking not needed; all we care for here is to try to // reduce contention for the initial resolution if (lookup == null) { synchronized (this) { lookup = EnumResolver.constructUnsafeUsingToString(_enumClass(), ctxt.getAnnotationIntrospector()) .constructLookup(); } _lookupByToString = lookup; } return lookup; } } EnumMapDeserializer.java000066400000000000000000000416531325620701100371250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.ResolvableDeserializer; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator; import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Deserializer for {@link EnumMap} values. *

* Note: casting within this class is all messed up -- just could not figure out a way * to properly deal with recursive definition of "EnumMap<K extends Enum<K>, V> */ @SuppressWarnings({ "unchecked", "rawtypes" }) public class EnumMapDeserializer extends ContainerDeserializerBase> implements ContextualDeserializer, ResolvableDeserializer { private static final long serialVersionUID = 1; protected final Class _enumClass; protected KeyDeserializer _keyDeserializer; protected JsonDeserializer _valueDeserializer; /** * If value instances have polymorphic type information, this * is the type deserializer that can handle it */ protected final TypeDeserializer _valueTypeDeserializer; // // Instance construction settings: /** * @since 2.9 */ protected final ValueInstantiator _valueInstantiator; /** * Deserializer that is used iff delegate-based creator is * to be used for deserializing from JSON Object. */ protected JsonDeserializer _delegateDeserializer; /** * If the Map is to be instantiated using non-default constructor * or factory method * that takes one or more named properties as argument(s), * this creator is used for instantiation. */ protected PropertyBasedCreator _propertyBasedCreator; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @since 2.9 */ public EnumMapDeserializer(JavaType mapType, ValueInstantiator valueInst, KeyDeserializer keyDeser, JsonDeserializer valueDeser, TypeDeserializer vtd, NullValueProvider nuller) { super(mapType, nuller, null); _enumClass = mapType.getKeyType().getRawClass(); _keyDeserializer = keyDeser; _valueDeserializer = (JsonDeserializer) valueDeser; _valueTypeDeserializer = vtd; _valueInstantiator = valueInst; } /** * @since 2.9 */ protected EnumMapDeserializer(EnumMapDeserializer base, KeyDeserializer keyDeser, JsonDeserializer valueDeser, TypeDeserializer vtd, NullValueProvider nuller) { super(base, nuller, base._unwrapSingle); _enumClass = base._enumClass; _keyDeserializer = keyDeser; _valueDeserializer = (JsonDeserializer) valueDeser; _valueTypeDeserializer = vtd; _valueInstantiator = base._valueInstantiator; _delegateDeserializer = base._delegateDeserializer; _propertyBasedCreator = base._propertyBasedCreator; } @Deprecated // since 2.9 public EnumMapDeserializer(JavaType mapType, KeyDeserializer keyDeser, JsonDeserializer valueDeser, TypeDeserializer vtd) { this(mapType, null, keyDeser, valueDeser, vtd, null); } public EnumMapDeserializer withResolved(KeyDeserializer keyDeserializer, JsonDeserializer valueDeserializer, TypeDeserializer valueTypeDeser, NullValueProvider nuller) { if ((keyDeserializer == _keyDeserializer) && (nuller == _nullProvider) && (valueDeserializer == _valueDeserializer) && (valueTypeDeser == _valueTypeDeserializer)) { return this; } return new EnumMapDeserializer(this, keyDeserializer, valueDeserializer, valueTypeDeser, nuller); } /* /********************************************************** /* Validation, post-processing (ResolvableDeserializer) /********************************************************** */ @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException { // May need to resolve types for delegate- and/or property-based creators: if (_valueInstantiator != null) { if (_valueInstantiator.canCreateUsingDelegate()) { JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig()); if (delegateType == null) { ctxt.reportBadDefinition(_containerType, String.format( "Invalid delegate-creator definition for %s: value instantiator (%s) returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'", _containerType, _valueInstantiator.getClass().getName())); } /* Theoretically should be able to get CreatorProperty for delegate * parameter to pass; but things get tricky because DelegateCreator * may contain injectable values. So, for now, let's pass nothing. */ _delegateDeserializer = findDeserializer(ctxt, delegateType, null); } else if (_valueInstantiator.canCreateUsingArrayDelegate()) { JavaType delegateType = _valueInstantiator.getArrayDelegateType(ctxt.getConfig()); if (delegateType == null) { ctxt.reportBadDefinition(_containerType, String.format( "Invalid delegate-creator definition for %s: value instantiator (%s) returned true for 'canCreateUsingArrayDelegate()', but null for 'getArrayDelegateType()'", _containerType, _valueInstantiator.getClass().getName())); } _delegateDeserializer = findDeserializer(ctxt, delegateType, null); } else if (_valueInstantiator.canCreateFromObjectWith()) { SettableBeanProperty[] creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig()); _propertyBasedCreator = PropertyBasedCreator.construct(ctxt, _valueInstantiator, creatorProps, ctxt.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); } } } /** * Method called to finalize setup of this deserializer, * when it is known for which property deserializer is needed for. */ @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { // note: instead of finding key deserializer, with enums we actually // work with regular deserializers (less code duplication; but not // quite as clean as it ought to be) KeyDeserializer keyDeser = _keyDeserializer; if (keyDeser == null) { keyDeser = ctxt.findKeyDeserializer(_containerType.getKeyType(), property); } JsonDeserializer valueDeser = _valueDeserializer; final JavaType vt = _containerType.getContentType(); if (valueDeser == null) { valueDeser = ctxt.findContextualValueDeserializer(vt, property); } else { // if directly assigned, probably not yet contextual, so: valueDeser = ctxt.handleSecondaryContextualization(valueDeser, property, vt); } TypeDeserializer vtd = _valueTypeDeserializer; if (vtd != null) { vtd = vtd.forProperty(property); } return withResolved(keyDeser, valueDeser, vtd, findContentNullProvider(ctxt, property, valueDeser)); } /** * Because of costs associated with constructing Enum resolvers, * let's cache instances by default. */ @Override public boolean isCachable() { // Important: do NOT cache if polymorphic values return (_valueDeserializer == null) && (_keyDeserializer == null) && (_valueTypeDeserializer == null); } /* /********************************************************** /* ContainerDeserializerBase API /********************************************************** */ @Override public JsonDeserializer getContentDeserializer() { return _valueDeserializer; } // Must override since we do not expose ValueInstantiator @Override // since 2.9 public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { return constructMap(ctxt); } /* /********************************************************** /* Actual deserialization /********************************************************** */ @Override public EnumMap deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (_propertyBasedCreator != null) { return _deserializeUsingProperties(p, ctxt); } if (_delegateDeserializer != null) { return (EnumMap) _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt)); } // Ok: must point to START_OBJECT JsonToken t = p.getCurrentToken(); if ((t != JsonToken.START_OBJECT) && (t != JsonToken.FIELD_NAME) && (t != JsonToken.END_OBJECT)) { // (empty) String may be ok however; or single-String-arg ctor if (t == JsonToken.VALUE_STRING) { return (EnumMap) _valueInstantiator.createFromString(ctxt, p.getText()); } // slightly redundant (since String was passed above), but also handles empty array case: return _deserializeFromEmpty(p, ctxt); } EnumMap result = constructMap(ctxt); return deserialize(p, ctxt, result); } @Override public EnumMap deserialize(JsonParser p, DeserializationContext ctxt, EnumMap result) throws IOException { // [databind#631]: Assign current value, to be accessible by custom deserializers p.setCurrentValue(result); final JsonDeserializer valueDes = _valueDeserializer; final TypeDeserializer typeDeser = _valueTypeDeserializer; String keyStr; if (p.isExpectedStartObjectToken()) { keyStr = p.nextFieldName(); } else { JsonToken t = p.getCurrentToken(); if (t != JsonToken.FIELD_NAME) { if (t == JsonToken.END_OBJECT) { return result; } ctxt.reportWrongTokenException(this, JsonToken.FIELD_NAME, null); } keyStr = p.getCurrentName(); } for (; keyStr != null; keyStr = p.nextFieldName()) { // but we need to let key deserializer handle it separately, nonetheless Enum key = (Enum) _keyDeserializer.deserializeKey(keyStr, ctxt); JsonToken t = p.nextToken(); if (key == null) { if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { return (EnumMap) ctxt.handleWeirdStringValue(_enumClass, keyStr, "value not one of declared Enum instance names for %s", _containerType.getKeyType()); } // 24-Mar-2012, tatu: Null won't work as a key anyway, so let's // just skip the entry then. But we must skip the value as well, if so. p.skipChildren(); continue; } // And then the value... // note: MUST check for nulls separately: deserializers will // not handle them (and maybe fail or return bogus data) Object value; try { if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = _nullProvider.getNullValue(ctxt); } else if (typeDeser == null) { value = valueDes.deserialize(p, ctxt); } else { value = valueDes.deserializeWithType(p, ctxt, typeDeser); } } catch (Exception e) { return wrapAndThrow(e, result, keyStr); } result.put(key, value); } return result; } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // In future could check current token... for now this should be enough: return typeDeserializer.deserializeTypedFromObject(p, ctxt); } protected EnumMap constructMap(DeserializationContext ctxt) throws JsonMappingException { if (_valueInstantiator == null) { return new EnumMap(_enumClass); } try { if (!_valueInstantiator.canCreateUsingDefault()) { return (EnumMap) ctxt.handleMissingInstantiator(handledType(), getValueInstantiator(), null, "no default constructor found"); } return (EnumMap) _valueInstantiator.createUsingDefault(ctxt); } catch (IOException e) { return ClassUtil.throwAsMappingException(ctxt, e); } } public EnumMap _deserializeUsingProperties(JsonParser p, DeserializationContext ctxt) throws IOException { final PropertyBasedCreator creator = _propertyBasedCreator; // null -> no ObjectIdReader for EnumMaps PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, null); String keyName; if (p.isExpectedStartObjectToken()) { keyName = p.nextFieldName(); } else if (p.hasToken(JsonToken.FIELD_NAME)) { keyName = p.getCurrentName(); } else { keyName = null; } for (; keyName != null; keyName = p.nextFieldName()) { JsonToken t = p.nextToken(); // to get to value // creator property? SettableBeanProperty prop = creator.findCreatorProperty(keyName); if (prop != null) { // Last property to set? if (buffer.assignParameter(prop, prop.deserialize(p, ctxt))) { p.nextToken(); // from value to END_OBJECT or FIELD_NAME EnumMap result; try { result = (EnumMap)creator.build(ctxt, buffer); } catch (Exception e) { return wrapAndThrow(e, _containerType.getRawClass(), keyName); } return deserialize(p, ctxt, result); } continue; } // other property? needs buffering // but we need to let key deserializer handle it separately, nonetheless Enum key = (Enum) _keyDeserializer.deserializeKey(keyName, ctxt); if (key == null) { if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { return (EnumMap) ctxt.handleWeirdStringValue(_enumClass, keyName, "value not one of declared Enum instance names for %s", _containerType.getKeyType()); } // 24-Mar-2012, tatu: Null won't work as a key anyway, so let's // just skip the entry then. But we must skip the value as well, if so. p.nextToken(); p.skipChildren(); continue; } Object value; try { if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = _nullProvider.getNullValue(ctxt); } else if (_valueTypeDeserializer == null) { value = _valueDeserializer.deserialize(p, ctxt); } else { value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } } catch (Exception e) { wrapAndThrow(e, _containerType.getRawClass(), keyName); return null; } buffer.bufferMapProperty(key, value); } // end of JSON object? // if so, can just construct and leave... try { return (EnumMap)creator.build(ctxt, buffer); } catch (Exception e) { wrapAndThrow(e, _containerType.getRawClass(), keyName); return null; } } } EnumSetDeserializer.java000066400000000000000000000166221325620701100371410ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; /** * Standard deserializer for {@link EnumSet}s. *

* Note: casting within this class is all messed up -- just could not figure out a way * to properly deal with recursive definition of "EnumSet<K extends Enum<K>, V> */ @SuppressWarnings("rawtypes") public class EnumSetDeserializer extends StdDeserializer> implements ContextualDeserializer { private static final long serialVersionUID = 1L; // since 2.5 protected final JavaType _enumType; protected final Class _enumClass; protected JsonDeserializer> _enumDeserializer; /** * Specific override for this instance (from proper, or global per-type overrides) * to indicate whether single value may be taken to mean an unwrapped one-element array * or not. If null, left to global defaults. * * @since 2.7 */ protected final Boolean _unwrapSingle; /* /********************************************************** /* Life-cycle /********************************************************** */ @SuppressWarnings("unchecked" ) public EnumSetDeserializer(JavaType enumType, JsonDeserializer deser) { super(EnumSet.class); _enumType = enumType; _enumClass = (Class) enumType.getRawClass(); // sanity check if (!_enumClass.isEnum()) { throw new IllegalArgumentException("Type "+enumType+" not Java Enum type"); } _enumDeserializer = (JsonDeserializer>) deser; _unwrapSingle = null; } /** * @since 2.7 */ @SuppressWarnings("unchecked" ) protected EnumSetDeserializer(EnumSetDeserializer base, JsonDeserializer deser, Boolean unwrapSingle) { super(base); _enumType = base._enumType; _enumClass = base._enumClass; _enumDeserializer = (JsonDeserializer>) deser; _unwrapSingle = unwrapSingle; } public EnumSetDeserializer withDeserializer(JsonDeserializer deser) { if (_enumDeserializer == deser) { return this; } return new EnumSetDeserializer(this, deser, _unwrapSingle); } public EnumSetDeserializer withResolved(JsonDeserializer deser, Boolean unwrapSingle) { if ((_unwrapSingle == unwrapSingle) && (_enumDeserializer == deser)) { return this; } return new EnumSetDeserializer(this, deser, unwrapSingle); } /** * Because of costs associated with constructing Enum resolvers, * let's cache instances by default. */ @Override public boolean isCachable() { // One caveat: content deserializer should prevent caching if (_enumType.getValueHandler() != null) { return false; } return true; } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return Boolean.TRUE; } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { Boolean unwrapSingle = findFormatFeature(ctxt, property, EnumSet.class, JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); JsonDeserializer deser = _enumDeserializer; if (deser == null) { deser = ctxt.findContextualValueDeserializer(_enumType, property); } else { // if directly assigned, probably not yet contextual, so: deser = ctxt.handleSecondaryContextualization(deser, property, _enumType); } return withResolved(deser, unwrapSingle); } /* /********************************************************** /* JsonDeserializer API /********************************************************** */ @Override public EnumSet deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { EnumSet result = constructSet(); // Ok: must point to START_ARRAY (or equivalent) if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt, result); } return _deserialize(p, ctxt, result); } @Override public EnumSet deserialize(JsonParser p, DeserializationContext ctxt, EnumSet result) throws IOException { // Ok: must point to START_ARRAY (or equivalent) if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt, result); } return _deserialize(p, ctxt, result); } @SuppressWarnings("unchecked") protected final EnumSet _deserialize(JsonParser p, DeserializationContext ctxt, EnumSet result) throws IOException { JsonToken t; try { while ((t = p.nextToken()) != JsonToken.END_ARRAY) { /* What to do with nulls? Fail or ignore? Fail, for now * (note: would fail if we passed it to EnumDeserializer, too, * but in general nulls should never be passed to non-container * deserializers) */ if (t == JsonToken.VALUE_NULL) { return (EnumSet) ctxt.handleUnexpectedToken(_enumClass, p); } Enum value = _enumDeserializer.deserialize(p, ctxt); /* 24-Mar-2012, tatu: As per [JACKSON-810], may actually get nulls; * but EnumSets don't allow nulls so need to skip. */ if (value != null) { result.add(value); } } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, result, result.size()); } return result; } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException, JsonProcessingException { return typeDeserializer.deserializeTypedFromArray(p, ctxt); } @SuppressWarnings("unchecked") private EnumSet constructSet() { return EnumSet.noneOf(_enumClass); } @SuppressWarnings("unchecked") protected EnumSet handleNonArray(JsonParser p, DeserializationContext ctxt, EnumSet result) throws IOException { boolean canWrap = (_unwrapSingle == Boolean.TRUE) || ((_unwrapSingle == null) && ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); if (!canWrap) { return (EnumSet) ctxt.handleUnexpectedToken(EnumSet.class, p); } // First: since `null`s not allowed, slightly simpler... if (p.hasToken(JsonToken.VALUE_NULL)) { return (EnumSet) ctxt.handleUnexpectedToken(_enumClass, p); } try { Enum value = _enumDeserializer.deserialize(p, ctxt); if (value != null) { result.add(value); } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, result, result.size()); } return result; } } FactoryBasedEnumDeserializer.java000066400000000000000000000175141325620701100407550ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator; import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Deserializer that uses a single-String static factory method * for locating Enum values by String id. * * @since 2.8 (as stand-alone class; was static inner class of {@link EnumDeserializer} */ class FactoryBasedEnumDeserializer extends StdDeserializer implements ContextualDeserializer { private static final long serialVersionUID = 1; // Marker type; null if String expected; otherwise numeric wrapper protected final JavaType _inputType; protected final boolean _hasArgs; protected final AnnotatedMethod _factory; protected final JsonDeserializer _deser; protected final ValueInstantiator _valueInstantiator; protected final SettableBeanProperty[] _creatorProps; /** * Lazily instantiated property-based creator. * * @since 2.8 */ private transient PropertyBasedCreator _propCreator; public FactoryBasedEnumDeserializer(Class cls, AnnotatedMethod f, JavaType paramType, ValueInstantiator valueInstantiator, SettableBeanProperty[] creatorProps) { super(cls); _factory = f; _hasArgs = true; // We'll skip case of `String`, as well as no type (zero-args): _inputType = paramType.hasRawClass(String.class) ? null : paramType; _deser = null; _valueInstantiator = valueInstantiator; _creatorProps = creatorProps; } /** * @since 2.8 */ public FactoryBasedEnumDeserializer(Class cls, AnnotatedMethod f) { super(cls); _factory = f; _hasArgs = false; _inputType = null; _deser = null; _valueInstantiator = null; _creatorProps = null; } protected FactoryBasedEnumDeserializer(FactoryBasedEnumDeserializer base, JsonDeserializer deser) { super(base._valueClass); _inputType = base._inputType; _factory = base._factory; _hasArgs = base._hasArgs; _valueInstantiator = base._valueInstantiator; _creatorProps = base._creatorProps; _deser = deser; } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { if ((_deser == null) && (_inputType != null) && (_creatorProps == null)) { return new FactoryBasedEnumDeserializer(this, ctxt.findContextualValueDeserializer(_inputType, property)); } return this; } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return Boolean.FALSE; } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Object value = null; if (_deser != null) { value = _deser.deserialize(p, ctxt); } else if (_hasArgs) { JsonToken curr = p.getCurrentToken(); //There can be a JSON object passed for deserializing an Enum, //the below case handles it. if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) { value = p.getText(); } else if ((_creatorProps != null) && p.isExpectedStartObjectToken()) { if (_propCreator == null) { _propCreator = PropertyBasedCreator.construct(ctxt, _valueInstantiator, _creatorProps, ctxt.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); } p.nextToken(); return deserializeEnumUsingPropertyBased(p, ctxt, _propCreator); } else { value = p.getValueAsString(); } } else { // zero-args; just skip whatever value there may be p.skipChildren(); try { return _factory.call(); } catch (Exception e) { Throwable t = ClassUtil.throwRootCauseIfIOE(e); return ctxt.handleInstantiationProblem(_valueClass, null, t); } } try { return _factory.callOnWith(_valueClass, value); } catch (Exception e) { Throwable t = ClassUtil.throwRootCauseIfIOE(e); // [databind#1642]: if (ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL) && t instanceof IllegalArgumentException) { return null; } return ctxt.handleInstantiationProblem(_valueClass, value, t); } } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { if (_deser == null) { // String never has type info return deserialize(p, ctxt); } return typeDeserializer.deserializeTypedFromAny(p, ctxt); } // Method to deserialize the Enum using property based methodology protected Object deserializeEnumUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt, final PropertyBasedCreator creator) throws IOException { PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, null); JsonToken t = p.getCurrentToken(); for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); p.nextToken(); // to point to value SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); if (creatorProp != null) { buffer.assignParameter(creatorProp, _deserializeWithErrorWrapping(p, ctxt, creatorProp)); continue; } if (buffer.readIdProperty(propName)) { continue; } } return creator.build(ctxt, buffer); } // ************ Got the below methods from BeanDeserializer ********************// protected final Object _deserializeWithErrorWrapping(JsonParser p, DeserializationContext ctxt, SettableBeanProperty prop) throws IOException { try { return prop.deserialize(p, ctxt); } catch (Exception e) { return wrapAndThrow(e, handledType(), prop.getName(), ctxt); } } protected Object wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt) throws IOException { throw JsonMappingException.wrapWithPath(throwOrReturnThrowable(t, ctxt), bean, fieldName); } private Throwable throwOrReturnThrowable(Throwable t, DeserializationContext ctxt) throws IOException { t = ClassUtil.getRootCause(t); // Errors to be passed as is ClassUtil.throwIfError(t); boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS); // Ditto for IOExceptions; except we may want to wrap JSON exceptions if (t instanceof IOException) { if (!wrap || !(t instanceof JsonProcessingException)) { throw (IOException) t; } } else if (!wrap) { ClassUtil.throwIfRTE(t); } return t; } } FromStringDeserializer.java000066400000000000000000000306771325620701100376610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.*; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.nio.charset.Charset; import java.util.Currency; import java.util.Locale; import java.util.TimeZone; import java.util.regex.Pattern; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.util.VersionUtil; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Base class for simple deserializers that serialize values from String * representation: this includes JSON Strings and other Scalar values that * can be coerced into text, like Numbers and Booleans). * Simple JSON String values are trimmed using {@link java.lang.String#trim}. * Partial deserializer implementation will try to first access current token as * a String, calls {@link #_deserialize(String,DeserializationContext)} and * returns return value. * If this does not work (current token not a simple scalar type), attempts * are made so that: *
    *
  • Embedded values ({@link JsonToken#VALUE_EMBEDDED_OBJECT}) are returned as-is * if they are of compatible type *
  • *
  • Arrays may be "unwrapped" if (and only if) {@link DeserializationFeature#UNWRAP_SINGLE_VALUE_ARRAYS} * is enabled, and array contains just a single scalar value that can be deserialized * (for example, JSON Array with single JSON String element). *
  • *
*

* Special handling includes: *

    *
  • Null values ({@link JsonToken#VALUE_NULL}) are handled by returning value * returned by {@link JsonDeserializer#getNullValue(DeserializationContext)}: default * implementation simply returns Java `null` but this may be overridden. *
  • *
  • Empty String (after trimming) will result in {@link #_deserializeFromEmptyString} * getting called, and return value being returned as deserialization: default implementation * simply returns `null`. *
  • *
*/ @SuppressWarnings("serial") public abstract class FromStringDeserializer extends StdScalarDeserializer { public static Class[] types() { return new Class[] { File.class, URL.class, URI.class, Class.class, JavaType.class, Currency.class, Pattern.class, Locale.class, Charset.class, TimeZone.class, InetAddress.class, InetSocketAddress.class, StringBuilder.class, }; } /* /********************************************************** /* Deserializer implementations /********************************************************** */ protected FromStringDeserializer(Class vc) { super(vc); } /** * Factory method for trying to find a deserializer for one of supported * types that have simple from-String serialization. */ public static Std findDeserializer(Class rawType) { int kind = 0; if (rawType == File.class) { kind = Std.STD_FILE; } else if (rawType == URL.class) { kind = Std.STD_URL; } else if (rawType == URI.class) { kind = Std.STD_URI; } else if (rawType == Class.class) { kind = Std.STD_CLASS; } else if (rawType == JavaType.class) { kind = Std.STD_JAVA_TYPE; } else if (rawType == Currency.class) { kind = Std.STD_CURRENCY; } else if (rawType == Pattern.class) { kind = Std.STD_PATTERN; } else if (rawType == Locale.class) { kind = Std.STD_LOCALE; } else if (rawType == Charset.class) { kind = Std.STD_CHARSET; } else if (rawType == TimeZone.class) { kind = Std.STD_TIME_ZONE; } else if (rawType == InetAddress.class) { kind = Std.STD_INET_ADDRESS; } else if (rawType == InetSocketAddress.class) { kind = Std.STD_INET_SOCKET_ADDRESS; } else if (rawType == StringBuilder.class) { kind = Std.STD_STRING_BUILDER; } else { return null; } return new Std(rawType, kind); } /* /********************************************************** /* Deserializer implementations /********************************************************** */ @SuppressWarnings("unchecked") @Override public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // Let's get textual value, possibly via coercion from other scalar types String text = p.getValueAsString(); if (text != null) { // has String representation if (text.length() == 0 || (text = text.trim()).length() == 0) { // Usually should become null; but not always return _deserializeFromEmptyString(); } Exception cause = null; try { // 19-May-2017, tatu: Used to require non-null result (assuming `null` // indicated error; but that seems wrong. Should be able to return // `null` as value. return _deserialize(text, ctxt); } catch (IllegalArgumentException | MalformedURLException e) { cause = e; } // note: `cause` can't be null String msg = "not a valid textual representation"; String m2 = cause.getMessage(); if (m2 != null) { msg = msg + ", problem: "+m2; } // 05-May-2016, tatu: Unlike most usage, this seems legit, so... JsonMappingException e = ctxt.weirdStringException(text, _valueClass, msg); e.initCause(cause); throw e; // nothing to do here, yet? We'll fail anyway } JsonToken t = p.getCurrentToken(); // [databind#381] if (t == JsonToken.START_ARRAY) { return _deserializeFromArray(p, ctxt); } if (t == JsonToken.VALUE_EMBEDDED_OBJECT) { // Trivial cases; null to null, instance of type itself returned as is Object ob = p.getEmbeddedObject(); if (ob == null) { return null; } if (_valueClass.isAssignableFrom(ob.getClass())) { return (T) ob; } return _deserializeEmbedded(ob, ctxt); } return (T) ctxt.handleUnexpectedToken(_valueClass, p); } protected abstract T _deserialize(String value, DeserializationContext ctxt) throws IOException; protected T _deserializeEmbedded(Object ob, DeserializationContext ctxt) throws IOException { // default impl: error out ctxt.reportInputMismatch(this, "Don't know how to convert embedded Object of type %s into %s", ob.getClass().getName(), _valueClass.getName()); return null; } protected T _deserializeFromEmptyString() throws IOException { return null; } /* /********************************************************** /* A general-purpose implementation /********************************************************** */ /** * "Chameleon" deserializer that works on simple types that are deserialized * from a simple String. * * @since 2.4 */ public static class Std extends FromStringDeserializer { private static final long serialVersionUID = 1; public final static int STD_FILE = 1; public final static int STD_URL = 2; public final static int STD_URI = 3; public final static int STD_CLASS = 4; public final static int STD_JAVA_TYPE = 5; public final static int STD_CURRENCY = 6; public final static int STD_PATTERN = 7; public final static int STD_LOCALE = 8; public final static int STD_CHARSET = 9; public final static int STD_TIME_ZONE = 10; public final static int STD_INET_ADDRESS = 11; public final static int STD_INET_SOCKET_ADDRESS = 12; public final static int STD_STRING_BUILDER = 13; protected final int _kind; protected Std(Class valueType, int kind) { super(valueType); _kind = kind; } @Override protected Object _deserialize(String value, DeserializationContext ctxt) throws IOException { switch (_kind) { case STD_FILE: return new File(value); case STD_URL: return new URL(value); case STD_URI: return URI.create(value); case STD_CLASS: try { return ctxt.findClass(value); } catch (Exception e) { return ctxt.handleInstantiationProblem(_valueClass, value, ClassUtil.getRootCause(e)); } case STD_JAVA_TYPE: return ctxt.getTypeFactory().constructFromCanonical(value); case STD_CURRENCY: // will throw IAE if unknown: return Currency.getInstance(value); case STD_PATTERN: // will throw IAE (or its subclass) if malformed return Pattern.compile(value); case STD_LOCALE: { int ix = _firstHyphenOrUnderscore(value); if (ix < 0) { // single argument return new Locale(value); } String first = value.substring(0, ix); value = value.substring(ix+1); ix = _firstHyphenOrUnderscore(value); if (ix < 0) { // two pieces return new Locale(first, value); } String second = value.substring(0, ix); return new Locale(first, second, value.substring(ix+1)); } case STD_CHARSET: return Charset.forName(value); case STD_TIME_ZONE: return TimeZone.getTimeZone(value); case STD_INET_ADDRESS: return InetAddress.getByName(value); case STD_INET_SOCKET_ADDRESS: if (value.startsWith("[")) { // bracketed IPv6 (with port number) int i = value.lastIndexOf(']'); if (i == -1) { throw new InvalidFormatException(ctxt.getParser(), "Bracketed IPv6 address must contain closing bracket", value, InetSocketAddress.class); } int j = value.indexOf(':', i); int port = j > -1 ? Integer.parseInt(value.substring(j + 1)) : 0; return new InetSocketAddress(value.substring(0, i + 1), port); } int ix = value.indexOf(':'); if (ix >= 0 && value.indexOf(':', ix + 1) < 0) { // host:port int port = Integer.parseInt(value.substring(ix+1)); return new InetSocketAddress(value.substring(0, ix), port); } // host or unbracketed IPv6, without port number return new InetSocketAddress(value, 0); case STD_STRING_BUILDER: return new StringBuilder(value); } VersionUtil.throwInternal(); return null; } @Override protected Object _deserializeFromEmptyString() throws IOException { // As per [databind#398], URI requires special handling if (_kind == STD_URI) { return URI.create(""); } // As per [databind#1123], Locale too if (_kind == STD_LOCALE) { return Locale.ROOT; } if (_kind == STD_STRING_BUILDER) { return new StringBuilder(); } return super._deserializeFromEmptyString(); } protected int _firstHyphenOrUnderscore(String str) { for (int i = 0, end = str.length(); i < end; ++i) { char c = str.charAt(i); if (c == '_' || c == '-') { return i; } } return -1; } } } JdkDeserializers.java000066400000000000000000000033211325620701100364440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import com.fasterxml.jackson.databind.*; /** * Container class that contains serializers for JDK types that * require special handling for some reason. */ public class JdkDeserializers { private final static HashSet _classNames = new HashSet(); static { // note: can skip primitive types; other ways to check them: Class[] types = new Class[] { UUID.class, AtomicBoolean.class, StackTraceElement.class, ByteBuffer.class }; for (Class cls : types) { _classNames.add(cls.getName()); } for (Class cls : FromStringDeserializer.types()) { _classNames.add(cls.getName()); } } public static JsonDeserializer find(Class rawType, String clsName) { if (_classNames.contains(clsName)) { JsonDeserializer d = FromStringDeserializer.findDeserializer(rawType); if (d != null) { return d; } if (rawType == UUID.class) { return new UUIDDeserializer(); } if (rawType == StackTraceElement.class) { return new StackTraceElementDeserializer(); } if (rawType == AtomicBoolean.class) { // (note: AtomicInteger/Long work due to single-arg constructor. For now? return new AtomicBooleanDeserializer(); } if (rawType == ByteBuffer.class) { return new ByteBufferDeserializer(); } } return null; } } JsonLocationInstantiator.java000066400000000000000000000043171325620701100402160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.PropertyMetadata; import com.fasterxml.jackson.databind.PropertyName; import com.fasterxml.jackson.databind.deser.CreatorProperty; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; /** * For {@link JsonLocation}, we should be able to just implement * {@link ValueInstantiator} (not that explicit one would be very * hard but...) */ public class JsonLocationInstantiator extends ValueInstantiator.Base { public JsonLocationInstantiator() { super(JsonLocation.class); } @Override public boolean canCreateFromObjectWith() { return true; } @Override public SettableBeanProperty[] getFromObjectArguments(DeserializationConfig config) { JavaType intType = config.constructType(Integer.TYPE); JavaType longType = config.constructType(Long.TYPE); return new SettableBeanProperty[] { creatorProp("sourceRef", config.constructType(Object.class), 0), creatorProp("byteOffset", longType, 1), creatorProp("charOffset", longType, 2), creatorProp("lineNr", intType, 3), creatorProp("columnNr", intType, 4) }; } private static CreatorProperty creatorProp(String name, JavaType type, int index) { return new CreatorProperty(PropertyName.construct(name), type, null, null, null, null, index, null, PropertyMetadata.STD_REQUIRED); } @Override public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) { return new JsonLocation(args[0], _long(args[1]), _long(args[2]), _int(args[3]), _int(args[4])); } private final static long _long(Object o) { return (o == null) ? 0L : ((Number) o).longValue(); } private final static int _int(Object o) { return (o == null) ? 0 : ((Number) o).intValue(); } } JsonNodeDeserializer.java000066400000000000000000000554031325620701100373000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.node.*; import com.fasterxml.jackson.databind.util.RawValue; /** * Deserializer that can build instances of {@link JsonNode} from any * JSON content, using appropriate {@link JsonNode} type. */ @SuppressWarnings("serial") public class JsonNodeDeserializer extends BaseNodeDeserializer { /** * Singleton instance of generic deserializer for {@link JsonNode}. * Only used for types other than JSON Object and Array. */ private final static JsonNodeDeserializer instance = new JsonNodeDeserializer(); protected JsonNodeDeserializer() { // `null` means that explicit "merge" is honored and may or may not work, but // that per-type and global defaults do not enable merging. This because // some node types (Object, Array) do support, others don't. super(JsonNode.class, null); } /** * Factory method for accessing deserializer for specific node type */ public static JsonDeserializer getDeserializer(Class nodeClass) { if (nodeClass == ObjectNode.class) { return ObjectDeserializer.getInstance(); } if (nodeClass == ArrayNode.class) { return ArrayDeserializer.getInstance(); } // For others, generic one works fine return instance; } /* /********************************************************** /* Actual deserializer implementations /********************************************************** */ @Override public JsonNode getNullValue(DeserializationContext ctxt) { return NullNode.getInstance(); } /** * Implementation that will produce types of any JSON nodes; not just one * deserializer is registered to handle (in case of more specialized handler). * Overridden by typed sub-classes for more thorough checking */ @Override public JsonNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_START_OBJECT: return deserializeObject(p, ctxt, ctxt.getNodeFactory()); case JsonTokenId.ID_START_ARRAY: return deserializeArray(p, ctxt, ctxt.getNodeFactory()); default: } return deserializeAny(p, ctxt, ctxt.getNodeFactory()); } /* /********************************************************** /* Specific instances for more accurate types /********************************************************** */ final static class ObjectDeserializer extends BaseNodeDeserializer { private static final long serialVersionUID = 1L; protected final static ObjectDeserializer _instance = new ObjectDeserializer(); protected ObjectDeserializer() { super(ObjectNode.class, true); } public static ObjectDeserializer getInstance() { return _instance; } @Override public ObjectNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.isExpectedStartObjectToken()) { return deserializeObject(p, ctxt, ctxt.getNodeFactory()); } if (p.hasToken(JsonToken.FIELD_NAME)) { return deserializeObjectAtName(p, ctxt, ctxt.getNodeFactory()); } // 23-Sep-2015, tatu: Ugh. We may also be given END_OBJECT (similar to FIELD_NAME), // if caller has advanced to the first token of Object, but for empty Object if (p.hasToken(JsonToken.END_OBJECT)) { return ctxt.getNodeFactory().objectNode(); } return (ObjectNode) ctxt.handleUnexpectedToken(ObjectNode.class, p); } /** * Variant needed to support both root-level `updateValue()` and merging. * * @since 2.9 */ @Override public ObjectNode deserialize(JsonParser p, DeserializationContext ctxt, ObjectNode node) throws IOException { if (p.isExpectedStartObjectToken() || p.hasToken(JsonToken.FIELD_NAME)) { return (ObjectNode) updateObject(p, ctxt, (ObjectNode) node); } return (ObjectNode) ctxt.handleUnexpectedToken(ObjectNode.class, p); } } final static class ArrayDeserializer extends BaseNodeDeserializer { private static final long serialVersionUID = 1L; protected final static ArrayDeserializer _instance = new ArrayDeserializer(); protected ArrayDeserializer() { super(ArrayNode.class, true); } public static ArrayDeserializer getInstance() { return _instance; } @Override public ArrayNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.isExpectedStartArrayToken()) { return deserializeArray(p, ctxt, ctxt.getNodeFactory()); } return (ArrayNode) ctxt.handleUnexpectedToken(ArrayNode.class, p); } /** * Variant needed to support both root-level `updateValue()` and merging. * * @since 2.9 */ @Override public ArrayNode deserialize(JsonParser p, DeserializationContext ctxt, ArrayNode node) throws IOException { if (p.isExpectedStartArrayToken()) { return (ArrayNode) updateArray(p, ctxt, (ArrayNode) node); } return (ArrayNode) ctxt.handleUnexpectedToken(ArrayNode.class, p); } } } /** * Base class for all actual {@link JsonNode} deserializer * implementations */ @SuppressWarnings("serial") abstract class BaseNodeDeserializer extends StdDeserializer { protected final Boolean _supportsUpdates; public BaseNodeDeserializer(Class vc, Boolean supportsUpdates) { super(vc); _supportsUpdates = supportsUpdates; } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // Output can be as JSON Object, Array or scalar: no way to know a priori: return typeDeserializer.deserializeTypedFromAny(p, ctxt); } /* 07-Nov-2014, tatu: When investigating [databind#604], realized that it makes * sense to also mark this is cachable, since lookup not exactly free, and * since it's not uncommon to "read anything" */ @Override public boolean isCachable() { return true; } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return _supportsUpdates; } /* /********************************************************** /* Overridable methods /********************************************************** */ /** * Method called when there is a duplicate value for a field. * By default we don't care, and the last value is used. * Can be overridden to provide alternate handling, such as throwing * an exception, or choosing different strategy for combining values * or choosing which one to keep. * * @param fieldName Name of the field for which duplicate value was found * @param objectNode Object node that contains values * @param oldValue Value that existed for the object node before newValue * was added * @param newValue Newly added value just added to the object node */ protected void _handleDuplicateField(JsonParser p, DeserializationContext ctxt, JsonNodeFactory nodeFactory, String fieldName, ObjectNode objectNode, JsonNode oldValue, JsonNode newValue) throws JsonProcessingException { // [databind#237]: Report an error if asked to do so: if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY)) { ctxt.reportInputMismatch(JsonNode.class, "Duplicate field '%s' for ObjectNode: not allowed when FAIL_ON_READING_DUP_TREE_KEY enabled", fieldName); } } /* /********************************************************** /* Helper methods /********************************************************** */ /** * Method called to deserialize Object node instance when there is no existing * node to modify. */ protected final ObjectNode deserializeObject(JsonParser p, DeserializationContext ctxt, final JsonNodeFactory nodeFactory) throws IOException { final ObjectNode node = nodeFactory.objectNode(); String key = p.nextFieldName(); for (; key != null; key = p.nextFieldName()) { JsonNode value; JsonToken t = p.nextToken(); if (t == null) { // can this ever occur? t = JsonToken.NOT_AVAILABLE; // can this ever occur? } switch (t.id()) { case JsonTokenId.ID_START_OBJECT: value = deserializeObject(p, ctxt, nodeFactory); break; case JsonTokenId.ID_START_ARRAY: value = deserializeArray(p, ctxt, nodeFactory); break; case JsonTokenId.ID_EMBEDDED_OBJECT: value = _fromEmbedded(p, ctxt, nodeFactory); break; case JsonTokenId.ID_STRING: value = nodeFactory.textNode(p.getText()); break; case JsonTokenId.ID_NUMBER_INT: value = _fromInt(p, ctxt, nodeFactory); break; case JsonTokenId.ID_TRUE: value = nodeFactory.booleanNode(true); break; case JsonTokenId.ID_FALSE: value = nodeFactory.booleanNode(false); break; case JsonTokenId.ID_NULL: value = nodeFactory.nullNode(); break; default: value = deserializeAny(p, ctxt, nodeFactory); } JsonNode old = node.replace(key, value); if (old != null) { _handleDuplicateField(p, ctxt, nodeFactory, key, node, old, value); } } return node; } /** * Alternate deserialization method used when parser already points to first * FIELD_NAME and not START_OBJECT. * * @since 2.9 */ protected final ObjectNode deserializeObjectAtName(JsonParser p, DeserializationContext ctxt, final JsonNodeFactory nodeFactory) throws IOException { final ObjectNode node = nodeFactory.objectNode(); String key = p.getCurrentName(); for (; key != null; key = p.nextFieldName()) { JsonNode value; JsonToken t = p.nextToken(); if (t == null) { // can this ever occur? t = JsonToken.NOT_AVAILABLE; // can this ever occur? } switch (t.id()) { case JsonTokenId.ID_START_OBJECT: value = deserializeObject(p, ctxt, nodeFactory); break; case JsonTokenId.ID_START_ARRAY: value = deserializeArray(p, ctxt, nodeFactory); break; case JsonTokenId.ID_EMBEDDED_OBJECT: value = _fromEmbedded(p, ctxt, nodeFactory); break; case JsonTokenId.ID_STRING: value = nodeFactory.textNode(p.getText()); break; case JsonTokenId.ID_NUMBER_INT: value = _fromInt(p, ctxt, nodeFactory); break; case JsonTokenId.ID_TRUE: value = nodeFactory.booleanNode(true); break; case JsonTokenId.ID_FALSE: value = nodeFactory.booleanNode(false); break; case JsonTokenId.ID_NULL: value = nodeFactory.nullNode(); break; default: value = deserializeAny(p, ctxt, nodeFactory); } JsonNode old = node.replace(key, value); if (old != null) { _handleDuplicateField(p, ctxt, nodeFactory, key, node, old, value); } } return node; } /** * Alternate deserialization method that is to update existing {@link ObjectNode} * if possible. * * @since 2.9 */ protected final JsonNode updateObject(JsonParser p, DeserializationContext ctxt, final ObjectNode node) throws IOException { String key; if (p.isExpectedStartObjectToken()) { key = p.nextFieldName(); } else { if (!p.hasToken(JsonToken.FIELD_NAME)) { return deserialize(p, ctxt); } key = p.getCurrentName(); } for (; key != null; key = p.nextFieldName()) { // If not, fall through to regular handling JsonToken t = p.nextToken(); // First: see if we can merge things: JsonNode old = node.get(key); if (old != null) { if (old instanceof ObjectNode) { JsonNode newValue = updateObject(p, ctxt, (ObjectNode) old); if (newValue != old) { node.set(key, newValue); } continue; } if (old instanceof ArrayNode) { JsonNode newValue = updateArray(p, ctxt, (ArrayNode) old); if (newValue != old) { node.set(key, newValue); } continue; } } if (t == null) { // can this ever occur? t = JsonToken.NOT_AVAILABLE; } JsonNode value; JsonNodeFactory nodeFactory = ctxt.getNodeFactory(); switch (t.id()) { case JsonTokenId.ID_START_OBJECT: value = deserializeObject(p, ctxt, nodeFactory); break; case JsonTokenId.ID_START_ARRAY: value = deserializeArray(p, ctxt, nodeFactory); break; case JsonTokenId.ID_EMBEDDED_OBJECT: value = _fromEmbedded(p, ctxt, nodeFactory); break; case JsonTokenId.ID_STRING: value = nodeFactory.textNode(p.getText()); break; case JsonTokenId.ID_NUMBER_INT: value = _fromInt(p, ctxt, nodeFactory); break; case JsonTokenId.ID_TRUE: value = nodeFactory.booleanNode(true); break; case JsonTokenId.ID_FALSE: value = nodeFactory.booleanNode(false); break; case JsonTokenId.ID_NULL: value = nodeFactory.nullNode(); break; default: value = deserializeAny(p, ctxt, nodeFactory); } if (old != null) { _handleDuplicateField(p, ctxt, nodeFactory, key, node, old, value); } node.set(key, value); } return node; } protected final ArrayNode deserializeArray(JsonParser p, DeserializationContext ctxt, final JsonNodeFactory nodeFactory) throws IOException { ArrayNode node = nodeFactory.arrayNode(); while (true) { JsonToken t = p.nextToken(); switch (t.id()) { case JsonTokenId.ID_START_OBJECT: node.add(deserializeObject(p, ctxt, nodeFactory)); break; case JsonTokenId.ID_START_ARRAY: node.add(deserializeArray(p, ctxt, nodeFactory)); break; case JsonTokenId.ID_END_ARRAY: return node; case JsonTokenId.ID_EMBEDDED_OBJECT: node.add(_fromEmbedded(p, ctxt, nodeFactory)); break; case JsonTokenId.ID_STRING: node.add(nodeFactory.textNode(p.getText())); break; case JsonTokenId.ID_NUMBER_INT: node.add(_fromInt(p, ctxt, nodeFactory)); break; case JsonTokenId.ID_TRUE: node.add(nodeFactory.booleanNode(true)); break; case JsonTokenId.ID_FALSE: node.add(nodeFactory.booleanNode(false)); break; case JsonTokenId.ID_NULL: node.add(nodeFactory.nullNode()); break; default: node.add(deserializeAny(p, ctxt, nodeFactory)); break; } } } /** * Alternate deserialization method that is to update existing {@link ObjectNode} * if possible. * * @since 2.9 */ protected final JsonNode updateArray(JsonParser p, DeserializationContext ctxt, final ArrayNode node) throws IOException { final JsonNodeFactory nodeFactory = ctxt.getNodeFactory(); while (true) { JsonToken t = p.nextToken(); switch (t.id()) { case JsonTokenId.ID_START_OBJECT: node.add(deserializeObject(p, ctxt, nodeFactory)); break; case JsonTokenId.ID_START_ARRAY: node.add(deserializeArray(p, ctxt, nodeFactory)); break; case JsonTokenId.ID_END_ARRAY: return node; case JsonTokenId.ID_EMBEDDED_OBJECT: node.add(_fromEmbedded(p, ctxt, nodeFactory)); break; case JsonTokenId.ID_STRING: node.add(nodeFactory.textNode(p.getText())); break; case JsonTokenId.ID_NUMBER_INT: node.add(_fromInt(p, ctxt, nodeFactory)); break; case JsonTokenId.ID_TRUE: node.add(nodeFactory.booleanNode(true)); break; case JsonTokenId.ID_FALSE: node.add(nodeFactory.booleanNode(false)); break; case JsonTokenId.ID_NULL: node.add(nodeFactory.nullNode()); break; default: node.add(deserializeAny(p, ctxt, nodeFactory)); break; } } } protected final JsonNode deserializeAny(JsonParser p, DeserializationContext ctxt, final JsonNodeFactory nodeFactory) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_END_OBJECT: // for empty JSON Objects we may point to this? return nodeFactory.objectNode(); case JsonTokenId.ID_FIELD_NAME: return deserializeObjectAtName(p, ctxt, nodeFactory); case JsonTokenId.ID_EMBEDDED_OBJECT: return _fromEmbedded(p, ctxt, nodeFactory); case JsonTokenId.ID_STRING: return nodeFactory.textNode(p.getText()); case JsonTokenId.ID_NUMBER_INT: return _fromInt(p, ctxt, nodeFactory); case JsonTokenId.ID_NUMBER_FLOAT: return _fromFloat(p, ctxt, nodeFactory); case JsonTokenId.ID_TRUE: return nodeFactory.booleanNode(true); case JsonTokenId.ID_FALSE: return nodeFactory.booleanNode(false); case JsonTokenId.ID_NULL: return nodeFactory.nullNode(); /* Caller checks for these, should not get here ever case JsonTokenId.ID_START_OBJECT: return deserializeObject(p, ctxt, nodeFactory); case JsonTokenId.ID_START_ARRAY: return deserializeArray(p, ctxt, nodeFactory); */ // These states cannot be mapped; input stream is // off by an event or two //case END_OBJECT: //case END_ARRAY: default: } return (JsonNode) ctxt.handleUnexpectedToken(handledType(), p); } protected final JsonNode _fromInt(JsonParser p, DeserializationContext ctxt, JsonNodeFactory nodeFactory) throws IOException { JsonParser.NumberType nt; int feats = ctxt.getDeserializationFeatures(); if ((feats & F_MASK_INT_COERCIONS) != 0) { if (DeserializationFeature.USE_BIG_INTEGER_FOR_INTS.enabledIn(feats)) { nt = JsonParser.NumberType.BIG_INTEGER; } else if (DeserializationFeature.USE_LONG_FOR_INTS.enabledIn(feats)) { nt = JsonParser.NumberType.LONG; } else { nt = p.getNumberType(); } } else { nt = p.getNumberType(); } if (nt == JsonParser.NumberType.INT) { return nodeFactory.numberNode(p.getIntValue()); } if (nt == JsonParser.NumberType.LONG) { return nodeFactory.numberNode(p.getLongValue()); } return nodeFactory.numberNode(p.getBigIntegerValue()); } protected final JsonNode _fromFloat(JsonParser p, DeserializationContext ctxt, final JsonNodeFactory nodeFactory) throws IOException { JsonParser.NumberType nt = p.getNumberType(); if (nt == JsonParser.NumberType.BIG_DECIMAL) { return nodeFactory.numberNode(p.getDecimalValue()); } if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { // 20-May-2016, tatu: As per [databind#1028], need to be careful // (note: JDK 1.8 would have `Double.isFinite()`) if (p.isNaN()) { return nodeFactory.numberNode(p.getDoubleValue()); } return nodeFactory.numberNode(p.getDecimalValue()); } if (nt == JsonParser.NumberType.FLOAT) { return nodeFactory.numberNode(p.getFloatValue()); } return nodeFactory.numberNode(p.getDoubleValue()); } protected final JsonNode _fromEmbedded(JsonParser p, DeserializationContext ctxt, JsonNodeFactory nodeFactory) throws IOException { Object ob = p.getEmbeddedObject(); if (ob == null) { // should this occur? return nodeFactory.nullNode(); } Class type = ob.getClass(); if (type == byte[].class) { // most common special case return nodeFactory.binaryNode((byte[]) ob); } // [databind#743]: Don't forget RawValue if (ob instanceof RawValue) { return nodeFactory.rawValueNode((RawValue) ob); } if (ob instanceof JsonNode) { // [databind#433]: but could also be a JsonNode hiding in there! return (JsonNode) ob; } // any other special handling needed? return nodeFactory.pojoNode(ob); } } MapDeserializer.java000066400000000000000000001012301325620701100362640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator; import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer; import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.ArrayBuilders; /** * Basic serializer that can take JSON "Object" structure and * construct a {@link java.util.Map} instance, with typed contents. *

* Note: for untyped content (one indicated by passing Object.class * as the type), {@link UntypedObjectDeserializer} is used instead. * It can also construct {@link java.util.Map}s, but not with specific * POJO types, only other containers and primitives/wrappers. */ @JacksonStdImpl public class MapDeserializer extends ContainerDeserializerBase> implements ContextualDeserializer, ResolvableDeserializer { private static final long serialVersionUID = 1L; // // Configuration: typing, deserializers /** * Key deserializer to use; either passed via constructor * (when indicated by annotations), or resolved when * {@link #resolve} is called; */ protected final KeyDeserializer _keyDeserializer; /** * Flag set to indicate that the key type is * {@link java.lang.String} (or {@link java.lang.Object}, for * which String is acceptable), and that the * default Jackson key deserializer would be used. * If both are true, can optimize handling. */ protected boolean _standardStringKey; /** * Value deserializer. */ protected final JsonDeserializer _valueDeserializer; /** * If value instances have polymorphic type information, this * is the type deserializer that can handle it */ protected final TypeDeserializer _valueTypeDeserializer; // // Instance construction settings: protected final ValueInstantiator _valueInstantiator; /** * Deserializer that is used iff delegate-based creator is * to be used for deserializing from JSON Object. */ protected JsonDeserializer _delegateDeserializer; /** * If the Map is to be instantiated using non-default constructor * or factory method * that takes one or more named properties as argument(s), * this creator is used for instantiation. */ protected PropertyBasedCreator _propertyBasedCreator; protected final boolean _hasDefaultCreator; // // Any properties to ignore if seen? protected Set _ignorableProperties; /* /********************************************************** /* Life-cycle /********************************************************** */ public MapDeserializer(JavaType mapType, ValueInstantiator valueInstantiator, KeyDeserializer keyDeser, JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser) { super(mapType, null, null); _keyDeserializer = keyDeser; _valueDeserializer = valueDeser; _valueTypeDeserializer = valueTypeDeser; _valueInstantiator = valueInstantiator; _hasDefaultCreator = valueInstantiator.canCreateUsingDefault(); _delegateDeserializer = null; _propertyBasedCreator = null; _standardStringKey = _isStdKeyDeser(mapType, keyDeser); } /** * Copy-constructor that can be used by sub-classes to allow * copy-on-write styling copying of settings of an existing instance. */ protected MapDeserializer(MapDeserializer src) { super(src); _keyDeserializer = src._keyDeserializer; _valueDeserializer = src._valueDeserializer; _valueTypeDeserializer = src._valueTypeDeserializer; _valueInstantiator = src._valueInstantiator; _propertyBasedCreator = src._propertyBasedCreator; _delegateDeserializer = src._delegateDeserializer; _hasDefaultCreator = src._hasDefaultCreator; // should we make a copy here? _ignorableProperties = src._ignorableProperties; _standardStringKey = src._standardStringKey; } protected MapDeserializer(MapDeserializer src, KeyDeserializer keyDeser, JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser, NullValueProvider nuller, Set ignorable) { super(src, nuller, src._unwrapSingle); _keyDeserializer = keyDeser; _valueDeserializer = valueDeser; _valueTypeDeserializer = valueTypeDeser; _valueInstantiator = src._valueInstantiator; _propertyBasedCreator = src._propertyBasedCreator; _delegateDeserializer = src._delegateDeserializer; _hasDefaultCreator = src._hasDefaultCreator; _ignorableProperties = ignorable; _standardStringKey = _isStdKeyDeser(_containerType, keyDeser); } /** * Fluent factory method used to create a copy with slightly * different settings. When sub-classing, MUST be overridden. */ @SuppressWarnings("unchecked") protected MapDeserializer withResolved(KeyDeserializer keyDeser, TypeDeserializer valueTypeDeser, JsonDeserializer valueDeser, NullValueProvider nuller, Set ignorable) { if ((_keyDeserializer == keyDeser) && (_valueDeserializer == valueDeser) && (_valueTypeDeserializer == valueTypeDeser) && (_nullProvider == nuller) && (_ignorableProperties == ignorable)) { return this; } return new MapDeserializer(this, keyDeser, (JsonDeserializer) valueDeser, valueTypeDeser, nuller, ignorable); } /** * Helper method used to check whether we can just use the default key * deserialization, where JSON String becomes Java String. */ protected final boolean _isStdKeyDeser(JavaType mapType, KeyDeserializer keyDeser) { if (keyDeser == null) { return true; } JavaType keyType = mapType.getKeyType(); if (keyType == null) { // assumed to be Object return true; } Class rawKeyType = keyType.getRawClass(); return ((rawKeyType == String.class || rawKeyType == Object.class) && isDefaultKeyDeserializer(keyDeser)); } public void setIgnorableProperties(String[] ignorable) { _ignorableProperties = (ignorable == null || ignorable.length == 0) ? null : ArrayBuilders.arrayToSet(ignorable); } public void setIgnorableProperties(Set ignorable) { _ignorableProperties = (ignorable == null || ignorable.size() == 0) ? null : ignorable; } /* /********************************************************** /* Validation, post-processing (ResolvableDeserializer) /********************************************************** */ @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException { // May need to resolve types for delegate- and/or property-based creators: if (_valueInstantiator.canCreateUsingDelegate()) { JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig()); if (delegateType == null) { ctxt.reportBadDefinition(_containerType, String.format( "Invalid delegate-creator definition for %s: value instantiator (%s) returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'", _containerType, _valueInstantiator.getClass().getName())); } // Theoretically should be able to get CreatorProperty for delegate // parameter to pass; but things get tricky because DelegateCreator // may contain injectable values. So, for now, let's pass nothing. _delegateDeserializer = findDeserializer(ctxt, delegateType, null); } else if (_valueInstantiator.canCreateUsingArrayDelegate()) { JavaType delegateType = _valueInstantiator.getArrayDelegateType(ctxt.getConfig()); if (delegateType == null) { ctxt.reportBadDefinition(_containerType, String.format( "Invalid delegate-creator definition for %s: value instantiator (%s) returned true for 'canCreateUsingArrayDelegate()', but null for 'getArrayDelegateType()'", _containerType, _valueInstantiator.getClass().getName())); } _delegateDeserializer = findDeserializer(ctxt, delegateType, null); } if (_valueInstantiator.canCreateFromObjectWith()) { SettableBeanProperty[] creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig()); _propertyBasedCreator = PropertyBasedCreator.construct(ctxt, _valueInstantiator, creatorProps, ctxt.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); } _standardStringKey = _isStdKeyDeser(_containerType, _keyDeserializer); } /** * Method called to finalize setup of this deserializer, * when it is known for which property deserializer is needed for. */ @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { KeyDeserializer keyDeser = _keyDeserializer; if (keyDeser == null) { keyDeser = ctxt.findKeyDeserializer(_containerType.getKeyType(), property); } else { if (keyDeser instanceof ContextualKeyDeserializer) { keyDeser = ((ContextualKeyDeserializer) keyDeser).createContextual(ctxt, property); } } JsonDeserializer valueDeser = _valueDeserializer; // [databind#125]: May have a content converter if (property != null) { valueDeser = findConvertingContentDeserializer(ctxt, property, valueDeser); } final JavaType vt = _containerType.getContentType(); if (valueDeser == null) { valueDeser = ctxt.findContextualValueDeserializer(vt, property); } else { // if directly assigned, probably not yet contextual, so: valueDeser = ctxt.handleSecondaryContextualization(valueDeser, property, vt); } TypeDeserializer vtd = _valueTypeDeserializer; if (vtd != null) { vtd = vtd.forProperty(property); } Set ignored = _ignorableProperties; AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (_neitherNull(intr, property)) { AnnotatedMember member = property.getMember(); if (member != null) { JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnorals(member); if (ignorals != null) { Set ignoresToAdd = ignorals.findIgnoredForDeserialization(); if (!ignoresToAdd.isEmpty()) { ignored = (ignored == null) ? new HashSet() : new HashSet(ignored); for (String str : ignoresToAdd) { ignored.add(str); } } } } } return withResolved(keyDeser, vtd, valueDeser, findContentNullProvider(ctxt, property, valueDeser), ignored); } /* /********************************************************** /* ContainerDeserializerBase API /********************************************************** */ @Override public JsonDeserializer getContentDeserializer() { return _valueDeserializer; } @Override public ValueInstantiator getValueInstantiator() { return _valueInstantiator; } /* /********************************************************** /* JsonDeserializer API /********************************************************** */ /** * Turns out that these are expensive enough to create so that caching * does make sense. *

* IMPORTANT: but, note, that instances CAN NOT BE CACHED if there is * a value type deserializer; this caused an issue with 2.4.4 of * JAXB Annotations (failing a test). * It is also possible that some other settings could make deserializers * un-cacheable; but on the other hand, caching can make a big positive * difference with performance... so it's a hard choice. * * @since 2.4.4 */ @Override public boolean isCachable() { // As per [databind#735], existence of value or key deserializer (only passed // if annotated to use non-standard one) should also prevent caching. return (_valueDeserializer == null) && (_keyDeserializer == null) && (_valueTypeDeserializer == null) && (_ignorableProperties == null); } @Override @SuppressWarnings("unchecked") public Map deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (_propertyBasedCreator != null) { return _deserializeUsingCreator(p, ctxt); } if (_delegateDeserializer != null) { return (Map) _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt)); } if (!_hasDefaultCreator) { return (Map ) ctxt.handleMissingInstantiator(getMapClass(), getValueInstantiator(), p, "no default constructor found"); } // Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT JsonToken t = p.getCurrentToken(); if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME && t != JsonToken.END_OBJECT) { // (empty) String may be ok however; or single-String-arg ctor if (t == JsonToken.VALUE_STRING) { return (Map) _valueInstantiator.createFromString(ctxt, p.getText()); } // slightly redundant (since String was passed above), but also handles empty array case: return _deserializeFromEmpty(p, ctxt); } final Map result = (Map) _valueInstantiator.createUsingDefault(ctxt); if (_standardStringKey) { _readAndBindStringKeyMap(p, ctxt, result); return result; } _readAndBind(p, ctxt, result); return result; } @SuppressWarnings("unchecked") @Override public Map deserialize(JsonParser p, DeserializationContext ctxt, Map result) throws IOException { // [databind#631]: Assign current value, to be accessible by custom deserializers p.setCurrentValue(result); // Ok: must point to START_OBJECT or FIELD_NAME JsonToken t = p.getCurrentToken(); if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME) { return (Map) ctxt.handleUnexpectedToken(getMapClass(), p); } // 21-Apr-2017, tatu: Need separate methods to do proper merging if (_standardStringKey) { _readAndUpdateStringKeyMap(p, ctxt, result); return result; } _readAndUpdate(p, ctxt, result); return result; } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // In future could check current token... for now this should be enough: return typeDeserializer.deserializeTypedFromObject(p, ctxt); } /* /********************************************************** /* Other public accessors /********************************************************** */ @SuppressWarnings("unchecked") public final Class getMapClass() { return (Class>) _containerType.getRawClass(); } @Override public JavaType getValueType() { return _containerType; } /* /********************************************************** /* Internal methods, non-merging deserialization /********************************************************** */ protected final void _readAndBind(JsonParser p, DeserializationContext ctxt, Map result) throws IOException { final KeyDeserializer keyDes = _keyDeserializer; final JsonDeserializer valueDes = _valueDeserializer; final TypeDeserializer typeDeser = _valueTypeDeserializer; MapReferringAccumulator referringAccumulator = null; boolean useObjectId = valueDes.getObjectIdReader() != null; if (useObjectId) { referringAccumulator = new MapReferringAccumulator(_containerType.getContentType().getRawClass(), result); } String keyStr; if (p.isExpectedStartObjectToken()) { keyStr = p.nextFieldName(); } else { JsonToken t = p.getCurrentToken(); if (t != JsonToken.FIELD_NAME) { if (t == JsonToken.END_OBJECT) { return; } ctxt.reportWrongTokenException(this, JsonToken.FIELD_NAME, null); } keyStr = p.getCurrentName(); } for (; keyStr != null; keyStr = p.nextFieldName()) { Object key = keyDes.deserializeKey(keyStr, ctxt); // And then the value... JsonToken t = p.nextToken(); if (_ignorableProperties != null && _ignorableProperties.contains(keyStr)) { p.skipChildren(); continue; } try { // Note: must handle null explicitly here; value deserializers won't Object value; if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = _nullProvider.getNullValue(ctxt); } else if (typeDeser == null) { value = valueDes.deserialize(p, ctxt); } else { value = valueDes.deserializeWithType(p, ctxt, typeDeser); } if (useObjectId) { referringAccumulator.put(key, value); } else { result.put(key, value); } } catch (UnresolvedForwardReference reference) { handleUnresolvedReference(ctxt, referringAccumulator, key, reference); } catch (Exception e) { wrapAndThrow(e, result, keyStr); } } } /** * Optimized method used when keys can be deserialized as plain old * {@link java.lang.String}s, and there is no custom deserialized * specified. */ protected final void _readAndBindStringKeyMap(JsonParser p, DeserializationContext ctxt, Map result) throws IOException { final JsonDeserializer valueDes = _valueDeserializer; final TypeDeserializer typeDeser = _valueTypeDeserializer; MapReferringAccumulator referringAccumulator = null; boolean useObjectId = (valueDes.getObjectIdReader() != null); if (useObjectId) { referringAccumulator = new MapReferringAccumulator(_containerType.getContentType().getRawClass(), result); } String key; if (p.isExpectedStartObjectToken()) { key = p.nextFieldName(); } else { JsonToken t = p.getCurrentToken(); if (t == JsonToken.END_OBJECT) { return; } if (t != JsonToken.FIELD_NAME) { ctxt.reportWrongTokenException(this, JsonToken.FIELD_NAME, null); } key = p.getCurrentName(); } for (; key != null; key = p.nextFieldName()) { JsonToken t = p.nextToken(); if (_ignorableProperties != null && _ignorableProperties.contains(key)) { p.skipChildren(); continue; } try { // Note: must handle null explicitly here; value deserializers won't Object value; if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = _nullProvider.getNullValue(ctxt); } else if (typeDeser == null) { value = valueDes.deserialize(p, ctxt); } else { value = valueDes.deserializeWithType(p, ctxt, typeDeser); } if (useObjectId) { referringAccumulator.put(key, value); } else { result.put(key, value); } } catch (UnresolvedForwardReference reference) { handleUnresolvedReference(ctxt, referringAccumulator, key, reference); } catch (Exception e) { wrapAndThrow(e, result, key); } } // 23-Mar-2015, tatu: TODO: verify we got END_OBJECT? } @SuppressWarnings("unchecked") public Map _deserializeUsingCreator(JsonParser p, DeserializationContext ctxt) throws IOException { final PropertyBasedCreator creator = _propertyBasedCreator; // null -> no ObjectIdReader for Maps (yet?) PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, null); final JsonDeserializer valueDes = _valueDeserializer; final TypeDeserializer typeDeser = _valueTypeDeserializer; String key; if (p.isExpectedStartObjectToken()) { key = p.nextFieldName(); } else if (p.hasToken(JsonToken.FIELD_NAME)) { key = p.getCurrentName(); } else { key = null; } for (; key != null; key = p.nextFieldName()) { JsonToken t = p.nextToken(); // to get to value if (_ignorableProperties != null && _ignorableProperties.contains(key)) { p.skipChildren(); // and skip it (in case of array/object) continue; } // creator property? SettableBeanProperty prop = creator.findCreatorProperty(key); if (prop != null) { // Last property to set? if (buffer.assignParameter(prop, prop.deserialize(p, ctxt))) { p.nextToken(); // from value to END_OBJECT or FIELD_NAME Map result; try { result = (Map)creator.build(ctxt, buffer); } catch (Exception e) { return wrapAndThrow(e, _containerType.getRawClass(), key); } _readAndBind(p, ctxt, result); return result; } continue; } // other property? needs buffering Object actualKey = _keyDeserializer.deserializeKey(key, ctxt); Object value; try { if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = _nullProvider.getNullValue(ctxt); } else if (typeDeser == null) { value = valueDes.deserialize(p, ctxt); } else { value = valueDes.deserializeWithType(p, ctxt, typeDeser); } } catch (Exception e) { wrapAndThrow(e, _containerType.getRawClass(), key); return null; } buffer.bufferMapProperty(actualKey, value); } // end of JSON object? // if so, can just construct and leave... try { return (Map)creator.build(ctxt, buffer); } catch (Exception e) { wrapAndThrow(e, _containerType.getRawClass(), key); return null; } } /* /********************************************************** /* Internal methods, non-merging deserialization /********************************************************** */ /** * @since 2.9 */ protected final void _readAndUpdate(JsonParser p, DeserializationContext ctxt, Map result) throws IOException { final KeyDeserializer keyDes = _keyDeserializer; final JsonDeserializer valueDes = _valueDeserializer; final TypeDeserializer typeDeser = _valueTypeDeserializer; // Note: assumption is that Object Id handling can't really work with merging // and thereby we can (and should) just drop that part String keyStr; if (p.isExpectedStartObjectToken()) { keyStr = p.nextFieldName(); } else { JsonToken t = p.getCurrentToken(); if (t == JsonToken.END_OBJECT) { return; } if (t != JsonToken.FIELD_NAME) { ctxt.reportWrongTokenException(this, JsonToken.FIELD_NAME, null); } keyStr = p.getCurrentName(); } for (; keyStr != null; keyStr = p.nextFieldName()) { Object key = keyDes.deserializeKey(keyStr, ctxt); // And then the value... JsonToken t = p.nextToken(); if (_ignorableProperties != null && _ignorableProperties.contains(keyStr)) { p.skipChildren(); continue; } try { // Note: must handle null explicitly here, can't merge etc if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } result.put(key, _nullProvider.getNullValue(ctxt)); continue; } Object old = result.get(key); Object value; if (old != null) { value = valueDes.deserialize(p, ctxt, old); } else if (typeDeser == null) { value = valueDes.deserialize(p, ctxt); } else { value = valueDes.deserializeWithType(p, ctxt, typeDeser); } if (value != old) { result.put(key, value); } } catch (Exception e) { wrapAndThrow(e, result, keyStr); } } } /** * Optimized method used when keys can be deserialized as plain old * {@link java.lang.String}s, and there is no custom deserialized * specified. * * @since 2.9 */ protected final void _readAndUpdateStringKeyMap(JsonParser p, DeserializationContext ctxt, Map result) throws IOException { final JsonDeserializer valueDes = _valueDeserializer; final TypeDeserializer typeDeser = _valueTypeDeserializer; // Note: assumption is that Object Id handling can't really work with merging // and thereby we can (and should) just drop that part String key; if (p.isExpectedStartObjectToken()) { key = p.nextFieldName(); } else { JsonToken t = p.getCurrentToken(); if (t == JsonToken.END_OBJECT) { return; } if (t != JsonToken.FIELD_NAME) { ctxt.reportWrongTokenException(this, JsonToken.FIELD_NAME, null); } key = p.getCurrentName(); } for (; key != null; key = p.nextFieldName()) { JsonToken t = p.nextToken(); if (_ignorableProperties != null && _ignorableProperties.contains(key)) { p.skipChildren(); continue; } try { // Note: must handle null explicitly here, can't merge etc if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } result.put(key, _nullProvider.getNullValue(ctxt)); continue; } Object old = result.get(key); Object value; if (old != null) { value = valueDes.deserialize(p, ctxt, old); } else if (typeDeser == null) { value = valueDes.deserialize(p, ctxt); } else { value = valueDes.deserializeWithType(p, ctxt, typeDeser); } if (value != old) { result.put(key, value); } } catch (Exception e) { wrapAndThrow(e, result, key); } } } /* /********************************************************** /* Internal methods, other /********************************************************** */ private void handleUnresolvedReference(DeserializationContext ctxt, MapReferringAccumulator accumulator, Object key, UnresolvedForwardReference reference) throws JsonMappingException { if (accumulator == null) { ctxt.reportInputMismatch(this, "Unresolved forward reference but no identity info: "+reference); } Referring referring = accumulator.handleUnresolvedReference(reference, key); reference.getRoid().appendReferring(referring); } private final static class MapReferringAccumulator { private final Class _valueType; private Map _result; /** * A list of {@link MapReferring} to maintain ordering. */ private List _accumulator = new ArrayList(); public MapReferringAccumulator(Class valueType, Map result) { _valueType = valueType; _result = result; } public void put(Object key, Object value) { if (_accumulator.isEmpty()) { _result.put(key, value); } else { MapReferring ref = _accumulator.get(_accumulator.size() - 1); ref.next.put(key, value); } } public Referring handleUnresolvedReference(UnresolvedForwardReference reference, Object key) { MapReferring id = new MapReferring(this, reference, _valueType, key); _accumulator.add(id); return id; } public void resolveForwardReference(Object id, Object value) throws IOException { Iterator iterator = _accumulator.iterator(); // Resolve ordering after resolution of an id. This means either: // 1- adding to the result map in case of the first unresolved id. // 2- merge the content of the resolved id with its previous unresolved id. Map previous = _result; while (iterator.hasNext()) { MapReferring ref = iterator.next(); if (ref.hasId(id)) { iterator.remove(); previous.put(ref.key, value); previous.putAll(ref.next); return; } previous = ref.next; } throw new IllegalArgumentException("Trying to resolve a forward reference with id [" + id + "] that wasn't previously seen as unresolved."); } } /** * Helper class to maintain processing order of value. * The resolved object associated with {@link #key} comes before the values in * {@link #next}. */ static class MapReferring extends Referring { private final MapReferringAccumulator _parent; public final Map next = new LinkedHashMap(); public final Object key; MapReferring(MapReferringAccumulator parent, UnresolvedForwardReference ref, Class valueType, Object key) { super(ref, valueType); _parent = parent; this.key = key; } @Override public void handleResolvedForwardReference(Object id, Object value) throws IOException { _parent.resolveForwardReference(id, value); } } } MapEntryDeserializer.java000066400000000000000000000213321325620701100373120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; /** * Basic serializer that can take JSON "Object" structure and * construct a {@link java.util.Map} instance, with typed contents. *

* Note: for untyped content (one indicated by passing Object.class * as the type), {@link UntypedObjectDeserializer} is used instead. * It can also construct {@link java.util.Map}s, but not with specific * POJO types, only other containers and primitives/wrappers. */ @JacksonStdImpl public class MapEntryDeserializer extends ContainerDeserializerBase> implements ContextualDeserializer { private static final long serialVersionUID = 1; // // Configuration: typing, deserializers /** * Key deserializer to use; either passed via constructor * (when indicated by annotations), or resolved when * {@link #createContextual} is called; */ protected final KeyDeserializer _keyDeserializer; /** * Value deserializer. */ protected final JsonDeserializer _valueDeserializer; /** * If value instances have polymorphic type information, this * is the type deserializer that can handle it */ protected final TypeDeserializer _valueTypeDeserializer; /* /********************************************************** /* Life-cycle /********************************************************** */ public MapEntryDeserializer(JavaType type, KeyDeserializer keyDeser, JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser) { super(type); if (type.containedTypeCount() != 2) { // sanity check throw new IllegalArgumentException("Missing generic type information for "+type); } _keyDeserializer = keyDeser; _valueDeserializer = valueDeser; _valueTypeDeserializer = valueTypeDeser; } /** * Copy-constructor that can be used by sub-classes to allow * copy-on-write styling copying of settings of an existing instance. */ protected MapEntryDeserializer(MapEntryDeserializer src) { super(src); _keyDeserializer = src._keyDeserializer; _valueDeserializer = src._valueDeserializer; _valueTypeDeserializer = src._valueTypeDeserializer; } protected MapEntryDeserializer(MapEntryDeserializer src, KeyDeserializer keyDeser, JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser) { super(src); _keyDeserializer = keyDeser; _valueDeserializer = valueDeser; _valueTypeDeserializer = valueTypeDeser; } /** * Fluent factory method used to create a copy with slightly * different settings. When sub-classing, MUST be overridden. */ @SuppressWarnings("unchecked") protected MapEntryDeserializer withResolved(KeyDeserializer keyDeser, TypeDeserializer valueTypeDeser, JsonDeserializer valueDeser) { if ((_keyDeserializer == keyDeser) && (_valueDeserializer == valueDeser) && (_valueTypeDeserializer == valueTypeDeser)) { return this; } return new MapEntryDeserializer(this, keyDeser, (JsonDeserializer) valueDeser, valueTypeDeser); } /* /********************************************************** /* Validation, post-processing (ResolvableDeserializer) /********************************************************** */ /** * Method called to finalize setup of this deserializer, * when it is known for which property deserializer is needed for. */ @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { KeyDeserializer kd = _keyDeserializer; if (kd == null) { kd = ctxt.findKeyDeserializer(_containerType.containedType(0), property); } else { if (kd instanceof ContextualKeyDeserializer) { kd = ((ContextualKeyDeserializer) kd).createContextual(ctxt, property); } } JsonDeserializer vd = _valueDeserializer; vd = findConvertingContentDeserializer(ctxt, property, vd); JavaType contentType = _containerType.containedType(1); if (vd == null) { vd = ctxt.findContextualValueDeserializer(contentType, property); } else { // if directly assigned, probably not yet contextual, so: vd = ctxt.handleSecondaryContextualization(vd, property, contentType); } TypeDeserializer vtd = _valueTypeDeserializer; if (vtd != null) { vtd = vtd.forProperty(property); } return withResolved(kd, vtd, vd); } /* /********************************************************** /* ContainerDeserializerBase API /********************************************************** */ @Override public JavaType getContentType() { return _containerType.containedType(1); } @Override public JsonDeserializer getContentDeserializer() { return _valueDeserializer; } /* /********************************************************** /* JsonDeserializer API /********************************************************** */ @SuppressWarnings("unchecked") @Override public Map.Entry deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT JsonToken t = p.getCurrentToken(); if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME && t != JsonToken.END_OBJECT) { // String may be ok however: // slightly redundant (since String was passed above), but return _deserializeFromEmpty(p, ctxt); } if (t == JsonToken.START_OBJECT) { t = p.nextToken(); } if (t != JsonToken.FIELD_NAME) { if (t == JsonToken.END_OBJECT) { return ctxt.reportInputMismatch(this, "Cannot deserialize a Map.Entry out of empty JSON Object"); } return (Map.Entry) ctxt.handleUnexpectedToken(handledType(), p); } final KeyDeserializer keyDes = _keyDeserializer; final JsonDeserializer valueDes = _valueDeserializer; final TypeDeserializer typeDeser = _valueTypeDeserializer; final String keyStr = p.getCurrentName(); Object key = keyDes.deserializeKey(keyStr, ctxt); Object value = null; // And then the value... t = p.nextToken(); try { // Note: must handle null explicitly here; value deserializers won't if (t == JsonToken.VALUE_NULL) { value = valueDes.getNullValue(ctxt); } else if (typeDeser == null) { value = valueDes.deserialize(p, ctxt); } else { value = valueDes.deserializeWithType(p, ctxt, typeDeser); } } catch (Exception e) { wrapAndThrow(e, Map.Entry.class, keyStr); } // Close, but also verify that we reached the END_OBJECT t = p.nextToken(); if (t != JsonToken.END_OBJECT) { if (t == JsonToken.FIELD_NAME) { // most likely ctxt.reportInputMismatch(this, "Problem binding JSON into Map.Entry: more than one entry in JSON (second field: '%s')", p.getCurrentName()); } else { // how would this occur? ctxt.reportInputMismatch(this, "Problem binding JSON into Map.Entry: unexpected content after JSON Object entry: "+t); } return null; } return new AbstractMap.SimpleEntry(key, value); } @Override public Map.Entry deserialize(JsonParser p, DeserializationContext ctxt, Map.Entry result) throws IOException { throw new IllegalStateException("Cannot update Map.Entry values"); } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // In future could check current token... for now this should be enough: return typeDeserializer.deserializeTypedFromObject(p, ctxt); } } NullifyingDeserializer.java000066400000000000000000000037751325620701100377060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; /** * Bogus deserializer that will simply skip all content there is to map * and returns Java null reference. * * @since 2.2 */ public class NullifyingDeserializer extends StdDeserializer { private static final long serialVersionUID = 1L; public final static NullifyingDeserializer instance = new NullifyingDeserializer(); public NullifyingDeserializer() { super(Object.class); } /* /********************************************************** /* Deserializer API /********************************************************** */ @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return Boolean.FALSE; } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 29-Jan-2016, tatu: Simple skipping for all other tokens, but FIELD_NAME bit // special unfortunately if (p.hasToken(JsonToken.FIELD_NAME)) { while (true) { JsonToken t = p.nextToken(); if ((t == null) || (t == JsonToken.END_OBJECT)) { break; } p.skipChildren(); } } else { p.skipChildren(); } return null; } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // Not sure if we need to bother but: switch (p.getCurrentTokenId()) { case JsonTokenId.ID_START_ARRAY: case JsonTokenId.ID_START_OBJECT: case JsonTokenId.ID_FIELD_NAME: return typeDeserializer.deserializeTypedFromAny(p, ctxt); default: return null; } } } NumberDeserializers.java000066400000000000000000001141001325620701100371620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.HashSet; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.NumberInput; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.AccessPattern; /** * Container class for deserializers that handle core JDK primitive * (and matching wrapper) types, as well as standard "big" numeric types. * Note that this includes types such as {@link java.lang.Boolean} * and {@link java.lang.Character} which are not strictly numeric, * but are part of primitive/wrapper types. */ public class NumberDeserializers { private final static HashSet _classNames = new HashSet(); static { // note: can skip primitive types; other ways to check them: Class[] numberTypes = new Class[] { Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Long.class, Float.class, Double.class, // and more generic ones Number.class, BigDecimal.class, BigInteger.class }; for (Class cls : numberTypes) { _classNames.add(cls.getName()); } } public static JsonDeserializer find(Class rawType, String clsName) { if (rawType.isPrimitive()) { if (rawType == Integer.TYPE) { return IntegerDeserializer.primitiveInstance; } if (rawType == Boolean.TYPE) { return BooleanDeserializer.primitiveInstance; } if (rawType == Long.TYPE) { return LongDeserializer.primitiveInstance; } if (rawType == Double.TYPE) { return DoubleDeserializer.primitiveInstance; } if (rawType == Character.TYPE) { return CharacterDeserializer.primitiveInstance; } if (rawType == Byte.TYPE) { return ByteDeserializer.primitiveInstance; } if (rawType == Short.TYPE) { return ShortDeserializer.primitiveInstance; } if (rawType == Float.TYPE) { return FloatDeserializer.primitiveInstance; } } else if (_classNames.contains(clsName)) { // Start with most common types; int, boolean, long, double if (rawType == Integer.class) { return IntegerDeserializer.wrapperInstance; } if (rawType == Boolean.class) { return BooleanDeserializer.wrapperInstance; } if (rawType == Long.class) { return LongDeserializer.wrapperInstance; } if (rawType == Double.class) { return DoubleDeserializer.wrapperInstance; } if (rawType == Character.class) { return CharacterDeserializer.wrapperInstance; } if (rawType == Byte.class) { return ByteDeserializer.wrapperInstance; } if (rawType == Short.class) { return ShortDeserializer.wrapperInstance; } if (rawType == Float.class) { return FloatDeserializer.wrapperInstance; } if (rawType == Number.class) { return NumberDeserializer.instance; } if (rawType == BigDecimal.class) { return BigDecimalDeserializer.instance; } if (rawType == BigInteger.class) { return BigIntegerDeserializer.instance; } } else { return null; } // should never occur throw new IllegalArgumentException("Internal error: can't find deserializer for "+rawType.getName()); } /* /********************************************************** /* Then one intermediate base class for things that have /* both primitive and wrapper types /********************************************************** */ protected abstract static class PrimitiveOrWrapperDeserializer extends StdScalarDeserializer { private static final long serialVersionUID = 1L; protected final T _nullValue; // @since 2.9 protected final T _emptyValue; protected final boolean _primitive; protected PrimitiveOrWrapperDeserializer(Class vc, T nvl, T empty) { super(vc); _nullValue = nvl; _emptyValue = empty; _primitive = vc.isPrimitive(); } @Override public AccessPattern getNullAccessPattern() { // 02-Feb-2017, tatu: For primitives we must dynamically check (and possibly throw // exception); for wrappers not. if (_primitive) { return AccessPattern.DYNAMIC; } if (_nullValue == null) { return AccessPattern.ALWAYS_NULL; } return AccessPattern.CONSTANT; } @Override public final T getNullValue(DeserializationContext ctxt) throws JsonMappingException { // 01-Mar-2017, tatu: Alas, not all paths lead to `_coerceNull()`, as `SettableBeanProperty` // short-circuits `null` handling. Hence need this check as well. if (_primitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) { ctxt.reportInputMismatch(this, "Cannot map `null` into type %s (set DeserializationConfig.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES to 'false' to allow)", handledType().toString()); } return _nullValue; } @Override public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { return _emptyValue; } } /* /********************************************************** /* Then primitive/wrapper types /********************************************************** */ @JacksonStdImpl public final static class BooleanDeserializer extends PrimitiveOrWrapperDeserializer { private static final long serialVersionUID = 1L; final static BooleanDeserializer primitiveInstance = new BooleanDeserializer(Boolean.TYPE, Boolean.FALSE); final static BooleanDeserializer wrapperInstance = new BooleanDeserializer(Boolean.class, null); public BooleanDeserializer(Class cls, Boolean nvl) { super(cls, nvl, Boolean.FALSE); } @Override public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_TRUE) { return Boolean.TRUE; } if (t == JsonToken.VALUE_FALSE) { return Boolean.FALSE; } return _parseBoolean(p, ctxt); } // Since we can never have type info ("natural type"; String, Boolean, Integer, Double): // (is it an error to even call this version?) @Override public Boolean deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_TRUE) { return Boolean.TRUE; } if (t == JsonToken.VALUE_FALSE) { return Boolean.FALSE; } return _parseBoolean(p, ctxt); } protected final Boolean _parseBoolean(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_NULL) { return (Boolean) _coerceNullToken(ctxt, _primitive); } if (t == JsonToken.START_ARRAY) { // unwrapping? return _deserializeFromArray(p, ctxt); } // should accept ints too, (0 == false, otherwise true) if (t == JsonToken.VALUE_NUMBER_INT) { return Boolean.valueOf(_parseBooleanFromInt(p, ctxt)); } // And finally, let's allow Strings to be converted too if (t == JsonToken.VALUE_STRING) { String text = p.getText().trim(); // [databind#422]: Allow aliases if ("true".equals(text) || "True".equals(text)) { _verifyStringForScalarCoercion(ctxt, text); return Boolean.TRUE; } if ("false".equals(text) || "False".equals(text)) { _verifyStringForScalarCoercion(ctxt, text); return Boolean.FALSE; } if (text.length() == 0) { return (Boolean) _coerceEmptyString(ctxt, _primitive); } if (_hasTextualNull(text)) { return (Boolean) _coerceTextualNull(ctxt, _primitive); } return (Boolean) ctxt.handleWeirdStringValue(_valueClass, text, "only \"true\" or \"false\" recognized"); } // usually caller should have handled but: if (t == JsonToken.VALUE_TRUE) { return Boolean.TRUE; } if (t == JsonToken.VALUE_FALSE) { return Boolean.FALSE; } // Otherwise, no can do: return (Boolean) ctxt.handleUnexpectedToken(_valueClass, p); } } @JacksonStdImpl public static class ByteDeserializer extends PrimitiveOrWrapperDeserializer { private static final long serialVersionUID = 1L; final static ByteDeserializer primitiveInstance = new ByteDeserializer(Byte.TYPE, (byte) 0); final static ByteDeserializer wrapperInstance = new ByteDeserializer(Byte.class, null); public ByteDeserializer(Class cls, Byte nvl) { super(cls, nvl, (byte) 0); } @Override public Byte deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) { return p.getByteValue(); } return _parseByte(p, ctxt); } protected Byte _parseByte(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse String text = p.getText().trim(); if (_hasTextualNull(text)) { return (Byte) _coerceTextualNull(ctxt, _primitive); } int len = text.length(); if (len == 0) { return (Byte) _coerceEmptyString(ctxt, _primitive); } _verifyStringForScalarCoercion(ctxt, text); int value; try { value = NumberInput.parseInt(text); } catch (IllegalArgumentException iae) { return (Byte) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid Byte value"); } // So far so good: but does it fit? // as per [JACKSON-804], allow range up to 255, inclusive if (_byteOverflow(value)) { return (Byte) ctxt.handleWeirdStringValue(_valueClass, text, "overflow, value cannot be represented as 8-bit value"); // fall-through for deferred fails } return Byte.valueOf((byte) value); } if (t == JsonToken.VALUE_NUMBER_FLOAT) { if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) { _failDoubleToIntCoercion(p, ctxt, "Byte"); } return p.getByteValue(); } if (t == JsonToken.VALUE_NULL) { return (Byte) _coerceNullToken(ctxt, _primitive); } // [databind#381] if (t == JsonToken.START_ARRAY) { return _deserializeFromArray(p, ctxt); } if (t == JsonToken.VALUE_NUMBER_INT) { // shouldn't usually be called with it but return p.getByteValue(); } return (Byte) ctxt.handleUnexpectedToken(_valueClass, p); } } @JacksonStdImpl public static class ShortDeserializer extends PrimitiveOrWrapperDeserializer { private static final long serialVersionUID = 1L; final static ShortDeserializer primitiveInstance = new ShortDeserializer(Short.TYPE, Short.valueOf((short)0)); final static ShortDeserializer wrapperInstance = new ShortDeserializer(Short.class, null); public ShortDeserializer(Class cls, Short nvl) { super(cls, nvl, (short)0); } @Override public Short deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return _parseShort(p, ctxt); } protected Short _parseShort(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_NUMBER_INT) { return p.getShortValue(); } if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse String text = p.getText().trim(); int len = text.length(); if (len == 0) { return (Short) _coerceEmptyString(ctxt, _primitive); } if (_hasTextualNull(text)) { return (Short) _coerceTextualNull(ctxt, _primitive); } _verifyStringForScalarCoercion(ctxt, text); int value; try { value = NumberInput.parseInt(text); } catch (IllegalArgumentException iae) { return (Short) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid Short value"); } // So far so good: but does it fit? if (_shortOverflow(value)) { return (Short) ctxt.handleWeirdStringValue(_valueClass, text, "overflow, value cannot be represented as 16-bit value"); } return Short.valueOf((short) value); } if (t == JsonToken.VALUE_NUMBER_FLOAT) { if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) { _failDoubleToIntCoercion(p, ctxt, "Short"); } return p.getShortValue(); } if (t == JsonToken.VALUE_NULL) { return (Short) _coerceNullToken(ctxt, _primitive); } if (t == JsonToken.START_ARRAY) { return _deserializeFromArray(p, ctxt); } return (Short) ctxt.handleUnexpectedToken(_valueClass, p); } } @JacksonStdImpl public static class CharacterDeserializer extends PrimitiveOrWrapperDeserializer { private static final long serialVersionUID = 1L; final static CharacterDeserializer primitiveInstance = new CharacterDeserializer(Character.TYPE, '\0'); final static CharacterDeserializer wrapperInstance = new CharacterDeserializer(Character.class, null); public CharacterDeserializer(Class cls, Character nvl) { super(cls, nvl, '\0'); } @Override public Character deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_NUMBER_INT: // ok iff ascii value _verifyNumberForScalarCoercion(ctxt, p); int value = p.getIntValue(); if (value >= 0 && value <= 0xFFFF) { return Character.valueOf((char) value); } break; case JsonTokenId.ID_STRING: // this is the usual type // But does it have to be exactly one char? String text = p.getText(); if (text.length() == 1) { return Character.valueOf(text.charAt(0)); } // actually, empty should become null? if (text.length() == 0) { return (Character) _coerceEmptyString(ctxt, _primitive); } break; case JsonTokenId.ID_NULL: return (Character) _coerceNullToken(ctxt, _primitive); case JsonTokenId.ID_START_ARRAY: return _deserializeFromArray(p, ctxt); default: } return (Character) ctxt.handleUnexpectedToken(_valueClass, p); } } @JacksonStdImpl public final static class IntegerDeserializer extends PrimitiveOrWrapperDeserializer { private static final long serialVersionUID = 1L; final static IntegerDeserializer primitiveInstance = new IntegerDeserializer(Integer.TYPE, 0); final static IntegerDeserializer wrapperInstance = new IntegerDeserializer(Integer.class, null); public IntegerDeserializer(Class cls, Integer nvl) { super(cls, nvl, 0); } // since 2.6, slightly faster lookups for this very common type @Override public boolean isCachable() { return true; } @Override public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) { return p.getIntValue(); } return _parseInteger(p, ctxt); } // Since we can never have type info ("natural type"; String, Boolean, Integer, Double): // (is it an error to even call this version?) @Override public Integer deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) { return p.getIntValue(); } return _parseInteger(p, ctxt); } protected final Integer _parseInteger(JsonParser p, DeserializationContext ctxt) throws IOException { switch (p.getCurrentTokenId()) { // NOTE: caller assumed to usually check VALUE_NUMBER_INT in fast path case JsonTokenId.ID_NUMBER_INT: return Integer.valueOf(p.getIntValue()); case JsonTokenId.ID_NUMBER_FLOAT: // coercing may work too if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) { _failDoubleToIntCoercion(p, ctxt, "Integer"); } return Integer.valueOf(p.getValueAsInt()); case JsonTokenId.ID_STRING: // let's do implicit re-parse String text = p.getText().trim(); int len = text.length(); if (len == 0) { return (Integer) _coerceEmptyString(ctxt, _primitive); } if (_hasTextualNull(text)) { return (Integer) _coerceTextualNull(ctxt, _primitive); } _verifyStringForScalarCoercion(ctxt, text); try { if (len > 9) { long l = Long.parseLong(text); if (_intOverflow(l)) { return (Integer) ctxt.handleWeirdStringValue(_valueClass, text, String.format( "Overflow: numeric value (%s) out of range of Integer (%d - %d)", text, Integer.MIN_VALUE, Integer.MAX_VALUE)); } return Integer.valueOf((int) l); } return Integer.valueOf(NumberInput.parseInt(text)); } catch (IllegalArgumentException iae) { return (Integer) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid Integer value"); } case JsonTokenId.ID_NULL: return (Integer) _coerceNullToken(ctxt, _primitive); case JsonTokenId.ID_START_ARRAY: return _deserializeFromArray(p, ctxt); } // Otherwise, no can do: return (Integer) ctxt.handleUnexpectedToken(_valueClass, p); } } @JacksonStdImpl public final static class LongDeserializer extends PrimitiveOrWrapperDeserializer { private static final long serialVersionUID = 1L; final static LongDeserializer primitiveInstance = new LongDeserializer(Long.TYPE, 0L); final static LongDeserializer wrapperInstance = new LongDeserializer(Long.class, null); public LongDeserializer(Class cls, Long nvl) { super(cls, nvl, 0L); } // since 2.6, slightly faster lookups for this very common type @Override public boolean isCachable() { return true; } @Override public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) { return p.getLongValue(); } return _parseLong(p, ctxt); } protected final Long _parseLong(JsonParser p, DeserializationContext ctxt) throws IOException { switch (p.getCurrentTokenId()) { // NOTE: caller assumed to usually check VALUE_NUMBER_INT in fast path case JsonTokenId.ID_NUMBER_INT: return p.getLongValue(); case JsonTokenId.ID_NUMBER_FLOAT: if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) { _failDoubleToIntCoercion(p, ctxt, "Long"); } return p.getValueAsLong(); case JsonTokenId.ID_STRING: String text = p.getText().trim(); if (text.length() == 0) { return (Long) _coerceEmptyString(ctxt, _primitive); } if (_hasTextualNull(text)) { return (Long) _coerceTextualNull(ctxt, _primitive); } _verifyStringForScalarCoercion(ctxt, text); // let's allow Strings to be converted too try { return Long.valueOf(NumberInput.parseLong(text)); } catch (IllegalArgumentException iae) { } return (Long) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid Long value"); // fall-through case JsonTokenId.ID_NULL: return (Long) _coerceNullToken(ctxt, _primitive); case JsonTokenId.ID_START_ARRAY: return _deserializeFromArray(p, ctxt); } // Otherwise, no can do: return (Long) ctxt.handleUnexpectedToken(_valueClass, p); } } @JacksonStdImpl public static class FloatDeserializer extends PrimitiveOrWrapperDeserializer { private static final long serialVersionUID = 1L; final static FloatDeserializer primitiveInstance = new FloatDeserializer(Float.TYPE, 0.f); final static FloatDeserializer wrapperInstance = new FloatDeserializer(Float.class, null); public FloatDeserializer(Class cls, Float nvl) { super(cls, nvl, 0.f); } @Override public Float deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return _parseFloat(p, ctxt); } protected final Float _parseFloat(JsonParser p, DeserializationContext ctxt) throws IOException { // We accept couple of different types; obvious ones first: JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_NUMBER_FLOAT || t == JsonToken.VALUE_NUMBER_INT) { // coercing should work too return p.getFloatValue(); } // And finally, let's allow Strings to be converted too if (t == JsonToken.VALUE_STRING) { String text = p.getText().trim(); if ((text.length() == 0)) { return (Float) _coerceEmptyString(ctxt, _primitive); } if (_hasTextualNull(text)) { return (Float) _coerceTextualNull(ctxt, _primitive); } switch (text.charAt(0)) { case 'I': if (_isPosInf(text)) { return Float.POSITIVE_INFINITY; } break; case 'N': if (_isNaN(text)) { return Float.NaN; } break; case '-': if (_isNegInf(text)) { return Float.NEGATIVE_INFINITY; } break; } _verifyStringForScalarCoercion(ctxt, text); try { return Float.parseFloat(text); } catch (IllegalArgumentException iae) { } return (Float) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid Float value"); } if (t == JsonToken.VALUE_NULL) { return (Float) _coerceNullToken(ctxt, _primitive); } if (t == JsonToken.START_ARRAY) { return _deserializeFromArray(p, ctxt); } // Otherwise, no can do: return (Float) ctxt.handleUnexpectedToken(_valueClass, p); } } @JacksonStdImpl public static class DoubleDeserializer extends PrimitiveOrWrapperDeserializer { private static final long serialVersionUID = 1L; final static DoubleDeserializer primitiveInstance = new DoubleDeserializer(Double.TYPE, 0.d); final static DoubleDeserializer wrapperInstance = new DoubleDeserializer(Double.class, null); public DoubleDeserializer(Class cls, Double nvl) { super(cls, nvl, 0.d); } @Override public Double deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return _parseDouble(p, ctxt); } // Since we can never have type info ("natural type"; String, Boolean, Integer, Double): // (is it an error to even call this version?) @Override public Double deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { return _parseDouble(p, ctxt); } protected final Double _parseDouble(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too return p.getDoubleValue(); } if (t == JsonToken.VALUE_STRING) { String text = p.getText().trim(); if ((text.length() == 0)) { return (Double) _coerceEmptyString(ctxt, _primitive); } if (_hasTextualNull(text)) { return (Double) _coerceTextualNull(ctxt, _primitive); } switch (text.charAt(0)) { case 'I': if (_isPosInf(text)) { return Double.POSITIVE_INFINITY; } break; case 'N': if (_isNaN(text)) { return Double.NaN; } break; case '-': if (_isNegInf(text)) { return Double.NEGATIVE_INFINITY; } break; } _verifyStringForScalarCoercion(ctxt, text); try { return parseDouble(text); } catch (IllegalArgumentException iae) { } return (Double) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid Double value"); } if (t == JsonToken.VALUE_NULL) { return (Double) _coerceNullToken(ctxt, _primitive); } if (t == JsonToken.START_ARRAY) { return _deserializeFromArray(p, ctxt); } // Otherwise, no can do: return (Double) ctxt.handleUnexpectedToken(_valueClass, p); } } /** * For type Number.class, we can just rely on type * mappings that plain {@link JsonParser#getNumberValue} returns. *

* There is one additional complication: some numeric * types (specifically, int/Integer and double/Double) are "non-typed"; * meaning that they will NEVER be output with type information. * But other numeric types may need such type information. * This is why {@link #deserializeWithType} must be overridden. */ @SuppressWarnings("serial") @JacksonStdImpl public static class NumberDeserializer extends StdScalarDeserializer { public final static NumberDeserializer instance = new NumberDeserializer(); public NumberDeserializer() { super(Number.class); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_NUMBER_INT: if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) { return _coerceIntegral(p, ctxt); } return p.getNumberValue(); case JsonTokenId.ID_NUMBER_FLOAT: if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { // 10-Mar-2017, tatu: NaN and BigDecimal won't mix... if (!p.isNaN()) { return p.getDecimalValue(); } } return p.getNumberValue(); case JsonTokenId.ID_STRING: /* Textual values are more difficult... not parsing itself, but figuring * out 'minimal' type to use */ String text = p.getText().trim(); if ((text.length() == 0)) { // note: no need to call `coerce` as this is never primitive return getNullValue(ctxt); } if (_hasTextualNull(text)) { // note: no need to call `coerce` as this is never primitive return getNullValue(ctxt); } if (_isPosInf(text)) { return Double.POSITIVE_INFINITY; } if (_isNegInf(text)) { return Double.NEGATIVE_INFINITY; } if (_isNaN(text)) { return Double.NaN; } _verifyStringForScalarCoercion(ctxt, text); try { if (!_isIntNumber(text)) { if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { return new BigDecimal(text); } return Double.valueOf(text); } if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) { return new BigInteger(text); } long value = Long.parseLong(text); if (!ctxt.isEnabled(DeserializationFeature.USE_LONG_FOR_INTS)) { if (value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) { return Integer.valueOf((int) value); } } return Long.valueOf(value); } catch (IllegalArgumentException iae) { return ctxt.handleWeirdStringValue(_valueClass, text, "not a valid number"); } case JsonTokenId.ID_START_ARRAY: return _deserializeFromArray(p, ctxt); } // Otherwise, no can do: return ctxt.handleUnexpectedToken(_valueClass, p); } /** * As mentioned in class Javadoc, there is additional complexity in * handling potentially mixed type information here. Because of this, * we must actually check for "raw" integers and doubles first, before * calling type deserializer. */ @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_NUMBER_INT: case JsonTokenId.ID_NUMBER_FLOAT: case JsonTokenId.ID_STRING: // cannot point to type information: hence must be non-typed (int/double) return deserialize(p, ctxt); } return typeDeserializer.deserializeTypedFromScalar(p, ctxt); } } /* /********************************************************** /* And then bit more complicated (but non-structured) number /* types /********************************************************** */ /** * This is bit trickier to implement efficiently, while avoiding * overflow problems. */ @SuppressWarnings("serial") @JacksonStdImpl public static class BigIntegerDeserializer extends StdScalarDeserializer { public final static BigIntegerDeserializer instance = new BigIntegerDeserializer(); public BigIntegerDeserializer() { super(BigInteger.class); } @Override public Object getEmptyValue(DeserializationContext ctxt) { return BigInteger.ZERO; } @SuppressWarnings("incomplete-switch") @Override public BigInteger deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_NUMBER_INT: switch (p.getNumberType()) { case INT: case LONG: case BIG_INTEGER: return p.getBigIntegerValue(); } break; case JsonTokenId.ID_NUMBER_FLOAT: if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) { _failDoubleToIntCoercion(p, ctxt, "java.math.BigInteger"); } return p.getDecimalValue().toBigInteger(); case JsonTokenId.ID_START_ARRAY: return _deserializeFromArray(p, ctxt); case JsonTokenId.ID_STRING: // let's do implicit re-parse String text = p.getText().trim(); // note: no need to call `coerce` as this is never primitive if (_isEmptyOrTextualNull(text)) { _verifyNullForScalarCoercion(ctxt, text); return getNullValue(ctxt); } _verifyStringForScalarCoercion(ctxt, text); try { return new BigInteger(text); } catch (IllegalArgumentException iae) { } return (BigInteger) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid representation"); } // String is ok too, can easily convert; otherwise, no can do: return (BigInteger) ctxt.handleUnexpectedToken(_valueClass, p); } } @SuppressWarnings("serial") @JacksonStdImpl public static class BigDecimalDeserializer extends StdScalarDeserializer { public final static BigDecimalDeserializer instance = new BigDecimalDeserializer(); public BigDecimalDeserializer() { super(BigDecimal.class); } @Override public Object getEmptyValue(DeserializationContext ctxt) { return BigDecimal.ZERO; } @Override public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_NUMBER_INT: case JsonTokenId.ID_NUMBER_FLOAT: return p.getDecimalValue(); case JsonTokenId.ID_STRING: String text = p.getText().trim(); // note: no need to call `coerce` as this is never primitive if (_isEmptyOrTextualNull(text)) { _verifyNullForScalarCoercion(ctxt, text); return getNullValue(ctxt); } _verifyStringForScalarCoercion(ctxt, text); try { return new BigDecimal(text); } catch (IllegalArgumentException iae) { } return (BigDecimal) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid representation"); case JsonTokenId.ID_START_ARRAY: return _deserializeFromArray(p, ctxt); } // Otherwise, no can do: return (BigDecimal) ctxt.handleUnexpectedToken(_valueClass, p); } } } ObjectArrayDeserializer.java000066400000000000000000000311671325620701100377670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.lang.reflect.Array; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.AccessPattern; import com.fasterxml.jackson.databind.util.ObjectBuffer; /** * Basic serializer that can serialize non-primitive arrays. */ @JacksonStdImpl public class ObjectArrayDeserializer extends ContainerDeserializerBase implements ContextualDeserializer { private static final long serialVersionUID = 1L; protected final static Object[] NO_OBJECTS = new Object[0]; // // Configuration /** * Flag that indicates whether the component type is Object or not. * Used for minor optimization when constructing result. */ protected final boolean _untyped; /** * Type of contained elements: needed for constructing actual * result array */ protected final Class _elementClass; /** * Element deserializer */ protected JsonDeserializer _elementDeserializer; /** * If element instances have polymorphic type information, this * is the type deserializer that can handle it */ protected final TypeDeserializer _elementTypeDeserializer; /* /********************************************************** /* Life-cycle /********************************************************** */ public ObjectArrayDeserializer(JavaType arrayType, JsonDeserializer elemDeser, TypeDeserializer elemTypeDeser) { super(arrayType, null, null); _elementClass = arrayType.getContentType().getRawClass(); _untyped = (_elementClass == Object.class); _elementDeserializer = elemDeser; _elementTypeDeserializer = elemTypeDeser; } protected ObjectArrayDeserializer(ObjectArrayDeserializer base, JsonDeserializer elemDeser, TypeDeserializer elemTypeDeser, NullValueProvider nuller, Boolean unwrapSingle) { super(base, nuller, unwrapSingle); _elementClass = base._elementClass; _untyped = base._untyped; _elementDeserializer = elemDeser; _elementTypeDeserializer = elemTypeDeser; } /** * Overridable fluent-factory method used to create contextual instances */ public ObjectArrayDeserializer withDeserializer(TypeDeserializer elemTypeDeser, JsonDeserializer elemDeser) { return withResolved(elemTypeDeser, elemDeser, _nullProvider, _unwrapSingle); } /** * @since 2.7 */ @SuppressWarnings("unchecked") public ObjectArrayDeserializer withResolved(TypeDeserializer elemTypeDeser, JsonDeserializer elemDeser, NullValueProvider nuller, Boolean unwrapSingle) { if ((unwrapSingle == _unwrapSingle) && (nuller == _nullProvider) && (elemDeser == _elementDeserializer) && (elemTypeDeser == _elementTypeDeserializer)) { return this; } return new ObjectArrayDeserializer(this, (JsonDeserializer) elemDeser, elemTypeDeser, nuller, unwrapSingle); } @Override // since 2.5 public boolean isCachable() { // Important: do NOT cache if polymorphic values, or if there are annotation-based // custom deserializers return (_elementDeserializer == null) && (_elementTypeDeserializer == null); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { JsonDeserializer valueDeser = _elementDeserializer; Boolean unwrapSingle = findFormatFeature(ctxt, property, _containerType.getRawClass(), JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); // May have a content converter valueDeser = findConvertingContentDeserializer(ctxt, property, valueDeser); final JavaType vt = _containerType.getContentType(); if (valueDeser == null) { valueDeser = ctxt.findContextualValueDeserializer(vt, property); } else { // if directly assigned, probably not yet contextual, so: valueDeser = ctxt.handleSecondaryContextualization(valueDeser, property, vt); } TypeDeserializer elemTypeDeser = _elementTypeDeserializer; if (elemTypeDeser != null) { elemTypeDeser = elemTypeDeser.forProperty(property); } NullValueProvider nuller = findContentNullProvider(ctxt, property, valueDeser); return withResolved(elemTypeDeser, valueDeser, nuller, unwrapSingle); } /* /********************************************************** /* ContainerDeserializerBase API /********************************************************** */ @Override public JsonDeserializer getContentDeserializer() { return _elementDeserializer; } @Override // since 2.9 public AccessPattern getEmptyAccessPattern() { // immutable, shareable so: return AccessPattern.CONSTANT; } // need to override as we can't expose ValueInstantiator @Override // since 2.9 public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { return NO_OBJECTS; } /* /********************************************************** /* JsonDeserializer API /********************************************************** */ @Override public Object[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // Ok: must point to START_ARRAY (or equivalent) if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt); } final ObjectBuffer buffer = ctxt.leaseObjectBuffer(); Object[] chunk = buffer.resetAndStart(); int ix = 0; JsonToken t; final TypeDeserializer typeDeser = _elementTypeDeserializer; try { while ((t = p.nextToken()) != JsonToken.END_ARRAY) { // Note: must handle null explicitly here; value deserializers won't Object value; if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = _nullProvider.getNullValue(ctxt); } else if (typeDeser == null) { value = _elementDeserializer.deserialize(p, ctxt); } else { value = _elementDeserializer.deserializeWithType(p, ctxt, typeDeser); } if (ix >= chunk.length) { chunk = buffer.appendCompletedChunk(chunk); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, buffer.bufferedSize() + ix); } Object[] result; if (_untyped) { result = buffer.completeAndClearBuffer(chunk, ix); } else { result = buffer.completeAndClearBuffer(chunk, ix, _elementClass); } ctxt.returnObjectBuffer(buffer); return result; } @Override public Object[] deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // Should there be separate handling for base64 stuff? // for now this should be enough: return (Object[]) typeDeserializer.deserializeTypedFromArray(p, ctxt); } @Override // since 2.9 public Object[] deserialize(JsonParser p, DeserializationContext ctxt, Object[] intoValue) throws IOException { if (!p.isExpectedStartArrayToken()) { Object[] arr = handleNonArray(p, ctxt); if (arr == null) { return intoValue; } final int offset = intoValue.length; Object[] result = new Object[offset + arr.length]; System.arraycopy(intoValue, 0, result, 0, offset); System.arraycopy(arr, 0, result, offset, arr.length); return result; } final ObjectBuffer buffer = ctxt.leaseObjectBuffer(); int ix = intoValue.length; Object[] chunk = buffer.resetAndStart(intoValue, ix); JsonToken t; final TypeDeserializer typeDeser = _elementTypeDeserializer; try { while ((t = p.nextToken()) != JsonToken.END_ARRAY) { Object value; if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = _nullProvider.getNullValue(ctxt); } else if (typeDeser == null) { value = _elementDeserializer.deserialize(p, ctxt); } else { value = _elementDeserializer.deserializeWithType(p, ctxt, typeDeser); } if (ix >= chunk.length) { chunk = buffer.appendCompletedChunk(chunk); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, buffer.bufferedSize() + ix); } Object[] result; if (_untyped) { result = buffer.completeAndClearBuffer(chunk, ix); } else { result = buffer.completeAndClearBuffer(chunk, ix, _elementClass); } ctxt.returnObjectBuffer(buffer); return result; } /* /********************************************************** /* Internal methods /********************************************************** */ protected Byte[] deserializeFromBase64(JsonParser p, DeserializationContext ctxt) throws IOException { // First same as what PrimitiveArrayDeserializers.ByteDeser does: byte[] b = p.getBinaryValue(ctxt.getBase64Variant()); // But then need to convert to wrappers Byte[] result = new Byte[b.length]; for (int i = 0, len = b.length; i < len; ++i) { result[i] = Byte.valueOf(b[i]); } return result; } protected Object[] handleNonArray(JsonParser p, DeserializationContext ctxt) throws IOException { // Empty String can become null... if (p.hasToken(JsonToken.VALUE_STRING) && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { String str = p.getText(); if (str.length() == 0) { return null; } } // Can we do implicit coercion to a single-element array still? boolean canWrap = (_unwrapSingle == Boolean.TRUE) || ((_unwrapSingle == null) && ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); if (!canWrap) { // One exception; byte arrays are generally serialized as base64, so that should be handled JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_STRING // note: not `byte[]`, but `Byte[]` -- former is primitive array && _elementClass == Byte.class) { return deserializeFromBase64(p, ctxt); } return (Object[]) ctxt.handleUnexpectedToken(_containerType.getRawClass(), p); } JsonToken t = p.getCurrentToken(); Object value; if (t == JsonToken.VALUE_NULL) { // 03-Feb-2017, tatu: Should this be skipped or not? if (_skipNullValues) { return NO_OBJECTS; } value = _nullProvider.getNullValue(ctxt); } else if (_elementTypeDeserializer == null) { value = _elementDeserializer.deserialize(p, ctxt); } else { value = _elementDeserializer.deserializeWithType(p, ctxt, _elementTypeDeserializer); } // Ok: bit tricky, since we may want T[], not just Object[] Object[] result; if (_untyped) { result = new Object[1]; } else { result = (Object[]) Array.newInstance(_elementClass, 1); } result[0] = value; return result; } } PrimitiveArrayDeserializers.java000066400000000000000000001034011325620701100407030ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.lang.reflect.Array; import java.util.Arrays; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider; import com.fasterxml.jackson.databind.deser.impl.NullsFailProvider; import com.fasterxml.jackson.databind.exc.InvalidNullException; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.AccessPattern; import com.fasterxml.jackson.databind.util.ArrayBuilders; /** * Container for deserializers used for instantiating "primitive arrays", * arrays that contain non-object java primitive types. */ @SuppressWarnings("serial") public abstract class PrimitiveArrayDeserializers extends StdDeserializer implements ContextualDeserializer // since 2.7 { /** * Specific override for this instance (from proper, or global per-type overrides) * to indicate whether single value may be taken to mean an unwrapped one-element array * or not. If null, left to global defaults. * * @since 2.7 */ protected final Boolean _unwrapSingle; // since 2.9 private transient Object _emptyValue; /** * Flag that indicates need for special handling; either failing * (throw exception) or skipping */ protected final NullValueProvider _nuller; /* /******************************************************** /* Life-cycle /******************************************************** */ protected PrimitiveArrayDeserializers(Class cls) { super(cls); _unwrapSingle = null; _nuller = null; } /** * @since 2.7 */ protected PrimitiveArrayDeserializers(PrimitiveArrayDeserializers base, NullValueProvider nuller, Boolean unwrapSingle) { super(base._valueClass); _unwrapSingle = unwrapSingle; _nuller = nuller; } public static JsonDeserializer forType(Class rawType) { // Start with more common types... if (rawType == Integer.TYPE) { return IntDeser.instance; } if (rawType == Long.TYPE) { return LongDeser.instance; } if (rawType == Byte.TYPE) { return new ByteDeser(); } if (rawType == Short.TYPE) { return new ShortDeser(); } if (rawType == Float.TYPE) { return new FloatDeser(); } if (rawType == Double.TYPE) { return new DoubleDeser(); } if (rawType == Boolean.TYPE) { return new BooleanDeser(); } if (rawType == Character.TYPE) { return new CharDeser(); } throw new IllegalStateException(); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { Boolean unwrapSingle = findFormatFeature(ctxt, property, _valueClass, JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); NullValueProvider nuller = null; Nulls nullStyle = findContentNullStyle(ctxt, property); if (nullStyle == Nulls.SKIP) { nuller = NullsConstantProvider.skipper(); } else if (nullStyle == Nulls.FAIL) { if (property == null) { nuller = NullsFailProvider.constructForRootValue(ctxt.constructType(_valueClass)); } else { nuller = NullsFailProvider.constructForProperty(property); } } if ((unwrapSingle == _unwrapSingle) && (nuller == _nuller)) { return this; } return withResolved(nuller, unwrapSingle); } /* /******************************************************** /* Abstract methods for sub-classes to implement /******************************************************** */ /** * @since 2.9 */ protected abstract T _concat(T oldValue, T newValue); protected abstract T handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException; /** * @since 2.9 */ protected abstract PrimitiveArrayDeserializers withResolved(NullValueProvider nuller, Boolean unwrapSingle); // since 2.9 protected abstract T _constructEmpty(); /* /******************************************************** /* Default implementations /******************************************************** */ @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return Boolean.TRUE; } @Override public AccessPattern getEmptyAccessPattern() { // Empty values shareable freely return AccessPattern.CONSTANT; } @Override // since 2.9 public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { Object empty = _emptyValue; if (empty == null) { _emptyValue = empty = _constructEmpty(); } return empty; } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // Should there be separate handling for base64 stuff? // for now this should be enough: return typeDeserializer.deserializeTypedFromArray(p, ctxt); } @Override public T deserialize(JsonParser p, DeserializationContext ctxt, T existing) throws IOException { T newValue = deserialize(p, ctxt); if (existing == null) { return newValue; } int len = Array.getLength(existing); if (len == 0) { return newValue; } return _concat(existing, newValue); } /* /******************************************************** /* Helper methods for sub-classes /******************************************************** */ /* * Convenience method that constructs a concatenation of two arrays, * with the type they have. * * @since 2.9 @SuppressWarnings("unchecked") public static T concatArrays(T array1, T array2) { int len1 = Array.getLength(array1); if (len1 == 0) { return array2; } int len2 = Array.getLength(array2); if (len2 == 0) { return array1; } Object result = Arrays.copyOf((Object[]) array1, len1 + len2); System.arraycopy(array2, 0, result, len1, len2); return (T) result; } */ @SuppressWarnings("unchecked") protected T handleNonArray(JsonParser p, DeserializationContext ctxt) throws IOException { // Empty String can become null... if (p.hasToken(JsonToken.VALUE_STRING) && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { if (p.getText().length() == 0) { return null; } } boolean canWrap = (_unwrapSingle == Boolean.TRUE) || ((_unwrapSingle == null) && ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); if (canWrap) { return handleSingleElementUnwrapped(p, ctxt); } return (T) ctxt.handleUnexpectedToken(_valueClass, p); } protected void _failOnNull(DeserializationContext ctxt) throws IOException { throw InvalidNullException.from(ctxt, null, ctxt.constructType(_valueClass)); } /* /******************************************************** /* Actual deserializers: efficient String[], char[] deserializers /******************************************************** */ @JacksonStdImpl final static class CharDeser extends PrimitiveArrayDeserializers { private static final long serialVersionUID = 1L; public CharDeser() { super(char[].class); } protected CharDeser(CharDeser base, NullValueProvider nuller, Boolean unwrapSingle) { super(base, nuller, unwrapSingle); } @Override protected PrimitiveArrayDeserializers withResolved(NullValueProvider nuller, Boolean unwrapSingle) { // 11-Dec-2015, tatu: Not sure how re-wrapping would work; omit return this; } @Override protected char[] _constructEmpty() { return new char[0]; } @Override public char[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { /* Won't take arrays, must get a String (could also * convert other tokens to Strings... but let's not bother * yet, doesn't seem to make sense) */ JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_STRING) { // note: can NOT return shared internal buffer, must copy: char[] buffer = p.getTextCharacters(); int offset = p.getTextOffset(); int len = p.getTextLength(); char[] result = new char[len]; System.arraycopy(buffer, offset, result, 0, len); return result; } if (p.isExpectedStartArrayToken()) { // Let's actually build as a String, then get chars StringBuilder sb = new StringBuilder(64); while ((t = p.nextToken()) != JsonToken.END_ARRAY) { String str; if (t == JsonToken.VALUE_STRING) { str = p.getText(); } else if (t == JsonToken.VALUE_NULL) { if (_nuller != null) { _nuller.getNullValue(ctxt); continue; } _verifyNullForPrimitive(ctxt); str = "\0"; } else { CharSequence cs = (CharSequence) ctxt.handleUnexpectedToken(Character.TYPE, p); str = cs.toString(); } if (str.length() != 1) { ctxt.reportInputMismatch(this, "Cannot convert a JSON String of length %d into a char element of char array", str.length()); } sb.append(str.charAt(0)); } return sb.toString().toCharArray(); } // or, maybe an embedded object? if (t == JsonToken.VALUE_EMBEDDED_OBJECT) { Object ob = p.getEmbeddedObject(); if (ob == null) return null; if (ob instanceof char[]) { return (char[]) ob; } if (ob instanceof String) { return ((String) ob).toCharArray(); } // 04-Feb-2011, tatu: byte[] can be converted; assuming base64 is wanted if (ob instanceof byte[]) { return Base64Variants.getDefaultVariant().encode((byte[]) ob, false).toCharArray(); } // not recognized, just fall through } return (char[]) ctxt.handleUnexpectedToken(_valueClass, p); } @Override protected char[] handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { // not sure how this should work... return (char[]) ctxt.handleUnexpectedToken(_valueClass, p); } @Override protected char[] _concat(char[] oldValue, char[] newValue) { int len1 = oldValue.length; int len2 = newValue.length; char[] result = Arrays.copyOf(oldValue, len1+len2); System.arraycopy(newValue, 0, result, len1, len2); return result; } } /* /********************************************************** /* Actual deserializers: primivate array desers /********************************************************** */ @JacksonStdImpl final static class BooleanDeser extends PrimitiveArrayDeserializers { private static final long serialVersionUID = 1L; public BooleanDeser() { super(boolean[].class); } protected BooleanDeser(BooleanDeser base, NullValueProvider nuller, Boolean unwrapSingle) { super(base, nuller, unwrapSingle); } @Override protected PrimitiveArrayDeserializers withResolved(NullValueProvider nuller, Boolean unwrapSingle) { return new BooleanDeser(this, nuller, unwrapSingle); } @Override protected boolean[] _constructEmpty() { return new boolean[0]; } @Override public boolean[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt); } ArrayBuilders.BooleanBuilder builder = ctxt.getArrayBuilders().getBooleanBuilder(); boolean[] chunk = builder.resetAndStart(); int ix = 0; try { JsonToken t; while ((t = p.nextToken()) != JsonToken.END_ARRAY) { boolean value; if (t == JsonToken.VALUE_TRUE) { value = true; } else if (t == JsonToken.VALUE_FALSE) { value = false; } else if (t == JsonToken.VALUE_NULL) { if (_nuller != null) { _nuller.getNullValue(ctxt); continue; } _verifyNullForPrimitive(ctxt); value = false; } else { value = _parseBooleanPrimitive(p, ctxt); } if (ix >= chunk.length) { chunk = builder.appendCompletedChunk(chunk, ix); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); } return builder.completeAndClearBuffer(chunk, ix); } @Override protected boolean[] handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { return new boolean[] { _parseBooleanPrimitive(p, ctxt) }; } @Override protected boolean[] _concat(boolean[] oldValue, boolean[] newValue) { int len1 = oldValue.length; int len2 = newValue.length; boolean[] result = Arrays.copyOf(oldValue, len1+len2); System.arraycopy(newValue, 0, result, len1, len2); return result; } } /** * When dealing with byte arrays we have one more alternative (compared * to int/long/shorts): base64 encoded data. */ @JacksonStdImpl final static class ByteDeser extends PrimitiveArrayDeserializers { private static final long serialVersionUID = 1L; public ByteDeser() { super(byte[].class); } protected ByteDeser(ByteDeser base, NullValueProvider nuller,Boolean unwrapSingle) { super(base, nuller, unwrapSingle); } @Override protected PrimitiveArrayDeserializers withResolved(NullValueProvider nuller, Boolean unwrapSingle) { return new ByteDeser(this, nuller, unwrapSingle); } @Override protected byte[] _constructEmpty() { return new byte[0]; } @Override public byte[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); // Most likely case: base64 encoded String? if (t == JsonToken.VALUE_STRING) { try { return p.getBinaryValue(ctxt.getBase64Variant()); } catch (JsonParseException e) { // 25-Nov-2016, tatu: related to [databind#1425], try to convert // to a more usable one, as it's not really a JSON-level parse // exception, but rather binding from JSON String into base64 decoded // binary data String msg = e.getOriginalMessage(); if (msg.contains("base64")) { return (byte[]) ctxt.handleWeirdStringValue(byte[].class, p.getText(), msg); } } } // 31-Dec-2009, tatu: Also may be hidden as embedded Object if (t == JsonToken.VALUE_EMBEDDED_OBJECT) { Object ob = p.getEmbeddedObject(); if (ob == null) return null; if (ob instanceof byte[]) { return (byte[]) ob; } } if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt); } ArrayBuilders.ByteBuilder builder = ctxt.getArrayBuilders().getByteBuilder(); byte[] chunk = builder.resetAndStart(); int ix = 0; try { while ((t = p.nextToken()) != JsonToken.END_ARRAY) { // whether we should allow truncating conversions? byte value; if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // should we catch overflow exceptions? value = p.getByteValue(); } else { // should probably accept nulls as 0 if (t == JsonToken.VALUE_NULL) { if (_nuller != null) { _nuller.getNullValue(ctxt); continue; } _verifyNullForPrimitive(ctxt); value = (byte) 0; } else { value = _parseBytePrimitive(p, ctxt); } } if (ix >= chunk.length) { chunk = builder.appendCompletedChunk(chunk, ix); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); } return builder.completeAndClearBuffer(chunk, ix); } @Override protected byte[] handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { byte value; JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // should we catch overflow exceptions? value = p.getByteValue(); } else { // should probably accept nulls as 'false' if (t == JsonToken.VALUE_NULL) { if (_nuller != null) { _nuller.getNullValue(ctxt); return (byte[]) getEmptyValue(ctxt); } _verifyNullForPrimitive(ctxt); return null; } Number n = (Number) ctxt.handleUnexpectedToken(_valueClass.getComponentType(), p); value = n.byteValue(); } return new byte[] { value }; } @Override protected byte[] _concat(byte[] oldValue, byte[] newValue) { int len1 = oldValue.length; int len2 = newValue.length; byte[] result = Arrays.copyOf(oldValue, len1+len2); System.arraycopy(newValue, 0, result, len1, len2); return result; } } @JacksonStdImpl final static class ShortDeser extends PrimitiveArrayDeserializers { private static final long serialVersionUID = 1L; public ShortDeser() { super(short[].class); } protected ShortDeser(ShortDeser base, NullValueProvider nuller, Boolean unwrapSingle) { super(base, nuller, unwrapSingle); } @Override protected PrimitiveArrayDeserializers withResolved(NullValueProvider nuller, Boolean unwrapSingle) { return new ShortDeser(this, nuller, unwrapSingle); } @Override protected short[] _constructEmpty() { return new short[0]; } @Override public short[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt); } ArrayBuilders.ShortBuilder builder = ctxt.getArrayBuilders().getShortBuilder(); short[] chunk = builder.resetAndStart(); int ix = 0; try { JsonToken t; while ((t = p.nextToken()) != JsonToken.END_ARRAY) { short value; if (t == JsonToken.VALUE_NULL) { if (_nuller != null) { _nuller.getNullValue(ctxt); continue; } _verifyNullForPrimitive(ctxt); value = (short) 0; } else { value = _parseShortPrimitive(p, ctxt); } if (ix >= chunk.length) { chunk = builder.appendCompletedChunk(chunk, ix); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); } return builder.completeAndClearBuffer(chunk, ix); } @Override protected short[] handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { return new short[] { _parseShortPrimitive(p, ctxt) }; } @Override protected short[] _concat(short[] oldValue, short[] newValue) { int len1 = oldValue.length; int len2 = newValue.length; short[] result = Arrays.copyOf(oldValue, len1+len2); System.arraycopy(newValue, 0, result, len1, len2); return result; } } @JacksonStdImpl final static class IntDeser extends PrimitiveArrayDeserializers { private static final long serialVersionUID = 1L; public final static IntDeser instance = new IntDeser(); public IntDeser() { super(int[].class); } protected IntDeser(IntDeser base, NullValueProvider nuller, Boolean unwrapSingle) { super(base, nuller, unwrapSingle); } @Override protected PrimitiveArrayDeserializers withResolved(NullValueProvider nuller, Boolean unwrapSingle) { return new IntDeser(this, nuller, unwrapSingle); } @Override protected int[] _constructEmpty() { return new int[0]; } @Override public int[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt); } ArrayBuilders.IntBuilder builder = ctxt.getArrayBuilders().getIntBuilder(); int[] chunk = builder.resetAndStart(); int ix = 0; try { JsonToken t; while ((t = p.nextToken()) != JsonToken.END_ARRAY) { int value; if (t == JsonToken.VALUE_NUMBER_INT) { value = p.getIntValue(); } else if (t == JsonToken.VALUE_NULL) { if (_nuller != null) { _nuller.getNullValue(ctxt); continue; } _verifyNullForPrimitive(ctxt); value = 0; } else { value = _parseIntPrimitive(p, ctxt); } if (ix >= chunk.length) { chunk = builder.appendCompletedChunk(chunk, ix); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); } return builder.completeAndClearBuffer(chunk, ix); } @Override protected int[] handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { return new int[] { _parseIntPrimitive(p, ctxt) }; } @Override protected int[] _concat(int[] oldValue, int[] newValue) { int len1 = oldValue.length; int len2 = newValue.length; int[] result = Arrays.copyOf(oldValue, len1+len2); System.arraycopy(newValue, 0, result, len1, len2); return result; } } @JacksonStdImpl final static class LongDeser extends PrimitiveArrayDeserializers { private static final long serialVersionUID = 1L; public final static LongDeser instance = new LongDeser(); public LongDeser() { super(long[].class); } protected LongDeser(LongDeser base, NullValueProvider nuller, Boolean unwrapSingle) { super(base, nuller, unwrapSingle); } @Override protected PrimitiveArrayDeserializers withResolved(NullValueProvider nuller, Boolean unwrapSingle) { return new LongDeser(this, nuller, unwrapSingle); } @Override protected long[] _constructEmpty() { return new long[0]; } @Override public long[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt); } ArrayBuilders.LongBuilder builder = ctxt.getArrayBuilders().getLongBuilder(); long[] chunk = builder.resetAndStart(); int ix = 0; try { JsonToken t; while ((t = p.nextToken()) != JsonToken.END_ARRAY) { long value; if (t == JsonToken.VALUE_NUMBER_INT) { value = p.getLongValue(); } else if (t == JsonToken.VALUE_NULL) { if (_nuller != null) { _nuller.getNullValue(ctxt); continue; } _verifyNullForPrimitive(ctxt); value = 0L; } else { value = _parseLongPrimitive(p, ctxt); } if (ix >= chunk.length) { chunk = builder.appendCompletedChunk(chunk, ix); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); } return builder.completeAndClearBuffer(chunk, ix); } @Override protected long[] handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { return new long[] { _parseLongPrimitive(p, ctxt) }; } @Override protected long[] _concat(long[] oldValue, long[] newValue) { int len1 = oldValue.length; int len2 = newValue.length; long[] result = Arrays.copyOf(oldValue, len1+len2); System.arraycopy(newValue, 0, result, len1, len2); return result; } } @JacksonStdImpl final static class FloatDeser extends PrimitiveArrayDeserializers { private static final long serialVersionUID = 1L; public FloatDeser() { super(float[].class); } protected FloatDeser(FloatDeser base, NullValueProvider nuller, Boolean unwrapSingle) { super(base, nuller, unwrapSingle); } @Override protected PrimitiveArrayDeserializers withResolved(NullValueProvider nuller, Boolean unwrapSingle) { return new FloatDeser(this, nuller, unwrapSingle); } @Override protected float[] _constructEmpty() { return new float[0]; } @Override public float[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt); } ArrayBuilders.FloatBuilder builder = ctxt.getArrayBuilders().getFloatBuilder(); float[] chunk = builder.resetAndStart(); int ix = 0; try { JsonToken t; while ((t = p.nextToken()) != JsonToken.END_ARRAY) { // whether we should allow truncating conversions? if (t == JsonToken.VALUE_NULL) { if (_nuller != null) { _nuller.getNullValue(ctxt); continue; } } float value = _parseFloatPrimitive(p, ctxt); if (ix >= chunk.length) { chunk = builder.appendCompletedChunk(chunk, ix); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); } return builder.completeAndClearBuffer(chunk, ix); } @Override protected float[] handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { return new float[] { _parseFloatPrimitive(p, ctxt) }; } @Override protected float[] _concat(float[] oldValue, float[] newValue) { int len1 = oldValue.length; int len2 = newValue.length; float[] result = Arrays.copyOf(oldValue, len1+len2); System.arraycopy(newValue, 0, result, len1, len2); return result; } } @JacksonStdImpl final static class DoubleDeser extends PrimitiveArrayDeserializers { private static final long serialVersionUID = 1L; public DoubleDeser() { super(double[].class); } protected DoubleDeser(DoubleDeser base, NullValueProvider nuller, Boolean unwrapSingle) { super(base, nuller, unwrapSingle); } @Override protected PrimitiveArrayDeserializers withResolved(NullValueProvider nuller, Boolean unwrapSingle) { return new DoubleDeser(this, nuller, unwrapSingle); } @Override protected double[] _constructEmpty() { return new double[0]; } @Override public double[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt); } ArrayBuilders.DoubleBuilder builder = ctxt.getArrayBuilders().getDoubleBuilder(); double[] chunk = builder.resetAndStart(); int ix = 0; try { JsonToken t; while ((t = p.nextToken()) != JsonToken.END_ARRAY) { if (t == JsonToken.VALUE_NULL) { if (_nuller != null) { _nuller.getNullValue(ctxt); continue; } } double value = _parseDoublePrimitive(p, ctxt); if (ix >= chunk.length) { chunk = builder.appendCompletedChunk(chunk, ix); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); } return builder.completeAndClearBuffer(chunk, ix); } @Override protected double[] handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt) throws IOException { return new double[] { _parseDoublePrimitive(p, ctxt) }; } @Override protected double[] _concat(double[] oldValue, double[] newValue) { int len1 = oldValue.length; int len2 = newValue.length; double[] result = Arrays.copyOf(oldValue, len1+len2); System.arraycopy(newValue, 0, result, len1, len2); return result; } } } ReferenceTypeDeserializer.java000066400000000000000000000216561325620701100403240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.type.ReferenceType; import com.fasterxml.jackson.databind.util.AccessPattern; /** * Base deserializer implementation for properties {@link ReferenceType} values. * Implements most of functionality, only leaving couple of abstract * methods for sub-classes to implement * * @since 2.8 */ public abstract class ReferenceTypeDeserializer extends StdDeserializer implements ContextualDeserializer { private static final long serialVersionUID = 2L; // 2.9 /** * Full type of property (or root value) for which this deserializer * has been constructed and contextualized. */ protected final JavaType _fullType; protected final ValueInstantiator _valueInstantiator; protected final TypeDeserializer _valueTypeDeserializer; protected final JsonDeserializer _valueDeserializer; /* /********************************************************** /* Life-cycle /********************************************************** */ @SuppressWarnings("unchecked") public ReferenceTypeDeserializer(JavaType fullType, ValueInstantiator vi, TypeDeserializer typeDeser, JsonDeserializer deser) { super(fullType); _valueInstantiator = vi; _fullType = fullType; _valueDeserializer = (JsonDeserializer) deser; _valueTypeDeserializer = typeDeser; } @Deprecated // since 2.9 public ReferenceTypeDeserializer(JavaType fullType, TypeDeserializer typeDeser, JsonDeserializer deser) { this(fullType, null, typeDeser, deser); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { JsonDeserializer deser = _valueDeserializer; if (deser == null) { deser = ctxt.findContextualValueDeserializer(_fullType.getReferencedType(), property); } else { // otherwise directly assigned, probably not contextual yet: deser = ctxt.handleSecondaryContextualization(deser, property, _fullType.getReferencedType()); } TypeDeserializer typeDeser = _valueTypeDeserializer; if (typeDeser != null) { typeDeser = typeDeser.forProperty(property); } // !!! 23-Oct-2016, tatu: TODO: full support for configurable ValueInstantiators? if ((deser == _valueDeserializer) && (typeDeser == _valueTypeDeserializer)) { return this; } return withResolved(typeDeser, deser); } /* /********************************************************** /* Partial NullValueProvider impl /********************************************************** */ /** * Null value varies dynamically (unlike with scalar types), * so let's indicate this. */ @Override public AccessPattern getNullAccessPattern() { return AccessPattern.DYNAMIC; } @Override public AccessPattern getEmptyAccessPattern() { return AccessPattern.DYNAMIC; } /* /********************************************************** /* Abstract methods for sub-classes to implement /********************************************************** */ /** * Mutant factory method called when changes are needed; should construct * newly configured instance with new values as indicated. *

* NOTE: caller has verified that there are changes, so implementations * need NOT check if a new instance is needed. */ protected abstract ReferenceTypeDeserializer withResolved(TypeDeserializer typeDeser, JsonDeserializer valueDeser); @Override public abstract T getNullValue(DeserializationContext ctxt); @Override public Object getEmptyValue(DeserializationContext ctxt) { return getNullValue(ctxt); } public abstract T referenceValue(Object contents); /** * Method called in case of "merging update", in which we should try * update reference instead of creating a new one. If this does not * succeed, should just create a new instance. * * @since 2.9 */ public abstract T updateReference(T reference, Object contents); /** * Method that may be called to find contents of specified reference, * if any; or `null` if none. Note that method should never fail, so * for types that use concept of "absence" vs "presence", `null` is * to be returned for both "absent" and "reference to `null`" cases. * * @since 2.9 */ public abstract Object getReferenced(T reference); /* /********************************************************** /* Overridden accessors /********************************************************** */ @Override public JavaType getValueType() { return _fullType; } /** * By default we assume that updateability mostly relies on value * deserializer; if it supports updates, typically that's what * matters. So let's just delegate. */ @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return (_valueDeserializer == null) ? null : _valueDeserializer.supportsUpdate(config); } /* /********************************************************** /* Deserialization /********************************************************** */ @Override public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 23-Oct-2016, tatu: ValueInstantiator only defined for non-vanilla instances, // but do check... might work if (_valueInstantiator != null) { @SuppressWarnings("unchecked") T value = (T) _valueInstantiator.createUsingDefault(ctxt); return deserialize(p, ctxt, value); } Object contents = (_valueTypeDeserializer == null) ? _valueDeserializer.deserialize(p, ctxt) : _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); return referenceValue(contents); } @Override public T deserialize(JsonParser p, DeserializationContext ctxt, T reference) throws IOException { Object contents; // 26-Oct-2016, tatu: first things first; see if we should be able to merge: Boolean B = _valueDeserializer.supportsUpdate(ctxt.getConfig()); // if explicitly stated that merge won't work... if (B.equals(Boolean.FALSE) || (_valueTypeDeserializer != null)) { contents = (_valueTypeDeserializer == null) ? _valueDeserializer.deserialize(p, ctxt) : _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); } else { // Otherwise, see if we can merge the value contents = getReferenced(reference); // Whether to error or not... for now, just go back to default then if (contents == null) { contents = (_valueTypeDeserializer == null) ? _valueDeserializer.deserialize(p, ctxt) : _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer); return referenceValue(contents); } else { contents = _valueDeserializer.deserialize(p, ctxt, contents); } } return updateReference(reference, contents); } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { final JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_NULL) { // can this actually happen? return getNullValue(ctxt); } // 22-Oct-2015, tatu: This handling is probably not needed (or is wrong), but // could be result of older (pre-2.7) Jackson trying to serialize natural types. // Because of this, let's allow for now, unless proven problematic /* if ((t != null) && t.isScalarValue()) { return deserialize(p, ctxt); } */ // 19-Apr-2016, tatu: Alas, due to there typically really being anything for Reference wrapper // itself, need to just ignore `typeDeser`, use TypeDeserializer we do have for contents // and it might just work. if (_valueTypeDeserializer == null) { return deserialize(p, ctxt); } return referenceValue(_valueTypeDeserializer.deserializeTypedFromAny(p, ctxt)); } } StackTraceElementDeserializer.java000066400000000000000000000103231325620701100411070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; public class StackTraceElementDeserializer extends StdScalarDeserializer { private static final long serialVersionUID = 1L; public StackTraceElementDeserializer() { super(StackTraceElement.class); } @Override public StackTraceElement deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); // Must get an Object if (t == JsonToken.START_OBJECT) { String className = "", methodName = "", fileName = ""; // Java 9 adds couple more things String moduleName = null, moduleVersion = null; String classLoaderName = null; int lineNumber = -1; while ((t = p.nextValue()) != JsonToken.END_OBJECT) { String propName = p.getCurrentName(); // TODO: with Java 8, convert to switch if ("className".equals(propName)) { className = p.getText(); } else if ("classLoaderName".equals(propName)) { classLoaderName = p.getText(); } else if ("fileName".equals(propName)) { fileName = p.getText(); } else if ("lineNumber".equals(propName)) { if (t.isNumeric()) { lineNumber = p.getIntValue(); } else { lineNumber = _parseIntPrimitive(p, ctxt); } } else if ("methodName".equals(propName)) { methodName = p.getText(); } else if ("nativeMethod".equals(propName)) { // no setter, not passed via constructor: ignore } else if ("moduleName".equals(propName)) { moduleName = p.getText(); } else if ("moduleVersion".equals(propName)) { moduleVersion = p.getText(); } else if ("declaringClass".equals(propName) || "format".equals(propName)) { // 01-Nov-2017: [databind#1794] Not sure if we should but... let's prune it for now ; } else { handleUnknownProperty(p, ctxt, _valueClass, propName); } p.skipChildren(); // just in case we might get structured values } return constructValue(ctxt, className, methodName, fileName, lineNumber, moduleName, moduleVersion, classLoaderName); } else if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { p.nextToken(); final StackTraceElement value = deserialize(p, ctxt); if (p.nextToken() != JsonToken.END_ARRAY) { handleMissingEndArrayForSingle(p, ctxt); } return value; } return (StackTraceElement) ctxt.handleUnexpectedToken(_valueClass, p); } @Deprecated // since 2.9 protected StackTraceElement constructValue(DeserializationContext ctxt, String className, String methodName, String fileName, int lineNumber, String moduleName, String moduleVersion) { return constructValue(ctxt, className, methodName, fileName, lineNumber, moduleName, moduleVersion, null); } /** * Overridable factory method used for constructing {@link StackTraceElement}s. * * @since 2.8 */ protected StackTraceElement constructValue(DeserializationContext ctxt, String className, String methodName, String fileName, int lineNumber, String moduleName, String moduleVersion, String classLoaderName) { // 21-May-2016, tatu: With Java 9, need to use different constructor, probably // via different module, and throw exception here if extra args passed return new StackTraceElement(className, methodName, fileName, lineNumber); } } StdDelegatingDeserializer.java000066400000000000000000000215561325620701100403010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.ResolvableDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.Converter; /** * Deserializer implementation where given Java type is first deserialized * by a standard Jackson deserializer into a delegate type; and then * this delegate type is converted using a configured * {@link Converter} into desired target type. * Common delegate types to use are {@link java.util.Map} * and {@link com.fasterxml.jackson.databind.JsonNode}. *

* Note that although types (delegate, target) may be related, they must not be same; trying * to do this will result in an exception. *

* Since 2.5 There is {@link StdNodeBasedDeserializer} that is a simplified version * for cases where intermediate type is {@link JsonNode} * * @param Target type to convert to, from delegate type * * @since 2.1 * * @see StdNodeBasedDeserializer * @see Converter */ public class StdDelegatingDeserializer extends StdDeserializer implements ContextualDeserializer, ResolvableDeserializer { private static final long serialVersionUID = 1L; /** * Converter that was used for creating {@link #_delegateDeserializer}. */ protected final Converter _converter; /** * Fully resolved delegate type, with generic information if any available. */ protected final JavaType _delegateType; /** * Underlying serializer for type T. */ protected final JsonDeserializer _delegateDeserializer; /* /********************************************************** /* Life-cycle /********************************************************** */ @SuppressWarnings("unchecked") public StdDelegatingDeserializer(Converter converter) { super(Object.class); _converter = (Converter)converter; _delegateType = null; _delegateDeserializer = null; } @SuppressWarnings("unchecked") public StdDelegatingDeserializer(Converter converter, JavaType delegateType, JsonDeserializer delegateDeserializer) { super(delegateType); _converter = converter; _delegateType = delegateType; _delegateDeserializer = (JsonDeserializer) delegateDeserializer; } /** * @since 2.5 */ protected StdDelegatingDeserializer(StdDelegatingDeserializer src) { super(src); _converter = src._converter; _delegateType = src._delegateType; _delegateDeserializer = src._delegateDeserializer; } /** * Method used for creating resolved contextual instances. Must be * overridden when sub-classing. */ protected StdDelegatingDeserializer withDelegate(Converter converter, JavaType delegateType, JsonDeserializer delegateDeserializer) { ClassUtil.verifyMustOverride(StdDelegatingDeserializer.class, this, "withDelegate"); return new StdDelegatingDeserializer(converter, delegateType, delegateDeserializer); } /* /********************************************************** /* Contextualization /********************************************************** */ // Note: unlikely to get called since most likely instances explicitly constructed; // if so, caller must ensure delegating deserializer is properly resolve()d. @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException { if (_delegateDeserializer != null && _delegateDeserializer instanceof ResolvableDeserializer) { ((ResolvableDeserializer) _delegateDeserializer).resolve(ctxt); } } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { // First: if already got deserializer to delegate to, contextualize it: if (_delegateDeserializer != null) { JsonDeserializer deser = ctxt.handleSecondaryContextualization(_delegateDeserializer, property, _delegateType); if (deser != _delegateDeserializer) { return withDelegate(_converter, _delegateType, deser); } return this; } // Otherwise: figure out what is the fully generic delegate type, then find deserializer JavaType delegateType = _converter.getInputType(ctxt.getTypeFactory()); return withDelegate(_converter, delegateType, ctxt.findContextualValueDeserializer(delegateType, property)); } /* /********************************************************** /* Accessors /********************************************************** */ @Override public JsonDeserializer getDelegatee() { return _delegateDeserializer; } @Override public Class handledType() { return _delegateDeserializer.handledType(); } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return _delegateDeserializer.supportsUpdate(config); } /* /********************************************************** /* Serialization /********************************************************** */ @Override public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Object delegateValue = _delegateDeserializer.deserialize(p, ctxt); if (delegateValue == null) { return null; } return convertValue(delegateValue); } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { /* 12-Apr-2016, tatu: As predicted, earlier handling does not work * (see [databind#1189] for details). There does not seem to be any compelling * way to combine polymorphic types, Converters, but the least sucky way * is probably to use Converter and ignore polymorphic type. Alternative * would be to try to change `TypeDeserializer` to accept `Converter` to * invoke... but that is more intrusive, yet not guaranteeing success. */ // method called up to 2.7.3: // Object delegateValue = _delegateDeserializer.deserializeWithType(p, ctxt, typeDeserializer); // method called since 2.7.4 Object delegateValue = _delegateDeserializer.deserialize(p, ctxt); if (delegateValue == null) { return null; } return convertValue(delegateValue); } @SuppressWarnings("unchecked") @Override public T deserialize(JsonParser p, DeserializationContext ctxt, Object intoValue) throws IOException { if (_delegateType.getRawClass().isAssignableFrom(intoValue.getClass())){ return (T) _delegateDeserializer.deserialize(p, ctxt, intoValue); } return (T) _handleIncompatibleUpdateValue(p, ctxt, intoValue); } /** * Overridable handler method called when {@link #deserialize(JsonParser, DeserializationContext, Object)} * has been called with a value that is not compatible with delegate value. * Since no conversion are expected for such "updateValue" case, this is normally not * an operation that can be permitted, and the default behavior is to throw exception. * Sub-classes may choose to try alternative approach if they have more information on * exact usage and constraints. * * @since 2.6 */ protected Object _handleIncompatibleUpdateValue(JsonParser p, DeserializationContext ctxt, Object intoValue) throws IOException { throw new UnsupportedOperationException(String.format ("Cannot update object of type %s (using deserializer for type %s)" +intoValue.getClass().getName(), _delegateType)); } /* /********************************************************** /* Overridable methods /********************************************************** */ /** * Method called to convert from "delegate value" (which was deserialized * from JSON using standard Jackson deserializer for delegate type) * into desired target type. *

* The default implementation uses configured {@link Converter} to do * conversion. * * @param delegateValue * * @return Result of conversion */ protected T convertValue(Object delegateValue) { return _converter.convert(delegateValue); } } StdDeserializer.java000066400000000000000000001330541325620701100363120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.NumberInput; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.BeanDeserializerBase; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.deser.impl.NullsAsEmptyProvider; import com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider; import com.fasterxml.jackson.databind.deser.impl.NullsFailProvider; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.AccessPattern; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.Converter; /** * Base class for common deserializers. Contains shared * base functionality for dealing with primitive values, such * as (re)parsing from String. */ public abstract class StdDeserializer extends JsonDeserializer implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Bitmask that covers {@link DeserializationFeature#USE_BIG_INTEGER_FOR_INTS} * and {@link DeserializationFeature#USE_LONG_FOR_INTS}, used for more efficient * cheks when coercing integral values for untyped deserialization. * * @since 2.6 */ protected final static int F_MASK_INT_COERCIONS = DeserializationFeature.USE_BIG_INTEGER_FOR_INTS.getMask() | DeserializationFeature.USE_LONG_FOR_INTS.getMask(); // @since 2.9 protected final static int F_MASK_ACCEPT_ARRAYS = DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS.getMask() | DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT.getMask(); /** * Type of values this deserializer handles: sometimes * exact types, other time most specific supertype of * types deserializer handles (which may be as generic * as {@link Object} in some case) */ final protected Class _valueClass; protected StdDeserializer(Class vc) { _valueClass = vc; } protected StdDeserializer(JavaType valueType) { // 26-Sep-2017, tatu: [databind#1764] need to add null-check back until 3.x _valueClass = (valueType == null) ? Object.class : valueType.getRawClass(); } /** * Copy-constructor for sub-classes to use, most often when creating * new instances for {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer}. * * @since 2.5 */ protected StdDeserializer(StdDeserializer src) { _valueClass = src._valueClass; } /* /********************************************************** /* Accessors /********************************************************** */ @Override public Class handledType() { return _valueClass; } /* /********************************************************** /* Extended API /********************************************************** */ /** * @deprecated Since 2.3 use {@link #handledType} instead */ @Deprecated public final Class getValueClass() { return _valueClass; } /** * Exact structured type this deserializer handles, if known. *

* Default implementation just returns null. */ public JavaType getValueType() { return null; } /** * Method that can be called to determine if given deserializer is the default * deserializer Jackson uses; as opposed to a custom deserializer installed by * a module or calling application. Determination is done using * {@link JacksonStdImpl} annotation on deserializer class. */ protected boolean isDefaultDeserializer(JsonDeserializer deserializer) { return ClassUtil.isJacksonStdImpl(deserializer); } protected boolean isDefaultKeyDeserializer(KeyDeserializer keyDeser) { return ClassUtil.isJacksonStdImpl(keyDeser); } /* /********************************************************** /* Partial JsonDeserializer implementation /********************************************************** */ /** * Base implementation that does not assume specific type * inclusion mechanism. Sub-classes are expected to override * this method if they are to handle type information. */ @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { return typeDeserializer.deserializeTypedFromAny(p, ctxt); } /* /********************************************************** /* Helper methods for sub-classes, parsing: while mostly /* useful for numeric types, can be also useful for dealing /* with things serialized as numbers (such as Dates). /********************************************************** */ protected final boolean _parseBooleanPrimitive(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_TRUE) return true; if (t == JsonToken.VALUE_FALSE) return false; if (t == JsonToken.VALUE_NULL) { _verifyNullForPrimitive(ctxt); return false; } // should accept ints too, (0 == false, otherwise true) if (t == JsonToken.VALUE_NUMBER_INT) { return _parseBooleanFromInt(p, ctxt); } // And finally, let's allow Strings to be converted too if (t == JsonToken.VALUE_STRING) { String text = p.getText().trim(); // [databind#422]: Allow aliases if ("true".equals(text) || "True".equals(text)) { return true; } if ("false".equals(text) || "False".equals(text)) { return false; } if (_isEmptyOrTextualNull(text)) { _verifyNullForPrimitiveCoercion(ctxt, text); return false; } Boolean b = (Boolean) ctxt.handleWeirdStringValue(_valueClass, text, "only \"true\" or \"false\" recognized"); return Boolean.TRUE.equals(b); } // [databind#381] if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { p.nextToken(); final boolean parsed = _parseBooleanPrimitive(p, ctxt); _verifyEndArrayForSingle(p, ctxt); return parsed; } // Otherwise, no can do: return ((Boolean) ctxt.handleUnexpectedToken(_valueClass, p)).booleanValue(); } protected boolean _parseBooleanFromInt(JsonParser p, DeserializationContext ctxt) throws IOException { // 13-Oct-2016, tatu: As per [databind#1324], need to be careful wrt // degenerate case of huge integers, legal in JSON. // ... this is, on the other hand, probably wrong/sub-optimal for non-JSON // input. For now, no rea _verifyNumberForScalarCoercion(ctxt, p); // Anyway, note that since we know it's valid (JSON) integer, it can't have // extra whitespace to trim. return !"0".equals(p.getText()); } protected final byte _parseBytePrimitive(JsonParser p, DeserializationContext ctxt) throws IOException { int value = _parseIntPrimitive(p, ctxt); // So far so good: but does it fit? if (_byteOverflow(value)) { Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, String.valueOf(value), "overflow, value cannot be represented as 8-bit value"); return _nonNullNumber(v).byteValue(); } return (byte) value; } protected final short _parseShortPrimitive(JsonParser p, DeserializationContext ctxt) throws IOException { int value = _parseIntPrimitive(p, ctxt); // So far so good: but does it fit? if (_shortOverflow(value)) { Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, String.valueOf(value), "overflow, value cannot be represented as 16-bit value"); return _nonNullNumber(v).shortValue(); } return (short) value; } protected final int _parseIntPrimitive(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) { return p.getIntValue(); } switch (p.getCurrentTokenId()) { case JsonTokenId.ID_STRING: String text = p.getText().trim(); if (_isEmptyOrTextualNull(text)) { _verifyNullForPrimitiveCoercion(ctxt, text); return 0; } return _parseIntPrimitive(ctxt, text); case JsonTokenId.ID_NUMBER_FLOAT: if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) { _failDoubleToIntCoercion(p, ctxt, "int"); } return p.getValueAsInt(); case JsonTokenId.ID_NULL: _verifyNullForPrimitive(ctxt); return 0; case JsonTokenId.ID_START_ARRAY: if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { p.nextToken(); final int parsed = _parseIntPrimitive(p, ctxt); _verifyEndArrayForSingle(p, ctxt); return parsed; } break; default: } // Otherwise, no can do: return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).intValue(); } /** * @since 2.9 */ protected final int _parseIntPrimitive(DeserializationContext ctxt, String text) throws IOException { try { if (text.length() > 9) { long l = Long.parseLong(text); if (_intOverflow(l)) { Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text, "Overflow: numeric value (%s) out of range of int (%d -%d)", text, Integer.MIN_VALUE, Integer.MAX_VALUE); return _nonNullNumber(v).intValue(); } return (int) l; } return NumberInput.parseInt(text); } catch (IllegalArgumentException iae) { Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid int value"); return _nonNullNumber(v).intValue(); } } protected final long _parseLongPrimitive(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) { return p.getLongValue(); } switch (p.getCurrentTokenId()) { case JsonTokenId.ID_STRING: String text = p.getText().trim(); if (_isEmptyOrTextualNull(text)) { _verifyNullForPrimitiveCoercion(ctxt, text); return 0L; } return _parseLongPrimitive(ctxt, text); case JsonTokenId.ID_NUMBER_FLOAT: if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) { _failDoubleToIntCoercion(p, ctxt, "long"); } return p.getValueAsLong(); case JsonTokenId.ID_NULL: _verifyNullForPrimitive(ctxt); return 0L; case JsonTokenId.ID_START_ARRAY: if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { p.nextToken(); final long parsed = _parseLongPrimitive(p, ctxt); _verifyEndArrayForSingle(p, ctxt); return parsed; } break; } return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).longValue(); } /** * @since 2.9 */ protected final long _parseLongPrimitive(DeserializationContext ctxt, String text) throws IOException { try { return NumberInput.parseLong(text); } catch (IllegalArgumentException iae) { } { Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid long value"); return _nonNullNumber(v).longValue(); } } protected final float _parseFloatPrimitive(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_NUMBER_FLOAT)) { return p.getFloatValue(); } switch (p.getCurrentTokenId()) { case JsonTokenId.ID_STRING: String text = p.getText().trim(); if (_isEmptyOrTextualNull(text)) { _verifyNullForPrimitiveCoercion(ctxt, text); return 0.0f; } return _parseFloatPrimitive(ctxt, text); case JsonTokenId.ID_NUMBER_INT: return p.getFloatValue(); case JsonTokenId.ID_NULL: _verifyNullForPrimitive(ctxt); return 0.0f; case JsonTokenId.ID_START_ARRAY: if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { p.nextToken(); final float parsed = _parseFloatPrimitive(p, ctxt); _verifyEndArrayForSingle(p, ctxt); return parsed; } break; } // Otherwise, no can do: return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).floatValue(); } /** * @since 2.9 */ protected final float _parseFloatPrimitive(DeserializationContext ctxt, String text) throws IOException { switch (text.charAt(0)) { case 'I': if (_isPosInf(text)) { return Float.POSITIVE_INFINITY; } break; case 'N': if (_isNaN(text)) { return Float.NaN; } break; case '-': if (_isNegInf(text)) { return Float.NEGATIVE_INFINITY; } break; } try { return Float.parseFloat(text); } catch (IllegalArgumentException iae) { } Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid float value"); return _nonNullNumber(v).floatValue(); } protected final double _parseDoublePrimitive(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_NUMBER_FLOAT)) { return p.getDoubleValue(); } switch (p.getCurrentTokenId()) { case JsonTokenId.ID_STRING: String text = p.getText().trim(); if (_isEmptyOrTextualNull(text)) { _verifyNullForPrimitiveCoercion(ctxt, text); return 0.0; } return _parseDoublePrimitive(ctxt, text); case JsonTokenId.ID_NUMBER_INT: return p.getDoubleValue(); case JsonTokenId.ID_NULL: _verifyNullForPrimitive(ctxt); return 0.0; case JsonTokenId.ID_START_ARRAY: if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { p.nextToken(); final double parsed = _parseDoublePrimitive(p, ctxt); _verifyEndArrayForSingle(p, ctxt); return parsed; } break; } // Otherwise, no can do: return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).doubleValue(); } /** * @since 2.9 */ protected final double _parseDoublePrimitive(DeserializationContext ctxt, String text) throws IOException { switch (text.charAt(0)) { case 'I': if (_isPosInf(text)) { return Double.POSITIVE_INFINITY; } break; case 'N': if (_isNaN(text)) { return Double.NaN; } break; case '-': if (_isNegInf(text)) { return Double.NEGATIVE_INFINITY; } break; } try { return parseDouble(text); } catch (IllegalArgumentException iae) { } Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid double value (as String to convert)"); return _nonNullNumber(v).doubleValue(); } protected java.util.Date _parseDate(JsonParser p, DeserializationContext ctxt) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_STRING: return _parseDate(p.getText().trim(), ctxt); case JsonTokenId.ID_NUMBER_INT: { long ts; try { ts = p.getLongValue(); } catch (JsonParseException e) { Number v = (Number) ctxt.handleWeirdNumberValue(_valueClass, p.getNumberValue(), "not a valid 64-bit long for creating `java.util.Date`"); ts = v.longValue(); } return new java.util.Date(ts); } case JsonTokenId.ID_NULL: return (java.util.Date) getNullValue(ctxt); case JsonTokenId.ID_START_ARRAY: return _parseDateFromArray(p, ctxt); } return (java.util.Date) ctxt.handleUnexpectedToken(_valueClass, p); } // @since 2.9 protected java.util.Date _parseDateFromArray(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t; if (ctxt.hasSomeOfFeatures(F_MASK_ACCEPT_ARRAYS)) { t = p.nextToken(); if (t == JsonToken.END_ARRAY) { if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) { return (java.util.Date) getNullValue(ctxt); } } if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { final Date parsed = _parseDate(p, ctxt); _verifyEndArrayForSingle(p, ctxt); return parsed; } } else { t = p.getCurrentToken(); } return (java.util.Date) ctxt.handleUnexpectedToken(_valueClass, t, p, null); } /** * @since 2.8 */ protected java.util.Date _parseDate(String value, DeserializationContext ctxt) throws IOException { try { // Take empty Strings to mean 'empty' Value, usually 'null': if (_isEmptyOrTextualNull(value)) { return (java.util.Date) getNullValue(ctxt); } return ctxt.parseDate(value); } catch (IllegalArgumentException iae) { return (java.util.Date) ctxt.handleWeirdStringValue(_valueClass, value, "not a valid representation (error: %s)", iae.getMessage()); } } /** * Helper method for encapsulating calls to low-level double value parsing; single place * just because we need a work-around that must be applied to all calls. */ protected final static double parseDouble(String numStr) throws NumberFormatException { // avoid some nasty float representations... but should it be MIN_NORMAL or MIN_VALUE? if (NumberInput.NASTY_SMALL_DOUBLE.equals(numStr)) { return Double.MIN_NORMAL; // since 2.7; was MIN_VALUE prior } return Double.parseDouble(numStr); } /** * Helper method used for accessing String value, if possible, doing * necessary conversion or throwing exception as necessary. * * @since 2.1 */ protected final String _parseString(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_STRING) { return p.getText(); } // 07-Nov-2016, tatu: Caller should take care of unwrapping and there shouldn't // be need for extra pass here... /* // [databind#381] if ((t == JsonToken.START_ARRAY) && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { p.nextToken(); final String parsed = _parseString(p, ctxt); _verifyEndArrayForSingle(p, ctxt); return parsed; } */ String value = p.getValueAsString(); if (value != null) { return value; } return (String) ctxt.handleUnexpectedToken(String.class, p); } /** * Helper method that may be used to support fallback for Empty String / Empty Array * non-standard representations; usually for things serialized as JSON Objects. * * @since 2.5 */ @SuppressWarnings("unchecked") protected T _deserializeFromEmpty(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.START_ARRAY) { if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) { t = p.nextToken(); if (t == JsonToken.END_ARRAY) { return null; } return (T) ctxt.handleUnexpectedToken(handledType(), p); } } else if (t == JsonToken.VALUE_STRING) { if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { String str = p.getText().trim(); if (str.isEmpty()) { return null; } } } return (T) ctxt.handleUnexpectedToken(handledType(), p); } /** * Helper method called to determine if we are seeing String value of * "null", and, further, that it should be coerced to null just like * null token. * * @since 2.3 */ protected boolean _hasTextualNull(String value) { return "null".equals(value); } /** * @since 2.9 */ protected boolean _isEmptyOrTextualNull(String value) { return value.isEmpty() || "null".equals(value); } protected final boolean _isNegInf(String text) { return "-Infinity".equals(text) || "-INF".equals(text); } protected final boolean _isPosInf(String text) { return "Infinity".equals(text) || "INF".equals(text); } protected final boolean _isNaN(String text) { return "NaN".equals(text); } /* /********************************************************** /* Helper methods for sub-classes regarding decoding from /* alternate representations /********************************************************** */ /** * Helper method that allows easy support for array-related {@link DeserializationFeature}s * `ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT` and `UNWRAP_SINGLE_VALUE_ARRAYS`: checks for either * empty array, or single-value array-wrapped value (respectively), and either reports * an exception (if no match, or feature(s) not enabled), or returns appropriate * result value. *

* This method should NOT be called if Array representation is explicitly supported * for type: it should only be called in case it is otherwise unrecognized. *

* NOTE: in case of unwrapped single element, will handle actual decoding * by calling {@link #_deserializeWrappedValue}, which by default calls * {@link #deserialize(JsonParser, DeserializationContext)}. * * @since 2.9 */ protected T _deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t; if (ctxt.hasSomeOfFeatures(F_MASK_ACCEPT_ARRAYS)) { t = p.nextToken(); if (t == JsonToken.END_ARRAY) { if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) { return getNullValue(ctxt); } } if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { final T parsed = deserialize(p, ctxt); if (p.nextToken() != JsonToken.END_ARRAY) { handleMissingEndArrayForSingle(p, ctxt); } return parsed; } } else { t = p.getCurrentToken(); } @SuppressWarnings("unchecked") T result = (T) ctxt.handleUnexpectedToken(_valueClass, t, p, null); return result; } /** * Helper called to support {@link DeserializationFeature#UNWRAP_SINGLE_VALUE_ARRAYS}: * default implementation simply calls * {@link #deserialize(JsonParser, DeserializationContext)}, * but handling may be overridden. * * @since 2.9 */ protected T _deserializeWrappedValue(JsonParser p, DeserializationContext ctxt) throws IOException { // 23-Mar-2017, tatu: Let's specifically block recursive resolution to avoid // either supporting nested arrays, or to cause infinite looping. if (p.hasToken(JsonToken.START_ARRAY)) { String msg = String.format( "Cannot deserialize instance of %s out of %s token: nested Arrays not allowed with %s", ClassUtil.nameOf(_valueClass), JsonToken.START_ARRAY, "DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS"); @SuppressWarnings("unchecked") T result = (T) ctxt.handleUnexpectedToken(_valueClass, p.getCurrentToken(), p, msg); return result; } return (T) deserialize(p, ctxt); } /* /**************************************************** /* Helper methods for sub-classes, coercions /**************************************************** */ protected void _failDoubleToIntCoercion(JsonParser p, DeserializationContext ctxt, String type) throws IOException { ctxt.reportInputMismatch(handledType(), "Cannot coerce a floating-point value ('%s') into %s (enable `DeserializationFeature.ACCEPT_FLOAT_AS_INT` to allow)", p.getValueAsString(), type); } /** * Helper method called in case where an integral number is encountered, but * config settings suggest that a coercion may be needed to "upgrade" * {@link java.lang.Number} into "bigger" type like {@link java.lang.Long} or * {@link java.math.BigInteger} * * @see DeserializationFeature#USE_BIG_INTEGER_FOR_INTS * @see DeserializationFeature#USE_LONG_FOR_INTS * * @since 2.6 */ protected Object _coerceIntegral(JsonParser p, DeserializationContext ctxt) throws IOException { int feats = ctxt.getDeserializationFeatures(); if (DeserializationFeature.USE_BIG_INTEGER_FOR_INTS.enabledIn(feats)) { return p.getBigIntegerValue(); } if (DeserializationFeature.USE_LONG_FOR_INTS.enabledIn(feats)) { return p.getLongValue(); } return p.getBigIntegerValue(); // should be optimal, whatever it is } /** * Method to call when JSON `null` token is encountered. Note: only called when * this deserializer encounters it but NOT when reached via property * * @since 2.9 */ protected Object _coerceNullToken(DeserializationContext ctxt, boolean isPrimitive) throws JsonMappingException { if (isPrimitive) { _verifyNullForPrimitive(ctxt); } return getNullValue(ctxt); } /** * Method called when JSON String with value "null" is encountered. * * @since 2.9 */ protected Object _coerceTextualNull(DeserializationContext ctxt, boolean isPrimitive) throws JsonMappingException { Enum feat; boolean enable; if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) { feat = MapperFeature.ALLOW_COERCION_OF_SCALARS; enable = true; } else if (isPrimitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) { feat = DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES; enable = false; } else { return getNullValue(ctxt); } _reportFailedNullCoerce(ctxt, enable, feat, "String \"null\""); return null; } /** * Method called when JSON String with value "" (that is, zero length) is encountered. * * @since 2.9 */ protected Object _coerceEmptyString(DeserializationContext ctxt, boolean isPrimitive) throws JsonMappingException { Enum feat; boolean enable; if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) { feat = MapperFeature.ALLOW_COERCION_OF_SCALARS; enable = true; } else if (isPrimitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) { feat = DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES; enable = false; } else { return getNullValue(ctxt); } _reportFailedNullCoerce(ctxt, enable, feat, "empty String (\"\")"); return null; } // @since 2.9 protected final void _verifyNullForPrimitive(DeserializationContext ctxt) throws JsonMappingException { if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) { ctxt.reportInputMismatch(this, "Cannot coerce `null` %s (disable `DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES` to allow)", _coercedTypeDesc()); } } // NOTE: only for primitive Scalars // @since 2.9 protected final void _verifyNullForPrimitiveCoercion(DeserializationContext ctxt, String str) throws JsonMappingException { Enum feat; boolean enable; if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) { feat = MapperFeature.ALLOW_COERCION_OF_SCALARS; enable = true; } else if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) { feat = DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES; enable = false; } else { return; } String strDesc = str.isEmpty() ? "empty String (\"\")" : String.format("String \"%s\"", str); _reportFailedNullCoerce(ctxt, enable, feat, strDesc); } // NOTE: for non-primitive Scalars // @since 2.9 protected final void _verifyNullForScalarCoercion(DeserializationContext ctxt, String str) throws JsonMappingException { if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) { String strDesc = str.isEmpty() ? "empty String (\"\")" : String.format("String \"%s\"", str); _reportFailedNullCoerce(ctxt, true, MapperFeature.ALLOW_COERCION_OF_SCALARS, strDesc); } } // @since 2.9 protected void _verifyStringForScalarCoercion(DeserializationContext ctxt, String str) throws JsonMappingException { MapperFeature feat = MapperFeature.ALLOW_COERCION_OF_SCALARS; if (!ctxt.isEnabled(feat)) { ctxt.reportInputMismatch(this, "Cannot coerce String \"%s\" %s (enable `%s.%s` to allow)", str, _coercedTypeDesc(), feat.getClass().getSimpleName(), feat.name()); } } // @since 2.9 protected void _verifyNumberForScalarCoercion(DeserializationContext ctxt, JsonParser p) throws IOException { MapperFeature feat = MapperFeature.ALLOW_COERCION_OF_SCALARS; if (!ctxt.isEnabled(feat)) { // 31-Mar-2017, tatu: Since we don't know (or this deep, care) about exact type, // access as a String: may require re-encoding by parser which should be fine String valueDesc = p.getText(); ctxt.reportInputMismatch(this, "Cannot coerce Number (%s) %s (enable `%s.%s` to allow)", valueDesc, _coercedTypeDesc(), feat.getClass().getSimpleName(), feat.name()); } } protected void _reportFailedNullCoerce(DeserializationContext ctxt, boolean state, Enum feature, String inputDesc) throws JsonMappingException { String enableDesc = state ? "enable" : "disable"; ctxt.reportInputMismatch(this, "Cannot coerce %s to Null value %s (%s `%s.%s` to allow)", inputDesc, _coercedTypeDesc(), enableDesc, feature.getClass().getSimpleName(), feature.name()); } /** * Helper method called to get a description of type into which a scalar value coercion * is (most likely) being applied, to be used for constructing exception messages * on coerce failure. * * @return Message with backtick-enclosed name of type this deserializer supports * * @since 2.9 */ protected String _coercedTypeDesc() { boolean structured; String typeDesc; JavaType t = getValueType(); if ((t != null) && !t.isPrimitive()) { structured = (t.isContainerType() || t.isReferenceType()); // 21-Jul-2017, tatu: Probably want to change this (JavaType.toString() not very good) but... typeDesc = "'"+t.toString()+"'"; } else { Class cls = handledType(); structured = cls.isArray() || Collection.class.isAssignableFrom(cls) || Map.class.isAssignableFrom(cls); typeDesc = ClassUtil.nameOf(cls); } if (structured) { return "as content of type "+typeDesc; } return "for type "+typeDesc; } /* /**************************************************** /* Helper methods for sub-classes, resolving dependencies /**************************************************** */ /** * Helper method used to locate deserializers for properties the * type this deserializer handles contains (usually for properties of * bean types) * * @param type Type of property to deserialize * @param property Actual property object (field, method, constuctor parameter) used * for passing deserialized values; provided so deserializer can be contextualized if necessary */ protected JsonDeserializer findDeserializer(DeserializationContext ctxt, JavaType type, BeanProperty property) throws JsonMappingException { return ctxt.findContextualValueDeserializer(type, property); } /** * Helper method to check whether given text refers to what looks like a clean simple * integer number, consisting of optional sign followed by a sequence of digits. */ protected final boolean _isIntNumber(String text) { final int len = text.length(); if (len > 0) { char c = text.charAt(0); // skip leading sign (plus not allowed for strict JSON numbers but...) int i = (c == '-' || c == '+') ? 1 : 0; for (; i < len; ++i) { int ch = text.charAt(i); if (ch > '9' || ch < '0') { return false; } } return true; } return false; } /* /********************************************************** /* Helper methods for: deserializer construction /********************************************************** */ /** * Helper method that can be used to see if specified property has annotation * indicating that a converter is to be used for contained values (contents * of structured types; array/List/Map values) * * @param existingDeserializer (optional) configured content * serializer if one already exists. * * @since 2.2 */ protected JsonDeserializer findConvertingContentDeserializer(DeserializationContext ctxt, BeanProperty prop, JsonDeserializer existingDeserializer) throws JsonMappingException { final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); if (_neitherNull(intr, prop)) { AnnotatedMember member = prop.getMember(); if (member != null) { Object convDef = intr.findDeserializationContentConverter(member); if (convDef != null) { Converter conv = ctxt.converterInstance(prop.getMember(), convDef); JavaType delegateType = conv.getInputType(ctxt.getTypeFactory()); if (existingDeserializer == null) { existingDeserializer = ctxt.findContextualValueDeserializer(delegateType, prop); } return new StdDelegatingDeserializer(conv, delegateType, existingDeserializer); } } } return existingDeserializer; } /* /********************************************************** /* Helper methods for: accessing contextual config settings /********************************************************** */ /** * Helper method that may be used to find if this deserializer has specific * {@link JsonFormat} settings, either via property, or through type-specific * defaulting. * * @param typeForDefaults Type (erased) used for finding default format settings, if any * * @since 2.7 */ protected JsonFormat.Value findFormatOverrides(DeserializationContext ctxt, BeanProperty prop, Class typeForDefaults) { if (prop != null) { return prop.findPropertyFormat(ctxt.getConfig(), typeForDefaults); } // even without property or AnnotationIntrospector, may have type-specific defaults return ctxt.getDefaultPropertyFormat(typeForDefaults); } /** * Convenience method that uses {@link #findFormatOverrides} to find possible * defaults and/of overrides, and then calls * JsonFormat.Value.getFeature(feat) * to find whether that feature has been specifically marked as enabled or disabled. * * @param typeForDefaults Type (erased) used for finding default format settings, if any * * @since 2.7 */ protected Boolean findFormatFeature(DeserializationContext ctxt, BeanProperty prop, Class typeForDefaults, JsonFormat.Feature feat) { JsonFormat.Value format = findFormatOverrides(ctxt, prop, typeForDefaults); if (format != null) { return format.getFeature(feat); } return null; } /** * Method called to find {@link NullValueProvider} for a primary property, using * "value nulls" setting. If no provider found (not defined, or is "skip"), * will return `null`. * * @since 2.9 */ protected final NullValueProvider findValueNullProvider(DeserializationContext ctxt, SettableBeanProperty prop, PropertyMetadata propMetadata) throws JsonMappingException { if (prop != null) { return _findNullProvider(ctxt, prop, propMetadata.getValueNulls(), prop.getValueDeserializer()); } return null; } /** * Method called to find {@link NullValueProvider} for a contents of a structured * primary property (Collection, Map, array), using * "content nulls" setting. If no provider found (not defined), * will return given value deserializer (which is a null value provider itself). * * @since 2.9 */ protected NullValueProvider findContentNullProvider(DeserializationContext ctxt, BeanProperty prop, JsonDeserializer valueDeser) throws JsonMappingException { final Nulls nulls = findContentNullStyle(ctxt, prop); if (nulls == Nulls.SKIP) { return NullsConstantProvider.skipper(); } NullValueProvider prov = _findNullProvider(ctxt, prop, nulls, valueDeser); if (prov != null) { return prov; } return valueDeser; } protected Nulls findContentNullStyle(DeserializationContext ctxt, BeanProperty prop) throws JsonMappingException { if (prop != null) { return prop.getMetadata().getContentNulls(); } return null; } // @since 2.9 protected final NullValueProvider _findNullProvider(DeserializationContext ctxt, BeanProperty prop, Nulls nulls, JsonDeserializer valueDeser) throws JsonMappingException { if (nulls == Nulls.FAIL) { if (prop == null) { return NullsFailProvider.constructForRootValue(ctxt.constructType(valueDeser.handledType())); } return NullsFailProvider.constructForProperty(prop); } if (nulls == Nulls.AS_EMPTY) { // cannot deal with empty values if there is no value deserializer that // can indicate what "empty value" is: if (valueDeser == null) { return null; } // Let's first do some sanity checking... // NOTE: although we could use `ValueInstantiator.Gettable` in general, // let's not since that would prevent being able to use custom impls: if (valueDeser instanceof BeanDeserializerBase) { ValueInstantiator vi = ((BeanDeserializerBase) valueDeser).getValueInstantiator(); if (!vi.canCreateUsingDefault()) { final JavaType type = prop.getType(); ctxt.reportBadDefinition(type, String.format("Cannot create empty instance of %s, no default Creator", type)); } } // Second: can with pre-fetch value? { AccessPattern access = valueDeser.getEmptyAccessPattern(); if (access == AccessPattern.ALWAYS_NULL) { return NullsConstantProvider.nuller(); } if (access == AccessPattern.CONSTANT) { return NullsConstantProvider.forValue(valueDeser.getEmptyValue(ctxt)); } } return new NullsAsEmptyProvider(valueDeser); } if (nulls == Nulls.SKIP) { return NullsConstantProvider.skipper(); } return null; } /* /********************************************************** /* Helper methods for sub-classes, problem reporting /********************************************************** */ /** * Method called to deal with a property that did not map to a known * Bean property. Method can deal with the problem as it sees fit (ignore, * throw exception); but if it does return, it has to skip the matching * Json content parser has. * * @param p Parser that points to value of the unknown property * @param ctxt Context for deserialization; allows access to the parser, * error reporting functionality * @param instanceOrClass Instance that is being populated by this * deserializer, or if not known, Class that would be instantiated. * If null, will assume type is what {@link #getValueClass} returns. * @param propName Name of the property that cannot be mapped */ protected void handleUnknownProperty(JsonParser p, DeserializationContext ctxt, Object instanceOrClass, String propName) throws IOException { if (instanceOrClass == null) { instanceOrClass = handledType(); } // Maybe we have configured handler(s) to take care of it? if (ctxt.handleUnknownProperty(p, this, instanceOrClass, propName)) { return; } /* But if we do get this far, need to skip whatever value we * are pointing to now (although handler is likely to have done that already) */ p.skipChildren(); } protected void handleMissingEndArrayForSingle(JsonParser p, DeserializationContext ctxt) throws IOException { ctxt.reportWrongTokenException(this, JsonToken.END_ARRAY, "Attempted to unwrap '%s' value from an array (with `DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS`) but it contains more than one value", handledType().getName()); // 05-May-2016, tatu: Should recover somehow (maybe skip until END_ARRAY); // but for now just fall through } protected void _verifyEndArrayForSingle(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.nextToken(); if (t != JsonToken.END_ARRAY) { handleMissingEndArrayForSingle(p, ctxt); } } /* /********************************************************** /* Helper methods, other /********************************************************** */ /** * @since 2.9 */ protected final static boolean _neitherNull(Object a, Object b) { return (a != null) && (b != null); } /** * @since 2.9 */ protected final boolean _byteOverflow(int value) { // 07-nov-2016, tatu: We support "unsigned byte" as well // as Java signed range since that's relatively common usage return (value < Byte.MIN_VALUE || value > 255); } /** * @since 2.9 */ protected final boolean _shortOverflow(int value) { return (value < Short.MIN_VALUE || value > Short.MAX_VALUE); } /** * @since 2.9 */ protected final boolean _intOverflow(long value) { return (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE); } /** * @since 2.9 */ protected Number _nonNullNumber(Number n) { if (n == null) { n = Integer.valueOf(0); } return n; } } StdKeyDeserializer.java000066400000000000000000000376371325620701100367750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.util.*; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.io.NumberInput; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.EnumResolver; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Default {@link KeyDeserializer} implementation used for most {@link java.util.Map} * types Jackson supports. * Implemented as "chameleon" (or swiss pocket knife) class; not particularly elegant, * but helps reduce number of classes and jar size (class metadata adds significant * per-class overhead; much more than bytecode). */ @JacksonStdImpl public class StdKeyDeserializer extends KeyDeserializer implements java.io.Serializable { private static final long serialVersionUID = 1L; public final static int TYPE_BOOLEAN = 1; public final static int TYPE_BYTE = 2; public final static int TYPE_SHORT = 3; public final static int TYPE_CHAR = 4; public final static int TYPE_INT = 5; public final static int TYPE_LONG = 6; public final static int TYPE_FLOAT = 7; public final static int TYPE_DOUBLE = 8; public final static int TYPE_LOCALE = 9; public final static int TYPE_DATE = 10; public final static int TYPE_CALENDAR = 11; public final static int TYPE_UUID = 12; public final static int TYPE_URI = 13; public final static int TYPE_URL = 14; public final static int TYPE_CLASS = 15; public final static int TYPE_CURRENCY = 16; public final static int TYPE_BYTE_ARRAY = 17; // since 2.9 final protected int _kind; final protected Class _keyClass; /** * Some types that are deserialized using a helper deserializer. */ protected final FromStringDeserializer _deser; protected StdKeyDeserializer(int kind, Class cls) { this(kind, cls, null); } protected StdKeyDeserializer(int kind, Class cls, FromStringDeserializer deser) { _kind = kind; _keyClass = cls; _deser = deser; } public static StdKeyDeserializer forType(Class raw) { int kind; // first common types: if (raw == String.class || raw == Object.class || raw == CharSequence.class) { return StringKD.forType(raw); } else if (raw == UUID.class) { kind = TYPE_UUID; } else if (raw == Integer.class) { kind = TYPE_INT; } else if (raw == Long.class) { kind = TYPE_LONG; } else if (raw == Date.class) { kind = TYPE_DATE; } else if (raw == Calendar.class) { kind = TYPE_CALENDAR; // then less common ones... } else if (raw == Boolean.class) { kind = TYPE_BOOLEAN; } else if (raw == Byte.class) { kind = TYPE_BYTE; } else if (raw == Character.class) { kind = TYPE_CHAR; } else if (raw == Short.class) { kind = TYPE_SHORT; } else if (raw == Float.class) { kind = TYPE_FLOAT; } else if (raw == Double.class) { kind = TYPE_DOUBLE; } else if (raw == URI.class) { kind = TYPE_URI; } else if (raw == URL.class) { kind = TYPE_URL; } else if (raw == Class.class) { kind = TYPE_CLASS; } else if (raw == Locale.class) { FromStringDeserializer deser = FromStringDeserializer.findDeserializer(Locale.class); return new StdKeyDeserializer(TYPE_LOCALE, raw, deser); } else if (raw == Currency.class) { FromStringDeserializer deser = FromStringDeserializer.findDeserializer(Currency.class); return new StdKeyDeserializer(TYPE_CURRENCY, raw, deser); } else if (raw == byte[].class) { kind = TYPE_BYTE_ARRAY; } else { return null; } return new StdKeyDeserializer(kind, raw); } @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { if (key == null) { // is this even legal call? return null; } try { Object result = _parse(key, ctxt); if (result != null) { return result; } } catch (Exception re) { return ctxt.handleWeirdKey(_keyClass, key, "not a valid representation, problem: (%s) %s", re.getClass().getName(), re.getMessage()); } if (_keyClass.isEnum() && ctxt.getConfig().isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { return null; } return ctxt.handleWeirdKey(_keyClass, key, "not a valid representation"); } public Class getKeyClass() { return _keyClass; } protected Object _parse(String key, DeserializationContext ctxt) throws Exception { switch (_kind) { case TYPE_BOOLEAN: if ("true".equals(key)) { return Boolean.TRUE; } if ("false".equals(key)) { return Boolean.FALSE; } return ctxt.handleWeirdKey(_keyClass, key, "value not 'true' or 'false'"); case TYPE_BYTE: { int value = _parseInt(key); // allow range up to 255, inclusive (to support "unsigned" byte) if (value < Byte.MIN_VALUE || value > 255) { return ctxt.handleWeirdKey(_keyClass, key, "overflow, value cannot be represented as 8-bit value"); } return Byte.valueOf((byte) value); } case TYPE_SHORT: { int value = _parseInt(key); if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { return ctxt.handleWeirdKey(_keyClass, key, "overflow, value cannot be represented as 16-bit value"); // fall-through and truncate if need be } return Short.valueOf((short) value); } case TYPE_CHAR: if (key.length() == 1) { return Character.valueOf(key.charAt(0)); } return ctxt.handleWeirdKey(_keyClass, key, "can only convert 1-character Strings"); case TYPE_INT: return _parseInt(key); case TYPE_LONG: return _parseLong(key); case TYPE_FLOAT: // Bounds/range checks would be tricky here, so let's not bother even trying... return Float.valueOf((float) _parseDouble(key)); case TYPE_DOUBLE: return _parseDouble(key); case TYPE_LOCALE: try { return _deser._deserialize(key, ctxt); } catch (IllegalArgumentException e) { return _weirdKey(ctxt, key, e); } case TYPE_CURRENCY: try { return _deser._deserialize(key, ctxt); } catch (IllegalArgumentException e) { return _weirdKey(ctxt, key, e); } case TYPE_DATE: return ctxt.parseDate(key); case TYPE_CALENDAR: return ctxt.constructCalendar(ctxt.parseDate(key)); case TYPE_UUID: try { return UUID.fromString(key); } catch (Exception e) { return _weirdKey(ctxt, key, e); } case TYPE_URI: try { return URI.create(key); } catch (Exception e) { return _weirdKey(ctxt, key, e); } case TYPE_URL: try { return new URL(key); } catch (MalformedURLException e) { return _weirdKey(ctxt, key, e); } case TYPE_CLASS: try { return ctxt.findClass(key); } catch (Exception e) { return ctxt.handleWeirdKey(_keyClass, key, "unable to parse key as Class"); } case TYPE_BYTE_ARRAY: try { return ctxt.getConfig().getBase64Variant().decode(key); } catch (IllegalArgumentException e) { return _weirdKey(ctxt, key, e); } default: throw new IllegalStateException("Internal error: unknown key type "+_keyClass); } } /* /********************************************************** /* Helper methods for sub-classes /********************************************************** */ protected int _parseInt(String key) throws IllegalArgumentException { return Integer.parseInt(key); } protected long _parseLong(String key) throws IllegalArgumentException { return Long.parseLong(key); } protected double _parseDouble(String key) throws IllegalArgumentException { return NumberInput.parseDouble(key); } // @since 2.9 protected Object _weirdKey(DeserializationContext ctxt, String key, Exception e) throws IOException { return ctxt.handleWeirdKey(_keyClass, key, "problem: %s", e.getMessage()); } /* /********************************************************** /* First: the standard "String as String" deserializer /********************************************************** */ @JacksonStdImpl final static class StringKD extends StdKeyDeserializer { private static final long serialVersionUID = 1L; private final static StringKD sString = new StringKD(String.class); private final static StringKD sObject = new StringKD(Object.class); private StringKD(Class nominalType) { super(-1, nominalType); } public static StringKD forType(Class nominalType) { if (nominalType == String.class) { return sString; } if (nominalType == Object.class) { return sObject; } return new StringKD(nominalType); } @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException { return key; } } /* /********************************************************** /* Key deserializer implementations; other /********************************************************** */ /** * Key deserializer that wraps a "regular" deserializer (but one * that must recognize FIELD_NAMEs as text!) to reuse existing * handlers as key handlers. */ final static class DelegatingKD extends KeyDeserializer // note: NOT the std one implements java.io.Serializable { private static final long serialVersionUID = 1L; final protected Class _keyClass; protected final JsonDeserializer _delegate; protected DelegatingKD(Class cls, JsonDeserializer deser) { _keyClass = cls; _delegate = deser; } @SuppressWarnings("resource") @Override public final Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { if (key == null) { // is this even legal call? return null; } TokenBuffer tb = new TokenBuffer(ctxt.getParser(), ctxt); tb.writeString(key); try { // Ugh... should not have to give parser which may or may not be correct one... JsonParser p = tb.asParser(); p.nextToken(); Object result = _delegate.deserialize(p, ctxt); if (result != null) { return result; } return ctxt.handleWeirdKey(_keyClass, key, "not a valid representation"); } catch (Exception re) { return ctxt.handleWeirdKey(_keyClass, key, "not a valid representation: %s", re.getMessage()); } } public Class getKeyClass() { return _keyClass; } } @JacksonStdImpl final static class EnumKD extends StdKeyDeserializer { private static final long serialVersionUID = 1L; protected final EnumResolver _byNameResolver; protected final AnnotatedMethod _factory; /** * Lazily constructed alternative in case there is need to * use 'toString()' method as the source. * * @since 2.7.3 */ protected EnumResolver _byToStringResolver; protected final Enum _enumDefaultValue; protected EnumKD(EnumResolver er, AnnotatedMethod factory) { super(-1, er.getEnumClass()); _byNameResolver = er; _factory = factory; _enumDefaultValue = er.getDefaultValue(); } @Override public Object _parse(String key, DeserializationContext ctxt) throws IOException { if (_factory != null) { try { return _factory.call1(key); } catch (Exception e) { ClassUtil.unwrapAndThrowAsIAE(e); } } EnumResolver res = ctxt.isEnabled(DeserializationFeature.READ_ENUMS_USING_TO_STRING) ? _getToStringResolver(ctxt) : _byNameResolver; Enum e = res.findEnum(key); if (e == null) { if ((_enumDefaultValue != null) && ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)) { e = _enumDefaultValue; } else if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { return ctxt.handleWeirdKey(_keyClass, key, "not one of values excepted for Enum class: %s", res.getEnumIds()); } // fall-through if problems are collected, not immediately thrown } return e; } private EnumResolver _getToStringResolver(DeserializationContext ctxt) { EnumResolver res = _byToStringResolver; if (res == null) { synchronized (this) { res = EnumResolver.constructUnsafeUsingToString(_byNameResolver.getEnumClass(), ctxt.getAnnotationIntrospector()); } } return res; } } /** * Key deserializer that calls a single-string-arg constructor * to instantiate desired key type. */ final static class StringCtorKeyDeserializer extends StdKeyDeserializer { private static final long serialVersionUID = 1L; protected final Constructor _ctor; public StringCtorKeyDeserializer(Constructor ctor) { super(-1, ctor.getDeclaringClass()); _ctor = ctor; } @Override public Object _parse(String key, DeserializationContext ctxt) throws Exception { return _ctor.newInstance(key); } } /** * Key deserializer that calls a static no-args factory method * to instantiate desired key type. */ final static class StringFactoryKeyDeserializer extends StdKeyDeserializer { private static final long serialVersionUID = 1L; final Method _factoryMethod; public StringFactoryKeyDeserializer(Method fm) { super(-1, fm.getDeclaringClass()); _factoryMethod = fm; } @Override public Object _parse(String key, DeserializationContext ctxt) throws Exception { return _factoryMethod.invoke(null, key); } } } StdKeyDeserializers.java000066400000000000000000000072511325620701100371450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.KeyDeserializers; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.EnumResolver; /** * Helper class used to contain simple/well-known key deserializers. * Following kinds of Objects can be handled currently: *
    *
  • Primitive wrappers (Boolean, Byte, Char, Short, Integer, Float, Long, Double)
  • *
  • Enums (usually not needed, since EnumMap doesn't call us)
  • *
  • {@link java.util.Date}
  • *
  • {@link java.util.Calendar}
  • *
  • {@link java.util.UUID}
  • *
  • {@link java.util.Locale}
  • *
  • Anything with constructor that takes a single String arg * (if not explicitly @JsonIgnore'd)
  • *
  • Anything with {@code static T valueOf(String)} factory method * (if not explicitly @JsonIgnore'd)
  • *
*/ public class StdKeyDeserializers implements KeyDeserializers, java.io.Serializable { private static final long serialVersionUID = 1L; public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumResolver) { return new StdKeyDeserializer.EnumKD(enumResolver, null); } public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumResolver, AnnotatedMethod factory) { return new StdKeyDeserializer.EnumKD(enumResolver, factory); } public static KeyDeserializer constructDelegatingKeyDeserializer(DeserializationConfig config, JavaType type, JsonDeserializer deser) { return new StdKeyDeserializer.DelegatingKD(type.getRawClass(), deser); } public static KeyDeserializer findStringBasedKeyDeserializer(DeserializationConfig config, JavaType type) { /* We don't need full deserialization information, just need to * know creators. */ BeanDescription beanDesc = config.introspect(type); // Ok, so: can we find T(String) constructor? Constructor ctor = beanDesc.findSingleArgConstructor(String.class); if (ctor != null) { if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(ctor, config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } return new StdKeyDeserializer.StringCtorKeyDeserializer(ctor); } /* or if not, "static T valueOf(String)" (or equivalent marked * with @JsonCreator annotation?) */ Method m = beanDesc.findFactoryMethod(String.class); if (m != null){ if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(m, config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } return new StdKeyDeserializer.StringFactoryKeyDeserializer(m); } // nope, no such luck... return null; } /* /********************************************************** /* KeyDeserializers implementation /********************************************************** */ @Override public KeyDeserializer findKeyDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { Class raw = type.getRawClass(); // 23-Apr-2013, tatu: Map primitive types, just in case one was given if (raw.isPrimitive()) { raw = ClassUtil.wrapperType(raw); } return StdKeyDeserializer.forType(raw); } } StdNodeBasedDeserializer.java000066400000000000000000000055311325620701100400550ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ResolvableDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; /** * Convenience deserializer that may be used to deserialize values given an * intermediate tree representation ({@link JsonNode}). * Note that this is a slightly simplified alternative to {@link StdDelegatingDeserializer}). * * @param Target type of this deserializer; that is, type of values that * input data is deserialized into. * * @since 2.5 */ public abstract class StdNodeBasedDeserializer extends StdDeserializer implements ResolvableDeserializer { private static final long serialVersionUID = 1L; protected JsonDeserializer _treeDeserializer; /* /********************************************************** /* Life-cycle /********************************************************** */ protected StdNodeBasedDeserializer(JavaType targetType) { super(targetType); } protected StdNodeBasedDeserializer(Class targetType) { super(targetType); } /** * "Copy-constructor" used when creating a modified copies, most often * if sub-class implements {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer}. */ protected StdNodeBasedDeserializer(StdNodeBasedDeserializer src) { super(src); _treeDeserializer = src._treeDeserializer; } @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException { _treeDeserializer = ctxt.findRootValueDeserializer(ctxt.constructType(JsonNode.class)); } /* /********************************************************** /* Abstract methods for sub-classes /********************************************************** */ public abstract T convert(JsonNode root, DeserializationContext ctxt) throws IOException; /* /********************************************************** /* JsonDeserializer impl /********************************************************** */ @Override public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { JsonNode n = (JsonNode) _treeDeserializer.deserialize(jp, ctxt); return convert(n, ctxt); } @Override public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer td) throws IOException, JsonProcessingException { /* 19-Nov-2014, tatu: Quite likely we'd have some issues but... let's * try, just in case. */ JsonNode n = (JsonNode) _treeDeserializer.deserializeWithType(jp, ctxt, td); return convert(n, ctxt); } } StdScalarDeserializer.java000066400000000000000000000044111325620701100374320ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.AccessPattern; /** * Base class for deserializers that handle types that are serialized * as JSON scalars (non-structured, i.e. non-Object, non-Array, values). */ public abstract class StdScalarDeserializer extends StdDeserializer { private static final long serialVersionUID = 1L; protected StdScalarDeserializer(Class vc) { super(vc); } protected StdScalarDeserializer(JavaType valueType) { super(valueType); } // since 2.5 protected StdScalarDeserializer(StdScalarDeserializer src) { super(src); } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { return typeDeserializer.deserializeTypedFromScalar(p, ctxt); } /** * Overridden to simply call deserialize() method that does not take value * to update, since scalar values are usually non-mergeable. */ @Override // since 2.9 public T deserialize(JsonParser p, DeserializationContext ctxt, T intoValue) throws IOException { // 25-Oct-2016, tatu: And if attempt is made, see if we are to complain... ctxt.reportBadMerge(this); // except that it is possible to suppress this; and if so... return deserialize(p, ctxt); } /** * By default assumption is that scalar types cannot be updated: many are immutable * values (such as primitives and wrappers) */ @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return Boolean.FALSE; } // Typically Scalar values have default setting of "nulls as nulls" @Override public AccessPattern getNullAccessPattern() { return AccessPattern.ALWAYS_NULL; } // While some scalar types have non-null empty values (hence can't say "ALWAYS_NULL") // they are mostly immutable, shareable and so constant. @Override // since 2.9 public AccessPattern getEmptyAccessPattern() { return AccessPattern.CONSTANT; } } StdValueInstantiator.java000066400000000000000000000437541325620701100373530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Default {@link ValueInstantiator} implementation, which supports * Creator methods that can be indicated by standard Jackson * annotations. */ @JacksonStdImpl public class StdValueInstantiator extends ValueInstantiator implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Type of values that are instantiated; used * for error reporting purposes. */ protected final String _valueTypeDesc; /** * @since 2.8 */ protected final Class _valueClass; // // // Default (no-args) construction /** * Default (no-argument) constructor to use for instantiation * (with {@link #createUsingDefault}) */ protected AnnotatedWithParams _defaultCreator; // // // With-args (property-based) construction protected AnnotatedWithParams _withArgsCreator; protected SettableBeanProperty[] _constructorArguments; // // // Delegate construction protected JavaType _delegateType; protected AnnotatedWithParams _delegateCreator; protected SettableBeanProperty[] _delegateArguments; // // // Array delegate construction protected JavaType _arrayDelegateType; protected AnnotatedWithParams _arrayDelegateCreator; protected SettableBeanProperty[] _arrayDelegateArguments; // // // Scalar construction protected AnnotatedWithParams _fromStringCreator; protected AnnotatedWithParams _fromIntCreator; protected AnnotatedWithParams _fromLongCreator; protected AnnotatedWithParams _fromDoubleCreator; protected AnnotatedWithParams _fromBooleanCreator; // // // Incomplete creator protected AnnotatedParameter _incompleteParameter; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @deprecated Since 2.7 use constructor that takes {@link JavaType} instead */ @Deprecated public StdValueInstantiator(DeserializationConfig config, Class valueType) { _valueTypeDesc = ClassUtil.nameOf(valueType); _valueClass = (valueType == null) ? Object.class : valueType; } public StdValueInstantiator(DeserializationConfig config, JavaType valueType) { _valueTypeDesc = (valueType == null) ? "UNKNOWN TYPE" : valueType.toString(); _valueClass = (valueType == null) ? Object.class : valueType.getRawClass(); } /** * Copy-constructor that sub-classes can use when creating new instances * by fluent-style construction */ protected StdValueInstantiator(StdValueInstantiator src) { _valueTypeDesc = src._valueTypeDesc; _valueClass = src._valueClass; _defaultCreator = src._defaultCreator; _constructorArguments = src._constructorArguments; _withArgsCreator = src._withArgsCreator; _delegateType = src._delegateType; _delegateCreator = src._delegateCreator; _delegateArguments = src._delegateArguments; _arrayDelegateType = src._arrayDelegateType; _arrayDelegateCreator = src._arrayDelegateCreator; _arrayDelegateArguments = src._arrayDelegateArguments; _fromStringCreator = src._fromStringCreator; _fromIntCreator = src._fromIntCreator; _fromLongCreator = src._fromLongCreator; _fromDoubleCreator = src._fromDoubleCreator; _fromBooleanCreator = src._fromBooleanCreator; } /** * Method for setting properties related to instantiating values * from JSON Object. We will choose basically only one approach (out of possible * three), and clear other properties */ public void configureFromObjectSettings(AnnotatedWithParams defaultCreator, AnnotatedWithParams delegateCreator, JavaType delegateType, SettableBeanProperty[] delegateArgs, AnnotatedWithParams withArgsCreator, SettableBeanProperty[] constructorArgs) { _defaultCreator = defaultCreator; _delegateCreator = delegateCreator; _delegateType = delegateType; _delegateArguments = delegateArgs; _withArgsCreator = withArgsCreator; _constructorArguments = constructorArgs; } public void configureFromArraySettings( AnnotatedWithParams arrayDelegateCreator, JavaType arrayDelegateType, SettableBeanProperty[] arrayDelegateArgs) { _arrayDelegateCreator = arrayDelegateCreator; _arrayDelegateType = arrayDelegateType; _arrayDelegateArguments = arrayDelegateArgs; } public void configureFromStringCreator(AnnotatedWithParams creator) { _fromStringCreator = creator; } public void configureFromIntCreator(AnnotatedWithParams creator) { _fromIntCreator = creator; } public void configureFromLongCreator(AnnotatedWithParams creator) { _fromLongCreator = creator; } public void configureFromDoubleCreator(AnnotatedWithParams creator) { _fromDoubleCreator = creator; } public void configureFromBooleanCreator(AnnotatedWithParams creator) { _fromBooleanCreator = creator; } public void configureIncompleteParameter(AnnotatedParameter parameter) { _incompleteParameter = parameter; } /* /********************************************************** /* Public API implementation; metadata /********************************************************** */ @Override public String getValueTypeDesc() { return _valueTypeDesc; } @Override public Class getValueClass() { return _valueClass; } @Override public boolean canCreateFromString() { return (_fromStringCreator != null); } @Override public boolean canCreateFromInt() { return (_fromIntCreator != null); } @Override public boolean canCreateFromLong() { return (_fromLongCreator != null); } @Override public boolean canCreateFromDouble() { return (_fromDoubleCreator != null); } @Override public boolean canCreateFromBoolean() { return (_fromBooleanCreator != null); } @Override public boolean canCreateUsingDefault() { return (_defaultCreator != null); } @Override public boolean canCreateUsingDelegate() { return (_delegateType != null); } @Override public boolean canCreateUsingArrayDelegate() { return (_arrayDelegateType != null); } @Override public boolean canCreateFromObjectWith() { return (_withArgsCreator != null); } @Override public boolean canInstantiate() { return canCreateUsingDefault() || canCreateUsingDelegate() || canCreateUsingArrayDelegate() || canCreateFromObjectWith() || canCreateFromString() || canCreateFromInt() || canCreateFromLong() || canCreateFromDouble() || canCreateFromBoolean(); } @Override public JavaType getDelegateType(DeserializationConfig config) { return _delegateType; } @Override public JavaType getArrayDelegateType(DeserializationConfig config) { return _arrayDelegateType; } @Override public SettableBeanProperty[] getFromObjectArguments(DeserializationConfig config) { return _constructorArguments; } /* /********************************************************** /* Public API implementation; instantiation from JSON Object /********************************************************** */ @Override public Object createUsingDefault(DeserializationContext ctxt) throws IOException { if (_defaultCreator == null) { // sanity-check; caller should check return super.createUsingDefault(ctxt); } try { return _defaultCreator.call(); } catch (Exception e) { // 19-Apr-2017, tatu: Let's not catch Errors, just Exceptions return ctxt.handleInstantiationProblem(_valueClass, null, rewrapCtorProblem(ctxt, e)); } } @Override public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) throws IOException { if (_withArgsCreator == null) { // sanity-check; caller should check return super.createFromObjectWith(ctxt, args); } try { return _withArgsCreator.call(args); } catch (Exception e) { // 19-Apr-2017, tatu: Let's not catch Errors, just Exceptions return ctxt.handleInstantiationProblem(_valueClass, args, rewrapCtorProblem(ctxt, e)); } } @Override public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) throws IOException { // 04-Oct-2016, tatu: Need delegation to work around [databind#1392]... if (_delegateCreator == null) { if (_arrayDelegateCreator != null) { return _createUsingDelegate(_arrayDelegateCreator, _arrayDelegateArguments, ctxt, delegate); } } return _createUsingDelegate(_delegateCreator, _delegateArguments, ctxt, delegate); } @Override public Object createUsingArrayDelegate(DeserializationContext ctxt, Object delegate) throws IOException { if (_arrayDelegateCreator == null) { if (_delegateCreator != null) { // sanity-check; caller should check // fallback to the classic delegate creator return createUsingDelegate(ctxt, delegate); } } return _createUsingDelegate(_arrayDelegateCreator, _arrayDelegateArguments, ctxt, delegate); } /* /********************************************************** /* Public API implementation; instantiation from JSON scalars /********************************************************** */ @Override public Object createFromString(DeserializationContext ctxt, String value) throws IOException { if (_fromStringCreator == null) { return _createFromStringFallbacks(ctxt, value); } try { return _fromStringCreator.call1(value); } catch (Throwable t) { return ctxt.handleInstantiationProblem(_fromStringCreator.getDeclaringClass(), value, rewrapCtorProblem(ctxt, t)); } } @Override public Object createFromInt(DeserializationContext ctxt, int value) throws IOException { // First: "native" int methods work best: if (_fromIntCreator != null) { Object arg = Integer.valueOf(value); try { return _fromIntCreator.call1(arg); } catch (Throwable t0) { return ctxt.handleInstantiationProblem(_fromIntCreator.getDeclaringClass(), arg, rewrapCtorProblem(ctxt, t0)); } } // but if not, can do widening conversion if (_fromLongCreator != null) { Object arg = Long.valueOf(value); try { return _fromLongCreator.call1(arg); } catch (Throwable t0) { return ctxt.handleInstantiationProblem(_fromLongCreator.getDeclaringClass(), arg, rewrapCtorProblem(ctxt, t0)); } } return super.createFromInt(ctxt, value); } @Override public Object createFromLong(DeserializationContext ctxt, long value) throws IOException { if (_fromLongCreator == null) { return super.createFromLong(ctxt, value); } Object arg = Long.valueOf(value); try { return _fromLongCreator.call1(arg); } catch (Throwable t0) { return ctxt.handleInstantiationProblem(_fromLongCreator.getDeclaringClass(), arg, rewrapCtorProblem(ctxt, t0)); } } @Override public Object createFromDouble(DeserializationContext ctxt, double value) throws IOException { if (_fromDoubleCreator == null) { return super.createFromDouble(ctxt, value); } Object arg = Double.valueOf(value); try { return _fromDoubleCreator.call1(arg); } catch (Throwable t0) { return ctxt.handleInstantiationProblem(_fromDoubleCreator.getDeclaringClass(), arg, rewrapCtorProblem(ctxt, t0)); } } @Override public Object createFromBoolean(DeserializationContext ctxt, boolean value) throws IOException { if (_fromBooleanCreator == null) { return super.createFromBoolean(ctxt, value); } final Boolean arg = Boolean.valueOf(value); try { return _fromBooleanCreator.call1(arg); } catch (Throwable t0) { return ctxt.handleInstantiationProblem(_fromBooleanCreator.getDeclaringClass(), arg, rewrapCtorProblem(ctxt, t0)); } } /* /********************************************************** /* Extended API: configuration mutators, accessors /********************************************************** */ @Override public AnnotatedWithParams getDelegateCreator() { return _delegateCreator; } @Override public AnnotatedWithParams getArrayDelegateCreator() { return _arrayDelegateCreator; } @Override public AnnotatedWithParams getDefaultCreator() { return _defaultCreator; } @Override public AnnotatedWithParams getWithArgsCreator() { return _withArgsCreator; } @Override public AnnotatedParameter getIncompleteParameter() { return _incompleteParameter; } /* /********************************************************** /* Internal methods /********************************************************** */ /** * @deprecated Since 2.7 call either {@link #unwrapAndWrapException} or * {@link #wrapAsJsonMappingException} */ @Deprecated // since 2.7 protected JsonMappingException wrapException(Throwable t) { // 05-Nov-2015, tatu: This used to always unwrap the whole exception, but now only // does so if and until `JsonMappingException` is found. for (Throwable curr = t; curr != null; curr = curr.getCause()) { if (curr instanceof JsonMappingException) { return (JsonMappingException) curr; } } return new JsonMappingException(null, "Instantiation of "+getValueTypeDesc()+" value failed: "+t.getMessage(), t); } /** * @since 2.7 */ protected JsonMappingException unwrapAndWrapException(DeserializationContext ctxt, Throwable t) { // 05-Nov-2015, tatu: This used to always unwrap the whole exception, but now only // does so if and until `JsonMappingException` is found. for (Throwable curr = t; curr != null; curr = curr.getCause()) { if (curr instanceof JsonMappingException) { return (JsonMappingException) curr; } } return ctxt.instantiationException(getValueClass(), t); } /** * @since 2.7 */ protected JsonMappingException wrapAsJsonMappingException(DeserializationContext ctxt, Throwable t) { // 05-Nov-2015, tatu: Only avoid wrapping if already a JsonMappingException if (t instanceof JsonMappingException) { return (JsonMappingException) t; } return ctxt.instantiationException(getValueClass(), t); } /** * @since 2.7 */ protected JsonMappingException rewrapCtorProblem(DeserializationContext ctxt, Throwable t) { // 05-Nov-2015, tatu: Seems like there are really only 2 useless wrapper errors/exceptions, // so just peel those, and nothing else if ((t instanceof ExceptionInInitializerError) // from static initialization block || (t instanceof InvocationTargetException) // from constructor/method ) { Throwable cause = t.getCause(); if (cause != null) { t = cause; } } return wrapAsJsonMappingException(ctxt, t); } /* /********************************************************** /* Helper methods /********************************************************** */ private Object _createUsingDelegate( AnnotatedWithParams delegateCreator, SettableBeanProperty[] delegateArguments, DeserializationContext ctxt, Object delegate) throws IOException { if (delegateCreator == null) { // sanity-check; caller should check throw new IllegalStateException("No delegate constructor for "+getValueTypeDesc()); } try { // First simple case: just delegate, no injectables if (delegateArguments == null) { return delegateCreator.call1(delegate); } // And then the case with at least one injectable... final int len = delegateArguments.length; Object[] args = new Object[len]; for (int i = 0; i < len; ++i) { SettableBeanProperty prop = delegateArguments[i]; if (prop == null) { // delegate args[i] = delegate; } else { // nope, injectable: args[i] = ctxt.findInjectableValue(prop.getInjectableValueId(), prop, null); } } // and then try calling with full set of arguments return delegateCreator.call(args); } catch (Throwable t) { throw rewrapCtorProblem(ctxt, t); } } } StringArrayDeserializer.java000066400000000000000000000273301325620701100400240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.AccessPattern; import com.fasterxml.jackson.databind.util.ObjectBuffer; /** * Separate implementation for serializing String arrays (instead of * using {@link ObjectArrayDeserializer}. * Used if (and only if) no custom value deserializers are used. */ @JacksonStdImpl public final class StringArrayDeserializer // 28-Oct-2016, tatu: Should do this: // extends ContainerDeserializerBase // but for now won't: extends StdDeserializer implements ContextualDeserializer { private static final long serialVersionUID = 2L; private final static String[] NO_STRINGS = new String[0]; public final static StringArrayDeserializer instance = new StringArrayDeserializer(); /** * Value serializer to use, if not the standard one (which is inlined) */ protected JsonDeserializer _elementDeserializer; /** * Handler we need for dealing with nulls. * * @since 2.9 */ protected final NullValueProvider _nullProvider; /** * Specific override for this instance (from proper, or global per-type overrides) * to indicate whether single value may be taken to mean an unwrapped one-element array * or not. If null, left to global defaults. * * @since 2.7 */ protected final Boolean _unwrapSingle; /** * Marker flag set if the _nullProvider indicates that all null * content values should be skipped (instead of being possibly converted). * * @since 2.9 */ protected final boolean _skipNullValues; public StringArrayDeserializer() { this(null, null, null); } @SuppressWarnings("unchecked") protected StringArrayDeserializer(JsonDeserializer deser, NullValueProvider nuller, Boolean unwrapSingle) { super(String[].class); _elementDeserializer = (JsonDeserializer) deser; _nullProvider = nuller; _unwrapSingle = unwrapSingle; _skipNullValues = NullsConstantProvider.isSkipper(nuller); } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { return Boolean.TRUE; } @Override // since 2.9 public AccessPattern getEmptyAccessPattern() { // immutable, shareable so: return AccessPattern.CONSTANT; } @Override // since 2.9 public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { return NO_STRINGS; } /** * Contextualization is needed to see whether we can "inline" deserialization * of String values, or if we have to use separate value deserializer. */ @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { JsonDeserializer deser = _elementDeserializer; // May have a content converter deser = findConvertingContentDeserializer(ctxt, property, deser); JavaType type = ctxt.constructType(String.class); if (deser == null) { deser = ctxt.findContextualValueDeserializer(type, property); } else { // if directly assigned, probably not yet contextual, so: deser = ctxt.handleSecondaryContextualization(deser, property, type); } // One more thing: allow unwrapping? Boolean unwrapSingle = findFormatFeature(ctxt, property, String[].class, JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); NullValueProvider nuller = findContentNullProvider(ctxt, property, deser); // Ok ok: if all we got is the default String deserializer, can just forget about it if ((deser != null) && isDefaultDeserializer(deser)) { deser = null; } if ((_elementDeserializer == deser) && (_unwrapSingle == unwrapSingle) && (_nullProvider == nuller)) { return this; } return new StringArrayDeserializer(deser, nuller, unwrapSingle); } @Override public String[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // Ok: must point to START_ARRAY (or equivalent) if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt); } if (_elementDeserializer != null) { return _deserializeCustom(p, ctxt, null); } final ObjectBuffer buffer = ctxt.leaseObjectBuffer(); Object[] chunk = buffer.resetAndStart(); int ix = 0; try { while (true) { String value = p.nextTextValue(); if (value == null) { JsonToken t = p.getCurrentToken(); if (t == JsonToken.END_ARRAY) { break; } if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = (String) _nullProvider.getNullValue(ctxt); } else { value = _parseString(p, ctxt); } } if (ix >= chunk.length) { chunk = buffer.appendCompletedChunk(chunk); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, buffer.bufferedSize() + ix); } String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class); ctxt.returnObjectBuffer(buffer); return result; } /** * Offlined version used when we do not use the default deserialization method. */ protected final String[] _deserializeCustom(JsonParser p, DeserializationContext ctxt, String[] old) throws IOException { final ObjectBuffer buffer = ctxt.leaseObjectBuffer(); int ix; Object[] chunk; if (old == null) { ix = 0; chunk = buffer.resetAndStart(); } else { ix = old.length; chunk = buffer.resetAndStart(old, ix); } final JsonDeserializer deser = _elementDeserializer; try { while (true) { /* 30-Dec-2014, tatu: This may look odd, but let's actually call method * that suggest we are expecting a String; this helps with some formats, * notably XML. Note, however, that while we can get String, we can't * assume that's what we use due to custom deserializer */ String value; if (p.nextTextValue() == null) { JsonToken t = p.getCurrentToken(); if (t == JsonToken.END_ARRAY) { break; } // Ok: no need to convert Strings, but must recognize nulls if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = (String) _nullProvider.getNullValue(ctxt); } else { value = deser.deserialize(p, ctxt); } } else { value = deser.deserialize(p, ctxt); } if (ix >= chunk.length) { chunk = buffer.appendCompletedChunk(chunk); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { // note: pass String.class, not String[].class, as we need element type for error info throw JsonMappingException.wrapWithPath(e, String.class, ix); } String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class); ctxt.returnObjectBuffer(buffer); return result; } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { return typeDeserializer.deserializeTypedFromArray(p, ctxt); } @Override public String[] deserialize(JsonParser p, DeserializationContext ctxt, String[] intoValue) throws IOException { // Ok: must point to START_ARRAY (or equivalent) if (!p.isExpectedStartArrayToken()) { String[] arr = handleNonArray(p, ctxt); if (arr == null) { return intoValue; } final int offset = intoValue.length; String[] result = new String[offset + arr.length]; System.arraycopy(intoValue, 0, result, 0, offset); System.arraycopy(arr, 0, result, offset, arr.length); return result; } if (_elementDeserializer != null) { return _deserializeCustom(p, ctxt, intoValue); } final ObjectBuffer buffer = ctxt.leaseObjectBuffer(); int ix = intoValue.length; Object[] chunk = buffer.resetAndStart(intoValue, ix); try { while (true) { String value = p.nextTextValue(); if (value == null) { JsonToken t = p.getCurrentToken(); if (t == JsonToken.END_ARRAY) { break; } if (t == JsonToken.VALUE_NULL) { // 03-Feb-2017, tatu: Should we skip null here or not? if (_skipNullValues) { return NO_STRINGS; } value = (String) _nullProvider.getNullValue(ctxt); } else { value = _parseString(p, ctxt); } } if (ix >= chunk.length) { chunk = buffer.appendCompletedChunk(chunk); ix = 0; } chunk[ix++] = value; } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, chunk, buffer.bufferedSize() + ix); } String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class); ctxt.returnObjectBuffer(buffer); return result; } private final String[] handleNonArray(JsonParser p, DeserializationContext ctxt) throws IOException { // implicit arrays from single values? boolean canWrap = (_unwrapSingle == Boolean.TRUE) || ((_unwrapSingle == null) && ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); if (canWrap) { String value = p.hasToken(JsonToken.VALUE_NULL) ? (String) _nullProvider.getNullValue(ctxt) : _parseString(p, ctxt); return new String[] { value }; } if (p.hasToken(JsonToken.VALUE_STRING) && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { String str = p.getText(); if (str.length() == 0) { return null; } } return (String[]) ctxt.handleUnexpectedToken(_valueClass, p); } } StringCollectionDeserializer.java000066400000000000000000000261031325620701100410360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.Collection; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; /** * Specifically optimized version for {@link java.util.Collection}s * that contain String values; reason is that this is a very common * type and we can make use of the fact that Strings are final. */ @JacksonStdImpl public final class StringCollectionDeserializer extends ContainerDeserializerBase> implements ContextualDeserializer { private static final long serialVersionUID = 1L; // // Configuration /** * Value deserializer to use, if NOT the standard one * (if it is, will be null). */ protected final JsonDeserializer _valueDeserializer; // // Instance construction settings: /** * Instantiator used in case custom handling is needed for creation. */ protected final ValueInstantiator _valueInstantiator; /** * Deserializer that is used iff delegate-based creator is * to be used for deserializing from JSON Object. */ protected final JsonDeserializer _delegateDeserializer; // NOTE: no PropertyBasedCreator, as JSON Arrays have no properties /* /********************************************************** /* Life-cycle /********************************************************** */ public StringCollectionDeserializer(JavaType collectionType, JsonDeserializer valueDeser, ValueInstantiator valueInstantiator) { this(collectionType, valueInstantiator, null, valueDeser, valueDeser, null); } @SuppressWarnings("unchecked") protected StringCollectionDeserializer(JavaType collectionType, ValueInstantiator valueInstantiator, JsonDeserializer delegateDeser, JsonDeserializer valueDeser, NullValueProvider nuller, Boolean unwrapSingle) { super(collectionType, nuller, unwrapSingle); _valueDeserializer = (JsonDeserializer) valueDeser; _valueInstantiator = valueInstantiator; _delegateDeserializer = (JsonDeserializer) delegateDeser; } protected StringCollectionDeserializer withResolved(JsonDeserializer delegateDeser, JsonDeserializer valueDeser, NullValueProvider nuller, Boolean unwrapSingle) { if ((_unwrapSingle == unwrapSingle) && (_nullProvider == nuller) && (_valueDeserializer == valueDeser) && (_delegateDeserializer == delegateDeser)) { return this; } return new StringCollectionDeserializer(_containerType, _valueInstantiator, delegateDeser, valueDeser, nuller, unwrapSingle); } @Override // since 2.5 public boolean isCachable() { // 26-Mar-2015, tatu: Important: prevent caching if custom deserializers via annotations // are involved return (_valueDeserializer == null) && (_delegateDeserializer == null); } /* /********************************************************** /* Validation, post-processing /********************************************************** */ @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { // May need to resolve types for delegate-based creators: JsonDeserializer delegate = null; if (_valueInstantiator != null) { AnnotatedWithParams delegateCreator = _valueInstantiator.getDelegateCreator(); if (delegateCreator != null) { JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig()); delegate = findDeserializer(ctxt, delegateType, property); } } JsonDeserializer valueDeser = _valueDeserializer; final JavaType valueType = _containerType.getContentType(); if (valueDeser == null) { // [databind#125]: May have a content converter valueDeser = findConvertingContentDeserializer(ctxt, property, valueDeser); if (valueDeser == null) { // And we may also need to get deserializer for String valueDeser = ctxt.findContextualValueDeserializer(valueType, property); } } else { // if directly assigned, probably not yet contextual, so: valueDeser = ctxt.handleSecondaryContextualization(valueDeser, property, valueType); } // 11-Dec-2015, tatu: Should we pass basic `Collection.class`, or more refined? Mostly // comes down to "List vs Collection" I suppose... for now, pass Collection Boolean unwrapSingle = findFormatFeature(ctxt, property, Collection.class, JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); NullValueProvider nuller = findContentNullProvider(ctxt, property, valueDeser); if (isDefaultDeserializer(valueDeser)) { valueDeser = null; } return withResolved(delegate, valueDeser, nuller, unwrapSingle); } /* /********************************************************** /* ContainerDeserializerBase API /********************************************************** */ @SuppressWarnings("unchecked") @Override public JsonDeserializer getContentDeserializer() { JsonDeserializer deser = _valueDeserializer; return (JsonDeserializer) deser; } @Override public ValueInstantiator getValueInstantiator() { return _valueInstantiator; } /* /********************************************************** /* JsonDeserializer API /********************************************************** */ @SuppressWarnings("unchecked") @Override public Collection deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (_delegateDeserializer != null) { return (Collection) _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt)); } final Collection result = (Collection) _valueInstantiator.createUsingDefault(ctxt); return deserialize(p, ctxt, result); } @Override public Collection deserialize(JsonParser p, DeserializationContext ctxt, Collection result) throws IOException { // Ok: must point to START_ARRAY if (!p.isExpectedStartArrayToken()) { return handleNonArray(p, ctxt, result); } if (_valueDeserializer != null) { return deserializeUsingCustom(p, ctxt, result, _valueDeserializer); } try { while (true) { // First the common case: String value = p.nextTextValue(); if (value != null) { result.add(value); continue; } JsonToken t = p.getCurrentToken(); if (t == JsonToken.END_ARRAY) { break; } if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = (String) _nullProvider.getNullValue(ctxt); } else { value = _parseString(p, ctxt); } result.add(value); } } catch (Exception e) { throw JsonMappingException.wrapWithPath(e, result, result.size()); } return result; } private Collection deserializeUsingCustom(JsonParser p, DeserializationContext ctxt, Collection result, final JsonDeserializer deser) throws IOException { while (true) { /* 30-Dec-2014, tatu: This may look odd, but let's actually call method * that suggest we are expecting a String; this helps with some formats, * notably XML. Note, however, that while we can get String, we can't * assume that's what we use due to custom deserializer */ String value; if (p.nextTextValue() == null) { JsonToken t = p.getCurrentToken(); if (t == JsonToken.END_ARRAY) { break; } // Ok: no need to convert Strings, but must recognize nulls if (t == JsonToken.VALUE_NULL) { if (_skipNullValues) { continue; } value = (String) _nullProvider.getNullValue(ctxt); } else { value = deser.deserialize(p, ctxt); } } else { value = deser.deserialize(p, ctxt); } result.add(value); } return result; } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { // In future could check current token... for now this should be enough: return typeDeserializer.deserializeTypedFromArray(p, ctxt); } /** * Helper method called when current token is not START_ARRAY. Will either * throw an exception, or try to handle value as if member of implicit * array, depending on configuration. */ @SuppressWarnings("unchecked") private final Collection handleNonArray(JsonParser p, DeserializationContext ctxt, Collection result) throws IOException { // implicit arrays from single values? boolean canWrap = (_unwrapSingle == Boolean.TRUE) || ((_unwrapSingle == null) && ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); if (!canWrap) { return (Collection) ctxt.handleUnexpectedToken(_containerType.getRawClass(), p); } // Strings are one of "native" (intrinsic) types, so there's never type deserializer involved JsonDeserializer valueDes = _valueDeserializer; JsonToken t = p.getCurrentToken(); String value; if (t == JsonToken.VALUE_NULL) { // 03-Feb-2017, tatu: Does this work? if (_skipNullValues) { return result; } value = (String) _nullProvider.getNullValue(ctxt); } else { value = (valueDes == null) ? _parseString(p, ctxt) : valueDes.deserialize(p, ctxt); } result.add(value); return result; } } StringDeserializer.java000066400000000000000000000047121325620701100370240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; @JacksonStdImpl public class StringDeserializer extends StdScalarDeserializer // non-final since 2.9 { private static final long serialVersionUID = 1L; /** * @since 2.2 */ public final static StringDeserializer instance = new StringDeserializer(); public StringDeserializer() { super(String.class); } // since 2.6, slightly faster lookups for this very common type @Override public boolean isCachable() { return true; } @Override // since 2.9 public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { return ""; } @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_STRING)) { return p.getText(); } JsonToken t = p.getCurrentToken(); // [databind#381] if (t == JsonToken.START_ARRAY) { return _deserializeFromArray(p, ctxt); } // need to gracefully handle byte[] data, as base64 if (t == JsonToken.VALUE_EMBEDDED_OBJECT) { Object ob = p.getEmbeddedObject(); if (ob == null) { return null; } if (ob instanceof byte[]) { return ctxt.getBase64Variant().encode((byte[]) ob, false); } // otherwise, try conversion using toString()... return ob.toString(); } // allow coercions for other scalar types // 17-Jan-2018, tatu: Related to [databind#1853] avoid FIELD_NAME by ensuring it's // "real" scalar if (t.isScalarValue()) { String text = p.getValueAsString(); if (text != null) { return text; } } return (String) ctxt.handleUnexpectedToken(_valueClass, p); } // Since we can never have type info ("natural type"; String, Boolean, Integer, Double): // (is it an error to even call this version?) @Override public String deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { return deserialize(p, ctxt); } } ThrowableDeserializer.java000066400000000000000000000146461325620701100375140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.BeanDeserializer; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Deserializer that builds on basic {@link BeanDeserializer} but * override some aspects like instance construction. */ public class ThrowableDeserializer extends BeanDeserializer { private static final long serialVersionUID = 1L; protected final static String PROP_NAME_MESSAGE = "message"; /* /************************************************************ /* Construction /************************************************************ */ public ThrowableDeserializer(BeanDeserializer baseDeserializer) { super(baseDeserializer); // need to disable this, since we do post-processing _vanillaProcessing = false; } /** * Alternative constructor used when creating "unwrapping" deserializers */ protected ThrowableDeserializer(BeanDeserializer src, NameTransformer unwrapper) { super(src, unwrapper); } @Override public JsonDeserializer unwrappingDeserializer(NameTransformer unwrapper) { if (getClass() != ThrowableDeserializer.class) { return this; } /* main thing really is to just enforce ignoring of unknown * properties; since there may be multiple unwrapped values * and properties for all may be interleaved... */ return new ThrowableDeserializer(this, unwrapper); } /* /************************************************************ /* Overridden methods /************************************************************ */ @Override public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException { // 30-Sep-2010, tatu: Need to allow use of @JsonCreator, so: if (_propertyBasedCreator != null) { // proper @JsonCreator return _deserializeUsingPropertyBased(p, ctxt); } if (_delegateDeserializer != null) { return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt)); } if (_beanType.isAbstract()) { // for good measure, check this too return ctxt.handleMissingInstantiator(handledType(), getValueInstantiator(), p, "abstract type (need to add/enable type information?)"); } boolean hasStringCreator = _valueInstantiator.canCreateFromString(); boolean hasDefaultCtor = _valueInstantiator.canCreateUsingDefault(); // and finally, verify we do have single-String arg constructor (if no @JsonCreator) if (!hasStringCreator && !hasDefaultCtor) { return ctxt.handleMissingInstantiator(handledType(), getValueInstantiator(), p, "Throwable needs a default contructor, a single-String-arg constructor; or explicit @JsonCreator"); } Object throwable = null; Object[] pending = null; int pendingIx = 0; for (; p.getCurrentToken() != JsonToken.END_OBJECT; p.nextToken()) { String propName = p.getCurrentName(); SettableBeanProperty prop = _beanProperties.find(propName); p.nextToken(); // to point to field value if (prop != null) { // normal case if (throwable != null) { prop.deserializeAndSet(p, ctxt, throwable); continue; } // nope; need to defer if (pending == null) { int len = _beanProperties.size(); pending = new Object[len + len]; } pending[pendingIx++] = prop; pending[pendingIx++] = prop.deserialize(p, ctxt); continue; } // Maybe it's "message"? final boolean isMessage = PROP_NAME_MESSAGE.equals(propName); if (isMessage) { if (hasStringCreator) { throwable = _valueInstantiator.createFromString(ctxt, p.getValueAsString()); // any pending values? if (pending != null) { for (int i = 0, len = pendingIx; i < len; i += 2) { prop = (SettableBeanProperty)pending[i]; prop.set(throwable, pending[i+1]); } pending = null; } continue; } } // Things marked as ignorable should not be passed to any setter if ((_ignorableProps != null) && _ignorableProps.contains(propName)) { p.skipChildren(); continue; } if (_anySetter != null) { _anySetter.deserializeAndSet(p, ctxt, throwable, propName); continue; } // 23-Jan-2018, tatu: One concern would be `message`, but without any-setter or single-String-ctor // (or explicit constructor). We could just ignore it but for now, let it fail // Unknown: let's call handler method handleUnknownProperty(p, ctxt, throwable, propName); } // Sanity check: did we find "message"? if (throwable == null) { /* 15-Oct-2010, tatu: Can't assume missing message is an error, since it may be * suppressed during serialization, as per [JACKSON-388]. * * Should probably allow use of default constructor, too... */ //throw new JsonMappingException("No 'message' property found: could not deserialize "+_beanType); if (hasStringCreator) { throwable = _valueInstantiator.createFromString(ctxt, null); } else { throwable = _valueInstantiator.createUsingDefault(ctxt); } // any pending values? if (pending != null) { for (int i = 0, len = pendingIx; i < len; i += 2) { SettableBeanProperty prop = (SettableBeanProperty)pending[i]; prop.set(throwable, pending[i+1]); } } } return throwable; } } TokenBufferDeserializer.java000066400000000000000000000025301325620701100377640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * We also want to directly support deserialization of {@link TokenBuffer}. *

* Note that we use scalar deserializer base just because we claim * to be of scalar for type information inclusion purposes; actual * underlying content can be of any (Object, Array, scalar) type. *

* Since 2.3, another important thing is that possible native ids * (type id, object id) should be properly copied even when converting * with {@link TokenBuffer}. Such ids are supported if (and only if!) * source {@link JsonParser} supports them. */ @JacksonStdImpl public class TokenBufferDeserializer extends StdScalarDeserializer { private static final long serialVersionUID = 1L; public TokenBufferDeserializer() { super(TokenBuffer.class); } @Override public TokenBuffer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return createBufferInstance(p).deserialize(p, ctxt); } protected TokenBuffer createBufferInstance(JsonParser p) { return new TokenBuffer(p); } }UUIDDeserializer.java000066400000000000000000000122701325620701100363220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.Arrays; import java.util.UUID; import com.fasterxml.jackson.core.Base64Variants; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.exc.InvalidFormatException; public class UUIDDeserializer extends FromStringDeserializer { private static final long serialVersionUID = 1L; final static int[] HEX_DIGITS = new int[127]; static { Arrays.fill(HEX_DIGITS, -1); for (int i = 0; i < 10; ++i) { HEX_DIGITS['0' + i] = i; } for (int i = 0; i < 6; ++i) { HEX_DIGITS['a' + i] = 10 + i; HEX_DIGITS['A' + i] = 10 + i; } } public UUIDDeserializer() { super(UUID.class); } @Override protected UUID _deserialize(String id, DeserializationContext ctxt) throws IOException { // Adapted from java-uuid-generator (https://github.com/cowtowncoder/java-uuid-generator) // which is 5x faster than UUID.fromString(value), as oper "ManualReadPerfWithUUID" if (id.length() != 36) { /* 14-Sep-2013, tatu: One trick we do allow, Base64-encoding, since we know * length it must have... */ if (id.length() == 24) { byte[] stuff = Base64Variants.getDefaultVariant().decode(id); return _fromBytes(stuff, ctxt); } return _badFormat(id, ctxt); } // verify hyphens first: if ((id.charAt(8) != '-') || (id.charAt(13) != '-') || (id.charAt(18) != '-') || (id.charAt(23) != '-')) { _badFormat(id, ctxt); } long l1 = intFromChars(id, 0, ctxt); l1 <<= 32; long l2 = ((long) shortFromChars(id, 9, ctxt)) << 16; l2 |= shortFromChars(id, 14, ctxt); long hi = l1 + l2; int i1 = (shortFromChars(id, 19, ctxt) << 16) | shortFromChars(id, 24, ctxt); l1 = i1; l1 <<= 32; l2 = intFromChars(id, 28, ctxt); l2 = (l2 << 32) >>> 32; // sign removal, Java-style. Ugh. long lo = l1 | l2; return new UUID(hi, lo); } @Override protected UUID _deserializeEmbedded(Object ob, DeserializationContext ctxt) throws IOException { if (ob instanceof byte[]) { return _fromBytes((byte[]) ob, ctxt); } super._deserializeEmbedded(ob, ctxt); return null; // never gets here } private UUID _badFormat(String uuidStr, DeserializationContext ctxt) throws IOException { return (UUID) ctxt.handleWeirdStringValue(handledType(), uuidStr, "UUID has to be represented by standard 36-char representation"); } int intFromChars(String str, int index, DeserializationContext ctxt) throws JsonMappingException { return (byteFromChars(str, index, ctxt) << 24) + (byteFromChars(str, index+2, ctxt) << 16) + (byteFromChars(str, index+4, ctxt) << 8) + byteFromChars(str, index+6, ctxt); } int shortFromChars(String str, int index, DeserializationContext ctxt) throws JsonMappingException { return (byteFromChars(str, index, ctxt) << 8) + byteFromChars(str, index+2, ctxt); } int byteFromChars(String str, int index, DeserializationContext ctxt) throws JsonMappingException { final char c1 = str.charAt(index); final char c2 = str.charAt(index+1); if (c1 <= 127 && c2 <= 127) { int hex = (HEX_DIGITS[c1] << 4) | HEX_DIGITS[c2]; if (hex >= 0) { return hex; } } if (c1 > 127 || HEX_DIGITS[c1] < 0) { return _badChar(str, index, ctxt, c1); } return _badChar(str, index+1, ctxt, c2); } int _badChar(String uuidStr, int index, DeserializationContext ctxt, char c) throws JsonMappingException { // 15-May-2016, tatu: Ideally should not throw, but call `handleWeirdStringValue`... // however, control flow is gnarly here, so for now just throw throw ctxt.weirdStringException(uuidStr, handledType(), String.format( "Non-hex character '%c' (value 0x%s), not valid for UUID String", c, Integer.toHexString(c))); } private UUID _fromBytes(byte[] bytes, DeserializationContext ctxt) throws JsonMappingException { if (bytes.length != 16) { throw InvalidFormatException.from(ctxt.getParser(), "Can only construct UUIDs from byte[16]; got "+bytes.length+" bytes", bytes, handledType()); } return new UUID(_long(bytes, 0), _long(bytes, 8)); } private static long _long(byte[] b, int offset) { long l1 = ((long) _int(b, offset)) << 32; long l2 = _int(b, offset+4); // faster to just do it than check if it has sign l2 = (l2 << 32) >>> 32; // to get rid of sign return l1 | l2; } private static int _int(byte[] b, int offset) { return (b[offset] << 24) | ((b[offset+1] & 0xFF) << 16) | ((b[offset+2] & 0xFF) << 8) | (b[offset+3] & 0xFF); } }UntypedObjectDeserializer.java000066400000000000000000001047051325620701100403400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/stdpackage com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.ResolvableDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.ObjectBuffer; /** * Deserializer implementation that is used if it is necessary to bind content of * "unknown" type; something declared as basic {@link java.lang.Object} * (either explicitly, or due to type erasure). * If so, "natural" mapping is used to convert JSON values to their natural * Java object matches: JSON arrays to Java {@link java.util.List}s (or, if configured, * Object[]), JSON objects to {@link java.util.Map}s, numbers to * {@link java.lang.Number}s, booleans to {@link java.lang.Boolean}s and * strings to {@link java.lang.String} (and nulls to nulls). */ @JacksonStdImpl public class UntypedObjectDeserializer extends StdDeserializer implements ResolvableDeserializer, ContextualDeserializer { private static final long serialVersionUID = 1L; protected final static Object[] NO_OBJECTS = new Object[0]; /* /********************************************************** /* Possible custom deserializer overrides we need to use /********************************************************** */ protected JsonDeserializer _mapDeserializer; protected JsonDeserializer _listDeserializer; protected JsonDeserializer _stringDeserializer; protected JsonDeserializer _numberDeserializer; /** * If {@link java.util.List} has been mapped to non-default implementation, * we'll store type here * * @since 2.6 */ protected JavaType _listType; /** * If {@link java.util.Map} has been mapped to non-default implementation, * we'll store type here * * @since 2.6 */ protected JavaType _mapType; /** * @since 2.9 */ protected final boolean _nonMerging; /** * @deprecated Since 2.6 use variant takes type arguments */ @Deprecated public UntypedObjectDeserializer() { this(null, null); } public UntypedObjectDeserializer(JavaType listType, JavaType mapType) { super(Object.class); _listType = listType; _mapType = mapType; _nonMerging = false; } @SuppressWarnings("unchecked") public UntypedObjectDeserializer(UntypedObjectDeserializer base, JsonDeserializer mapDeser, JsonDeserializer listDeser, JsonDeserializer stringDeser, JsonDeserializer numberDeser) { super(Object.class); _mapDeserializer = (JsonDeserializer) mapDeser; _listDeserializer = (JsonDeserializer) listDeser; _stringDeserializer = (JsonDeserializer) stringDeser; _numberDeserializer = (JsonDeserializer) numberDeser; _listType = base._listType; _mapType = base._mapType; _nonMerging = base._nonMerging; } /** * @since 2.9 */ protected UntypedObjectDeserializer(UntypedObjectDeserializer base, boolean nonMerging) { super(Object.class); _mapDeserializer = base._mapDeserializer; _listDeserializer = base._listDeserializer; _stringDeserializer = base._stringDeserializer; _numberDeserializer = base._numberDeserializer; _listType = base._listType; _mapType = base._mapType; _nonMerging = nonMerging; } /* /********************************************************** /* Initialization /********************************************************** */ /** * We need to implement this method to properly find things to delegate * to: it cannot be done earlier since delegated deserializers almost * certainly require access to this instance (at least "List" and "Map" ones) */ @SuppressWarnings("unchecked") @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException { JavaType obType = ctxt.constructType(Object.class); JavaType stringType = ctxt.constructType(String.class); TypeFactory tf = ctxt.getTypeFactory(); /* 26-Nov-2014, tatu: This is highly unusual, as in general contextualization * should always be called separately, from within "createContextual()". * But this is a very singular deserializer since it operates on `Object` * (and often for `?` type parameter), and as a result, easily and commonly * results in cycles, being value deserializer for various Maps and Collections. * Because of this, we must somehow break the cycles. This is done here by * forcing pseudo-contextualization with null property. */ // So: first find possible custom instances if (_listType == null) { _listDeserializer = _clearIfStdImpl(_findCustomDeser(ctxt, tf.constructCollectionType(List.class, obType))); } else { // NOTE: if non-default List type, always consider to be non-standard deser _listDeserializer = _findCustomDeser(ctxt, _listType); } if (_mapType == null) { _mapDeserializer = _clearIfStdImpl(_findCustomDeser(ctxt, tf.constructMapType(Map.class, stringType, obType))); } else { // NOTE: if non-default Map type, always consider to be non-standard deser _mapDeserializer = _findCustomDeser(ctxt, _mapType); } _stringDeserializer = _clearIfStdImpl(_findCustomDeser(ctxt, stringType)); _numberDeserializer = _clearIfStdImpl(_findCustomDeser(ctxt, tf.constructType(Number.class))); // and then do bogus contextualization, in case custom ones need to resolve dependencies of // their own JavaType unknown = TypeFactory.unknownType(); _mapDeserializer = (JsonDeserializer) ctxt.handleSecondaryContextualization(_mapDeserializer, null, unknown); _listDeserializer = (JsonDeserializer) ctxt.handleSecondaryContextualization(_listDeserializer, null, unknown); _stringDeserializer = (JsonDeserializer) ctxt.handleSecondaryContextualization(_stringDeserializer, null, unknown); _numberDeserializer = (JsonDeserializer) ctxt.handleSecondaryContextualization(_numberDeserializer, null, unknown); } protected JsonDeserializer _findCustomDeser(DeserializationContext ctxt, JavaType type) throws JsonMappingException { // Since we are calling from `resolve`, we should NOT try to contextualize yet; // contextualization will only occur at a later point return ctxt.findNonContextualValueDeserializer(type); } protected JsonDeserializer _clearIfStdImpl(JsonDeserializer deser) { return ClassUtil.isJacksonStdImpl(deser) ? null : deser; } /** * We only use contextualization for optimizing the case where no customization * occurred; if so, can slip in a more streamlined version. */ @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { // 14-Jun-2017, tatu: [databind#1625]: may want to block merging, for root value boolean preventMerge = (property == null) && Boolean.FALSE.equals(ctxt.getConfig().getDefaultMergeable(Object.class)); // 20-Apr-2014, tatu: If nothing custom, let's use "vanilla" instance, // simpler and can avoid some of delegation if ((_stringDeserializer == null) && (_numberDeserializer == null) && (_mapDeserializer == null) && (_listDeserializer == null) && getClass() == UntypedObjectDeserializer.class) { return Vanilla.instance(preventMerge); } if (preventMerge != _nonMerging) { return new UntypedObjectDeserializer(this, preventMerge); } return this; } /* /********************************************************** /* Deserializer API /********************************************************** */ /* 07-Nov-2014, tatu: When investigating [databind#604], realized that it makes * sense to also mark this is cachable, since lookup not exactly free, and * since it's not uncommon to "read anything" */ @Override public boolean isCachable() { /* 26-Mar-2015, tatu: With respect to [databind#735], there are concerns over * cachability. It seems like we SHOULD be safe here; but just in case there * are problems with false sharing, this may need to be revisited. */ return true; } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { // 21-Apr-2017, tatu: Bit tricky... some values, yes. So let's say "dunno" return null; } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_START_OBJECT: case JsonTokenId.ID_FIELD_NAME: // 28-Oct-2015, tatu: [databind#989] We may also be given END_OBJECT (similar to FIELD_NAME), // if caller has advanced to the first token of Object, but for empty Object case JsonTokenId.ID_END_OBJECT: if (_mapDeserializer != null) { return _mapDeserializer.deserialize(p, ctxt); } return mapObject(p, ctxt); case JsonTokenId.ID_START_ARRAY: if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) { return mapArrayToArray(p, ctxt); } if (_listDeserializer != null) { return _listDeserializer.deserialize(p, ctxt); } return mapArray(p, ctxt); case JsonTokenId.ID_EMBEDDED_OBJECT: return p.getEmbeddedObject(); case JsonTokenId.ID_STRING: if (_stringDeserializer != null) { return _stringDeserializer.deserialize(p, ctxt); } return p.getText(); case JsonTokenId.ID_NUMBER_INT: if (_numberDeserializer != null) { return _numberDeserializer.deserialize(p, ctxt); } /* Caller may want to get all integral values returned as {@link java.math.BigInteger}, * or {@link java.lang.Long} for consistency */ if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) { return _coerceIntegral(p, ctxt); } return p.getNumberValue(); // should be optimal, whatever it is case JsonTokenId.ID_NUMBER_FLOAT: if (_numberDeserializer != null) { return _numberDeserializer.deserialize(p, ctxt); } // Need to allow overriding the behavior regarding which type to use if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { return p.getDecimalValue(); } // as per [databind#1453] should not assume Double but: return p.getNumberValue(); case JsonTokenId.ID_TRUE: return Boolean.TRUE; case JsonTokenId.ID_FALSE: return Boolean.FALSE; case JsonTokenId.ID_NULL: // 08-Nov-2016, tatu: yes, occurs return null; // case JsonTokenId.ID_END_ARRAY: // invalid default: } return ctxt.handleUnexpectedToken(Object.class, p); } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { switch (p.getCurrentTokenId()) { // First: does it look like we had type id wrapping of some kind? case JsonTokenId.ID_START_ARRAY: case JsonTokenId.ID_START_OBJECT: case JsonTokenId.ID_FIELD_NAME: // Output can be as JSON Object, Array or scalar: no way to know at this point: return typeDeserializer.deserializeTypedFromAny(p, ctxt); case JsonTokenId.ID_EMBEDDED_OBJECT: return p.getEmbeddedObject(); /* Otherwise we probably got a "native" type (ones that map * naturally and thus do not need or use type ids) */ case JsonTokenId.ID_STRING: if (_stringDeserializer != null) { return _stringDeserializer.deserialize(p, ctxt); } return p.getText(); case JsonTokenId.ID_NUMBER_INT: if (_numberDeserializer != null) { return _numberDeserializer.deserialize(p, ctxt); } // May need coercion to "bigger" types: if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) { return _coerceIntegral(p, ctxt); } return p.getNumberValue(); // should be optimal, whatever it is case JsonTokenId.ID_NUMBER_FLOAT: if (_numberDeserializer != null) { return _numberDeserializer.deserialize(p, ctxt); } if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { return p.getDecimalValue(); } return p.getNumberValue(); case JsonTokenId.ID_TRUE: return Boolean.TRUE; case JsonTokenId.ID_FALSE: return Boolean.FALSE; case JsonTokenId.ID_NULL: // should not get this far really but... return null; default: } return ctxt.handleUnexpectedToken(Object.class, p); } @SuppressWarnings("unchecked") @Override // since 2.9 (to support deep merge) public Object deserialize(JsonParser p, DeserializationContext ctxt, Object intoValue) throws IOException { if (_nonMerging) { return deserialize(p, ctxt); } switch (p.getCurrentTokenId()) { case JsonTokenId.ID_START_OBJECT: case JsonTokenId.ID_FIELD_NAME: // 28-Oct-2015, tatu: [databind#989] We may also be given END_OBJECT (similar to FIELD_NAME), // if caller has advanced to the first token of Object, but for empty Object case JsonTokenId.ID_END_OBJECT: if (_mapDeserializer != null) { return _mapDeserializer.deserialize(p, ctxt, intoValue); } if (intoValue instanceof Map) { return mapObject(p, ctxt, (Map) intoValue); } return mapObject(p, ctxt); case JsonTokenId.ID_START_ARRAY: if (_listDeserializer != null) { return _listDeserializer.deserialize(p, ctxt, intoValue); } if (intoValue instanceof Collection) { return mapArray(p, ctxt, (Collection) intoValue); } if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) { return mapArrayToArray(p, ctxt); } return mapArray(p, ctxt); case JsonTokenId.ID_EMBEDDED_OBJECT: return p.getEmbeddedObject(); case JsonTokenId.ID_STRING: if (_stringDeserializer != null) { return _stringDeserializer.deserialize(p, ctxt, intoValue); } return p.getText(); case JsonTokenId.ID_NUMBER_INT: if (_numberDeserializer != null) { return _numberDeserializer.deserialize(p, ctxt, intoValue); } if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) { return _coerceIntegral(p, ctxt); } return p.getNumberValue(); case JsonTokenId.ID_NUMBER_FLOAT: if (_numberDeserializer != null) { return _numberDeserializer.deserialize(p, ctxt, intoValue); } if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { return p.getDecimalValue(); } return p.getNumberValue(); case JsonTokenId.ID_TRUE: return Boolean.TRUE; case JsonTokenId.ID_FALSE: return Boolean.FALSE; case JsonTokenId.ID_NULL: // 21-Apr-2017, tatu: May need to consider "skip nulls" at some point but... return null; default: } // easiest to just delegate to "dumb" version for the rest? return deserialize(p, ctxt); } /* /********************************************************** /* Internal methods /********************************************************** */ /** * Method called to map a JSON Array into a Java value. */ protected Object mapArray(JsonParser p, DeserializationContext ctxt) throws IOException { // Minor optimization to handle small lists (default size for ArrayList is 10) if (p.nextToken() == JsonToken.END_ARRAY) { return new ArrayList(2); } Object value = deserialize(p, ctxt); if (p.nextToken() == JsonToken.END_ARRAY) { ArrayList l = new ArrayList(2); l.add(value); return l; } Object value2 = deserialize(p, ctxt); if (p.nextToken() == JsonToken.END_ARRAY) { ArrayList l = new ArrayList(2); l.add(value); l.add(value2); return l; } ObjectBuffer buffer = ctxt.leaseObjectBuffer(); Object[] values = buffer.resetAndStart(); int ptr = 0; values[ptr++] = value; values[ptr++] = value2; int totalSize = ptr; do { value = deserialize(p, ctxt); ++totalSize; if (ptr >= values.length) { values = buffer.appendCompletedChunk(values); ptr = 0; } values[ptr++] = value; } while (p.nextToken() != JsonToken.END_ARRAY); // let's create full array then ArrayList result = new ArrayList(totalSize); buffer.completeAndClearBuffer(values, ptr, result); return result; } protected Object mapArray(JsonParser p, DeserializationContext ctxt, Collection result) throws IOException { // we start by pointing to START_ARRAY. Also, no real merging; array/Collection // just appends always while (p.nextToken() != JsonToken.END_ARRAY) { result.add(deserialize(p, ctxt)); } return result; } /** * Method called to map a JSON Object into a Java value. */ protected Object mapObject(JsonParser p, DeserializationContext ctxt) throws IOException { String key1; JsonToken t = p.getCurrentToken(); if (t == JsonToken.START_OBJECT) { key1 = p.nextFieldName(); } else if (t == JsonToken.FIELD_NAME) { key1 = p.getCurrentName(); } else { if (t != JsonToken.END_OBJECT) { return ctxt.handleUnexpectedToken(handledType(), p); } key1 = null; } if (key1 == null) { // empty map might work; but caller may want to modify... so better just give small modifiable return new LinkedHashMap(2); } // minor optimization; let's handle 1 and 2 entry cases separately // 24-Mar-2015, tatu: Ideally, could use one of 'nextXxx()' methods, but for // that we'd need new method(s) in JsonDeserializer. So not quite yet. p.nextToken(); Object value1 = deserialize(p, ctxt); String key2 = p.nextFieldName(); if (key2 == null) { // has to be END_OBJECT, then // single entry; but we want modifiable LinkedHashMap result = new LinkedHashMap(2); result.put(key1, value1); return result; } p.nextToken(); Object value2 = deserialize(p, ctxt); String key = p.nextFieldName(); if (key == null) { LinkedHashMap result = new LinkedHashMap(4); result.put(key1, value1); result.put(key2, value2); return result; } // And then the general case; default map size is 16 LinkedHashMap result = new LinkedHashMap(); result.put(key1, value1); result.put(key2, value2); do { p.nextToken(); result.put(key, deserialize(p, ctxt)); } while ((key = p.nextFieldName()) != null); return result; } /** * Method called to map a JSON Array into a Java Object array (Object[]). */ protected Object[] mapArrayToArray(JsonParser p, DeserializationContext ctxt) throws IOException { // Minor optimization to handle small lists (default size for ArrayList is 10) if (p.nextToken() == JsonToken.END_ARRAY) { return NO_OBJECTS; } ObjectBuffer buffer = ctxt.leaseObjectBuffer(); Object[] values = buffer.resetAndStart(); int ptr = 0; do { Object value = deserialize(p, ctxt); if (ptr >= values.length) { values = buffer.appendCompletedChunk(values); ptr = 0; } values[ptr++] = value; } while (p.nextToken() != JsonToken.END_ARRAY); return buffer.completeAndClearBuffer(values, ptr); } protected Object mapObject(JsonParser p, DeserializationContext ctxt, Map m) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.START_OBJECT) { t = p.nextToken(); } if (t == JsonToken.END_OBJECT) { return m; } // NOTE: we are guaranteed to point to FIELD_NAME String key = p.getCurrentName(); do { p.nextToken(); // and possibly recursive merge here Object old = m.get(key); Object newV; if (old != null) { newV = deserialize(p, ctxt, old); } else { newV = deserialize(p, ctxt); } if (newV != old) { m.put(key, newV); } } while ((key = p.nextFieldName()) != null); return m; } /* /********************************************************** /* Separate "vanilla" implementation for common case of /* no custom deserializer overrides /********************************************************** */ @JacksonStdImpl public static class Vanilla extends StdDeserializer { private static final long serialVersionUID = 1L; public final static Vanilla std = new Vanilla(); /** * @since 2.9 */ protected final boolean _nonMerging; public Vanilla() { this(false); } protected Vanilla(boolean nonMerging) { super(Object.class); _nonMerging = nonMerging; } public static Vanilla instance(boolean nonMerging) { if (nonMerging) { return new Vanilla(true); } return std; } @Override // since 2.9 public Boolean supportsUpdate(DeserializationConfig config) { // 21-Apr-2017, tatu: Bit tricky... some values, yes. So let's say "dunno" // 14-Jun-2017, tatu: Well, if merging blocked, can say no, as well. return _nonMerging ? Boolean.FALSE : null; } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_START_OBJECT: { JsonToken t = p.nextToken(); if (t == JsonToken.END_OBJECT) { return new LinkedHashMap(2); } } case JsonTokenId.ID_FIELD_NAME: return mapObject(p, ctxt); case JsonTokenId.ID_START_ARRAY: { JsonToken t = p.nextToken(); if (t == JsonToken.END_ARRAY) { // and empty one too if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) { return NO_OBJECTS; } return new ArrayList(2); } } if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) { return mapArrayToArray(p, ctxt); } return mapArray(p, ctxt); case JsonTokenId.ID_EMBEDDED_OBJECT: return p.getEmbeddedObject(); case JsonTokenId.ID_STRING: return p.getText(); case JsonTokenId.ID_NUMBER_INT: if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) { return _coerceIntegral(p, ctxt); } return p.getNumberValue(); // should be optimal, whatever it is case JsonTokenId.ID_NUMBER_FLOAT: if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { return p.getDecimalValue(); } return p.getNumberValue(); case JsonTokenId.ID_TRUE: return Boolean.TRUE; case JsonTokenId.ID_FALSE: return Boolean.FALSE; case JsonTokenId.ID_END_OBJECT: // 28-Oct-2015, tatu: [databind#989] We may also be given END_OBJECT (similar to FIELD_NAME), // if caller has advanced to the first token of Object, but for empty Object return new LinkedHashMap(2); case JsonTokenId.ID_NULL: // 08-Nov-2016, tatu: yes, occurs return null; //case JsonTokenId.ID_END_ARRAY: // invalid default: } return ctxt.handleUnexpectedToken(Object.class, p); } @Override public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { switch (p.getCurrentTokenId()) { case JsonTokenId.ID_START_ARRAY: case JsonTokenId.ID_START_OBJECT: case JsonTokenId.ID_FIELD_NAME: return typeDeserializer.deserializeTypedFromAny(p, ctxt); case JsonTokenId.ID_STRING: return p.getText(); case JsonTokenId.ID_NUMBER_INT: if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) { return p.getBigIntegerValue(); } return p.getNumberValue(); case JsonTokenId.ID_NUMBER_FLOAT: if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { return p.getDecimalValue(); } return p.getNumberValue(); case JsonTokenId.ID_TRUE: return Boolean.TRUE; case JsonTokenId.ID_FALSE: return Boolean.FALSE; case JsonTokenId.ID_EMBEDDED_OBJECT: return p.getEmbeddedObject(); case JsonTokenId.ID_NULL: // should not get this far really but... return null; default: } return ctxt.handleUnexpectedToken(Object.class, p); } @SuppressWarnings("unchecked") @Override // since 2.9 (to support deep merge) public Object deserialize(JsonParser p, DeserializationContext ctxt, Object intoValue) throws IOException { if (_nonMerging) { return deserialize(p, ctxt); } switch (p.getCurrentTokenId()) { case JsonTokenId.ID_END_OBJECT: case JsonTokenId.ID_END_ARRAY: return intoValue; case JsonTokenId.ID_START_OBJECT: { JsonToken t = p.nextToken(); // to get to FIELD_NAME or END_OBJECT if (t == JsonToken.END_OBJECT) { return intoValue; } } case JsonTokenId.ID_FIELD_NAME: if (intoValue instanceof Map) { Map m = (Map) intoValue; // NOTE: we are guaranteed to point to FIELD_NAME String key = p.getCurrentName(); do { p.nextToken(); // and possibly recursive merge here Object old = m.get(key); Object newV; if (old != null) { newV = deserialize(p, ctxt, old); } else { newV = deserialize(p, ctxt); } if (newV != old) { m.put(key, newV); } } while ((key = p.nextFieldName()) != null); return intoValue; } break; case JsonTokenId.ID_START_ARRAY: { JsonToken t = p.nextToken(); // to get to FIELD_NAME or END_OBJECT if (t == JsonToken.END_ARRAY) { return intoValue; } } if (intoValue instanceof Collection) { Collection c = (Collection) intoValue; // NOTE: merge for arrays/Collections means append, can't merge contents do { c.add(deserialize(p, ctxt)); } while (p.nextToken() != JsonToken.END_ARRAY); return intoValue; } // 21-Apr-2017, tatu: Should we try to support merging of Object[] values too? // ... maybe future improvement break; } // Easiest handling for the rest, delegate. Only (?) question: how about nulls? return deserialize(p, ctxt); } protected Object mapArray(JsonParser p, DeserializationContext ctxt) throws IOException { Object value = deserialize(p, ctxt); if (p.nextToken() == JsonToken.END_ARRAY) { ArrayList l = new ArrayList(2); l.add(value); return l; } Object value2 = deserialize(p, ctxt); if (p.nextToken() == JsonToken.END_ARRAY) { ArrayList l = new ArrayList(2); l.add(value); l.add(value2); return l; } ObjectBuffer buffer = ctxt.leaseObjectBuffer(); Object[] values = buffer.resetAndStart(); int ptr = 0; values[ptr++] = value; values[ptr++] = value2; int totalSize = ptr; do { value = deserialize(p, ctxt); ++totalSize; if (ptr >= values.length) { values = buffer.appendCompletedChunk(values); ptr = 0; } values[ptr++] = value; } while (p.nextToken() != JsonToken.END_ARRAY); // let's create full array then ArrayList result = new ArrayList(totalSize); buffer.completeAndClearBuffer(values, ptr, result); return result; } /** * Method called to map a JSON Array into a Java Object array (Object[]). */ protected Object[] mapArrayToArray(JsonParser p, DeserializationContext ctxt) throws IOException { ObjectBuffer buffer = ctxt.leaseObjectBuffer(); Object[] values = buffer.resetAndStart(); int ptr = 0; do { Object value = deserialize(p, ctxt); if (ptr >= values.length) { values = buffer.appendCompletedChunk(values); ptr = 0; } values[ptr++] = value; } while (p.nextToken() != JsonToken.END_ARRAY); return buffer.completeAndClearBuffer(values, ptr); } /** * Method called to map a JSON Object into a Java value. */ protected Object mapObject(JsonParser p, DeserializationContext ctxt) throws IOException { // will point to FIELD_NAME at this point, guaranteed String key1 = p.getText(); p.nextToken(); Object value1 = deserialize(p, ctxt); String key2 = p.nextFieldName(); if (key2 == null) { // single entry; but we want modifiable LinkedHashMap result = new LinkedHashMap(2); result.put(key1, value1); return result; } p.nextToken(); Object value2 = deserialize(p, ctxt); String key = p.nextFieldName(); if (key == null) { LinkedHashMap result = new LinkedHashMap(4); result.put(key1, value1); result.put(key2, value2); return result; } // And then the general case; default map size is 16 LinkedHashMap result = new LinkedHashMap(); result.put(key1, value1); result.put(key2, value2); do { p.nextToken(); result.put(key, deserialize(p, ctxt)); } while ((key = p.nextFieldName()) != null); return result; } } } package-info.java000066400000000000000000000011011325620701100355240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/deser/std/** * Contains public standard implementations of abstraction that * Jackson uses. This means that they are not merely implementation * details, but part of semi-public interface where project * tries to maintain backwards compatibility at higher level * than for 'impl' types (although less so than with fully * public interfaces). *

* Note that since this package was only added relatively late * in development cycle, not all classes that belong here are * included. Plan is to move more classes over time. */ package com.fasterxml.jackson.databind.deser.std; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/exc/000077500000000000000000000000001325620701100313065ustar00rootroot00000000000000IgnoredPropertyException.java000066400000000000000000000050121325620701100371030ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import java.util.*; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonMappingException; /** * Specialized {@link JsonMappingException} sub-class used to indicate * case where an explicitly ignored property is encountered, and mapper * is configured to consider this an error. * * @since 2.3 */ public class IgnoredPropertyException extends PropertyBindingException { private static final long serialVersionUID = 1L; /** * @since 2.7 */ public IgnoredPropertyException(JsonParser p, String msg, JsonLocation loc, Class referringClass, String propName, Collection propertyIds) { super(p, msg, loc, referringClass, propName, propertyIds); } /** * @deprecated Since 2.7 */ @Deprecated public IgnoredPropertyException(String msg, JsonLocation loc, Class referringClass, String propName, Collection propertyIds) { super(msg, loc, referringClass, propName, propertyIds); } /** * Factory method used for constructing instances of this exception type. * * @param p Underlying parser used for reading input being used for data-binding * @param fromObjectOrClass Reference to either instance of problematic type ( * if available), or if not, type itself * @param propertyName Name of unrecognized property * @param propertyIds (optional, null if not available) Set of properties that * type would recognize, if completely known: null if set cannot be determined. */ public static IgnoredPropertyException from(JsonParser p, Object fromObjectOrClass, String propertyName, Collection propertyIds) { Class ref; if (fromObjectOrClass instanceof Class) { ref = (Class) fromObjectOrClass; } else { // also acts as null check: ref = fromObjectOrClass.getClass(); } String msg = String.format("Ignored field \"%s\" (class %s) encountered; mapper configured not to allow this", propertyName, ref.getName()); IgnoredPropertyException e = new IgnoredPropertyException(p, msg, p.getCurrentLocation(), ref, propertyName, propertyIds); // but let's also ensure path includes this last (missing) segment e.prependPath(fromObjectOrClass, propertyName); return e; } } InvalidDefinitionException.java000066400000000000000000000066501325620701100373570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; /** * Intermediate exception type used as the base class for all {@link JsonMappingException}s * that are due to problems with target type definition; usually a problem with * annotations used on a class or its properties. * This is in contrast to {@link MismatchedInputException} which * signals a problem with input to map. * * @since 2.9 */ @SuppressWarnings("serial") public class InvalidDefinitionException extends JsonMappingException { protected final JavaType _type; protected transient BeanDescription _beanDesc; protected transient BeanPropertyDefinition _property; protected InvalidDefinitionException(JsonParser p, String msg, JavaType type) { super(p, msg); _type = type; _beanDesc = null; _property = null; } protected InvalidDefinitionException(JsonGenerator g, String msg, JavaType type) { super(g, msg); _type = type; _beanDesc = null; _property = null; } protected InvalidDefinitionException(JsonParser p, String msg, BeanDescription bean, BeanPropertyDefinition prop) { super(p, msg); _type = (bean == null) ? null : bean.getType(); _beanDesc = bean; _property = prop; } protected InvalidDefinitionException(JsonGenerator g, String msg, BeanDescription bean, BeanPropertyDefinition prop) { super(g, msg); _type = (bean == null) ? null : bean.getType(); _beanDesc = bean; _property = prop; } public static InvalidDefinitionException from(JsonParser p, String msg, BeanDescription bean, BeanPropertyDefinition prop) { return new InvalidDefinitionException(p, msg, bean, prop); } public static InvalidDefinitionException from(JsonParser p, String msg, JavaType type) { return new InvalidDefinitionException(p, msg, type); } public static InvalidDefinitionException from(JsonGenerator g, String msg, BeanDescription bean, BeanPropertyDefinition prop) { return new InvalidDefinitionException(g, msg, bean, prop); } public static InvalidDefinitionException from(JsonGenerator g, String msg, JavaType type) { return new InvalidDefinitionException(g, msg, type); } /** * Accessor for type fully resolved type that had the problem; this should always * known and available, never null */ public JavaType getType() { return _type; } /** * Accessor for type definition (class) that had the definition problem, if any; may sometimes * be undefined or unknown; if so, returns null. */ public BeanDescription getBeanDescription() { return _beanDesc; } /** * Accessor for property that had the definition problem if any * (none, for example if the problem relates to type in general), * if known. If not known (or relevant), returns null. */ public BeanPropertyDefinition getProperty() { return _property; } } InvalidFormatException.java000066400000000000000000000044731325620701100365200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonParser; /** * Specialized sub-class of {@link MismatchedInputException} * that is used when the underlying problem appears to be that * of bad formatting of a value to deserialize. * * @since 2.1 */ public class InvalidFormatException extends MismatchedInputException // since 2.9 { private static final long serialVersionUID = 1L; // silly Eclipse, warnings /** * Underlying value that could not be deserialized into * target type, if available. */ protected final Object _value; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @deprecated Since 2.7 Use variant that takes {@link JsonParser} */ @Deprecated // since 2.7 public InvalidFormatException(String msg, Object value, Class targetType) { super(null, msg); _value = value; _targetType = targetType; } /** * @deprecated Since 2.7 Use variant that takes {@link JsonParser} */ @Deprecated // since 2.7 public InvalidFormatException(String msg, JsonLocation loc, Object value, Class targetType) { super(null, msg, loc); _value = value; _targetType = targetType; } /** * @since 2.7 */ public InvalidFormatException(JsonParser p, String msg, Object value, Class targetType) { super(p, msg, targetType); _value = value; } public static InvalidFormatException from(JsonParser p, String msg, Object value, Class targetType) { return new InvalidFormatException(p, msg, value, targetType); } /* /********************************************************** /* Additional accessors /********************************************************** */ /** * Accessor for checking source value (String, Number usually) that could not * be deserialized into target type ({@link #getTargetType}). * Note that value may not be available, depending on who throws the exception * and when. */ public Object getValue() { return _value; } } InvalidNullException.java000066400000000000000000000031501325620701100361710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.PropertyName; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Exception thrown if a `null` value is being encountered for a property * designed as "fail on null" property (see {@link com.fasterxml.jackson.annotation.JsonSetter}). * * @since 2.9 */ public class InvalidNullException extends MismatchedInputException // since 2.9 { private static final long serialVersionUID = 1L; // silly Eclipse, warnings /** * Name of property, if known, for which null was encountered. */ protected final PropertyName _propertyName; /* /********************************************************** /* Life-cycle /********************************************************** */ protected InvalidNullException(DeserializationContext ctxt, String msg, PropertyName pname) { super(ctxt.getParser(), msg); _propertyName = pname; } public static InvalidNullException from(DeserializationContext ctxt, PropertyName name, JavaType type) { String msg = String.format("Invalid `null` value encountered for property %s", ClassUtil.quotedOr(name, "")); InvalidNullException exc = new InvalidNullException(ctxt, msg, name); if (type != null) { exc.setTargetType(type); } return exc; } public PropertyName getPropertyName() { return _propertyName; } } InvalidTypeIdException.java000066400000000000000000000027331325620701100364630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JavaType; /** * Exception thrown when resolution of a type id fails. * * @since 2.8 */ public class InvalidTypeIdException extends MismatchedInputException // since 2.9 { private static final long serialVersionUID = 1L; // silly Eclipse, warnings /** * Basetype for which subtype was to be resolved */ protected final JavaType _baseType; /** * Type id that failed to be resolved to a subtype; `null` in cases * where no type id was located (since 2.9). */ protected final String _typeId; /* /********************************************************** /* Life-cycle /********************************************************** */ public InvalidTypeIdException(JsonParser p, String msg, JavaType baseType, String typeId) { super(p, msg); _baseType = baseType; _typeId = typeId; } public static InvalidTypeIdException from(JsonParser p, String msg, JavaType baseType, String typeId) { return new InvalidTypeIdException(p, msg, baseType, typeId); } /* /********************************************************** /* Accessors /********************************************************** */ public JavaType getBaseType() { return _baseType; } public String getTypeId() { return _typeId; } } MismatchedInputException.java000066400000000000000000000053341325620701100370540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.util.ClassUtil; /** * General exception type used as the base class for all {@link JsonMappingException}s * that are due to input not mapping to target definition; these are typically * considered "client errors" since target type definition itself is not the root cause * but mismatching input. This is in contrast to {@link InvalidDefinitionException} which * signals a problem with target type definition and not input. *

* This type is used as-is for some input problems, but in most cases there should be * more explicit subtypes to use. *

* NOTE: name chosen to differ from `java.util.InputMismatchException` since while that * would have been better name, use of same overlapping name causes nasty issues * with IDE auto-completion, so slightly less optimal chosen. * * @since 2.9 */ @SuppressWarnings("serial") public class MismatchedInputException extends JsonMappingException { /** * Type of value that was to be deserialized */ protected Class _targetType; protected MismatchedInputException(JsonParser p, String msg) { this(p, msg, (JavaType) null); } protected MismatchedInputException(JsonParser p, String msg, JsonLocation loc) { super(p, msg, loc); } protected MismatchedInputException(JsonParser p, String msg, Class targetType) { super(p, msg); _targetType = targetType; } protected MismatchedInputException(JsonParser p, String msg, JavaType targetType) { super(p, msg); _targetType = ClassUtil.rawClass(targetType); } // Only to prevent super-class static method from getting called @Deprecated // as of 2.9 public static MismatchedInputException from(JsonParser p, String msg) { return from(p, (Class) null, msg); } public static MismatchedInputException from(JsonParser p, JavaType targetType, String msg) { return new MismatchedInputException(p, msg, targetType); } public static MismatchedInputException from(JsonParser p, Class targetType, String msg) { return new MismatchedInputException(p, msg, targetType); } public MismatchedInputException setTargetType(JavaType t) { _targetType = t.getRawClass(); return this; } /** * Accessor for getting intended target type, with which input did not match, * if known; `null` if not known for some reason. */ public Class getTargetType() { return _targetType; } } PropertyBindingException.java000066400000000000000000000104251325620701100370720ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonMappingException; /** * Base class for {@link JsonMappingException}s that are specifically related * to problems related to binding an individual property. * * @since 2.3 */ @SuppressWarnings("serial") public abstract class PropertyBindingException extends MismatchedInputException // since 2.9 { /** * Class that does not contain mapping for the unrecognized property. */ protected final Class _referringClass; /** *

* Note: redundant information since it is also included in the * reference path. */ protected final String _propertyName; /** * Set of ids of properties that are known for the type, if this * can be statically determined. */ protected final Collection _propertyIds; /** * Lazily constructed description of known properties, used for * constructing actual message if and as needed. */ protected transient String _propertiesAsString; /** * @since 2.7 */ protected PropertyBindingException(JsonParser p, String msg, JsonLocation loc, Class referringClass, String propName, Collection propertyIds) { super(p, msg, loc); _referringClass = referringClass; _propertyName = propName; _propertyIds = propertyIds; } /** * @deprecated Since 2.7 */ @Deprecated // since 2.7 protected PropertyBindingException(String msg, JsonLocation loc, Class referringClass, String propName, Collection propertyIds) { this(null, msg, loc, referringClass, propName, propertyIds); } /* /********************************************************** /* Overrides /********************************************************** */ /** * Somewhat arbitrary limit, but let's try not to create uselessly * huge error messages */ private final static int MAX_DESC_LENGTH = 1000; @Override public String getMessageSuffix() { String suffix = _propertiesAsString; if (suffix == null && _propertyIds != null) { StringBuilder sb = new StringBuilder(100); int len = _propertyIds.size(); if (len == 1) { sb.append(" (one known property: \""); sb.append(String.valueOf(_propertyIds.iterator().next())); sb.append('"'); } else { sb.append(" (").append(len).append(" known properties: "); Iterator it = _propertyIds.iterator(); while (it.hasNext()) { sb.append('"'); sb.append(String.valueOf(it.next())); sb.append('"'); // one other thing: limit max length if (sb.length() > MAX_DESC_LENGTH) { sb.append(" [truncated]"); break; } if (it.hasNext()) { sb.append(", "); } } } sb.append("])"); _propertiesAsString = suffix = sb.toString(); } return suffix; } /* /********************************************************** /* Extended API /********************************************************** */ /** * Method for accessing type (class) that is missing definition to allow * binding of the unrecognized property. */ public Class getReferringClass() { return _referringClass; } /** * Convenience method for accessing logical property name that could * not be mapped. Note that it is the last path reference in the * underlying path. */ public String getPropertyName() { return _propertyName; } public Collection getKnownPropertyIds() { if (_propertyIds == null) { return null; } return Collections.unmodifiableCollection(_propertyIds); } } UnrecognizedPropertyException.java000066400000000000000000000047751325620701100401670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import java.util.*; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonMappingException; /** * Specialized {@link JsonMappingException} sub-class specifically used * to indicate problems due to encountering a JSON property that could * not be mapped to an Object property (via getter, constructor argument * or field). */ public class UnrecognizedPropertyException extends PropertyBindingException { private static final long serialVersionUID = 1L; public UnrecognizedPropertyException(JsonParser p, String msg, JsonLocation loc, Class referringClass, String propName, Collection propertyIds) { super(p, msg, loc, referringClass, propName, propertyIds); } /** * @deprecated Since 2.7 */ @Deprecated // since 2.7 public UnrecognizedPropertyException(String msg, JsonLocation loc, Class referringClass, String propName, Collection propertyIds) { super(msg, loc, referringClass, propName, propertyIds); } /** * Factory method used for constructing instances of this exception type. * * @param p Underlying parser used for reading input being used for data-binding * @param fromObjectOrClass Reference to either instance of problematic type ( * if available), or if not, type itself * @param propertyName Name of unrecognized property * @param propertyIds (optional, null if not available) Set of properties that * type would recognize, if completely known: null if set cannot be determined. */ public static UnrecognizedPropertyException from(JsonParser p, Object fromObjectOrClass, String propertyName, Collection propertyIds) { Class ref; if (fromObjectOrClass instanceof Class) { ref = (Class) fromObjectOrClass; } else { ref = fromObjectOrClass.getClass(); } String msg = String.format("Unrecognized field \"%s\" (class %s), not marked as ignorable", propertyName, ref.getName()); UnrecognizedPropertyException e = new UnrecognizedPropertyException(p, msg, p.getCurrentLocation(), ref, propertyName, propertyIds); // but let's also ensure path includes this last (missing) segment e.prependPath(fromObjectOrClass, propertyName); return e; } } jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ext/000077500000000000000000000000001325620701100313275ustar00rootroot00000000000000CoreXMLDeserializers.java000066400000000000000000000110431325620701100361110ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import java.io.IOException; import java.util.*; import javax.xml.datatype.*; import javax.xml.namespace.QName; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.Deserializers; import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer; /** * Container deserializers that handle "core" XML types: ones included in standard * JDK 1.5. Types are directly needed by JAXB, but may be unavailable on some * limited platforms; hence separate out from basic deserializer factory. */ public class CoreXMLDeserializers extends Deserializers.Base { /** * Data type factories are thread-safe after instantiation (and * configuration, if any); and since instantion (esp. implementation * introspection) can be expensive we better reuse the instance. */ final static DatatypeFactory _dataTypeFactory; static { try { _dataTypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException e) { throw new RuntimeException(e); } } @Override public JsonDeserializer findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) { Class raw = type.getRawClass(); if (raw == QName.class) { return new Std(raw, TYPE_QNAME); } if (raw == XMLGregorianCalendar.class) { return new Std(raw, TYPE_G_CALENDAR); } if (raw == Duration.class) { return new Std(raw, TYPE_DURATION); } return null; } /* /********************************************************** /* Concrete deserializers /********************************************************** */ protected final static int TYPE_DURATION = 1; protected final static int TYPE_G_CALENDAR = 2; protected final static int TYPE_QNAME = 3; /** * Combo-deserializer that supports deserialization of somewhat optional * javax.xml types {@link QName}, {@link Duration} and {@link XMLGregorianCalendar}. * Combined into a single class to eliminate bunch of one-off implementation * classes, to reduce resulting jar size (mostly). * * @since 2.4 */ public static class Std extends FromStringDeserializer { private static final long serialVersionUID = 1L; protected final int _kind; public Std(Class raw, int kind) { super(raw); _kind = kind; } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // For most types, use super impl; but GregorianCalendar also allows // integer value (timestamp), which needs separate handling if (_kind == TYPE_G_CALENDAR) { if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) { return _gregorianFromDate(ctxt, _parseDate(p, ctxt)); } } return super.deserialize(p, ctxt); } @Override protected Object _deserialize(String value, DeserializationContext ctxt) throws IOException { switch (_kind) { case TYPE_DURATION: return _dataTypeFactory.newDuration(value); case TYPE_QNAME: return QName.valueOf(value); case TYPE_G_CALENDAR: Date d; try { d = _parseDate(value, ctxt); } catch (JsonMappingException e) { // try to parse from native XML Schema 1.0 lexical representation String, // which includes time-only formats not handled by parseXMLGregorianCalendarFromJacksonFormat(...) return _dataTypeFactory.newXMLGregorianCalendar(value); } return _gregorianFromDate(ctxt, d); } throw new IllegalStateException(); } protected XMLGregorianCalendar _gregorianFromDate(DeserializationContext ctxt, Date d) { if (d == null) { return null; } GregorianCalendar calendar = new GregorianCalendar(); calendar.setTime(d); TimeZone tz = ctxt.getTimeZone(); if (tz != null) { calendar.setTimeZone(tz); } return _dataTypeFactory.newXMLGregorianCalendar(calendar); } } } CoreXMLSerializers.java000066400000000000000000000076161325620701100356130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import java.io.IOException; import java.util.Calendar; import javax.xml.datatype.Duration; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.Serializers; import com.fasterxml.jackson.databind.ser.std.CalendarSerializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; /** * Provider for serializers of XML types that are part of full JDK 1.5, but * that some alleged 1.5 platforms are missing (Android, GAE). * And for this reason these are added using more dynamic mechanism. *

* Note: since many of classes defined are abstract, caller must take * care not to just use straight equivalency check but rather consider * subclassing as well. */ public class CoreXMLSerializers extends Serializers.Base { @Override public JsonSerializer findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc) { Class raw = type.getRawClass(); if (Duration.class.isAssignableFrom(raw) || QName.class.isAssignableFrom(raw)) { return ToStringSerializer.instance; } if (XMLGregorianCalendar.class.isAssignableFrom(raw)) { return XMLGregorianCalendarSerializer.instance; } return null; } @SuppressWarnings("serial") public static class XMLGregorianCalendarSerializer extends StdSerializer implements ContextualSerializer { final static XMLGregorianCalendarSerializer instance = new XMLGregorianCalendarSerializer(); final JsonSerializer _delegate; public XMLGregorianCalendarSerializer() { this(CalendarSerializer.instance); } @SuppressWarnings("unchecked") protected XMLGregorianCalendarSerializer(JsonSerializer del) { super(XMLGregorianCalendar.class); _delegate = (JsonSerializer) del; } @Override public JsonSerializer getDelegatee() { return _delegate; } @Override public boolean isEmpty(SerializerProvider provider, XMLGregorianCalendar value) { return _delegate.isEmpty(provider, _convert(value)); } @Override public void serialize(XMLGregorianCalendar value, JsonGenerator gen, SerializerProvider provider) throws IOException { _delegate.serialize(_convert(value), gen, provider); } @Override public void serializeWithType(XMLGregorianCalendar value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { _delegate.serializeWithType(_convert(value), gen, provider, typeSer); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { _delegate.acceptJsonFormatVisitor(visitor, null); } @Override public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { JsonSerializer ser = prov.handlePrimaryContextualization(_delegate, property); if (ser != _delegate) { return new XMLGregorianCalendarSerializer(ser); } return this; } protected Calendar _convert(XMLGregorianCalendar input) { return (input == null) ? null : input.toGregorianCalendar(); } } } DOMDeserializer.java000066400000000000000000000066151325620701100351050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import java.io.StringReader; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer; /** * Base for serializers that allows parsing DOM Documents from JSON Strings. * Nominal type can be either {@link org.w3c.dom.Node} or * {@link org.w3c.dom.Document}. */ public abstract class DOMDeserializer extends FromStringDeserializer { private static final long serialVersionUID = 1L; private final static DocumentBuilderFactory DEFAULT_PARSER_FACTORY; static { DocumentBuilderFactory parserFactory = DocumentBuilderFactory.newInstance(); // yup, only cave men do XML without recognizing namespaces... parserFactory.setNamespaceAware(true); // [databind#1279]: make sure external entities NOT expanded by default parserFactory.setExpandEntityReferences(false); // ... and in general, aim for "safety" try { parserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); } catch(ParserConfigurationException pce) { // not much point to do anything; could log but... } catch (Error e) { // 14-Jul-2016, tatu: Not sure how or why, but during code coverage runs // (via Cobertura) we get `java.lang.AbstractMethodError` so... ignore that too } DEFAULT_PARSER_FACTORY = parserFactory; } protected DOMDeserializer(Class cls) { super(cls); } @Override public abstract T _deserialize(String value, DeserializationContext ctxt); protected final Document parse(String value) throws IllegalArgumentException { try { return documentBuilder().parse(new InputSource(new StringReader(value))); } catch (Exception e) { throw new IllegalArgumentException("Failed to parse JSON String as XML: "+e.getMessage(), e); } } /** * Overridable factory method used to create {@link DocumentBuilder} for parsing * XML as DOM. * * @since 2.7.6 */ protected DocumentBuilder documentBuilder() throws ParserConfigurationException { return DEFAULT_PARSER_FACTORY.newDocumentBuilder(); } /* /********************************************************** /* Concrete deserializers /********************************************************** */ public static class NodeDeserializer extends DOMDeserializer { private static final long serialVersionUID = 1L; public NodeDeserializer() { super(Node.class); } @Override public Node _deserialize(String value, DeserializationContext ctxt) throws IllegalArgumentException { return parse(value); } } public static class DocumentDeserializer extends DOMDeserializer { private static final long serialVersionUID = 1L; public DocumentDeserializer() { super(Document.class); } @Override public Document _deserialize(String value, DeserializationContext ctxt) throws IllegalArgumentException { return parse(value); } } } DOMSerializer.java000066400000000000000000000037011325620701100345650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import java.io.IOException; import org.w3c.dom.Node; import org.w3c.dom.bootstrap.DOMImplementationRegistry; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSSerializer; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.ser.std.StdSerializer; @SuppressWarnings("serial") public class DOMSerializer extends StdSerializer { protected final DOMImplementationLS _domImpl; public DOMSerializer() { super(Node.class); DOMImplementationRegistry registry; try { registry = DOMImplementationRegistry.newInstance(); } catch (Exception e) { throw new IllegalStateException("Could not instantiate DOMImplementationRegistry: "+e.getMessage(), e); } _domImpl = (DOMImplementationLS)registry.getDOMImplementation("LS"); } @Override public void serialize(Node value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { if (_domImpl == null) throw new IllegalStateException("Could not find DOM LS"); LSSerializer writer = _domImpl.createLSSerializer(); jgen.writeString(writer.writeToString(value)); } @Override public JsonNode getSchema(SerializerProvider provider, java.lang.reflect.Type typeHint) { // Well... it is serialized as String return createSchemaNode("string", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { if (visitor != null) visitor.expectAnyFormat(typeHint); } } Java7Support.java000066400000000000000000000034731325620701100344670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.PropertyName; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.util.ClassUtil; /** * To support Java7-incomplete platforms, we will offer support for JDK 7 * annotations through this class, loaded dynamically; if loading fails, * support will be missing. This class is the non-JDK-7-dependent API, * and {@link Java7SupportImpl} is JDK7-dependent implementation of * functionality. */ public abstract class Java7Support { private final static Java7Support IMPL; static { Java7Support impl = null; try { Class cls = Class.forName("com.fasterxml.jackson.databind.ext.Java7SupportImpl"); impl = (Java7Support) ClassUtil.createInstance(cls, false); } catch (Throwable t) { // 24-Nov-2015, tatu: Should we log or not? java.util.logging.Logger.getLogger(Java7Support.class.getName()) .warning("Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added"); } IMPL = impl; } public static Java7Support instance() { return IMPL; } public abstract Boolean findTransient(Annotated a); public abstract Boolean hasCreatorAnnotation(Annotated a); public abstract PropertyName findConstructorName(AnnotatedParameter p); public abstract Class getClassJavaNioFilePath(); public abstract JsonDeserializer getDeserializerForJavaNioFilePath(Class rawType); public abstract JsonSerializer getSerializerForJavaNioFilePath(Class rawType); } Java7SupportImpl.java000066400000000000000000000051051325620701100353030ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import java.beans.ConstructorProperties; import java.beans.Transient; import java.nio.file.Path; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.PropertyName; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams; /** * @since 2.8 */ public class Java7SupportImpl extends Java7Support { @SuppressWarnings("unused") // compiler warns, just needed side-effects private final Class _bogus; public Java7SupportImpl() { // Trigger loading of annotations that only JDK 7 has... Class cls = Transient.class; cls = ConstructorProperties.class; _bogus = cls; } @Override public Class getClassJavaNioFilePath() { return Path.class; } @Override public JsonDeserializer getDeserializerForJavaNioFilePath(Class rawType) { if (rawType == Path.class) { return new NioPathDeserializer(); } return null; } @Override public JsonSerializer getSerializerForJavaNioFilePath(Class rawType) { if (Path.class.isAssignableFrom(rawType)) { return new NioPathSerializer(); } return null; } @Override public Boolean findTransient(Annotated a) { Transient t = a.getAnnotation(Transient.class); if (t != null) { return t.value(); } return null; } @Override public Boolean hasCreatorAnnotation(Annotated a) { ConstructorProperties props = a.getAnnotation(ConstructorProperties.class); // 08-Nov-2015, tatu: One possible check would be to ensure there is at least // one name iff constructor has arguments. But seems unnecessary for now. if (props != null) { return Boolean.TRUE; } return null; } @Override public PropertyName findConstructorName(AnnotatedParameter p) { AnnotatedWithParams ctor = p.getOwner(); if (ctor != null) { ConstructorProperties props = ctor.getAnnotation(ConstructorProperties.class); if (props != null) { String[] names = props.value(); int ix = p.getIndex(); if (ix < names.length) { return PropertyName.construct(names[ix]); } } } return null; } } NioPathDeserializer.java000066400000000000000000000024661325620701100360300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Path; import java.nio.file.Paths; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; /** * @since 2.8 */ public class NioPathDeserializer extends StdScalarDeserializer { private static final long serialVersionUID = 1; public NioPathDeserializer() { super(Path.class); } @Override public Path deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (!p.hasToken(JsonToken.VALUE_STRING)) { return (Path) ctxt.handleUnexpectedToken(Path.class, p); } final String value = p.getText(); // If someone gives us an input with no : at all, treat as local path, instead of failing // with invalid URI. if (value.indexOf(':') < 0) { return Paths.get(value); } try { URI uri = new URI(value); return Paths.get(uri); } catch (URISyntaxException e) { return (Path) ctxt.handleInstantiationProblem(handledType(), value, e); } } } NioPathSerializer.java000066400000000000000000000026511325620701100355130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ext package com.fasterxml.jackson.databind.ext; import java.io.IOException; import java.nio.file.Path; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; /** * @since 2.8 */ public class NioPathSerializer extends StdScalarSerializer { private static final long serialVersionUID = 1; public NioPathSerializer() { super(Path.class); } @Override public void serialize(Path value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // write the Path as a URI, always. gen.writeString(value.toUri().toString()); } // [databind#1688]: Not sure this is 100% ok, considering there are legitimately different // impls... but has to do @Override public void serializeWithType(Path value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // Better ensure we don't use specific sub-classes: WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, Path.class, JsonToken.VALUE_STRING)); serialize(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } } OptionalHandlerFactory.java000066400000000000000000000162361325620701100365360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import java.util.logging.Logger; import java.util.logging.Level; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.Deserializers; import com.fasterxml.jackson.databind.ser.Serializers; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Helper class used for isolating details of handling optional+external types * (javax.xml classes) from standard factories that offer them. *

* Note that 2.7 changed handling to slightly less dynamic, to avoid having to * traverse class hierarchy, which turned to be a performance issue in * certain cases. Since DOM classes are assumed to exist on all Java 1.6 * environments (yes, even on Android/GAE), this part could be simplified by * slightly less dynamic lookups. *

* Also with 2.7 we are supporting JDK 1.7/Java 7 type(s). */ public class OptionalHandlerFactory implements java.io.Serializable { private static final long serialVersionUID = 1; /* To make 2 main "optional" handler groups (javax.xml.stream) * more dynamic, we better only figure out handlers completely dynamically, if and * when they are needed. To do this we need to assume package prefixes. */ private final static String PACKAGE_PREFIX_JAVAX_XML = "javax.xml."; private final static String SERIALIZERS_FOR_JAVAX_XML = "com.fasterxml.jackson.databind.ext.CoreXMLSerializers"; private final static String DESERIALIZERS_FOR_JAVAX_XML = "com.fasterxml.jackson.databind.ext.CoreXMLDeserializers"; // Plus we also have a single serializer for DOM Node: // private final static String CLASS_NAME_DOM_NODE = "org.w3c.dom.Node"; // private final static String CLASS_NAME_DOM_DOCUMENT = "org.w3c.dom.Document"; private final static String SERIALIZER_FOR_DOM_NODE = "com.fasterxml.jackson.databind.ext.DOMSerializer"; private final static String DESERIALIZER_FOR_DOM_DOCUMENT = "com.fasterxml.jackson.databind.ext.DOMDeserializer$DocumentDeserializer"; private final static String DESERIALIZER_FOR_DOM_NODE = "com.fasterxml.jackson.databind.ext.DOMDeserializer$NodeDeserializer"; // // Since 2.7, we will assume DOM classes are always found, both due to JDK 1.6 minimum // // and because Android (and presumably GAE) have these classes private final static Class CLASS_DOM_NODE; private final static Class CLASS_DOM_DOCUMENT; static { Class doc = null, node = null; try { node = org.w3c.dom.Node.class; doc = org.w3c.dom.Document.class; } catch (Exception e) { // not optimal but will do Logger.getLogger(OptionalHandlerFactory.class.getName()) .log(Level.INFO, "Could not load DOM `Node` and/or `Document` classes: no DOM support"); } CLASS_DOM_NODE = node; CLASS_DOM_DOCUMENT = doc; } // // But Java7 type(s) may or may not be; dynamic lookup should be fine, still // // (note: also assume it comes from JDK so that ClassLoader issues with OSGi // // can, I hope, be avoided?) private static final Java7Support _jdk7Helper; static { Java7Support x = null; try { x = Java7Support.instance(); } catch (Throwable t) { } _jdk7Helper = x; } public final static OptionalHandlerFactory instance = new OptionalHandlerFactory(); protected OptionalHandlerFactory() { } /* /********************************************************** /* Public API /********************************************************** */ public JsonSerializer findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc) { final Class rawType = type.getRawClass(); if (_jdk7Helper != null) { JsonSerializer ser = _jdk7Helper.getSerializerForJavaNioFilePath(rawType); if (ser != null) { return ser; } } if ((CLASS_DOM_NODE != null) && CLASS_DOM_NODE.isAssignableFrom(rawType)) { return (JsonSerializer) instantiate(SERIALIZER_FOR_DOM_NODE); } String className = rawType.getName(); String factoryName; if (className.startsWith(PACKAGE_PREFIX_JAVAX_XML) || hasSuperClassStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) { factoryName = SERIALIZERS_FOR_JAVAX_XML; } else { return null; } Object ob = instantiate(factoryName); if (ob == null) { // could warn, if we had logging system (j.u.l?) return null; } return ((Serializers) ob).findSerializer(config, type, beanDesc); } public JsonDeserializer findDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { final Class rawType = type.getRawClass(); if (_jdk7Helper != null) { JsonDeserializer deser = _jdk7Helper.getDeserializerForJavaNioFilePath(rawType); if (deser != null) { return deser; } } if ((CLASS_DOM_NODE != null) && CLASS_DOM_NODE.isAssignableFrom(rawType)) { return (JsonDeserializer) instantiate(DESERIALIZER_FOR_DOM_NODE); } if ((CLASS_DOM_DOCUMENT != null) && CLASS_DOM_DOCUMENT.isAssignableFrom(rawType)) { return (JsonDeserializer) instantiate(DESERIALIZER_FOR_DOM_DOCUMENT); } String className = rawType.getName(); String factoryName; if (className.startsWith(PACKAGE_PREFIX_JAVAX_XML) || hasSuperClassStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) { factoryName = DESERIALIZERS_FOR_JAVAX_XML; } else { return null; } Object ob = instantiate(factoryName); if (ob == null) { // could warn, if we had logging system (j.u.l?) return null; } return ((Deserializers) ob).findBeanDeserializer(type, config, beanDesc); } /* /********************************************************** /* Internal helper methods /********************************************************** */ private Object instantiate(String className) { try { return ClassUtil.createInstance(Class.forName(className), false); } catch (LinkageError e) { } // too many different kinds to enumerate here: catch (Exception e) { } return null; } /** * Since 2.7 we only need to check for class extension, as all implemented * types are classes, not interfaces. This has performance implications for * some cases, as we do not need to go over interfaces implemented, just * superclasses * * @since 2.7 */ private boolean hasSuperClassStartingWith(Class rawType, String prefix) { for (Class supertype = rawType.getSuperclass(); supertype != null; supertype = supertype.getSuperclass()) { if (supertype == Object.class) { return false; } if (supertype.getName().startsWith(prefix)) { return true; } } return false; } } package-info.java000066400000000000000000000014631325620701100344430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ext/** Contains extended support for "external" packages: things that may or may not be present in runtime environment, but that are commonly enough used so that explicit support can be added.

Currently supported extensions include:

  • Support for Java 1.5 core XML datatypes: the reason these are considered "external" is that some platforms that claim to be 1.5 conformant are only partially so (Google Android, GAE) and do not included these types.
  • Joda time. This package has superior date/time handling functionality, and is thus supported. However, to minimize forced dependencies this support is added as extension so that Joda is not needed by Jackson itself: but if it is present, its core types are supported to some degree
*/ package com.fasterxml.jackson.databind.ext; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspect/000077500000000000000000000000001325620701100327215ustar00rootroot00000000000000Annotated.java000066400000000000000000000054211325620701100354240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeBindings; /** * Shared base class used for anything on which annotations (included * within a {@link AnnotationMap}). */ public abstract class Annotated { protected Annotated() { } public abstract A getAnnotation(Class acls); public abstract boolean hasAnnotation(Class acls); /** * @since 2.7 */ public abstract boolean hasOneOf(Class[] annoClasses); /** * Method that can be used to find actual JDK element that this instance * represents. It is non-null, except for method/constructor parameters * which do not have a JDK counterpart. */ public abstract AnnotatedElement getAnnotated(); protected abstract int getModifiers(); public boolean isPublic() { return Modifier.isPublic(getModifiers()); } public abstract String getName(); /** * Full generic type of the annotated element; definition * of what exactly this means depends on sub-class. * * @since 2.7 */ public abstract JavaType getType(); /** * @deprecated Since 2.7 Use {@link #getType()} instead. To be removed from 2.9 */ @Deprecated public final JavaType getType(TypeBindings bogus) { return getType(); } /** * JDK declared generic type of the annotated element; definition * of what exactly this means depends on sub-class. Note that such type * cannot be reliably resolved without {@link TypeResolutionContext}, and * as a result use of this method was deprecated in Jackson 2.7: see * {@link #getType} for replacement. * * @deprecated Since 2.7 should instead use {@link #getType()}. To be removed from 2.9 */ @Deprecated public Type getGenericType() { return getRawType(); } /** * "Raw" type (type-erased class) of the annotated element; definition * of what exactly this means depends on sub-class. */ public abstract Class getRawType(); /** * Accessor that can be used to iterate over all the annotations * associated with annotated component. * * @since 2.3 * @deprecated Since 2.9 should instead use {@link #getAnnotated()} */ @Deprecated public abstract Iterable annotations(); // Also: ensure we can use #equals, #hashCode @Override public abstract boolean equals(Object o); @Override public abstract int hashCode(); @Override public abstract String toString(); } AnnotatedClass.java000066400000000000000000000317201325620701100364130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.lang.reflect.*; import java.util.*; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.ClassIntrospector.MixInResolver; import com.fasterxml.jackson.databind.type.TypeBindings; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.Annotations; import com.fasterxml.jackson.databind.util.ClassUtil; public final class AnnotatedClass extends Annotated implements TypeResolutionContext { private final static Creators NO_CREATORS = new Creators(null, Collections.emptyList(), Collections.emptyList()); /* /********************************************************** /* Configuration /********************************************************** */ /** * @since 2.7 */ final protected JavaType _type; /** * Class for which annotations apply, and that owns other * components (constructors, methods) */ final protected Class _class; /** * Type bindings to use for members of {@link #_class}. * * @since 2.7 */ final protected TypeBindings _bindings; /** * Ordered set of super classes and interfaces of the * class itself: included in order of precedence */ final protected List _superTypes; /** * Filter used to determine which annotations to gather; used * to optimize things so that unnecessary annotations are * ignored. */ final protected AnnotationIntrospector _annotationIntrospector; /** * @since 2.7 */ final protected TypeFactory _typeFactory; /** * Object that knows mapping of mix-in classes (ones that contain * annotations to add) with their target classes (ones that * get these additional annotations "mixed in"). */ final protected MixInResolver _mixInResolver; /** * Primary mix-in class; one to use for the annotated class * itself. Can be null. */ final protected Class _primaryMixIn; /* /********************************************************** /* Gathered information /********************************************************** */ /** * Combined list of Jackson annotations that the class has, * including inheritable ones from super classes and interfaces */ final protected Annotations _classAnnotations; /** * @since 2.9 */ protected Creators _creators; /** * Member methods of interest; for now ones with 0 or 1 arguments * (just optimization, since others won't be used now) */ protected AnnotatedMethodMap _memberMethods; /** * Member fields of interest: ones that are either public, * or have at least one annotation. */ protected List _fields; /** * Lazily determined property to see if this is a non-static inner * class. * * @since 2.8.7 */ protected transient Boolean _nonStaticInnerClass; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * Constructor will not do any initializations, to allow for * configuring instances differently depending on use cases * * @param type Fully resolved type; may be `null`, but ONLY if no member fields or * methods are to be accessed * @param rawType Type-erased class; pass if no `type` needed or available */ AnnotatedClass(JavaType type, Class rawType, List superTypes, Class primaryMixIn, Annotations classAnnotations, TypeBindings bindings, AnnotationIntrospector aintr, MixInResolver mir, TypeFactory tf) { _type = type; _class = rawType; _superTypes = superTypes; _primaryMixIn = primaryMixIn; _classAnnotations = classAnnotations; _bindings = bindings; _annotationIntrospector = aintr; _mixInResolver = mir; _typeFactory = tf; } /** * Constructor (only) used for creating primordial simple types (during bootstrapping) * and array type placeholders where no fields or methods are needed. * * @since 2.9 */ AnnotatedClass(Class rawType) { _type = null; _class = rawType; _superTypes = Collections.emptyList(); _primaryMixIn = null; _classAnnotations = AnnotationCollector.emptyAnnotations(); _bindings = TypeBindings.emptyBindings(); _annotationIntrospector = null; _mixInResolver = null; _typeFactory = null; } /** * @deprecated Since 2.9, use methods in {@link AnnotatedClassResolver} instead. */ @Deprecated public static AnnotatedClass construct(JavaType type, MapperConfig config) { return construct(type, config, (MixInResolver) config); } /** * @deprecated Since 2.9, use methods in {@link AnnotatedClassResolver} instead. */ @Deprecated public static AnnotatedClass construct(JavaType type, MapperConfig config, MixInResolver mir) { return AnnotatedClassResolver.resolve(config, type, mir); } /** * Method similar to {@link #construct}, but that will NOT include * information from supertypes; only class itself and any direct * mix-ins it may have. */ /** * @deprecated Since 2.9, use methods in {@link AnnotatedClassResolver} instead. */ @Deprecated public static AnnotatedClass constructWithoutSuperTypes(Class raw, MapperConfig config) { return constructWithoutSuperTypes(raw, config, config); } /** * @deprecated Since 2.9, use methods in {@link AnnotatedClassResolver} instead. */ @Deprecated public static AnnotatedClass constructWithoutSuperTypes(Class raw, MapperConfig config, MixInResolver mir) { return AnnotatedClassResolver.resolveWithoutSuperTypes(config, raw, mir); } /* /********************************************************** /* TypeResolutionContext implementation /********************************************************** */ @Override public JavaType resolveType(Type type) { return _typeFactory.constructType(type, _bindings); } /* /********************************************************** /* Annotated impl /********************************************************** */ @Override public Class getAnnotated() { return _class; } @Override public int getModifiers() { return _class.getModifiers(); } @Override public String getName() { return _class.getName(); } @Override public A getAnnotation(Class acls) { return _classAnnotations.get(acls); } @Override public boolean hasAnnotation(Class acls) { return _classAnnotations.has(acls); } @Override public boolean hasOneOf(Class[] annoClasses) { return _classAnnotations.hasOneOf(annoClasses); } @Override public Class getRawType() { return _class; } @Override @Deprecated public Iterable annotations() { if (_classAnnotations instanceof AnnotationMap) { return ((AnnotationMap) _classAnnotations).annotations(); } else if (_classAnnotations instanceof AnnotationCollector.OneAnnotation || _classAnnotations instanceof AnnotationCollector.TwoAnnotations) { throw new UnsupportedOperationException("please use getAnnotations/ hasAnnotation to check for Annotations"); } return Collections.emptyList(); } @Override public JavaType getType() { return _type; } /* /********************************************************** /* Public API, generic accessors /********************************************************** */ public Annotations getAnnotations() { return _classAnnotations; } public boolean hasAnnotations() { return _classAnnotations.size() > 0; } public AnnotatedConstructor getDefaultConstructor() { return _creators().defaultConstructor; } public List getConstructors() { return _creators().constructors; } /** * @since 2.9 */ public List getFactoryMethods() { return _creators().creatorMethods; } /** * @deprecated Since 2.9; use {@link #getFactoryMethods} instead. */ @Deprecated public List getStaticMethods() { return getFactoryMethods(); } public Iterable memberMethods() { return _methods(); } public int getMemberMethodCount() { return _methods().size(); } public AnnotatedMethod findMethod(String name, Class[] paramTypes) { return _methods().find(name, paramTypes); } public int getFieldCount() { return _fields().size(); } public Iterable fields() { return _fields(); } /** * @since 2.9 */ public boolean isNonStaticInnerClass() { Boolean B = _nonStaticInnerClass; if (B == null) { _nonStaticInnerClass = B = ClassUtil.isNonStaticInnerClass(_class); } return B.booleanValue(); } /* /********************************************************** /* Lazily-operating accessors /********************************************************** */ private final List _fields() { List f = _fields; if (f == null) { // 09-Jun-2017, tatu: _type only null for primordial, placeholder array types. if (_type == null) { f = Collections.emptyList(); } else { f = AnnotatedFieldCollector.collectFields(_annotationIntrospector, this, _mixInResolver, _typeFactory, _type); } _fields = f; } return f; } private final AnnotatedMethodMap _methods() { AnnotatedMethodMap m = _memberMethods; if (m == null) { // 09-Jun-2017, tatu: _type only null for primordial, placeholder array types. // NOTE: would be great to have light-weight shareable maps; no such impl exists for now if (_type == null) { m = new AnnotatedMethodMap(); } else { m = AnnotatedMethodCollector.collectMethods(_annotationIntrospector, this, _mixInResolver, _typeFactory, _type, _superTypes, _primaryMixIn); } _memberMethods = m; } return m; } private final Creators _creators() { Creators c = _creators; if (c == null) { if (_type == null) { c = NO_CREATORS; } else { c = AnnotatedCreatorCollector.collectCreators(_annotationIntrospector, this, _type, _primaryMixIn); } _creators = c; } return c; } /* /********************************************************** /* Standard method overrides /********************************************************** */ @Override public String toString() { return "[AnnotedClass "+_class.getName()+"]"; } @Override public int hashCode() { return _class.getName().hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; if (!ClassUtil.hasClass(o, getClass())) { return false; } return ((AnnotatedClass) o)._class == _class; } /* /********************************************************** /* Helper classes /********************************************************** */ public static final class Creators { /** * Default constructor of the annotated class, if it has one. */ public final AnnotatedConstructor defaultConstructor; /** * Single argument constructors the class has, if any. */ public final List constructors; /** * Single argument static methods that might be usable * as factory methods */ public final List creatorMethods; public Creators(AnnotatedConstructor defCtor, List ctors, List ctorMethods) { defaultConstructor = defCtor; constructors = ctors; creatorMethods = ctorMethods; } } } AnnotatedClassResolver.java000066400000000000000000000217541325620701100401430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.Collections; import java.util.List; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.ClassIntrospector.MixInResolver; import com.fasterxml.jackson.databind.type.TypeBindings; import com.fasterxml.jackson.databind.util.Annotations; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Helper class that contains logic for resolving annotations to construct * {@link AnnotatedClass} instances. * * @since 2.9 */ public class AnnotatedClassResolver { private final static Annotations NO_ANNOTATIONS = AnnotationCollector.emptyAnnotations(); private final MapperConfig _config; private final AnnotationIntrospector _intr; private final MixInResolver _mixInResolver; private final TypeBindings _bindings; private final JavaType _type; private final Class _class; private final Class _primaryMixin; AnnotatedClassResolver(MapperConfig config, JavaType type, MixInResolver r) { _config = config; _type = type; _class = type.getRawClass(); _mixInResolver = r; _bindings = type.getBindings(); _intr = config.isAnnotationProcessingEnabled() ? config.getAnnotationIntrospector() : null; _primaryMixin = _config.findMixInClassFor(_class); } AnnotatedClassResolver(MapperConfig config, Class cls, MixInResolver r) { _config = config; _type = null; _class = cls; _mixInResolver = r; _bindings = TypeBindings.emptyBindings(); if (config == null) { _intr = null; _primaryMixin = null; } else { _intr = config.isAnnotationProcessingEnabled() ? config.getAnnotationIntrospector() : null; _primaryMixin = _config.findMixInClassFor(_class); } } public static AnnotatedClass resolve(MapperConfig config, JavaType forType, MixInResolver r) { if (forType.isArrayType() && skippableArray(config, forType.getRawClass())) { return createArrayType(config, forType.getRawClass()); } return new AnnotatedClassResolver(config, forType, r).resolveFully(); } public static AnnotatedClass resolveWithoutSuperTypes(MapperConfig config, Class forType) { return resolveWithoutSuperTypes(config, forType, config); } public static AnnotatedClass resolveWithoutSuperTypes(MapperConfig config, JavaType forType, MixInResolver r) { if (forType.isArrayType() && skippableArray(config, forType.getRawClass())) { return createArrayType(config, forType.getRawClass()); } return new AnnotatedClassResolver(config, forType, r).resolveWithoutSuperTypes(); } public static AnnotatedClass resolveWithoutSuperTypes(MapperConfig config, Class forType, MixInResolver r) { if (forType.isArray() && skippableArray(config, forType)) { return createArrayType(config, forType); } return new AnnotatedClassResolver(config, forType, r).resolveWithoutSuperTypes(); } private static boolean skippableArray(MapperConfig config, Class type) { return (config == null) || (config.findMixInClassFor(type) == null); } /** * Internal helper method used for resolving a small set of "primordial" types for which * we do not accept any annotation information or overrides. */ static AnnotatedClass createPrimordial(Class raw) { return new AnnotatedClass(raw); } /** * Internal helper method used for resolving array types, unless they happen * to have associated mix-in to apply. */ static AnnotatedClass createArrayType(MapperConfig config, Class raw) { return new AnnotatedClass(raw); } AnnotatedClass resolveFully() { List superTypes = ClassUtil.findSuperTypes(_type, null, false); return new AnnotatedClass(_type, _class, superTypes, _primaryMixin, resolveClassAnnotations(superTypes), _bindings, _intr, _mixInResolver, _config.getTypeFactory()); } AnnotatedClass resolveWithoutSuperTypes() { List superTypes = Collections.emptyList(); return new AnnotatedClass(null, _class, superTypes, _primaryMixin, resolveClassAnnotations(superTypes), _bindings, _intr, _config, _config.getTypeFactory()); } /* /********************************************************** /* Class annotation resolution /********************************************************** */ /** * Initialization method that will recursively collect Jackson * annotations for this class and all super classes and * interfaces. */ private Annotations resolveClassAnnotations(List superTypes) { // Should skip processing if annotation processing disabled if (_intr == null) { return NO_ANNOTATIONS; } AnnotationCollector resolvedCA = AnnotationCollector.emptyCollector(); // add mix-in annotations first (overrides) if (_primaryMixin != null) { resolvedCA = _addClassMixIns(resolvedCA, _class, _primaryMixin); } // then annotations from the class itself: resolvedCA = _addAnnotationsIfNotPresent(resolvedCA, ClassUtil.findClassAnnotations(_class)); // and then from super types for (JavaType type : superTypes) { // and mix mix-in annotations in-between if (_mixInResolver != null) { Class cls = type.getRawClass(); resolvedCA = _addClassMixIns(resolvedCA, cls, _mixInResolver.findMixInClassFor(cls)); } resolvedCA = _addAnnotationsIfNotPresent(resolvedCA, ClassUtil.findClassAnnotations(type.getRawClass())); } /* and finally... any annotations there might be for plain * old Object.class: separate because for all other purposes * it is just ignored (not included in super types) */ // 12-Jul-2009, tatu: Should this be done for interfaces too? // For now, yes, seems useful for some cases, and not harmful for any? if (_mixInResolver != null) { resolvedCA = _addClassMixIns(resolvedCA, Object.class, _mixInResolver.findMixInClassFor(Object.class)); } return resolvedCA.asAnnotations(); } private AnnotationCollector _addClassMixIns(AnnotationCollector annotations, Class target, Class mixin) { if (mixin != null) { // Ok, first: annotations from mix-in class itself: annotations = _addAnnotationsIfNotPresent(annotations, ClassUtil.findClassAnnotations(mixin)); // And then from its supertypes, if any. But note that we will only consider // super-types up until reaching the masked class (if found); this because // often mix-in class is a sub-class (for convenience reasons). // And if so, we absolutely must NOT include super types of masked class, // as that would inverse precedence of annotations. for (Class parent : ClassUtil.findSuperClasses(mixin, target, false)) { annotations = _addAnnotationsIfNotPresent(annotations, ClassUtil.findClassAnnotations(parent)); } } return annotations; } private AnnotationCollector _addAnnotationsIfNotPresent(AnnotationCollector c, Annotation[] anns) { if (anns != null) { for (Annotation ann : anns) { // first: direct annotations // note: we will NOT filter out non-Jackson annotations any more if (!c.isPresent(ann)) { c = c.addOrOverride(ann); if (_intr.isAnnotationBundle(ann)) { c = _addFromBundleIfNotPresent(c, ann); } } } } return c; } private AnnotationCollector _addFromBundleIfNotPresent(AnnotationCollector c, Annotation bundle) { for (Annotation ann : ClassUtil.findClassAnnotations(bundle.annotationType())) { // minor optimization: by-pass 2 common JDK meta-annotations if ((ann instanceof Target) || (ann instanceof Retention)) { continue; } if (!c.isPresent(ann)) { c = c.addOrOverride(ann); if (_intr.isAnnotationBundle(ann)) { c = _addFromBundleIfNotPresent(c, ann); } } } return c; } } AnnotatedConstructor.java000066400000000000000000000145511325620701100376760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.util.ClassUtil; public final class AnnotatedConstructor extends AnnotatedWithParams { private static final long serialVersionUID = 1L; protected final Constructor _constructor; /** * Field that is used to make JDK serialization work with this * object. * * @since 2.1 */ protected Serialization _serialization; /* /********************************************************** /* Life-cycle /********************************************************** */ public AnnotatedConstructor(TypeResolutionContext ctxt, Constructor constructor, AnnotationMap classAnn, AnnotationMap[] paramAnn) { super(ctxt, classAnn, paramAnn); if (constructor == null) { throw new IllegalArgumentException("Null constructor not allowed"); } _constructor = constructor; } /** * Method used for JDK serialization support * @since 2.1 */ protected AnnotatedConstructor(Serialization ser) { super(null, null, null); _constructor = null; _serialization = ser; } @Override public AnnotatedConstructor withAnnotations(AnnotationMap ann) { return new AnnotatedConstructor(_typeContext, _constructor, ann, _paramAnnotations); } /* /********************************************************** /* Annotated impl /********************************************************** */ @Override public Constructor getAnnotated() { return _constructor; } @Override public int getModifiers() { return _constructor.getModifiers(); } @Override public String getName() { return _constructor.getName(); } @Override public JavaType getType() { return _typeContext.resolveType(getRawType()); } @Override public Class getRawType() { return _constructor.getDeclaringClass(); } /* /********************************************************** /* Extended API /********************************************************** */ @Override public int getParameterCount() { return _constructor.getParameterTypes().length; } @Override public Class getRawParameterType(int index) { Class[] types = _constructor.getParameterTypes(); return (index >= types.length) ? null : types[index]; } @Override public JavaType getParameterType(int index) { Type[] types = _constructor.getGenericParameterTypes(); if (index >= types.length) { return null; } return _typeContext.resolveType(types[index]); } @Override @Deprecated // since 2.7 public Type getGenericParameterType(int index) { Type[] types = _constructor.getGenericParameterTypes(); if (index >= types.length) { return null; } return types[index]; } @Override public final Object call() throws Exception { return _constructor.newInstance(); } @Override public final Object call(Object[] args) throws Exception { return _constructor.newInstance(args); } @Override public final Object call1(Object arg) throws Exception { return _constructor.newInstance(arg); } /* /********************************************************** /* AnnotatedMember impl /********************************************************** */ @Override public Class getDeclaringClass() { return _constructor.getDeclaringClass(); } @Override public Member getMember() { return _constructor; } @Override public void setValue(Object pojo, Object value) throws UnsupportedOperationException { throw new UnsupportedOperationException("Cannot call setValue() on constructor of " +getDeclaringClass().getName()); } @Override public Object getValue(Object pojo) throws UnsupportedOperationException { throw new UnsupportedOperationException("Cannot call getValue() on constructor of " +getDeclaringClass().getName()); } /* /********************************************************** /* Extended API, specific annotations /********************************************************** */ @Override public String toString() { return "[constructor for "+getName()+", annotations: "+_annotations+"]"; } @Override public int hashCode() { return _constructor.getName().hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; return ClassUtil.hasClass(o, getClass()) && (((AnnotatedConstructor) o)._constructor == _constructor); } /* /********************************************************** /* JDK serialization handling /********************************************************** */ Object writeReplace() { return new AnnotatedConstructor(new Serialization(_constructor)); } Object readResolve() { Class clazz = _serialization.clazz; try { Constructor ctor = clazz.getDeclaredConstructor(_serialization.args); // 06-Oct-2012, tatu: Has "lost" its security override, must force back if (!ctor.isAccessible()) { ClassUtil.checkAndFixAccess(ctor, false); } return new AnnotatedConstructor(null, ctor, null, null); } catch (Exception e) { throw new IllegalArgumentException("Could not find constructor with " +_serialization.args.length+" args from Class '"+clazz.getName()); } } /** * Helper class that is used as the workaround to persist * Field references. It basically just stores declaring class * and field name. */ private final static class Serialization implements java.io.Serializable { private static final long serialVersionUID = 1L; protected Class clazz; protected Class[] args; public Serialization(Constructor ctor) { clazz = ctor.getDeclaringClass(); args = ctor.getParameterTypes(); } } } AnnotatedCreatorCollector.java000066400000000000000000000355351325620701100406240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.introspect.AnnotatedClass.Creators; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Helper class used to contain details of how Creators (annotated constructors * and static methods) are discovered to be accessed by and via {@link AnnotatedClass}. * * @since 2.9 */ final class AnnotatedCreatorCollector extends CollectorBase { // // // Configuration private final TypeResolutionContext _typeContext; // // // Collected state private AnnotatedConstructor _defaultConstructor; AnnotatedCreatorCollector(AnnotationIntrospector intr, TypeResolutionContext tc) { super(intr); _typeContext = tc; } public static Creators collectCreators(AnnotationIntrospector intr, TypeResolutionContext tc, JavaType type, Class primaryMixIn) { // Constructor also always members of resolved class, parent == resolution context return new AnnotatedCreatorCollector(intr, tc) .collect(type, primaryMixIn); } Creators collect(JavaType type, Class primaryMixIn) { // 30-Apr-2016, tatu: [databind#1215]: Actually, while true, this does // NOT apply to context since sub-class may have type bindings // TypeResolutionContext typeContext = new TypeResolutionContext.Basic(_typeFactory, _type.getBindings()); List constructors = _findPotentialConstructors(type, primaryMixIn); List factories = _findPotentialFactories(type, primaryMixIn); /* And then... let's remove all constructors that are deemed * ignorable after all annotations have been properly collapsed. */ // AnnotationIntrospector is null if annotations not enabled; if so, can skip: if (_intr != null) { if (_defaultConstructor != null) { if (_intr.hasIgnoreMarker(_defaultConstructor)) { _defaultConstructor = null; } } // count down to allow safe removal for (int i = constructors.size(); --i >= 0; ) { if (_intr.hasIgnoreMarker(constructors.get(i))) { constructors.remove(i); } } for (int i = factories.size(); --i >= 0; ) { if (_intr.hasIgnoreMarker(factories.get(i))) { factories.remove(i); } } } return new AnnotatedClass.Creators(_defaultConstructor, constructors, factories); } /** * Helper method for locating constructors (and matching mix-in overrides) * we might want to use; this is needed in order to mix information between * the two and construct resulting {@link AnnotatedConstructor}s */ private List _findPotentialConstructors(JavaType type, Class primaryMixIn) { ClassUtil.Ctor defaultCtor = null; List ctors = null; // 18-Jun-2016, tatu: Enum constructors will never be useful (unlike // possibly static factory methods); but they can be royal PITA // due to some oddities by JVM; see: // [https://github.com/FasterXML/jackson-module-parameter-names/issues/35] // for more. So, let's just skip them. if (!type.isEnumType()) { ClassUtil.Ctor[] declaredCtors = ClassUtil.getConstructors(type.getRawClass()); for (ClassUtil.Ctor ctor : declaredCtors) { if (!isIncludableConstructor(ctor.getConstructor())) { continue; } if (ctor.getParamCount() == 0) { defaultCtor = ctor; } else { if (ctors == null) { ctors = new ArrayList<>(); } ctors.add(ctor); } } } List result; int ctorCount; if (ctors == null) { result = Collections.emptyList(); // Nothing found? Short-circuit if (defaultCtor == null) { return result; } ctorCount = 0; } else { ctorCount = ctors.size(); result = new ArrayList<>(ctorCount); for (int i = 0; i < ctorCount; ++i) { result.add(null); } } // so far so good; but do we also need to find mix-ins overrides? if (primaryMixIn != null) { MemberKey[] ctorKeys = null; for (ClassUtil.Ctor mixinCtor : ClassUtil.getConstructors(primaryMixIn)) { if (mixinCtor.getParamCount() == 0) { if (defaultCtor != null) { _defaultConstructor = constructDefaultConstructor(defaultCtor, mixinCtor); defaultCtor = null; } continue; } if (ctors != null) { if (ctorKeys == null) { ctorKeys = new MemberKey[ctorCount]; for (int i = 0; i < ctorCount; ++i) { ctorKeys[i] = new MemberKey(ctors.get(i).getConstructor()); } } MemberKey key = new MemberKey(mixinCtor.getConstructor()); for (int i = 0; i < ctorCount; ++i) { if (key.equals(ctorKeys[i])) { result.set(i, constructNonDefaultConstructor(ctors.get(i), mixinCtor)); break; } } } } } // Ok: anything within mix-ins has been resolved; anything remaining we must resolve if (defaultCtor != null) { _defaultConstructor = constructDefaultConstructor(defaultCtor, null); } for (int i = 0; i < ctorCount; ++i) { AnnotatedConstructor ctor = result.get(i); if (ctor == null) { result.set(i, constructNonDefaultConstructor(ctors.get(i), null)); } } return result; } private List _findPotentialFactories(JavaType type, Class primaryMixIn) { List candidates = null; // First find all potentially relevant static methods for (Method m : ClassUtil.getClassMethods(type.getRawClass())) { if (!Modifier.isStatic(m.getModifiers())) { continue; } // all factory methods are fine: //int argCount = m.getParameterTypes().length; if (candidates == null) { candidates = new ArrayList<>(); } candidates.add(m); } // and then locate mix-ins, if any if (candidates == null) { return Collections.emptyList(); } int factoryCount = candidates.size(); List result = new ArrayList<>(factoryCount); for (int i = 0; i < factoryCount; ++i) { result.add(null); } // so far so good; but do we also need to find mix-ins overrides? if (primaryMixIn != null) { MemberKey[] methodKeys = null; for (Method mixinFactory : ClassUtil.getDeclaredMethods(primaryMixIn)) { if (!Modifier.isStatic(mixinFactory.getModifiers())) { continue; } if (methodKeys == null) { methodKeys = new MemberKey[factoryCount]; for (int i = 0; i < factoryCount; ++i) { methodKeys[i] = new MemberKey(candidates.get(i)); } } MemberKey key = new MemberKey(mixinFactory); for (int i = 0; i < factoryCount; ++i) { if (key.equals(methodKeys[i])) { result.set(i, constructFactoryCreator(candidates.get(i), mixinFactory)); break; } } } } // Ok: anything within mix-ins has been resolved; anything remaining we must resolve for (int i = 0; i < factoryCount; ++i) { AnnotatedMethod factory = result.get(i); if (factory == null) { result.set(i, constructFactoryCreator(candidates.get(i), null)); } } return result; } protected AnnotatedConstructor constructDefaultConstructor(ClassUtil.Ctor ctor, ClassUtil.Ctor mixin) { if (_intr == null) { // when annotation processing is disabled return new AnnotatedConstructor(_typeContext, ctor.getConstructor(), _emptyAnnotationMap(), NO_ANNOTATION_MAPS); } return new AnnotatedConstructor(_typeContext, ctor.getConstructor(), collectAnnotations(ctor, mixin), collectAnnotations(ctor.getConstructor().getParameterAnnotations(), (mixin == null) ? null : mixin.getConstructor().getParameterAnnotations())); } protected AnnotatedConstructor constructNonDefaultConstructor(ClassUtil.Ctor ctor, ClassUtil.Ctor mixin) { final int paramCount = ctor.getParamCount(); if (_intr == null) { // when annotation processing is disabled return new AnnotatedConstructor(_typeContext, ctor.getConstructor(), _emptyAnnotationMap(), _emptyAnnotationMaps(paramCount)); } /* Looks like JDK has discrepancy, whereas annotations for implicit 'this' * (for non-static inner classes) are NOT included, but type is? * Strange, sounds like a bug. Alas, we can't really fix that... */ if (paramCount == 0) { // no-arg default constructors, can simplify slightly return new AnnotatedConstructor(_typeContext, ctor.getConstructor(), collectAnnotations(ctor, mixin), NO_ANNOTATION_MAPS); } // Also: enum value constructors AnnotationMap[] resolvedAnnotations; Annotation[][] paramAnns = ctor.getParameterAnnotations(); if (paramCount != paramAnns.length) { // Limits of the work-around (to avoid hiding real errors): // first, only applicable for member classes and then either: resolvedAnnotations = null; Class dc = ctor.getDeclaringClass(); // (a) is enum, which have two extra hidden params (name, index) if (dc.isEnum() && (paramCount == paramAnns.length + 2)) { Annotation[][] old = paramAnns; paramAnns = new Annotation[old.length+2][]; System.arraycopy(old, 0, paramAnns, 2, old.length); resolvedAnnotations = collectAnnotations(paramAnns, null); } else if (dc.isMemberClass()) { // (b) non-static inner classes, get implicit 'this' for parameter, not annotation if (paramCount == (paramAnns.length + 1)) { // hack attack: prepend a null entry to make things match Annotation[][] old = paramAnns; paramAnns = new Annotation[old.length+1][]; System.arraycopy(old, 0, paramAnns, 1, old.length); paramAnns[0] = NO_ANNOTATIONS; resolvedAnnotations = collectAnnotations(paramAnns, null); } } if (resolvedAnnotations == null) { throw new IllegalStateException(String.format( "Internal error: constructor for %s has mismatch: %d parameters; %d sets of annotations", ctor.getDeclaringClass().getName(), paramCount, paramAnns.length)); } } else { resolvedAnnotations = collectAnnotations(paramAnns, (mixin == null) ? null : mixin.getParameterAnnotations()); } return new AnnotatedConstructor(_typeContext, ctor.getConstructor(), collectAnnotations(ctor, mixin), resolvedAnnotations); } protected AnnotatedMethod constructFactoryCreator(Method m, Method mixin) { final int paramCount = m.getParameterTypes().length; if (_intr == null) { // when annotation processing is disabled return new AnnotatedMethod(_typeContext, m, _emptyAnnotationMap(), _emptyAnnotationMaps(paramCount)); } if (paramCount == 0) { // common enough we can slightly optimize return new AnnotatedMethod(_typeContext, m, collectAnnotations(m, mixin), NO_ANNOTATION_MAPS); } return new AnnotatedMethod(_typeContext, m, collectAnnotations(m, mixin), collectAnnotations(m.getParameterAnnotations(), (mixin == null) ? null : mixin.getParameterAnnotations())); } private AnnotationMap[] collectAnnotations(Annotation[][] mainAnns, Annotation[][] mixinAnns) { final int count = mainAnns.length; AnnotationMap[] result = new AnnotationMap[count]; for (int i = 0; i < count; ++i) { AnnotationCollector c = collectAnnotations(AnnotationCollector.emptyCollector(), mainAnns[i]); if (mixinAnns != null) { c = collectAnnotations(c, mixinAnns[i]); } result[i] = c.asAnnotationMap(); } return result; } // // NOTE: these are only called when we know we have AnnotationIntrospector private AnnotationMap collectAnnotations(ClassUtil.Ctor main, ClassUtil.Ctor mixin) { AnnotationCollector c = collectAnnotations(main.getConstructor().getDeclaredAnnotations()); if (mixin != null) { c = collectAnnotations(c, mixin.getConstructor().getDeclaredAnnotations()); } return c.asAnnotationMap(); } private final AnnotationMap collectAnnotations(AnnotatedElement main, AnnotatedElement mixin) { AnnotationCollector c = collectAnnotations(main.getDeclaredAnnotations()); if (mixin != null) { c = collectAnnotations(c, mixin.getDeclaredAnnotations()); } return c.asAnnotationMap(); } // for [databind#1005]: do not use or expose synthetic constructors private static boolean isIncludableConstructor(Constructor c) { return !c.isSynthetic(); } } AnnotatedField.java000066400000000000000000000124041325620701100363670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Object that represents non-static (and usually non-transient/volatile) * fields of a class. */ public final class AnnotatedField extends AnnotatedMember implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Actual {@link Field} used for access. *

* Transient since it cannot be persisted directly using * JDK serialization */ protected final transient Field _field; /** * Temporary field required for JDK serialization support */ protected Serialization _serialization; /* /********************************************************** /* Life-cycle /********************************************************** */ public AnnotatedField(TypeResolutionContext contextClass, Field field, AnnotationMap annMap) { super(contextClass, annMap); _field = field; } @Override public AnnotatedField withAnnotations(AnnotationMap ann) { return new AnnotatedField(_typeContext, _field, ann); } /** * Method used for JDK serialization support */ protected AnnotatedField(Serialization ser) { super(null, null); _field = null; _serialization = ser; } /* /********************************************************** /* Annotated impl /********************************************************** */ @Override public Field getAnnotated() { return _field; } @Override public int getModifiers() { return _field.getModifiers(); } @Override public String getName() { return _field.getName(); } @Override public Class getRawType() { return _field.getType(); } @Deprecated @Override public Type getGenericType() { return _field.getGenericType(); } @Override public JavaType getType() { return _typeContext.resolveType(_field.getGenericType()); } /* /********************************************************** /* AnnotatedMember impl /********************************************************** */ @Override public Class getDeclaringClass() { return _field.getDeclaringClass(); } @Override public Member getMember() { return _field; } @Override public void setValue(Object pojo, Object value) throws IllegalArgumentException { try { _field.set(pojo, value); } catch (IllegalAccessException e) { throw new IllegalArgumentException("Failed to setValue() for field " +getFullName()+": "+e.getMessage(), e); } } @Override public Object getValue(Object pojo) throws IllegalArgumentException { try { return _field.get(pojo); } catch (IllegalAccessException e) { throw new IllegalArgumentException("Failed to getValue() for field " +getFullName()+": "+e.getMessage(), e); } } /* /********************************************************** /* Extended API, generic /********************************************************** */ public int getAnnotationCount() { return _annotations.size(); } /** * @since 2.6 */ public boolean isTransient() { return Modifier.isTransient(getModifiers()); } @Override public int hashCode() { return _field.getName().hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; return ClassUtil.hasClass(o, getClass()) && (((AnnotatedField) o)._field == _field); } @Override public String toString() { return "[field "+getFullName()+"]"; } /* /********************************************************** /* JDK serialization handling /********************************************************** */ Object writeReplace() { return new AnnotatedField(new Serialization(_field)); } Object readResolve() { Class clazz = _serialization.clazz; try { Field f = clazz.getDeclaredField(_serialization.name); // 06-Oct-2012, tatu: Has "lost" its security override, may need to force back if (!f.isAccessible()) { ClassUtil.checkAndFixAccess(f, false); } return new AnnotatedField(null, f, null); } catch (Exception e) { throw new IllegalArgumentException("Could not find method '"+_serialization.name +"' from Class '"+clazz.getName()); } } /** * Helper class that is used as the workaround to persist * Field references. It basically just stores declaring class * and field name. */ private final static class Serialization implements java.io.Serializable { private static final long serialVersionUID = 1L; protected Class clazz; protected String name; public Serialization(Field f) { clazz = f.getDeclaringClass(); name = f.getName(); } } } AnnotatedFieldCollector.java000066400000000000000000000126431325620701100402430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.*; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.introspect.ClassIntrospector.MixInResolver; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; public class AnnotatedFieldCollector extends CollectorBase { // // // Configuration private final TypeFactory _typeFactory; private final MixInResolver _mixInResolver; // // // Collected state AnnotatedFieldCollector(AnnotationIntrospector intr, TypeFactory types, MixInResolver mixins) { super(intr); _typeFactory = types; _mixInResolver = (intr == null) ? null : mixins; } public static List collectFields(AnnotationIntrospector intr, TypeResolutionContext tc, MixInResolver mixins, TypeFactory types, JavaType type) { return new AnnotatedFieldCollector(intr, types, mixins).collect(tc, type); } List collect(TypeResolutionContext tc, JavaType type) { Map foundFields = _findFields(tc, type, null); if (foundFields == null) { return Collections.emptyList(); } List result = new ArrayList<>(foundFields.size()); for (FieldBuilder b : foundFields.values()) { result.add(b.build()); } return result; } private Map _findFields(TypeResolutionContext tc, JavaType type, Map fields) { // First, a quick test: we only care for regular classes (not interfaces, //primitive types etc), except for Object.class. A simple check to rule out // other cases is to see if there is a super class or not. JavaType parent = type.getSuperClass(); if (parent == null) { return fields; } final Class cls = type.getRawClass(); // Let's add super-class' fields first, then ours. fields = _findFields(new TypeResolutionContext.Basic(_typeFactory, parent.getBindings()), parent, fields); for (Field f : ClassUtil.getDeclaredFields(cls)) { // static fields not included (transients are at this point, filtered out later) if (!_isIncludableField(f)) { continue; } // Ok now: we can (and need) not filter out ignorable fields at this point; partly // because mix-ins haven't been added, and partly because logic can be done // when determining get/settability of the field. if (fields == null) { fields = new LinkedHashMap<>(); } FieldBuilder b = new FieldBuilder(tc, f); if (_intr != null) { b.annotations = collectAnnotations(b.annotations, f.getDeclaredAnnotations()); } fields.put(f.getName(), b); } // And then... any mix-in overrides? if (_mixInResolver != null) { Class mixin = _mixInResolver.findMixInClassFor(cls); if (mixin != null) { _addFieldMixIns(mixin, cls, fields); } } return fields; } /** * Method called to add field mix-ins from given mix-in class (and its fields) * into already collected actual fields (from introspected classes and their * super-classes) */ private void _addFieldMixIns(Class mixInCls, Class targetClass, Map fields) { List> parents = ClassUtil.findSuperClasses(mixInCls, targetClass, true); for (Class mixin : parents) { for (Field mixinField : ClassUtil.getDeclaredFields(mixin)) { // there are some dummy things (static, synthetic); better ignore if (!_isIncludableField(mixinField)) { continue; } String name = mixinField.getName(); // anything to mask? (if not, quietly ignore) FieldBuilder b = fields.get(name); if (b != null) { b.annotations = collectAnnotations(b.annotations, mixinField.getDeclaredAnnotations()); } } } } private boolean _isIncludableField(Field f) { // Most likely synthetic fields, if any, are to be skipped similar to methods if (f.isSynthetic()) { return false; } // Static fields are never included. Transient are (since 2.6), for // purpose of propagating removal int mods = f.getModifiers(); if (Modifier.isStatic(mods)) { return false; } return true; } private final static class FieldBuilder { public final TypeResolutionContext typeContext; public final Field field; public AnnotationCollector annotations; public FieldBuilder(TypeResolutionContext tc, Field f) { typeContext = tc; field = f; annotations = AnnotationCollector.emptyCollector(); } public AnnotatedField build() { return new AnnotatedField(typeContext, field, annotations.asAnnotationMap()); } } } AnnotatedMember.java000066400000000000000000000117771325620701100365670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.util.Collections; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Intermediate base class for annotated entities that are members of * a class; fields, methods and constructors. This is a superset * of things that can represent logical properties as it contains * constructors in addition to fields and methods. */ public abstract class AnnotatedMember extends Annotated implements java.io.Serializable { private static final long serialVersionUID = 1L; // since 2.5 // 19-Dec-2014, tatu: Similarly, assumed NOT to be needed in cases where // owning object (ObjectMapper or relatives) is being JDK-serialized /** * Context object needed for resolving generic type associated with this * member (method parameter or return value, or field type). * * @since 2.7 */ protected final transient TypeResolutionContext _typeContext; // Transient since information not needed after construction, so // no need to persist protected final transient AnnotationMap _annotations; protected AnnotatedMember(TypeResolutionContext ctxt, AnnotationMap annotations) { super(); _typeContext = ctxt; _annotations = annotations; } /** * Copy-constructor. * * @since 2.5 */ protected AnnotatedMember(AnnotatedMember base) { _typeContext = base._typeContext; _annotations = base._annotations; } /** * Fluent factory method that will construct a new instance that uses specified * instance annotations instead of currently configured ones. * * @since 2.9 (promoted from `Annotated`) */ public abstract Annotated withAnnotations(AnnotationMap fallback); /** * Actual physical class in which this memmber was declared. */ public abstract Class getDeclaringClass(); public abstract Member getMember(); public String getFullName() { return getDeclaringClass().getName() + "#" + getName(); } /** * Accessor for {@link TypeResolutionContext} that is used for resolving * full generic type of this member. * * @since 2.7 * * @deprecated Since 2.9 */ @Deprecated public TypeResolutionContext getTypeContext() { return _typeContext; } @Override public final A getAnnotation(Class acls) { if (_annotations == null) { return null; } return _annotations.get(acls); } @Override public final boolean hasAnnotation(Class acls) { if (_annotations == null) { return false; } return _annotations.has(acls); } @Override public boolean hasOneOf(Class[] annoClasses) { if (_annotations == null) { return false; } return _annotations.hasOneOf(annoClasses); } @Override @Deprecated public Iterable annotations() { if (_annotations == null) { return Collections.emptyList(); } return _annotations.annotations(); } /** *

* NOTE: promoted in 2.9 from `Annotated` up */ public AnnotationMap getAllAnnotations() { // alas, used by at least one module, hence public return _annotations; } /** * Method that can be called to modify access rights, by calling * {@link java.lang.reflect.AccessibleObject#setAccessible} on * the underlying annotated element. *

* Note that caller should verify that * {@link com.fasterxml.jackson.databind.MapperFeature#CAN_OVERRIDE_ACCESS_MODIFIERS} * is enabled before calling this method; as well as pass * force flag appropriately. * * @since 2.7 */ public final void fixAccess(boolean force) { Member m = getMember(); if (m != null) { // may be null for virtual members ClassUtil.checkAndFixAccess(m, force); } } /** * Optional method that can be used to assign value of * this member on given object, if this is a supported * operation for member type. *

* This is implemented for fields and single-argument * member methods; but not for constructor parameters or * other types of methods (like static methods) */ public abstract void setValue(Object pojo, Object value) throws UnsupportedOperationException, IllegalArgumentException; /** * Optional method that can be used to access the value of * this member on given object, if this is a supported * operation for member type. *

* This is implemented for fields and no-argument * member methods; but not for constructor parameters or * other types of methods (like static methods) */ public abstract Object getValue(Object pojo) throws UnsupportedOperationException, IllegalArgumentException; } AnnotatedMethod.java000066400000000000000000000203231325620701100365630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.util.ClassUtil; public final class AnnotatedMethod extends AnnotatedWithParams implements java.io.Serializable { private static final long serialVersionUID = 1L; final protected transient Method _method; // // Simple lazy-caching: protected Class[] _paramClasses; /** * Field that is used to make JDK serialization work with this * object. * * @since 2.1 */ protected Serialization _serialization; /* /***************************************************** /* Life-cycle /***************************************************** */ public AnnotatedMethod(TypeResolutionContext ctxt, Method method, AnnotationMap classAnn, AnnotationMap[] paramAnnotations) { super(ctxt, classAnn, paramAnnotations); if (method == null) { throw new IllegalArgumentException("Cannot construct AnnotatedMethod with null Method"); } _method = method; } /** * Method used for JDK serialization support * @since 2.1 */ protected AnnotatedMethod(Serialization ser) { super(null, null, null); _method = null; _serialization = ser; } @Override public AnnotatedMethod withAnnotations(AnnotationMap ann) { return new AnnotatedMethod(_typeContext, _method, ann, _paramAnnotations); } @Override public Method getAnnotated() { return _method; } @Override public int getModifiers() { return _method.getModifiers(); } @Override public String getName() { return _method.getName(); } /** * For methods, this returns declared return type, which is only * useful with getters (setters do not return anything; hence `Void` * would be returned here) */ @Override public JavaType getType() { return _typeContext.resolveType(_method.getGenericReturnType()); } /** * For methods, this returns declared return type, which is only * useful with getters (setters do not usually return anything; * hence "void" type is returned here) */ @Override public Class getRawType() { return _method.getReturnType(); } @Deprecated @Override public Type getGenericType() { return _method.getGenericReturnType(); } /* /***************************************************** /* AnnotatedWithParams /***************************************************** */ @Override public final Object call() throws Exception { return _method.invoke(null); } @Override public final Object call(Object[] args) throws Exception { return _method.invoke(null, args); } @Override public final Object call1(Object arg) throws Exception { return _method.invoke(null, arg); } public final Object callOn(Object pojo) throws Exception { return _method.invoke(pojo, (Object[]) null); } public final Object callOnWith(Object pojo, Object... args) throws Exception { return _method.invoke(pojo, args); } /* /******************************************************** /* AnnotatedMember impl /******************************************************** */ @Override public int getParameterCount() { return getRawParameterTypes().length; } @Override public Class getRawParameterType(int index) { Class[] types = getRawParameterTypes(); return (index >= types.length) ? null : types[index]; } @Override public JavaType getParameterType(int index) { Type[] types = _method.getGenericParameterTypes(); if (index >= types.length) { return null; } return _typeContext.resolveType(types[index]); } @Override @Deprecated // since 2.7 public Type getGenericParameterType(int index) { Type[] types = getGenericParameterTypes(); if (index >= types.length) { return null; } return types[index]; } @Override public Class getDeclaringClass() { return _method.getDeclaringClass(); } @Override public Method getMember() { return _method; } @Override public void setValue(Object pojo, Object value) throws IllegalArgumentException { try { _method.invoke(pojo, value); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalArgumentException("Failed to setValue() with method " +getFullName()+": "+e.getMessage(), e); } } @Override public Object getValue(Object pojo) throws IllegalArgumentException { try { return _method.invoke(pojo, (Object[]) null); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalArgumentException("Failed to getValue() with method " +getFullName()+": "+e.getMessage(), e); } } /* /***************************************************** /* Extended API, generic /***************************************************** */ @Override public String getFullName() { return String.format("%s(%d params)", super.getFullName(), getParameterCount()); } public Class[] getRawParameterTypes() { if (_paramClasses == null) { _paramClasses = _method.getParameterTypes(); } return _paramClasses; } @Deprecated // since 2.7 public Type[] getGenericParameterTypes() { return _method.getGenericParameterTypes(); } public Class getRawReturnType() { return _method.getReturnType(); } /** * Helper method that can be used to check whether method returns * a value or not; if return type declared as void, returns * false, otherwise true * * @since 2.4 */ public boolean hasReturnType() { Class rt = getRawReturnType(); return (rt != Void.TYPE && rt != Void.class); } /* /******************************************************** /* Other /******************************************************** */ @Override public String toString() { return "[method "+getFullName()+"]"; } @Override public int hashCode() { return _method.getName().hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; return ClassUtil.hasClass(o, getClass()) && (((AnnotatedMethod) o)._method == _method); } /* /********************************************************** /* JDK serialization handling /********************************************************** */ Object writeReplace() { return new AnnotatedMethod(new Serialization(_method)); } Object readResolve() { Class clazz = _serialization.clazz; try { Method m = clazz.getDeclaredMethod(_serialization.name, _serialization.args); // 06-Oct-2012, tatu: Has "lost" its security override, may need to force back if (!m.isAccessible()) { ClassUtil.checkAndFixAccess(m, false); } return new AnnotatedMethod(null, m, null, null); } catch (Exception e) { throw new IllegalArgumentException("Could not find method '"+_serialization.name +"' from Class '"+clazz.getName()); } } /** * Helper class that is used as the workaround to persist * Field references. It basically just stores declaring class * and field name. */ private final static class Serialization implements java.io.Serializable { private static final long serialVersionUID = 1L; protected Class clazz; protected String name; protected Class[] args; public Serialization(Method setter) { clazz = setter.getDeclaringClass(); name = setter.getName(); args = setter.getParameterTypes(); } } } AnnotatedMethodCollector.java000066400000000000000000000211471325620701100404370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.introspect.ClassIntrospector.MixInResolver; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; public class AnnotatedMethodCollector extends CollectorBase { private final MixInResolver _mixInResolver; AnnotatedMethodCollector(AnnotationIntrospector intr, MixInResolver mixins) { super(intr); _mixInResolver = (intr == null) ? null : mixins; } public static AnnotatedMethodMap collectMethods(AnnotationIntrospector intr, TypeResolutionContext tc, MixInResolver mixins, TypeFactory types, JavaType type, List superTypes, Class primaryMixIn) { // Constructor also always members of resolved class, parent == resolution context return new AnnotatedMethodCollector(intr, mixins) .collect(types, tc, type, superTypes, primaryMixIn); } AnnotatedMethodMap collect(TypeFactory typeFactory, TypeResolutionContext tc, JavaType mainType, List superTypes, Class primaryMixIn) { Map methods = new LinkedHashMap<>(); // first: methods from the class itself _addMemberMethods(tc, mainType.getRawClass(), methods, primaryMixIn); // and then augment these with annotations from super-types: for (JavaType type : superTypes) { Class mixin = (_mixInResolver == null) ? null : _mixInResolver.findMixInClassFor(type.getRawClass()); _addMemberMethods( new TypeResolutionContext.Basic(typeFactory, type.getBindings()), type.getRawClass(), methods, mixin); } // Special case: mix-ins for Object.class? (to apply to ALL classes) /* if (_mixInResolver != null) { Class mixin = _mixInResolver.findMixInClassFor(Object.class); if (mixin != null) { _addMethodMixIns(tc, mainType.getRawClass(), memberMethods, mixin, mixins); } } // Any unmatched mix-ins? Most likely error cases (not matching any method); // but there is one possible real use case: exposing Object#hashCode // (alas, Object#getClass can NOT be exposed) if (_intr != null) { if (!mixins.isEmpty()) { Iterator it = mixins.iterator(); while (it.hasNext()) { AnnotatedMethod mixIn = it.next(); try { Method m = Object.class.getDeclaredMethod(mixIn.getName(), mixIn.getRawParameterTypes()); if (m != null) { // Since it's from java.lang.Object, no generics, no need for real type context: AnnotatedMethod am = _constructMethod(tc, m); _addMixOvers(mixIn.getAnnotated(), am, false); memberMethods.add(am); } } catch (Exception e) { } } } } */ // And then let's if (methods.isEmpty()) { return new AnnotatedMethodMap(); } Map actual = new LinkedHashMap<>(methods.size()); for (Map.Entry entry : methods.entrySet()) { AnnotatedMethod am = entry.getValue().build(); if (am != null) { actual.put(entry.getKey(), am); } } return new AnnotatedMethodMap(actual); } private void _addMemberMethods(TypeResolutionContext tc, Class cls, Map methods, Class mixInCls) { // first, mixIns, since they have higher priority then class methods if (mixInCls != null) { _addMethodMixIns(tc, cls, methods, mixInCls); } if (cls == null) { // just so caller need not check when passing super-class return; } // then methods from the class itself for (Method m : ClassUtil.getClassMethods(cls)) { if (!_isIncludableMemberMethod(m)) { continue; } final MemberKey key = new MemberKey(m); MethodBuilder b = methods.get(key); if (b == null) { AnnotationCollector c = (_intr == null) ? AnnotationCollector.emptyCollector() : collectAnnotations(m.getDeclaredAnnotations()); methods.put(key, new MethodBuilder(tc, m, c)); } else { if (_intr != null) { b.annotations = collectDefaultAnnotations(b.annotations, m.getDeclaredAnnotations()); } Method old = b.method; if (old == null) { // had "mix-over", replace b.method = m; // } else if (old.getDeclaringClass().isInterface() && !m.getDeclaringClass().isInterface()) { } else if (Modifier.isAbstract(old.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { // 06-Jan-2010, tatu: Except that if method we saw first is // from an interface, and we now find a non-interface definition, we should // use this method, but with combination of annotations. // This helps (or rather, is essential) with JAXB annotations and // may also result in faster method calls (interface calls are slightly // costlier than regular method calls) b.method = m; // 23-Aug-2017, tatu: [databind#1705] Also need to change the type resolution context if so // (note: mix-over case above shouldn't need it) b.typeContext = tc; } } } } protected void _addMethodMixIns(TypeResolutionContext tc, Class targetClass, Map methods, Class mixInCls) { if (_intr == null) { return; } for (Class mixin : ClassUtil.findRawSuperTypes(mixInCls, targetClass, true)) { for (Method m : ClassUtil.getDeclaredMethods(mixin)) { if (!_isIncludableMemberMethod(m)) { continue; } final MemberKey key = new MemberKey(m); MethodBuilder b = methods.get(key); Annotation[] anns = m.getDeclaredAnnotations(); if (b == null) { // nothing yet; add but do NOT specify method -- this marks it // as "mix-over", floating mix-in methods.put(key, new MethodBuilder(tc, null, collectAnnotations(anns))); } else { b.annotations = collectDefaultAnnotations(b.annotations, anns); } } } } private boolean _isIncludableMemberMethod(Method m) { if (Modifier.isStatic(m.getModifiers()) // Looks like generics can introduce hidden bridge and/or synthetic methods. // I don't think we want to consider those... || m.isSynthetic() || m.isBridge()) { return false; } // also, for now we have no use for methods with more than 2 arguments: // (2 argument methods for "any setter", fwtw) int pcount = m.getParameterTypes().length; return (pcount <= 2); } private final static class MethodBuilder { public TypeResolutionContext typeContext; // Method left empty for "floating" mix-in, filled in as need be public Method method; public AnnotationCollector annotations; public MethodBuilder(TypeResolutionContext tc, Method m, AnnotationCollector ann) { typeContext = tc; method = m; annotations = ann; } public AnnotatedMethod build() { if (method == null) { return null; } // 12-Apr-2017, tatu: Note that parameter annotations are NOT collected -- we could // collect them if that'd make sense but... return new AnnotatedMethod(typeContext, method, annotations.asAnnotationMap(), null); } } } AnnotatedMethodMap.java000066400000000000000000000027071325620701100372270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.Method; import java.util.*; /** * Simple helper class used to keep track of collection of * {@link AnnotatedMethod}s, accessible by lookup. Lookup * is usually needed for augmenting and overriding annotations. */ public final class AnnotatedMethodMap implements Iterable { protected Map _methods; public AnnotatedMethodMap() { } /** * @since 2.9 */ public AnnotatedMethodMap(Map m) { _methods = m; } public int size() { return (_methods == null) ? 0 : _methods.size(); } public AnnotatedMethod find(String name, Class[] paramTypes) { if (_methods == null) { return null; } return _methods.get(new MemberKey(name, paramTypes)); } public AnnotatedMethod find(Method m) { if (_methods == null) { return null; } return _methods.get(new MemberKey(m)); } /* /********************************************************** /* Iterable implementation (for iterating over values) /********************************************************** */ @Override public Iterator iterator() { if (_methods == null) { return Collections.emptyIterator(); } return _methods.values().iterator(); } } AnnotatedParameter.java000066400000000000000000000121021325620701100372570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Object that represents method parameters, mostly so that associated * annotations can be processed conveniently. Note that many of accessors * cannot return meaningful values since parameters do not have stand-alone * JDK objects associated; so access should mostly be limited to checking * annotation values which are properly aggregated and included. */ public final class AnnotatedParameter extends AnnotatedMember { private static final long serialVersionUID = 1L; /** * Member (method, constructor) that this parameter belongs to */ protected final AnnotatedWithParams _owner; /** * JDK type of the parameter, possibly contains generic type information */ protected final JavaType _type; /** * Index of the parameter within argument list */ protected final int _index; /* /********************************************************** /* Life-cycle /********************************************************** */ public AnnotatedParameter(AnnotatedWithParams owner, JavaType type, TypeResolutionContext typeContext, AnnotationMap annotations, int index) { super(typeContext, annotations); _owner = owner; _type = type; _index = index; } @Override public AnnotatedParameter withAnnotations(AnnotationMap ann) { if (ann == _annotations) { return this; } return _owner.replaceParameterAnnotations(_index, ann); } /* /********************************************************** /* Annotated impl /********************************************************** */ /** * Since there is no matching JDK element, this method will * always return null */ @Override public AnnotatedElement getAnnotated() { return null; } /** * Returns modifiers of the constructor, as parameters do not * have independent modifiers. */ @Override public int getModifiers() { return _owner.getModifiers(); } /** * Parameters have no names in bytecode (unlike in source code), * will always return empty String (""). */ @Override public String getName() { return ""; } @Override public Class getRawType() { return _type.getRawClass(); } @Override public JavaType getType() { return _type; } @Deprecated @Override public Type getGenericType() { return _owner.getGenericParameterType(_index); } /* /********************************************************** /* AnnotatedMember extras /********************************************************** */ @Override public Class getDeclaringClass() { return _owner.getDeclaringClass(); } @Override public Member getMember() { /* This is bit tricky: since there is no JDK equivalent; can either * return null or owner... let's do latter, for now. */ return _owner.getMember(); } @Override public void setValue(Object pojo, Object value) throws UnsupportedOperationException { throw new UnsupportedOperationException("Cannot call setValue() on constructor parameter of " +getDeclaringClass().getName()); } @Override public Object getValue(Object pojo) throws UnsupportedOperationException { throw new UnsupportedOperationException("Cannot call getValue() on constructor parameter of " +getDeclaringClass().getName()); } /* /********************************************************** /* Extended API /********************************************************** */ public Type getParameterType() { return _type; } /** * Accessor for 'owner' of this parameter; method or constructor that * has this parameter as member of its argument list. * * @return Owner (member or creator) object of this parameter */ public AnnotatedWithParams getOwner() { return _owner; } /** * Accessor for index of this parameter within argument list * * @return Index of this parameter within argument list */ public int getIndex() { return _index; } /* /******************************************************** /* Other /******************************************************** */ @Override public int hashCode() { return _owner.hashCode() + _index; } @Override public boolean equals(Object o) { if (o == this) return true; if (!ClassUtil.hasClass(o, getClass())) { return false; } AnnotatedParameter other = (AnnotatedParameter) o; return other._owner.equals(_owner) && (other._index == _index); } @Override public String toString() { return "[parameter #"+getIndex()+", annotations: "+_annotations+"]"; } } AnnotatedWithParams.java000066400000000000000000000103541325620701100374250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import com.fasterxml.jackson.databind.JavaType; /** * Intermediate base class that encapsulates features that * constructors and methods share. */ public abstract class AnnotatedWithParams extends AnnotatedMember { private static final long serialVersionUID = 1L; /** * Annotations associated with parameters of the annotated * entity (method or constructor parameters) */ protected final AnnotationMap[] _paramAnnotations; /* /********************************************************** /* Life-cycle /********************************************************** */ protected AnnotatedWithParams(TypeResolutionContext ctxt, AnnotationMap annotations, AnnotationMap[] paramAnnotations) { super(ctxt, annotations); _paramAnnotations = paramAnnotations; } /** * @since 2.8.1 */ protected AnnotatedWithParams(AnnotatedWithParams base, AnnotationMap[] paramAnnotations) { super(base); _paramAnnotations = paramAnnotations; } /** * Method called to override a method parameter annotation, * usually due to a mix-in * annotation masking or overriding an annotation 'real' method * has. */ public final void addOrOverrideParam(int paramIndex, Annotation a) { AnnotationMap old = _paramAnnotations[paramIndex]; if (old == null) { old = new AnnotationMap(); _paramAnnotations[paramIndex] = old; } old.add(a); } /** * Method called by parameter object when an augmented instance is created; * needs to replace parameter with new instance */ protected AnnotatedParameter replaceParameterAnnotations(int index, AnnotationMap ann) { _paramAnnotations[index] = ann; return getParameter(index); } /* /********************************************************** /* Extended API /********************************************************** */ public final AnnotationMap getParameterAnnotations(int index) { if (_paramAnnotations != null) { if (index >= 0 && index < _paramAnnotations.length) { return _paramAnnotations[index]; } } return null; } public final AnnotatedParameter getParameter(int index) { return new AnnotatedParameter(this, getParameterType(index), _typeContext, getParameterAnnotations(index), index); } public abstract int getParameterCount(); public abstract Class getRawParameterType(int index); /** * @since 2.7 */ public abstract JavaType getParameterType(int index); /** * @deprecated Since 2.7, remove in 2.9 */ @Deprecated public abstract Type getGenericParameterType(int index); public final int getAnnotationCount() { return _annotations.size(); } /** * Method that can be used to (try to) call this object without arguments. * This may succeed or fail, depending on expected number * of arguments: caller needs to take care to pass correct number. * Exceptions are thrown directly from actual low-level call. *

* Note: only works for constructors and static methods. */ public abstract Object call() throws Exception; /** * Method that can be used to (try to) call this object with specified arguments. * This may succeed or fail, depending on expected number * of arguments: caller needs to take care to pass correct number. * Exceptions are thrown directly from actual low-level call. *

* Note: only works for constructors and static methods. */ public abstract Object call(Object[] args) throws Exception; /** * Method that can be used to (try to) call this object with single arguments. * This may succeed or fail, depending on expected number * of arguments: caller needs to take care to pass correct number. * Exceptions are thrown directly from actual low-level call. *

* Note: only works for constructors and static methods. */ public abstract Object call1(Object arg) throws Exception; } AnnotationCollector.java000066400000000000000000000201241325620701100374650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import com.fasterxml.jackson.databind.util.Annotations; /** * Helper class used to collect annotations to be stored as * {@link com.fasterxml.jackson.databind.util.Annotations} (like {@link AnnotationMap}). * * @since 2.9 */ public abstract class AnnotationCollector { protected final static Annotations NO_ANNOTATIONS = new NoAnnotations(); /** * Optional data to carry along */ protected final Object _data; protected AnnotationCollector(Object d) { _data = d; } public static Annotations emptyAnnotations() { return NO_ANNOTATIONS; } public static AnnotationCollector emptyCollector() { return EmptyCollector.instance; } public static AnnotationCollector emptyCollector(Object data) { return new EmptyCollector(data); } public abstract Annotations asAnnotations(); public abstract AnnotationMap asAnnotationMap(); public Object getData() { return _data; } /* /********************************************************** /* API /********************************************************** */ public abstract boolean isPresent(Annotation ann); public abstract AnnotationCollector addOrOverride(Annotation ann); /* /********************************************************** /* Collector implementations /********************************************************** */ static class EmptyCollector extends AnnotationCollector { public final static EmptyCollector instance = new EmptyCollector(null); EmptyCollector(Object data) { super(data); } @Override public Annotations asAnnotations() { return NO_ANNOTATIONS; } @Override public AnnotationMap asAnnotationMap() { return new AnnotationMap(); } @Override public boolean isPresent(Annotation ann) { return false; } @Override public AnnotationCollector addOrOverride(Annotation ann) { return new OneCollector(_data, ann.annotationType(), ann); } } static class OneCollector extends AnnotationCollector { private Class _type; private Annotation _value; public OneCollector(Object data, Class type, Annotation value) { super(data); _type = type; _value = value; } @Override public Annotations asAnnotations() { return new OneAnnotation(_type, _value); } @Override public AnnotationMap asAnnotationMap() { return AnnotationMap.of(_type, _value); } @Override public boolean isPresent(Annotation ann) { return ann.annotationType() == _type; } @Override public AnnotationCollector addOrOverride(Annotation ann) { final Class type = ann.annotationType(); // true override? Just replace in-place, return if (_type == type) { _value = ann; return this; } return new NCollector(_data, _type, _value, type, ann); } } static class NCollector extends AnnotationCollector { protected final HashMap,Annotation> _annotations; public NCollector(Object data, Class type1, Annotation value1, Class type2, Annotation value2) { super(data); _annotations = new HashMap<>(); _annotations.put(type1, value1); _annotations.put(type2, value2); } @Override public Annotations asAnnotations() { if (_annotations.size() == 2) { Iterator,Annotation>> it = _annotations.entrySet().iterator(); Map.Entry,Annotation> en1 = it.next(), en2 = it.next(); return new TwoAnnotations(en1.getKey(), en1.getValue(), en2.getKey(), en2.getValue()); } return new AnnotationMap(_annotations); } @Override public AnnotationMap asAnnotationMap() { AnnotationMap result = new AnnotationMap(); for (Annotation ann : _annotations.values()) { result.add(ann); } return result; } @Override public boolean isPresent(Annotation ann) { return _annotations.containsKey(ann.annotationType()); } @Override public AnnotationCollector addOrOverride(Annotation ann) { _annotations.put(ann.annotationType(), ann); return this; } } /* /********************************************************** /* Annotations implementations /********************************************************** */ /** * Immutable implementation for case where no annotations are associated with * an annotatable entity. * * @since 2.9 */ public static class NoAnnotations implements Annotations, java.io.Serializable { private static final long serialVersionUID = 1L; NoAnnotations() { } @Override public A get(Class cls) { return null; } @Override public boolean has(Class cls) { return false; } @Override public boolean hasOneOf(Class[] annoClasses) { return false; } @Override public int size() { return 0; } } public static class OneAnnotation implements Annotations, java.io.Serializable { private static final long serialVersionUID = 1L; private final Class _type; private final Annotation _value; public OneAnnotation(Class type, Annotation value) { _type = type; _value = value; } @SuppressWarnings("unchecked") @Override public A get(Class cls) { if (_type == cls) { return (A) _value; } return null; } @Override public boolean has(Class cls) { return (_type == cls); } @Override public boolean hasOneOf(Class[] annoClasses) { for (Class cls : annoClasses) { if (cls == _type) { return true; } } return false; } @Override public int size() { return 1; } } public static class TwoAnnotations implements Annotations, java.io.Serializable { private static final long serialVersionUID = 1L; private final Class _type1, _type2; private final Annotation _value1, _value2; public TwoAnnotations(Class type1, Annotation value1, Class type2, Annotation value2) { _type1 = type1; _value1 = value1; _type2 = type2; _value2 = value2; } @SuppressWarnings("unchecked") @Override public A get(Class cls) { if (_type1 == cls) { return (A) _value1; } if (_type2 == cls) { return (A) _value2; } return null; } @Override public boolean has(Class cls) { return (_type1 == cls) || (_type2 == cls); } @Override public boolean hasOneOf(Class[] annoClasses) { for (Class cls : annoClasses) { if ((cls == _type1) || (cls == _type2)) { return true; } } return false; } @Override public int size() { return 2; } } } AnnotationIntrospectorPair.java000066400000000000000000000674371325620701100410700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.fasterxml.jackson.annotation.JacksonInject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Helper class that allows using 2 introspectors such that one * introspector acts as the primary one to use; and second one * as a fallback used if the primary does not provide conclusive * or useful result for a method. *

* An obvious consequence of priority is that it is easy to construct * longer chains of introspectors by linking multiple pairs. * Currently most likely combination is that of using the default * Jackson provider, along with JAXB annotation introspector. *

* Note: up until 2.0, this class was an inner class of * {@link AnnotationIntrospector}; moved here for convenience. * * @since 2.1 */ public class AnnotationIntrospectorPair extends AnnotationIntrospector implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final AnnotationIntrospector _primary, _secondary; public AnnotationIntrospectorPair(AnnotationIntrospector p, AnnotationIntrospector s) { _primary = p; _secondary = s; } @Override public Version version() { return _primary.version(); } /** * Helper method for constructing a Pair from two given introspectors (if * neither is null); or returning non-null introspector if one is null * (and return just null if both are null) */ public static AnnotationIntrospector create(AnnotationIntrospector primary, AnnotationIntrospector secondary) { if (primary == null) { return secondary; } if (secondary == null) { return primary; } return new AnnotationIntrospectorPair(primary, secondary); } @Override public Collection allIntrospectors() { return allIntrospectors(new ArrayList()); } @Override public Collection allIntrospectors(Collection result) { _primary.allIntrospectors(result); _secondary.allIntrospectors(result); return result; } // // // Generic annotation properties, lookup @Override public boolean isAnnotationBundle(Annotation ann) { return _primary.isAnnotationBundle(ann) || _secondary.isAnnotationBundle(ann); } /* /****************************************************** /* General class annotations /****************************************************** */ @Override public PropertyName findRootName(AnnotatedClass ac) { PropertyName name1 = _primary.findRootName(ac); if (name1 == null) { return _secondary.findRootName(ac); } if (name1.hasSimpleName()) { return name1; } // name1 is empty; how about secondary? PropertyName name2 = _secondary.findRootName(ac); return (name2 == null) ? name1 : name2; } @Override public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated a) { JsonIgnoreProperties.Value v2 = _secondary.findPropertyIgnorals(a); JsonIgnoreProperties.Value v1 = _primary.findPropertyIgnorals(a); return (v2 == null) // shouldn't occur but ? v1 : v2.withOverrides(v1); } @Override public Boolean isIgnorableType(AnnotatedClass ac) { Boolean result = _primary.isIgnorableType(ac); if (result == null) { result = _secondary.isIgnorableType(ac); } return result; } @Override public Object findFilterId(Annotated ann) { Object id = _primary.findFilterId(ann); if (id == null) { id = _secondary.findFilterId(ann); } return id; } @Override public Object findNamingStrategy(AnnotatedClass ac) { Object str = _primary.findNamingStrategy(ac); if (str == null) { str = _secondary.findNamingStrategy(ac); } return str; } @Override public String findClassDescription(AnnotatedClass ac) { String str = _primary.findClassDescription(ac); if ((str == null) || str.isEmpty()) { str = _secondary.findClassDescription(ac); } return str; } @Override @Deprecated // since 2.6 public String[] findPropertiesToIgnore(Annotated ac) { String[] result = _primary.findPropertiesToIgnore(ac); if (result == null) { result = _secondary.findPropertiesToIgnore(ac); } return result; } @Override @Deprecated // since 2.8 public String[] findPropertiesToIgnore(Annotated ac, boolean forSerialization) { String[] result = _primary.findPropertiesToIgnore(ac, forSerialization); if (result == null) { result = _secondary.findPropertiesToIgnore(ac, forSerialization); } return result; } @Override @Deprecated // since 2.8 public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) { Boolean result = _primary.findIgnoreUnknownProperties(ac); if (result == null) { result = _secondary.findIgnoreUnknownProperties(ac); } return result; } /* /****************************************************** /* Property auto-detection /****************************************************** */ @Override public VisibilityChecker findAutoDetectVisibility(AnnotatedClass ac, VisibilityChecker checker) { /* Note: to have proper priorities, we must actually call delegatees * in reverse order: */ checker = _secondary.findAutoDetectVisibility(ac, checker); return _primary.findAutoDetectVisibility(ac, checker); } /* /****************************************************** /* Type handling /****************************************************** */ @Override public TypeResolverBuilder findTypeResolver(MapperConfig config, AnnotatedClass ac, JavaType baseType) { TypeResolverBuilder b = _primary.findTypeResolver(config, ac, baseType); if (b == null) { b = _secondary.findTypeResolver(config, ac, baseType); } return b; } @Override public TypeResolverBuilder findPropertyTypeResolver(MapperConfig config, AnnotatedMember am, JavaType baseType) { TypeResolverBuilder b = _primary.findPropertyTypeResolver(config, am, baseType); if (b == null) { b = _secondary.findPropertyTypeResolver(config, am, baseType); } return b; } @Override public TypeResolverBuilder findPropertyContentTypeResolver(MapperConfig config, AnnotatedMember am, JavaType baseType) { TypeResolverBuilder b = _primary.findPropertyContentTypeResolver(config, am, baseType); if (b == null) { b = _secondary.findPropertyContentTypeResolver(config, am, baseType); } return b; } @Override public List findSubtypes(Annotated a) { List types1 = _primary.findSubtypes(a); List types2 = _secondary.findSubtypes(a); if (types1 == null || types1.isEmpty()) return types2; if (types2 == null || types2.isEmpty()) return types1; ArrayList result = new ArrayList(types1.size() + types2.size()); result.addAll(types1); result.addAll(types2); return result; } @Override public String findTypeName(AnnotatedClass ac) { String name = _primary.findTypeName(ac); if (name == null || name.length() == 0) { name = _secondary.findTypeName(ac); } return name; } /* /****************************************************** /* General member (field, method/constructor) annotations /****************************************************** */ @Override public ReferenceProperty findReferenceType(AnnotatedMember member) { ReferenceProperty r = _primary.findReferenceType(member); return (r == null) ? _secondary.findReferenceType(member) : r; } @Override public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member) { NameTransformer r = _primary.findUnwrappingNameTransformer(member); return (r == null) ? _secondary.findUnwrappingNameTransformer(member) : r; } @Override public JacksonInject.Value findInjectableValue(AnnotatedMember m) { JacksonInject.Value r = _primary.findInjectableValue(m); return (r == null) ? _secondary.findInjectableValue(m) : r; } @Override public boolean hasIgnoreMarker(AnnotatedMember m) { return _primary.hasIgnoreMarker(m) || _secondary.hasIgnoreMarker(m); } @Override public Boolean hasRequiredMarker(AnnotatedMember m) { Boolean r = _primary.hasRequiredMarker(m); return (r == null) ? _secondary.hasRequiredMarker(m) : r; } @Override @Deprecated // since 2.9 public Object findInjectableValueId(AnnotatedMember m) { Object r = _primary.findInjectableValueId(m); return (r == null) ? _secondary.findInjectableValueId(m) : r; } // // // Serialization: general annotations @Override public Object findSerializer(Annotated am) { Object r = _primary.findSerializer(am); if (_isExplicitClassOrOb(r, JsonSerializer.None.class)) { return r; } return _explicitClassOrOb(_secondary.findSerializer(am), JsonSerializer.None.class); } @Override public Object findKeySerializer(Annotated a) { Object r = _primary.findKeySerializer(a); if (_isExplicitClassOrOb(r, JsonSerializer.None.class)) { return r; } return _explicitClassOrOb(_secondary.findKeySerializer(a), JsonSerializer.None.class); } @Override public Object findContentSerializer(Annotated a) { Object r = _primary.findContentSerializer(a); if (_isExplicitClassOrOb(r, JsonSerializer.None.class)) { return r; } return _explicitClassOrOb(_secondary.findContentSerializer(a), JsonSerializer.None.class); } @Override public Object findNullSerializer(Annotated a) { Object r = _primary.findNullSerializer(a); if (_isExplicitClassOrOb(r, JsonSerializer.None.class)) { return r; } return _explicitClassOrOb(_secondary.findNullSerializer(a), JsonSerializer.None.class); } @Deprecated @Override public JsonInclude.Include findSerializationInclusion(Annotated a, JsonInclude.Include defValue) { // note: call secondary first, to give lower priority defValue = _secondary.findSerializationInclusion(a, defValue); defValue = _primary.findSerializationInclusion(a, defValue); return defValue; } @Deprecated @Override public JsonInclude.Include findSerializationInclusionForContent(Annotated a, JsonInclude.Include defValue) { // note: call secondary first, to give lower priority defValue = _secondary.findSerializationInclusionForContent(a, defValue); defValue = _primary.findSerializationInclusionForContent(a, defValue); return defValue; } @Override public JsonInclude.Value findPropertyInclusion(Annotated a) { JsonInclude.Value v2 = _secondary.findPropertyInclusion(a); JsonInclude.Value v1 = _primary.findPropertyInclusion(a); if (v2 == null) { // shouldn't occur but return v1; } return v2.withOverrides(v1); } @Override public JsonSerialize.Typing findSerializationTyping(Annotated a) { JsonSerialize.Typing r = _primary.findSerializationTyping(a); return (r == null) ? _secondary.findSerializationTyping(a) : r; } @Override public Object findSerializationConverter(Annotated a) { Object r = _primary.findSerializationConverter(a); return (r == null) ? _secondary.findSerializationConverter(a) : r; } @Override public Object findSerializationContentConverter(AnnotatedMember a) { Object r = _primary.findSerializationContentConverter(a); return (r == null) ? _secondary.findSerializationContentConverter(a) : r; } @Override public Class[] findViews(Annotated a) { /* Theoretically this could be trickier, if multiple introspectors * return non-null entries. For now, though, we'll just consider * first one to return non-null to win. */ Class[] result = _primary.findViews(a); if (result == null) { result = _secondary.findViews(a); } return result; } @Override public Boolean isTypeId(AnnotatedMember member) { Boolean b = _primary.isTypeId(member); return (b == null) ? _secondary.isTypeId(member) : b; } @Override public ObjectIdInfo findObjectIdInfo(Annotated ann) { ObjectIdInfo r = _primary.findObjectIdInfo(ann); return (r == null) ? _secondary.findObjectIdInfo(ann) : r; } @Override public ObjectIdInfo findObjectReferenceInfo(Annotated ann, ObjectIdInfo objectIdInfo) { // to give precedence for primary, must start with secondary: objectIdInfo = _secondary.findObjectReferenceInfo(ann, objectIdInfo); objectIdInfo = _primary.findObjectReferenceInfo(ann, objectIdInfo); return objectIdInfo; } @Override public JsonFormat.Value findFormat(Annotated ann) { JsonFormat.Value v1 = _primary.findFormat(ann); JsonFormat.Value v2 = _secondary.findFormat(ann); if (v2 == null) { // shouldn't occur but just in case return v1; } return v2.withOverrides(v1); } @Override public PropertyName findWrapperName(Annotated ann) { PropertyName name = _primary.findWrapperName(ann); if (name == null) { name = _secondary.findWrapperName(ann); } else if (name == PropertyName.USE_DEFAULT) { // does the other introspector have a better idea? PropertyName name2 = _secondary.findWrapperName(ann); if (name2 != null) { name = name2; } } return name; } @Override public String findPropertyDefaultValue(Annotated ann) { String str = _primary.findPropertyDefaultValue(ann); return (str == null || str.isEmpty()) ? _secondary.findPropertyDefaultValue(ann) : str; } @Override public String findPropertyDescription(Annotated ann) { String r = _primary.findPropertyDescription(ann); return (r == null) ? _secondary.findPropertyDescription(ann) : r; } @Override public Integer findPropertyIndex(Annotated ann) { Integer r = _primary.findPropertyIndex(ann); return (r == null) ? _secondary.findPropertyIndex(ann) : r; } @Override public String findImplicitPropertyName(AnnotatedMember ann) { String r = _primary.findImplicitPropertyName(ann); return (r == null) ? _secondary.findImplicitPropertyName(ann) : r; } @Override public List findPropertyAliases(Annotated ann) { List r = _primary.findPropertyAliases(ann); return (r == null) ? _secondary.findPropertyAliases(ann) : r; } @Override public JsonProperty.Access findPropertyAccess(Annotated ann) { JsonProperty.Access acc = _primary.findPropertyAccess(ann); if ((acc != null) && (acc != JsonProperty.Access.AUTO)) { return acc; } acc = _secondary.findPropertyAccess(ann); if (acc != null) { return acc; } return JsonProperty.Access.AUTO; } @Override // since 2.7 public AnnotatedMethod resolveSetterConflict(MapperConfig config, AnnotatedMethod setter1, AnnotatedMethod setter2) { AnnotatedMethod res = _primary.resolveSetterConflict(config, setter1, setter2); if (res == null) { res = _secondary.resolveSetterConflict(config, setter1, setter2); } return res; } // // // Serialization: type refinements @Override // since 2.7 public JavaType refineSerializationType(MapperConfig config, Annotated a, JavaType baseType) throws JsonMappingException { JavaType t = _secondary.refineSerializationType(config, a, baseType); return _primary.refineSerializationType(config, a, t); } @Override @Deprecated public Class findSerializationType(Annotated a) { Class r = _primary.findSerializationType(a); return (r == null) ? _secondary.findSerializationType(a) : r; } @Override @Deprecated public Class findSerializationKeyType(Annotated am, JavaType baseType) { Class r = _primary.findSerializationKeyType(am, baseType); return (r == null) ? _secondary.findSerializationKeyType(am, baseType) : r; } @Override @Deprecated public Class findSerializationContentType(Annotated am, JavaType baseType) { Class r = _primary.findSerializationContentType(am, baseType); return (r == null) ? _secondary.findSerializationContentType(am, baseType) : r; } // // // Serialization: class annotations @Override public String[] findSerializationPropertyOrder(AnnotatedClass ac) { String[] r = _primary.findSerializationPropertyOrder(ac); return (r == null) ? _secondary.findSerializationPropertyOrder(ac) : r; } @Override public Boolean findSerializationSortAlphabetically(Annotated ann) { Boolean r = _primary.findSerializationSortAlphabetically(ann); return (r == null) ? _secondary.findSerializationSortAlphabetically(ann) : r; } @Override public void findAndAddVirtualProperties(MapperConfig config, AnnotatedClass ac, List properties) { // first secondary, then primary, to give proper precedence _primary.findAndAddVirtualProperties(config, ac, properties); _secondary.findAndAddVirtualProperties(config, ac, properties); } // // // Serialization: property annotations @Override public PropertyName findNameForSerialization(Annotated a) { PropertyName n = _primary.findNameForSerialization(a); // note: "use default" should not block explicit answer, so: if (n == null) { n = _secondary.findNameForSerialization(a); } else if (n == PropertyName.USE_DEFAULT) { PropertyName n2 = _secondary.findNameForSerialization(a); if (n2 != null) { n = n2; } } return n; } @Override public Boolean hasAsValue(Annotated a) { Boolean b = _primary.hasAsValue(a); if (b == null) { b = _secondary.hasAsValue(a); } return b; } @Override public Boolean hasAnyGetter(Annotated a) { Boolean b = _primary.hasAnyGetter(a); if (b == null) { b = _secondary.hasAnyGetter(a); } return b; } @Override public String[] findEnumValues(Class enumType, Enum[] enumValues, String[] names) { // reverse order to give _primary higher precedence names = _secondary.findEnumValues(enumType, enumValues, names); names = _primary.findEnumValues(enumType, enumValues, names); return names; } @Override public Enum findDefaultEnumValue(Class> enumCls) { Enum en = _primary.findDefaultEnumValue(enumCls); return (en == null) ? _secondary.findDefaultEnumValue(enumCls) : en; } @Override @Deprecated // since 2.8 public String findEnumValue(Enum value) { String r = _primary.findEnumValue(value); return (r == null) ? _secondary.findEnumValue(value) : r; } @Override @Deprecated // since 2.9 public boolean hasAsValueAnnotation(AnnotatedMethod am) { return _primary.hasAsValueAnnotation(am) || _secondary.hasAsValueAnnotation(am); } @Override @Deprecated // since 2.9 public boolean hasAnyGetterAnnotation(AnnotatedMethod am) { return _primary.hasAnyGetterAnnotation(am) || _secondary.hasAnyGetterAnnotation(am); } // // // Deserialization: general annotations @Override public Object findDeserializer(Annotated a) { Object r = _primary.findDeserializer(a); if (_isExplicitClassOrOb(r, JsonDeserializer.None.class)) { return r; } return _explicitClassOrOb(_secondary.findDeserializer(a), JsonDeserializer.None.class); } @Override public Object findKeyDeserializer(Annotated a) { Object r = _primary.findKeyDeserializer(a); if (_isExplicitClassOrOb(r, KeyDeserializer.None.class)) { return r; } return _explicitClassOrOb(_secondary.findKeyDeserializer(a), KeyDeserializer.None.class); } @Override public Object findContentDeserializer(Annotated am) { Object r = _primary.findContentDeserializer(am); if (_isExplicitClassOrOb(r, JsonDeserializer.None.class)) { return r; } return _explicitClassOrOb(_secondary.findContentDeserializer(am), JsonDeserializer.None.class); } @Override public Object findDeserializationConverter(Annotated a) { Object ob = _primary.findDeserializationConverter(a); return (ob == null) ? _secondary.findDeserializationConverter(a) : ob; } @Override public Object findDeserializationContentConverter(AnnotatedMember a) { Object ob = _primary.findDeserializationContentConverter(a); return (ob == null) ? _secondary.findDeserializationContentConverter(a) : ob; } // // // Deserialization: type refinements // since 2.7 @Override public JavaType refineDeserializationType(MapperConfig config, Annotated a, JavaType baseType) throws JsonMappingException { JavaType t = _secondary.refineDeserializationType(config, a, baseType); return _primary.refineDeserializationType(config, a, t); } @Override @Deprecated public Class findDeserializationType(Annotated am, JavaType baseType) { Class r = _primary.findDeserializationType(am, baseType); return (r != null) ? r : _secondary.findDeserializationType(am, baseType); } @Override @Deprecated public Class findDeserializationKeyType(Annotated am, JavaType baseKeyType) { Class result = _primary.findDeserializationKeyType(am, baseKeyType); return (result == null) ? _secondary.findDeserializationKeyType(am, baseKeyType) : result; } @Override @Deprecated public Class findDeserializationContentType(Annotated am, JavaType baseContentType) { Class result = _primary.findDeserializationContentType(am, baseContentType); return (result == null) ? _secondary.findDeserializationContentType(am, baseContentType) : result; } // // // Deserialization: class annotations @Override public Object findValueInstantiator(AnnotatedClass ac) { Object result = _primary.findValueInstantiator(ac); return (result == null) ? _secondary.findValueInstantiator(ac) : result; } @Override public Class findPOJOBuilder(AnnotatedClass ac) { Class result = _primary.findPOJOBuilder(ac); return (result == null) ? _secondary.findPOJOBuilder(ac) : result; } @Override public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) { JsonPOJOBuilder.Value result = _primary.findPOJOBuilderConfig(ac); return (result == null) ? _secondary.findPOJOBuilderConfig(ac) : result; } // // // Deserialization: method annotations @Override public PropertyName findNameForDeserialization(Annotated a) { // note: "use default" should not block explicit answer, so: PropertyName n = _primary.findNameForDeserialization(a); if (n == null) { n = _secondary.findNameForDeserialization(a); } else if (n == PropertyName.USE_DEFAULT) { PropertyName n2 = _secondary.findNameForDeserialization(a); if (n2 != null) { n = n2; } } return n; } @Override public Boolean hasAnySetter(Annotated a) { Boolean b = _primary.hasAnySetter(a); if (b == null) { b = _secondary.hasAnySetter(a); } return b; } @Override public JsonSetter.Value findSetterInfo(Annotated a) { JsonSetter.Value v2 = _secondary.findSetterInfo(a); JsonSetter.Value v1 = _primary.findSetterInfo(a); return (v2 == null) // shouldn't occur but ? v1 : v2.withOverrides(v1); } @Override // since 2.9 public Boolean findMergeInfo(Annotated a) { Boolean b = _primary.findMergeInfo(a); if (b == null) { b = _secondary.findMergeInfo(a); } return b; } @Override @Deprecated // since 2.9 public boolean hasCreatorAnnotation(Annotated a) { return _primary.hasCreatorAnnotation(a) || _secondary.hasCreatorAnnotation(a); } @Override @Deprecated // since 2.9 public JsonCreator.Mode findCreatorBinding(Annotated a) { JsonCreator.Mode mode = _primary.findCreatorBinding(a); if (mode != null) { return mode; } return _secondary.findCreatorBinding(a); } @Override public JsonCreator.Mode findCreatorAnnotation(MapperConfig config, Annotated a) { JsonCreator.Mode mode = _primary.findCreatorAnnotation(config, a); return (mode == null) ? _secondary.findCreatorAnnotation(config, a) : mode; } @Override @Deprecated // since 2.9 public boolean hasAnySetterAnnotation(AnnotatedMethod am) { return _primary.hasAnySetterAnnotation(am) || _secondary.hasAnySetterAnnotation(am); } protected boolean _isExplicitClassOrOb(Object maybeCls, Class implicit) { if ((maybeCls == null) || (maybeCls == implicit)) { return false; } if (maybeCls instanceof Class) { return !ClassUtil.isBogusClass((Class) maybeCls); } return true; } // @since 2.9 protected Object _explicitClassOrOb(Object maybeCls, Class implicit) { if ((maybeCls == null) || (maybeCls == implicit)) { return null; } if ((maybeCls instanceof Class) && ClassUtil.isBogusClass((Class) maybeCls)) { return null; } return maybeCls; } } AnnotationMap.java000066400000000000000000000110101325620701100362460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.util.*; import com.fasterxml.jackson.databind.util.Annotations; /** * Simple helper class used to keep track of collection of * Jackson Annotations associated with annotatable things * (methods, constructors, classes). * Note that only Jackson-owned annotations are tracked (for now?). */ public final class AnnotationMap implements Annotations { protected HashMap,Annotation> _annotations; public AnnotationMap() { } public static AnnotationMap of(Class type, Annotation value) { HashMap,Annotation> ann = new HashMap<>(4); ann.put(type, value); return new AnnotationMap(ann); } AnnotationMap(HashMap,Annotation> a) { _annotations = a; } /* /********************************************************** /* Annotations impl /********************************************************** */ @SuppressWarnings("unchecked") @Override public A get(Class cls) { if (_annotations == null) { return null; } return (A) _annotations.get(cls); } @Override public boolean has(Class cls) { if (_annotations == null) { return false; } return _annotations.containsKey(cls); } /** * Helper method that can be used for a "bulk" check to see if at least * one of given annotation types is included within this map. * * @since 2.7 */ @Override public boolean hasOneOf(Class[] annoClasses) { if (_annotations != null) { for (int i = 0, end = annoClasses.length; i < end; ++i) { if (_annotations.containsKey(annoClasses[i])) { return true; } } } return false; } /* /********************************************************** /* Other API /********************************************************** */ /** * @since 2.3 */ public Iterable annotations() { if (_annotations == null || _annotations.size() == 0) { return Collections.emptyList(); } return _annotations.values(); } public static AnnotationMap merge(AnnotationMap primary, AnnotationMap secondary) { if (primary == null || primary._annotations == null || primary._annotations.isEmpty()) { return secondary; } if (secondary == null || secondary._annotations == null || secondary._annotations.isEmpty()) { return primary; } HashMap,Annotation> annotations = new HashMap,Annotation>(); // add secondary ones first for (Annotation ann : secondary._annotations.values()) { annotations.put(ann.annotationType(), ann); } // to be overridden by primary ones for (Annotation ann : primary._annotations.values()) { annotations.put(ann.annotationType(), ann); } return new AnnotationMap(annotations); } @Override public int size() { return (_annotations == null) ? 0 : _annotations.size(); } /** * Method called to add specified annotation in the Map, but * only if it didn't yet exist. */ public boolean addIfNotPresent(Annotation ann) { if (_annotations == null || !_annotations.containsKey(ann.annotationType())) { _add(ann); return true; } return false; } /** * Method called to add specified annotation in the Map. * * @return True if the addition changed the contents, that is, this map did not * already have specified annotation */ public boolean add(Annotation ann) { return _add(ann); } @Override public String toString() { if (_annotations == null) { return "[null]"; } return _annotations.toString(); } /* /********************************************************** /* Helper methods /********************************************************** */ protected final boolean _add(Annotation ann) { if (_annotations == null) { _annotations = new HashMap,Annotation>(); } Annotation previous = _annotations.put(ann.annotationType(), ann); return (previous == null) || !previous.equals(ann); } } BasicBeanDescription.java000066400000000000000000000622071325620701100375270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.type.TypeBindings; import com.fasterxml.jackson.databind.util.Annotations; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.Converter; /** * Default {@link BeanDescription} implementation used by Jackson. *

* Although sub-classing is a theoretical possibility there are no known * use cases for that, nor is such usage tested or supported. * Separation from API is mostly to isolate some implementation details * here and keep API simple. */ public class BasicBeanDescription extends BeanDescription { // since 2.9 private final static Class[] NO_VIEWS = new Class[0]; /* /********************************************************** /* General configuration /********************************************************** */ /** * We will hold a reference to the collector in cases where * information is lazily accessed and constructed; properties * are only accessed when they are actually needed. */ final protected POJOPropertiesCollector _propCollector; final protected MapperConfig _config; final protected AnnotationIntrospector _annotationIntrospector; /* /********************************************************** /* Information about type itself /********************************************************** */ /** * Information collected about the class introspected. */ final protected AnnotatedClass _classInfo; /** * @since 2.9 */ protected Class[] _defaultViews; /** * @since 2.9 */ protected boolean _defaultViewsResolved; /* /********************************************************** /* Member information /********************************************************** */ /** * Properties collected for the POJO; initialized as needed. */ protected List _properties; /** * Details of Object Id to include, if any */ protected ObjectIdInfo _objectIdInfo; /* /********************************************************** /* Life-cycle /********************************************************** */ protected BasicBeanDescription(POJOPropertiesCollector coll, JavaType type, AnnotatedClass classDef) { super(type); _propCollector = coll; _config = coll.getConfig(); // NOTE: null config only for some pre-constructed types if (_config == null) { _annotationIntrospector = null; } else { _annotationIntrospector = _config.getAnnotationIntrospector(); } _classInfo = classDef; } /** * Alternate constructor used in cases where property information is not needed, * only class info. */ protected BasicBeanDescription(MapperConfig config, JavaType type, AnnotatedClass classDef, List props) { super(type); _propCollector = null; _config = config; // NOTE: null config only for some pre-constructed types if (_config == null) { _annotationIntrospector = null; } else { _annotationIntrospector = _config.getAnnotationIntrospector(); } _classInfo = classDef; _properties = props; } protected BasicBeanDescription(POJOPropertiesCollector coll) { this(coll, coll.getType(), coll.getClassDef()); _objectIdInfo = coll.getObjectIdInfo(); } /** * Factory method to use for constructing an instance to use for building * deserializers. */ public static BasicBeanDescription forDeserialization(POJOPropertiesCollector coll) { return new BasicBeanDescription(coll); } /** * Factory method to use for constructing an instance to use for building * serializers. */ public static BasicBeanDescription forSerialization(POJOPropertiesCollector coll) { return new BasicBeanDescription(coll); } /** * Factory method to use for constructing an instance to use for purposes * other than building serializers or deserializers; will only have information * on class, not on properties. */ public static BasicBeanDescription forOtherUse(MapperConfig config, JavaType type, AnnotatedClass ac) { return new BasicBeanDescription(config, type, ac, Collections.emptyList()); } protected List _properties() { if (_properties == null) { _properties = _propCollector.getProperties(); } return _properties; } /* /********************************************************** /* Limited modifications by core databind functionality /********************************************************** */ /** * Method that can be used to prune unwanted properties, during * construction of serializers and deserializers. * Use with utmost care, if at all... * * @since 2.1 */ public boolean removeProperty(String propName) { Iterator it = _properties().iterator(); while (it.hasNext()) { BeanPropertyDefinition prop = it.next(); if (prop.getName().equals(propName)) { it.remove(); return true; } } return false; } public boolean addProperty(BeanPropertyDefinition def) { // first: ensure we do not have such property if (hasProperty(def.getFullName())) { return false; } _properties().add(def); return true; } /** * @since 2.6 */ public boolean hasProperty(PropertyName name) { return findProperty(name) != null; } /** * @since 2.6 */ public BeanPropertyDefinition findProperty(PropertyName name) { for (BeanPropertyDefinition prop : _properties()) { if (prop.hasName(name)) { return prop; } } return null; } /* /********************************************************** /* Simple accessors from BeanDescription /********************************************************** */ @Override public AnnotatedClass getClassInfo() { return _classInfo; } @Override public ObjectIdInfo getObjectIdInfo() { return _objectIdInfo; } @Override public List findProperties() { return _properties(); } @Override @Deprecated // since 2.9 public AnnotatedMethod findJsonValueMethod() { return (_propCollector == null) ? null : _propCollector.getJsonValueMethod(); } @Override // since 2.9 public AnnotatedMember findJsonValueAccessor() { return (_propCollector == null) ? null : _propCollector.getJsonValueAccessor(); } @Override public Set getIgnoredPropertyNames() { Set ign = (_propCollector == null) ? null : _propCollector.getIgnoredPropertyNames(); if (ign == null) { return Collections.emptySet(); } return ign; } @Override public boolean hasKnownClassAnnotations() { return _classInfo.hasAnnotations(); } @Override public Annotations getClassAnnotations() { return _classInfo.getAnnotations(); } @Override @Deprecated // since 2.7 public TypeBindings bindingsForBeanType() { return _type.getBindings(); } @Override @Deprecated // since 2.8 public JavaType resolveType(java.lang.reflect.Type jdkType) { if (jdkType == null) { return null; } return _config.getTypeFactory().constructType(jdkType, _type.getBindings()); } @Override public AnnotatedConstructor findDefaultConstructor() { return _classInfo.getDefaultConstructor(); } @Override public AnnotatedMember findAnySetterAccessor() throws IllegalArgumentException { if (_propCollector != null) { AnnotatedMethod anyMethod = _propCollector.getAnySetterMethod(); if (anyMethod != null) { // Also, let's be somewhat strict on how field name is to be // passed; String, Object make sense, others not so much. /* !!! 18-May-2009, tatu: how about enums? Can add support if * requested; easy enough for devs to add support within method. */ Class type = anyMethod.getRawParameterType(0); if ((type != String.class) && (type != Object.class)) { throw new IllegalArgumentException(String.format( "Invalid 'any-setter' annotation on method '%s()': first argument not of type String or Object, but %s", anyMethod.getName(), type.getName())); } return anyMethod; } AnnotatedMember anyField = _propCollector.getAnySetterField(); if (anyField != null) { // For now let's require a Map; in future can add support for other // types like perhaps Iterable? Class type = anyField.getRawType(); if (!Map.class.isAssignableFrom(type)) { throw new IllegalArgumentException(String.format( "Invalid 'any-setter' annotation on field '%s': type is not instance of java.util.Map", anyField.getName())); } return anyField; } } return null; } @Override public Map findInjectables() { if (_propCollector != null) { return _propCollector.getInjectables(); } return Collections.emptyMap(); } @Override public List getConstructors() { return _classInfo.getConstructors(); } @Override public Object instantiateBean(boolean fixAccess) { AnnotatedConstructor ac = _classInfo.getDefaultConstructor(); if (ac == null) { return null; } if (fixAccess) { ac.fixAccess(_config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } try { return ac.getAnnotated().newInstance(); } catch (Exception e) { Throwable t = e; while (t.getCause() != null) { t = t.getCause(); } ClassUtil.throwIfError(t); ClassUtil.throwIfRTE(t); throw new IllegalArgumentException("Failed to instantiate bean of type "+_classInfo.getAnnotated().getName()+": ("+t.getClass().getName()+") "+t.getMessage(), t); } } /* /********************************************************** /* Simple accessors, extended /********************************************************** */ @Override public AnnotatedMethod findMethod(String name, Class[] paramTypes) { return _classInfo.findMethod(name, paramTypes); } /* /********************************************************** /* General per-class annotation introspection /********************************************************** */ @Override public JsonFormat.Value findExpectedFormat(JsonFormat.Value defValue) { // 15-Apr-2016, tatu: Let's check both per-type defaults and annotations; per-type // defaults having higher precedence, so start with that if (_annotationIntrospector != null) { JsonFormat.Value v = _annotationIntrospector.findFormat(_classInfo); if (v != null) { if (defValue == null) { defValue = v; } else { defValue = defValue.withOverrides(v); } } } JsonFormat.Value v = _config.getDefaultPropertyFormat(_classInfo.getRawType()); if (v != null) { if (defValue == null) { defValue = v; } else { defValue = defValue.withOverrides(v); } } return defValue; } @Override // since 2.9 public Class[] findDefaultViews() { if (!_defaultViewsResolved) { _defaultViewsResolved = true; Class[] def = (_annotationIntrospector == null) ? null : _annotationIntrospector.findViews(_classInfo); // one more twist: if default inclusion disabled, need to force empty set of views if (def == null) { if (!_config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION)) { def = NO_VIEWS; } } _defaultViews = def; } return _defaultViews; } /* /********************************************************** /* Introspection for serialization /********************************************************** */ @Override public Converter findSerializationConverter() { if (_annotationIntrospector == null) { return null; } return _createConverter(_annotationIntrospector.findSerializationConverter(_classInfo)); } /** * Method for determining whether null properties should be written * out for a Bean of introspected type. This is based on global * feature (lowest priority, passed as argument) * and per-class annotation (highest priority). */ @Override public JsonInclude.Value findPropertyInclusion(JsonInclude.Value defValue) { if (_annotationIntrospector != null) { JsonInclude.Value incl = _annotationIntrospector.findPropertyInclusion(_classInfo); if (incl != null) { return (defValue == null) ? incl : defValue.withOverrides(incl); } } return defValue; } /** * Method used to locate the method of introspected class that * implements {@link com.fasterxml.jackson.annotation.JsonAnyGetter}. * If no such method exists null is returned. * If more than one are found, an exception is thrown. */ @Override public AnnotatedMember findAnyGetter() throws IllegalArgumentException { AnnotatedMember anyGetter = (_propCollector == null) ? null : _propCollector.getAnyGetter(); if (anyGetter != null) { /* For now let's require a Map; in future can add support for other * types like perhaps Iterable? */ Class type = anyGetter.getRawType(); if (!Map.class.isAssignableFrom(type)) { throw new IllegalArgumentException("Invalid 'any-getter' annotation on method "+anyGetter.getName()+"(): return type is not instance of java.util.Map"); } } return anyGetter; } @Override public List findBackReferences() { List result = null; HashSet names = null; for (BeanPropertyDefinition property : _properties()) { AnnotationIntrospector.ReferenceProperty refDef = property.findReferenceType(); if ((refDef == null) || !refDef.isBackReference()) { continue; } final String refName = refDef.getName(); if (result == null) { result = new ArrayList(); names = new HashSet<>(); names.add(refName); } else { if (!names.add(refName)) { throw new IllegalArgumentException("Multiple back-reference properties with name '"+refName+"'"); } } result.add(property); } return result; } @Deprecated // since 2.9 @Override public Map findBackReferenceProperties() { List props = findBackReferences(); if (props == null) { return null; } Map result = new HashMap<>(); for (BeanPropertyDefinition prop : props) { result.put(prop.getName(), prop.getMutator()); } return result; } /* /********************************************************** /* Introspection for deserialization, factories /********************************************************** */ @Override public List getFactoryMethods() { // must filter out anything that clearly is not a factory method List candidates = _classInfo.getFactoryMethods(); if (candidates.isEmpty()) { return candidates; } List result = null; for (AnnotatedMethod am : candidates) { if (isFactoryMethod(am)) { if (result == null) { result = new ArrayList(); } result.add(am); } } if (result == null) { return Collections.emptyList(); } return result; } @Override public Constructor findSingleArgConstructor(Class... argTypes) { for (AnnotatedConstructor ac : _classInfo.getConstructors()) { // This list is already filtered to only include accessible /* (note: for now this is a redundant check; but in future * that may change; thus leaving here for now) */ if (ac.getParameterCount() == 1) { Class actArg = ac.getRawParameterType(0); for (Class expArg : argTypes) { if (expArg == actArg) { return ac.getAnnotated(); } } } } return null; } @Override public Method findFactoryMethod(Class... expArgTypes) { // So, of all single-arg static methods: for (AnnotatedMethod am : _classInfo.getFactoryMethods()) { // 24-Oct-2016, tatu: Better ensure it only takes 1 arg, no matter what if (isFactoryMethod(am) && am.getParameterCount() == 1) { // And must take one of expected arg types (or supertype) Class actualArgType = am.getRawParameterType(0); for (Class expArgType : expArgTypes) { // And one that matches what we would pass in if (actualArgType.isAssignableFrom(expArgType)) { return am.getAnnotated(); } } } } return null; } protected boolean isFactoryMethod(AnnotatedMethod am) { // First: return type must be compatible with the introspected class // (i.e. allowed to be sub-class, although usually is the same class) Class rt = am.getRawReturnType(); if (!getBeanClass().isAssignableFrom(rt)) { return false; } /* Also: must be a recognized factory method, meaning: * (a) marked with @JsonCreator annotation, or * (b) "valueOf" (at this point, need not be public) */ JsonCreator.Mode mode = _annotationIntrospector.findCreatorAnnotation(_config, am); if ((mode != null) && (mode != JsonCreator.Mode.DISABLED)) { return true; } final String name = am.getName(); // 24-Oct-2016, tatu: As per [databind#1429] must ensure takes exactly one arg if ("valueOf".equals(name)) { if (am.getParameterCount() == 1) { return true; } } // [databind#208] Also accept "fromString()", if takes String or CharSequence if ("fromString".equals(name)) { if (am.getParameterCount() == 1) { Class cls = am.getRawParameterType(0); if (cls == String.class || CharSequence.class.isAssignableFrom(cls)) { return true; } } } return false; } /** * @deprecated since 2.8 */ @Deprecated // since 2.8, not used at least since 2.7 protected PropertyName _findCreatorPropertyName(AnnotatedParameter param) { PropertyName name = _annotationIntrospector.findNameForDeserialization(param); if (name == null || name.isEmpty()) { String str = _annotationIntrospector.findImplicitPropertyName(param); if (str != null && !str.isEmpty()) { name = PropertyName.construct(str); } } return name; } /* /********************************************************** /* Introspection for deserialization, other /********************************************************** */ @Override public Class findPOJOBuilder() { return (_annotationIntrospector == null) ? null : _annotationIntrospector.findPOJOBuilder(_classInfo); } @Override public JsonPOJOBuilder.Value findPOJOBuilderConfig() { return (_annotationIntrospector == null) ? null : _annotationIntrospector.findPOJOBuilderConfig(_classInfo); } @Override public Converter findDeserializationConverter() { if (_annotationIntrospector == null) { return null; } return _createConverter(_annotationIntrospector.findDeserializationConverter(_classInfo)); } @Override public String findClassDescription() { return (_annotationIntrospector == null) ? null : _annotationIntrospector.findClassDescription(_classInfo); } /* /********************************************************** /* Helper methods for field introspection /********************************************************** */ /** * @param ignoredProperties (optional) names of properties to ignore; * any fields that would be recognized as one of these properties * is ignored. * @param forSerialization If true, will collect serializable property * fields; if false, deserializable * * @return Ordered Map with logical property name as key, and * matching field as value. * * @deprecated Since 2.7.2, does not seem to be used? */ @Deprecated public LinkedHashMap _findPropertyFields( Collection ignoredProperties, boolean forSerialization) { LinkedHashMap results = new LinkedHashMap(); for (BeanPropertyDefinition property : _properties()) { AnnotatedField f = property.getField(); if (f != null) { String name = property.getName(); if (ignoredProperties != null) { if (ignoredProperties.contains(name)) { continue; } } results.put(name, f); } } return results; } /* /********************************************************** /* Helper methods, other /********************************************************** */ @SuppressWarnings("unchecked") protected Converter _createConverter(Object converterDef) { if (converterDef == null) { return null; } if (converterDef instanceof Converter) { return (Converter) converterDef; } if (!(converterDef instanceof Class)) { throw new IllegalStateException("AnnotationIntrospector returned Converter definition of type " +converterDef.getClass().getName()+"; expected type Converter or Class instead"); } Class converterClass = (Class)converterDef; // there are some known "no class" markers to consider too: if (converterClass == Converter.None.class || ClassUtil.isBogusClass(converterClass)) { return null; } if (!Converter.class.isAssignableFrom(converterClass)) { throw new IllegalStateException("AnnotationIntrospector returned Class " +converterClass.getName()+"; expected Class"); } HandlerInstantiator hi = _config.getHandlerInstantiator(); Converter conv = (hi == null) ? null : hi.converterInstance(_config, _classInfo, converterClass); if (conv == null) { conv = (Converter) ClassUtil.createInstance(converterClass, _config.canOverrideAccessModifiers()); } return (Converter) conv; } } BasicClassIntrospector.java000066400000000000000000000251231325620701100401330ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.util.Collection; import java.util.Map; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.type.SimpleType; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.LRUMap; public class BasicClassIntrospector extends ClassIntrospector implements java.io.Serializable { private static final long serialVersionUID = 1L; /* We keep a small set of pre-constructed descriptions to use for * common non-structured values, such as Numbers and Strings. * This is strictly performance optimization to reduce what is * usually one-time cost, but seems useful for some cases considering * simplicity. * * @since 2.4 */ protected final static BasicBeanDescription STRING_DESC; static { STRING_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(String.class), AnnotatedClassResolver.createPrimordial(String.class)); } protected final static BasicBeanDescription BOOLEAN_DESC; static { BOOLEAN_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(Boolean.TYPE), AnnotatedClassResolver.createPrimordial(Boolean.TYPE)); } protected final static BasicBeanDescription INT_DESC; static { INT_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(Integer.TYPE), AnnotatedClassResolver.createPrimordial(Integer.TYPE)); } protected final static BasicBeanDescription LONG_DESC; static { LONG_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(Long.TYPE), AnnotatedClassResolver.createPrimordial(Long.TYPE)); } /* /********************************************************** /* Life cycle /********************************************************** */ /** * Looks like 'forClassAnnotations()' gets called so frequently that we * should consider caching to avoid some of the lookups. * * @since 2.5 */ protected final LRUMap _cachedFCA; public BasicClassIntrospector() { // a small cache should go a long way here _cachedFCA = new LRUMap(16, 64); } /* /********************************************************** /* Factory method impls /********************************************************** */ @Override public BasicBeanDescription forSerialization(SerializationConfig cfg, JavaType type, MixInResolver r) { // minor optimization: for some JDK types do minimal introspection BasicBeanDescription desc = _findStdTypeDesc(type); if (desc == null) { // As per [databind#550], skip full introspection for some of standard // structured types as well desc = _findStdJdkCollectionDesc(cfg, type); if (desc == null) { desc = BasicBeanDescription.forSerialization(collectProperties(cfg, type, r, true, "set")); } // Also: this is a superset of "forClassAnnotations", so may optimize by optional add: _cachedFCA.putIfAbsent(type, desc); } return desc; } @Override public BasicBeanDescription forDeserialization(DeserializationConfig cfg, JavaType type, MixInResolver r) { // minor optimization: for some JDK types do minimal introspection BasicBeanDescription desc = _findStdTypeDesc(type); if (desc == null) { // As per [Databind#550], skip full introspection for some of standard // structured types as well desc = _findStdJdkCollectionDesc(cfg, type); if (desc == null) { desc = BasicBeanDescription.forDeserialization(collectProperties(cfg, type, r, false, "set")); } // Also: this is a superset of "forClassAnnotations", so may optimize by optional add: _cachedFCA.putIfAbsent(type, desc); } return desc; } @Override public BasicBeanDescription forDeserializationWithBuilder(DeserializationConfig cfg, JavaType type, MixInResolver r) { // no std JDK types with Builders, so: BasicBeanDescription desc = BasicBeanDescription.forDeserialization(collectPropertiesWithBuilder(cfg, type, r, false)); // this is still a superset of "forClassAnnotations", so may optimize by optional add: _cachedFCA.putIfAbsent(type, desc); return desc; } @Override public BasicBeanDescription forCreation(DeserializationConfig cfg, JavaType type, MixInResolver r) { BasicBeanDescription desc = _findStdTypeDesc(type); if (desc == null) { // As per [Databind#550], skip full introspection for some of standard // structured types as well desc = _findStdJdkCollectionDesc(cfg, type); if (desc == null) { desc = BasicBeanDescription.forDeserialization( collectProperties(cfg, type, r, false, "set")); } } // should this be cached for FCA? return desc; } @Override public BasicBeanDescription forClassAnnotations(MapperConfig config, JavaType type, MixInResolver r) { BasicBeanDescription desc = _findStdTypeDesc(type); if (desc == null) { desc = _cachedFCA.get(type); if (desc == null) { desc = BasicBeanDescription.forOtherUse(config, type, _resolveAnnotatedClass(config, type, r)); _cachedFCA.put(type, desc); } } return desc; } @Override public BasicBeanDescription forDirectClassAnnotations(MapperConfig config, JavaType type, MixInResolver r) { BasicBeanDescription desc = _findStdTypeDesc(type); if (desc == null) { desc = BasicBeanDescription.forOtherUse(config, type, _resolveAnnotatedWithoutSuperTypes(config, type, r)); } return desc; } /* /********************************************************** /* Overridable helper methods /********************************************************** */ protected POJOPropertiesCollector collectProperties(MapperConfig config, JavaType type, MixInResolver r, boolean forSerialization, String mutatorPrefix) { return constructPropertyCollector(config, _resolveAnnotatedClass(config, type, r), type, forSerialization, mutatorPrefix); } protected POJOPropertiesCollector collectPropertiesWithBuilder(MapperConfig config, JavaType type, MixInResolver r, boolean forSerialization) { AnnotatedClass ac = _resolveAnnotatedClass(config, type, r); AnnotationIntrospector ai = config.isAnnotationProcessingEnabled() ? config.getAnnotationIntrospector() : null; JsonPOJOBuilder.Value builderConfig = (ai == null) ? null : ai.findPOJOBuilderConfig(ac); String mutatorPrefix = (builderConfig == null) ? JsonPOJOBuilder.DEFAULT_WITH_PREFIX : builderConfig.withPrefix; return constructPropertyCollector(config, ac, type, forSerialization, mutatorPrefix); } /** * Overridable method called for creating {@link POJOPropertiesCollector} instance * to use; override is needed if a custom sub-class is to be used. */ protected POJOPropertiesCollector constructPropertyCollector(MapperConfig config, AnnotatedClass ac, JavaType type, boolean forSerialization, String mutatorPrefix) { return new POJOPropertiesCollector(config, forSerialization, type, ac, mutatorPrefix); } /** * Method called to see if type is one of core JDK types * that we have cached for efficiency. */ protected BasicBeanDescription _findStdTypeDesc(JavaType type) { Class cls = type.getRawClass(); if (cls.isPrimitive()) { if (cls == Boolean.TYPE) { return BOOLEAN_DESC; } if (cls == Integer.TYPE) { return INT_DESC; } if (cls == Long.TYPE) { return LONG_DESC; } } else { if (cls == String.class) { return STRING_DESC; } } return null; } /** * Helper method used to decide whether we can omit introspection * for members (methods, fields, constructors); we may do so for * a limited number of container types JDK provides. */ protected boolean _isStdJDKCollection(JavaType type) { if (!type.isContainerType() || type.isArrayType()) { return false; } Class raw = type.getRawClass(); String pkgName = ClassUtil.getPackageName(raw); if (pkgName != null) { if (pkgName.startsWith("java.lang") || pkgName.startsWith("java.util")) { /* 23-Sep-2014, tatu: Should we be conservative here (minimal number * of matches), or ambitious? Let's do latter for now. */ if (Collection.class.isAssignableFrom(raw) || Map.class.isAssignableFrom(raw)) { return true; } } } return false; } protected BasicBeanDescription _findStdJdkCollectionDesc(MapperConfig cfg, JavaType type) { if (_isStdJDKCollection(type)) { return BasicBeanDescription.forOtherUse(cfg, type, _resolveAnnotatedClass(cfg, type, cfg)); } return null; } /** * @since 2.9 */ protected AnnotatedClass _resolveAnnotatedClass(MapperConfig config, JavaType type, MixInResolver r) { return AnnotatedClassResolver.resolve(config, type, r); } /** * @since 2.9 */ protected AnnotatedClass _resolveAnnotatedWithoutSuperTypes(MapperConfig config, JavaType type, MixInResolver r) { return AnnotatedClassResolver.resolveWithoutSuperTypes(config, type, r); } } BeanPropertyDefinition.java000066400000000000000000000212571325620701100401370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.util.Iterator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.Named; /** * Simple value classes that contain definitions of properties, * used during introspection of properties to use for * serialization and deserialization purposes. * These instances are created before actual {@link BeanProperty} * instances are created, i.e. they are used earlier in the process * flow, and are typically use to construct actual * {@link BeanProperty} instances. */ public abstract class BeanPropertyDefinition implements Named { protected final static JsonInclude.Value EMPTY_INCLUDE = JsonInclude.Value.empty(); /* /********************************************************** /* Fluent factory methods for creating modified copies /********************************************************** */ /** * Method that can be used to create a definition with * same settings as this one, but with different * (external) name; that is, one for which * {@link #getName()} would return newName. * * @since 2.3 */ public abstract BeanPropertyDefinition withName(PropertyName newName); /** * Alternate "mutant factory" that will only change simple name, but * leave other optional parts (like namespace) as is. * * @since 2.3 */ public abstract BeanPropertyDefinition withSimpleName(String newSimpleName); /* /********************************************************** /* Property name information /********************************************************** */ /** * Accessor for name used for external representation (in JSON). */ @Override // from Named public abstract String getName(); public abstract PropertyName getFullName(); /** * @since 2.6 */ public boolean hasName(PropertyName name) { return getFullName().equals(name); } /** * Accessor that can be used to determine implicit name from underlying * element(s) before possible renaming. This is the "internal" * name derived from accessor ("x" from "getX"), and is not based on * annotations or naming strategy. */ public abstract String getInternalName(); /** * Accessor for finding wrapper name to use for property (if any). * * @since 2.2 */ public abstract PropertyName getWrapperName(); /** * Accessor that can be called to check whether property was included * due to an explicit marker (usually annotation), or just by naming * convention. * * @return True if property was explicitly included (usually by having * one of components being annotated); false if inclusion was purely * due to naming or visibility definitions (that is, implicit) */ public abstract boolean isExplicitlyIncluded(); /** * Accessor that can be called to check whether property name was * due to an explicit marker (usually annotation), or just by naming * convention or use of "use-default-name" marker (annotation). *

* Note that entries that return true from this method will always * return true for {@link #isExplicitlyIncluded()}, but not necessarily * vice versa. * * @since 2.4 */ public boolean isExplicitlyNamed() { return isExplicitlyIncluded(); } /* /********************************************************** /* Basic property metadata /********************************************************** */ /** * @since 2.9 */ public abstract JavaType getPrimaryType(); /** * @since 2.9 */ public abstract Class getRawPrimaryType(); /** * Method for accessing additional metadata. * NOTE: will never return null, so de-referencing return value * is safe. * * @since 2.3 */ public abstract PropertyMetadata getMetadata(); /** * Method used to check if this property is expected to have a value; * and if none found, should either be considered invalid (and most likely * fail deserialization), or handled by other means (by providing default * value) */ public boolean isRequired() { return getMetadata().isRequired(); } /* /********************************************************** /* Capabilities /********************************************************** */ public boolean couldDeserialize() { return getMutator() != null; } public boolean couldSerialize() { return getAccessor() != null; } /* /********************************************************** /* Access to accessors (fields, methods etc) /********************************************************** */ public abstract boolean hasGetter(); public abstract boolean hasSetter(); public abstract boolean hasField(); public abstract boolean hasConstructorParameter(); public abstract AnnotatedMethod getGetter(); public abstract AnnotatedMethod getSetter(); public abstract AnnotatedField getField(); public abstract AnnotatedParameter getConstructorParameter(); /** * Additional method that may be called instead of {@link #getConstructorParameter()} * to get access to all constructor parameters, not just the highest priority one. * * @since 2.5 */ public Iterator getConstructorParameters() { return ClassUtil.emptyIterator(); } /** * Method used to find accessor (getter, field to access) to use for accessing * value of the property. * Null if no such member exists. */ public AnnotatedMember getAccessor() { AnnotatedMember m = getGetter(); if (m == null) { m = getField(); } return m; } /** * Method used to find mutator (constructor parameter, setter, field) to use for * changing value of the property. * Null if no such member exists. */ public AnnotatedMember getMutator() { AnnotatedMember acc = getConstructorParameter(); if (acc == null) { acc = getSetter(); if (acc == null) { acc = getField(); } } return acc; } /** * @since 2.3 */ public AnnotatedMember getNonConstructorMutator() { AnnotatedMember m = getSetter(); if (m == null) { m = getField(); } return m; } /** * Method used to find the property member (getter, setter, field) that has * the highest precedence in current context (getter method when serializing, * if available, and so forth), if any. *

* Note: abstract since 2.5 * * @since 2.1 */ public abstract AnnotatedMember getPrimaryMember(); /* /********************************************************** /* More refined access to configuration features /* (usually based on annotations and/or config overrides) /* Since most trivial implementations do not support /* these methods, they are implemented as no-ops. /********************************************************** */ /** * Method used to find View-inclusion definitions for the property. */ public Class[] findViews() { return null; } /** * Method used to find whether property is part of a bi-directional * reference. */ public AnnotationIntrospector.ReferenceProperty findReferenceType() { return null; } /** * @since 2.9 */ public String findReferenceName() { AnnotationIntrospector.ReferenceProperty ref = findReferenceType(); return (ref == null) ? null : ref.getName(); } /** * Method used to check whether this logical property has a marker * to indicate it should be used as the type id for polymorphic type * handling. */ public boolean isTypeId() { return false; } /** * Method used to check whether this logical property indicates that * value POJOs should be written using additional Object Identifier * (or, when multiple references exist, all but first AS Object Identifier). */ public ObjectIdInfo findObjectIdInfo() { return null; } /** * Method used to check if this property has specific inclusion override * associated with it or not. * It should NOT check for any default settings (global, per-type, or * containing POJO settings) * * @since 2.5 */ public abstract JsonInclude.Value findInclusion(); } ClassIntrospector.java000066400000000000000000000073001325620701100371660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.cfg.MapperConfig; /** * Helper class used to introspect features of POJO value classes * used with Jackson. The main use is for finding out * POJO construction (creator) and value access (getters, setters) * methods and annotations that define configuration of using * those methods. */ public abstract class ClassIntrospector { /* /********************************************************** /* Helper interfaces /********************************************************** */ /** * Interface used for decoupling details of how mix-in annotation * definitions are accessed (via this interface), and how * they are stored (defined by classes that implement the interface) */ public interface MixInResolver { /** * Method that will check if there are "mix-in" classes (with mix-in * annotations) for given class */ public Class findMixInClassFor(Class cls); /** * Method called to create a new, non-shared copy, to be used by different * ObjectMapper instance, and one that should not be connected * to this instance, if resolver has mutable state. * If resolver is immutable may simply return `this`. * * @since 2.6 */ public MixInResolver copy(); } protected ClassIntrospector() { } /* /********************************************************** /* Public API: factory methods /********************************************************** */ /** * Factory method that constructs an introspector that has all * information needed for serialization purposes. */ public abstract BeanDescription forSerialization(SerializationConfig cfg, JavaType type, MixInResolver r); /** * Factory method that constructs an introspector that has all * information needed for deserialization purposes. */ public abstract BeanDescription forDeserialization(DeserializationConfig cfg, JavaType type, MixInResolver r); /** * Factory method that constructs an introspector that has all * information needed for constructing deserializers that use * intermediate Builder objects. */ public abstract BeanDescription forDeserializationWithBuilder(DeserializationConfig cfg, JavaType type, MixInResolver r); /** * Factory method that constructs an introspector that has * information necessary for creating instances of given * class ("creator"), as well as class annotations, but * no information on member methods */ public abstract BeanDescription forCreation(DeserializationConfig cfg, JavaType type, MixInResolver r); /** * Factory method that constructs an introspector that only has * information regarding annotations class itself (or its supertypes) has, * but nothing on methods or constructors. */ public abstract BeanDescription forClassAnnotations(MapperConfig cfg, JavaType type, MixInResolver r); /** * Factory method that constructs an introspector that only has * information regarding annotations class itself has (but NOT including * its supertypes), but nothing on methods or constructors. */ public abstract BeanDescription forDirectClassAnnotations(MapperConfig cfg, JavaType type, MixInResolver r); } CollectorBase.java000066400000000000000000000101531325620701100362260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.Target; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.util.ClassUtil; // @since 2.9 class CollectorBase { protected final static AnnotationMap[] NO_ANNOTATION_MAPS = new AnnotationMap[0]; protected final static Annotation[] NO_ANNOTATIONS = new Annotation[0]; protected final AnnotationIntrospector _intr; protected CollectorBase(AnnotationIntrospector intr) { _intr = intr; } // // // Annotation overrides ("mix over") protected final AnnotationCollector collectAnnotations(Annotation[] anns) { AnnotationCollector c = AnnotationCollector.emptyCollector(); for (int i = 0, end = anns.length; i < end; ++i) { Annotation ann = anns[i]; c = c.addOrOverride(ann); if (_intr.isAnnotationBundle(ann)) { c = collectFromBundle(c, ann); } } return c; } protected final AnnotationCollector collectAnnotations(AnnotationCollector c, Annotation[] anns) { for (int i = 0, end = anns.length; i < end; ++i) { Annotation ann = anns[i]; c = c.addOrOverride(ann); if (_intr.isAnnotationBundle(ann)) { c = collectFromBundle(c, ann); } } return c; } protected final AnnotationCollector collectFromBundle(AnnotationCollector c, Annotation bundle) { Annotation[] anns = ClassUtil.findClassAnnotations(bundle.annotationType()); for (int i = 0, end = anns.length; i < end; ++i) { Annotation ann = anns[i]; // minor optimization: by-pass 2 common JDK meta-annotations if (_ignorableAnnotation(ann)) { continue; } if (_intr.isAnnotationBundle(ann)) { // 11-Apr-2017, tatu: Also must guard against recursive definitions... if (!c.isPresent(ann)) { c = c.addOrOverride(ann); c = collectFromBundle(c, ann); } } else { c = c.addOrOverride(ann); } } return c; } // // // Defaulting ("mix under") // Variant that only adds annotations that are missing protected final AnnotationCollector collectDefaultAnnotations(AnnotationCollector c, Annotation[] anns) { for (int i = 0, end = anns.length; i < end; ++i) { Annotation ann = anns[i]; if (!c.isPresent(ann)) { c = c.addOrOverride(ann); if (_intr.isAnnotationBundle(ann)) { c = collectDefaultFromBundle(c, ann); } } } return c; } protected final AnnotationCollector collectDefaultFromBundle(AnnotationCollector c, Annotation bundle) { Annotation[] anns = ClassUtil.findClassAnnotations(bundle.annotationType()); for (int i = 0, end = anns.length; i < end; ++i) { Annotation ann = anns[i]; // minor optimization: by-pass 2 common JDK meta-annotations if (_ignorableAnnotation(ann)) { continue; } // also only defaulting, not overrides: if (!c.isPresent(ann)) { c = c.addOrOverride(ann); if (_intr.isAnnotationBundle(ann)) { c = collectFromBundle(c, ann); } } } return c; } protected final static boolean _ignorableAnnotation(Annotation a) { return (a instanceof Target) || (a instanceof Retention); } static AnnotationMap _emptyAnnotationMap() { return new AnnotationMap(); } static AnnotationMap[] _emptyAnnotationMaps(int count) { if (count == 0) { return NO_ANNOTATION_MAPS; } AnnotationMap[] maps = new AnnotationMap[count]; for (int i = 0; i < count; ++i) { maps[i] = _emptyAnnotationMap(); } return maps; } } ConcreteBeanPropertyBase.java000066400000000000000000000104141325620701100403750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.util.Collections; import java.util.List; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.PropertyMetadata; import com.fasterxml.jackson.databind.PropertyName; import com.fasterxml.jackson.databind.cfg.MapperConfig; /** * Intermediate {@link BeanProperty} class shared by concrete readable- and * writable property implementations for sharing common functionality. * * @since 2.7 */ public abstract class ConcreteBeanPropertyBase implements BeanProperty, java.io.Serializable { private static final long serialVersionUID = 1; /** * Additional information about property * * @since 2.3 */ protected final PropertyMetadata _metadata; /** * Lazily accessed value for per-property format override definition. * * @since 2.8 */ protected transient JsonFormat.Value _propertyFormat; /** * @since 2.9 */ protected transient List _aliases; protected ConcreteBeanPropertyBase(PropertyMetadata md) { _metadata = (md == null) ? PropertyMetadata.STD_REQUIRED_OR_OPTIONAL : md; } protected ConcreteBeanPropertyBase(ConcreteBeanPropertyBase src) { _metadata = src._metadata; _propertyFormat = src._propertyFormat; } @Override public boolean isRequired() { return _metadata.isRequired(); } @Override public PropertyMetadata getMetadata() { return _metadata; } @Override public boolean isVirtual() { return false; } @Override @Deprecated public final JsonFormat.Value findFormatOverrides(AnnotationIntrospector intr) { JsonFormat.Value f = null; if (intr != null) { AnnotatedMember member = getMember(); if (member != null) { f = intr.findFormat(member); } } if (f == null) { f = EMPTY_FORMAT; } return f; } @Override public JsonFormat.Value findPropertyFormat(MapperConfig config, Class baseType) { // 15-Apr-2016, tatu: Let's calculate lazily, retain; assumption being however that // baseType is always the same JsonFormat.Value v = _propertyFormat; if (v == null) { JsonFormat.Value v1 = config.getDefaultPropertyFormat(baseType); JsonFormat.Value v2 = null; AnnotationIntrospector intr = config.getAnnotationIntrospector(); if (intr != null) { AnnotatedMember member = getMember(); if (member != null) { v2 = intr.findFormat(member); } } if (v1 == null) { v = (v2 == null) ? EMPTY_FORMAT : v2; } else { v = (v2 == null) ? v1 : v1.withOverrides(v2); } _propertyFormat = v; } return v; } @Override public JsonInclude.Value findPropertyInclusion(MapperConfig config, Class baseType) { AnnotationIntrospector intr = config.getAnnotationIntrospector(); AnnotatedMember member = getMember(); if (member == null) { JsonInclude.Value def = config.getDefaultPropertyInclusion(baseType); return def; } JsonInclude.Value v0 = config.getDefaultInclusion(baseType, member.getRawType()); if (intr == null) { return v0; } JsonInclude.Value v = intr.findPropertyInclusion(member); if (v0 == null) { return v; } return v0.withOverrides(v); } @Override public List findAliases(MapperConfig config) { List aliases = _aliases; if (aliases == null) { AnnotationIntrospector intr = config.getAnnotationIntrospector(); if (intr != null) { aliases = intr.findPropertyAliases(getMember()); } if (aliases == null) { aliases = Collections.emptyList(); } _aliases = aliases; } return aliases; } } JacksonAnnotationIntrospector.java000066400000000000000000001550421325620701100415530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.*; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.ext.Java7Support; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter; import com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter; import com.fasterxml.jackson.databind.ser.std.RawSerializer; import com.fasterxml.jackson.databind.type.MapLikeType; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.*; /** * {@link AnnotationIntrospector} implementation that handles standard * Jackson annotations. */ public class JacksonAnnotationIntrospector extends AnnotationIntrospector implements java.io.Serializable { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") private final static Class[] ANNOTATIONS_TO_INFER_SER = (Class[]) new Class[] { JsonSerialize.class, JsonView.class, JsonFormat.class, JsonTypeInfo.class, JsonRawValue.class, JsonUnwrapped.class, JsonBackReference.class, JsonManagedReference.class }; @SuppressWarnings("unchecked") private final static Class[] ANNOTATIONS_TO_INFER_DESER = (Class[]) new Class[] { JsonDeserialize.class, JsonView.class, JsonFormat.class, JsonTypeInfo.class, JsonUnwrapped.class, JsonBackReference.class, JsonManagedReference.class, JsonMerge.class // since 2.9 }; // NOTE: loading of Java7 dependencies is encapsulated by handlers in Java7Support, // here we do not really need any handling; but for extra-safety use try-catch private static final Java7Support _java7Helper; static { Java7Support x = null; try { x = Java7Support.instance(); } catch (Throwable t) { } _java7Helper = x; } /** * Since introspection of annotation types is a performance issue in some * use cases (rare, but do exist), let's try a simple cache to reduce * need for actual meta-annotation introspection. *

* Non-final only because it needs to be re-created after deserialization. * * @since 2.7 */ protected transient LRUMap,Boolean> _annotationsInside = new LRUMap,Boolean>(48, 48); /* /********************************************************** /* Local configuration settings /********************************************************** */ /** * See {@link #setConstructorPropertiesImpliesCreator(boolean)} for * explanation. *

* Defaults to true. * * @since 2.7.4 */ protected boolean _cfgConstructorPropertiesImpliesCreator = true; /* /********************************************************** /* Life-cycle /********************************************************** */ public JacksonAnnotationIntrospector() { } @Override public Version version() { return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION; } protected Object readResolve() { if (_annotationsInside == null) { _annotationsInside = new LRUMap,Boolean>(48, 48); } return this; } /* /********************************************************** /* Configuration /********************************************************** */ /** * Method for changing behavior of {@link java.beans.ConstructorProperties}: * if set to `true`, existence DOES indicate that the given constructor should * be considered a creator; `false` that it should NOT be considered a creator * without explicit use of JsonCreator annotation. *

* Default setting is `true` * * @since 2.7.4 */ public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b) { _cfgConstructorPropertiesImpliesCreator = b; return this; } /* /********************************************************** /* General annotation properties /********************************************************** */ /** * Annotations with meta-annotation {@link JacksonAnnotationsInside} * are considered bundles. */ @Override public boolean isAnnotationBundle(Annotation ann) { // 22-Sep-2015, tatu: Caching here has modest effect on JavaSE, and only // mostly in degenerate cases where introspection used more often than // it should (like recreating ObjectMapper once per read/write). // But it may be more beneficial on platforms like Android (should verify) Class type = ann.annotationType(); Boolean b = _annotationsInside.get(type); if (b == null) { b = type.getAnnotation(JacksonAnnotationsInside.class) != null; _annotationsInside.putIfAbsent(type, b); } return b.booleanValue(); } /* /********************************************************** /* General annotations /********************************************************** */ /** * Since 2.6, we have supported use of {@link JsonProperty} for specifying * explicit serialized name */ @Override @Deprecated // since 2.8 public String findEnumValue(Enum value) { // 11-Jun-2015, tatu: As per [databind#677], need to allow explicit naming. // Unfortunately cannot quite use standard AnnotatedClass here (due to various // reasons, including odd representation JVM uses); has to do for now try { // We know that values are actually static fields with matching name so: Field f = value.getClass().getField(value.name()); if (f != null) { JsonProperty prop = f.getAnnotation(JsonProperty.class); if (prop != null) { String n = prop.value(); if (n != null && !n.isEmpty()) { return n; } } } } catch (SecurityException e) { // 17-Sep-2015, tatu: Anything we could/should do here? } catch (NoSuchFieldException e) { // 17-Sep-2015, tatu: should not really happen. But... can we do anything? } return value.name(); } @Override // since 2.7 public String[] findEnumValues(Class enumType, Enum[] enumValues, String[] names) { HashMap expl = null; for (Field f : ClassUtil.getDeclaredFields(enumType)) { if (!f.isEnumConstant()) { continue; } JsonProperty prop = f.getAnnotation(JsonProperty.class); if (prop == null) { continue; } String n = prop.value(); if (n.isEmpty()) { continue; } if (expl == null) { expl = new HashMap(); } expl.put(f.getName(), n); } // and then stitch them together if and as necessary if (expl != null) { for (int i = 0, end = enumValues.length; i < end; ++i) { String defName = enumValues[i].name(); String explValue = expl.get(defName); if (explValue != null) { names[i] = explValue; } } } return names; } /** * Finds the Enum value that should be considered the default value, if possible. *

* This implementation relies on {@link JsonEnumDefaultValue} annotation to determine the default value if present. * * @param enumCls The Enum class to scan for the default value. * @return null if none found or it's not possible to determine one. * @since 2.8 */ @Override public Enum findDefaultEnumValue(Class> enumCls) { return ClassUtil.findFirstAnnotatedEnumValue(enumCls, JsonEnumDefaultValue.class); } /* /********************************************************** /* General class annotations /********************************************************** */ @Override public PropertyName findRootName(AnnotatedClass ac) { JsonRootName ann = _findAnnotation(ac, JsonRootName.class); if (ann == null) { return null; } String ns = ann.namespace(); if (ns != null && ns.length() == 0) { ns = null; } return PropertyName.construct(ann.value(), ns); } @Override // since 2.8 public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated a) { JsonIgnoreProperties v = _findAnnotation(a, JsonIgnoreProperties.class); if (v == null) { return JsonIgnoreProperties.Value.empty(); } return JsonIgnoreProperties.Value.from(v); } @Override public Boolean isIgnorableType(AnnotatedClass ac) { JsonIgnoreType ignore = _findAnnotation(ac, JsonIgnoreType.class); return (ignore == null) ? null : ignore.value(); } @Override public Object findFilterId(Annotated a) { JsonFilter ann = _findAnnotation(a, JsonFilter.class); if (ann != null) { String id = ann.value(); // Empty String is same as not having annotation, to allow overrides if (id.length() > 0) { return id; } } return null; } @Override public Object findNamingStrategy(AnnotatedClass ac) { JsonNaming ann = _findAnnotation(ac, JsonNaming.class); return (ann == null) ? null : ann.value(); } @Override public String findClassDescription(AnnotatedClass ac) { JsonClassDescription ann = _findAnnotation(ac, JsonClassDescription.class); return (ann == null) ? null : ann.value(); } /* /********************************************************** /* Property auto-detection /********************************************************** */ @Override public VisibilityChecker findAutoDetectVisibility(AnnotatedClass ac, VisibilityChecker checker) { JsonAutoDetect ann = _findAnnotation(ac, JsonAutoDetect.class); return (ann == null) ? checker : checker.with(ann); } /* /********************************************************** /* General member (field, method/constructor) annotations /********************************************************** */ @Override public String findImplicitPropertyName(AnnotatedMember m) { PropertyName n = _findConstructorName(m); return (n == null) ? null : n.getSimpleName(); } @Override public List findPropertyAliases(Annotated m) { JsonAlias ann = _findAnnotation(m, JsonAlias.class); if (ann == null) { return null; } String[] strs = ann.value(); final int len = strs.length; if (len == 0) { return Collections.emptyList(); } List result = new ArrayList<>(len); for (int i = 0; i < len; ++i) { result.add(PropertyName.construct(strs[i])); } return result; } @Override public boolean hasIgnoreMarker(AnnotatedMember m) { return _isIgnorable(m); } @Override public Boolean hasRequiredMarker(AnnotatedMember m) { JsonProperty ann = _findAnnotation(m, JsonProperty.class); if (ann != null) { return ann.required(); } return null; } @Override public JsonProperty.Access findPropertyAccess(Annotated m) { JsonProperty ann = _findAnnotation(m, JsonProperty.class); if (ann != null) { return ann.access(); } return null; } @Override public String findPropertyDescription(Annotated ann) { JsonPropertyDescription desc = _findAnnotation(ann, JsonPropertyDescription.class); return (desc == null) ? null : desc.value(); } @Override public Integer findPropertyIndex(Annotated ann) { JsonProperty prop = _findAnnotation(ann, JsonProperty.class); if (prop != null) { int ix = prop.index(); if (ix != JsonProperty.INDEX_UNKNOWN) { return Integer.valueOf(ix); } } return null; } @Override public String findPropertyDefaultValue(Annotated ann) { JsonProperty prop = _findAnnotation(ann, JsonProperty.class); if (prop == null) { return null; } String str = prop.defaultValue(); // Since annotations do not allow nulls, need to assume empty means "none" return str.isEmpty() ? null : str; } @Override public JsonFormat.Value findFormat(Annotated ann) { JsonFormat f = _findAnnotation(ann, JsonFormat.class); return (f == null) ? null : new JsonFormat.Value(f); } @Override public ReferenceProperty findReferenceType(AnnotatedMember member) { JsonManagedReference ref1 = _findAnnotation(member, JsonManagedReference.class); if (ref1 != null) { return AnnotationIntrospector.ReferenceProperty.managed(ref1.value()); } JsonBackReference ref2 = _findAnnotation(member, JsonBackReference.class); if (ref2 != null) { return AnnotationIntrospector.ReferenceProperty.back(ref2.value()); } return null; } @Override public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member) { JsonUnwrapped ann = _findAnnotation(member, JsonUnwrapped.class); // if not enabled, just means annotation is not enabled; not necessarily // that unwrapping should not be done (relevant when using chained introspectors) if (ann == null || !ann.enabled()) { return null; } String prefix = ann.prefix(); String suffix = ann.suffix(); return NameTransformer.simpleTransformer(prefix, suffix); } @Override // since 2.9 public JacksonInject.Value findInjectableValue(AnnotatedMember m) { JacksonInject ann = _findAnnotation(m, JacksonInject.class); if (ann == null) { return null; } // Empty String means that we should use name of declared value class. JacksonInject.Value v = JacksonInject.Value.from(ann); if (!v.hasId()) { Object id; // slight complication; for setters, type if (!(m instanceof AnnotatedMethod)) { id = m.getRawType().getName(); } else { AnnotatedMethod am = (AnnotatedMethod) m; if (am.getParameterCount() == 0) { // getter id = m.getRawType().getName(); } else { // setter id = am.getRawParameterType(0).getName(); } } v = v.withId(id); } return v; } @Override @Deprecated // since 2.9 public Object findInjectableValueId(AnnotatedMember m) { JacksonInject.Value v = findInjectableValue(m); return (v == null) ? null : v.getId(); } @Override public Class[] findViews(Annotated a) { JsonView ann = _findAnnotation(a, JsonView.class); return (ann == null) ? null : ann.value(); } @Override // since 2.7 public AnnotatedMethod resolveSetterConflict(MapperConfig config, AnnotatedMethod setter1, AnnotatedMethod setter2) { Class cls1 = setter1.getRawParameterType(0); Class cls2 = setter2.getRawParameterType(0); // First: prefer primitives over non-primitives // 11-Dec-2015, tatu: TODO, perhaps consider wrappers for primitives too? if (cls1.isPrimitive()) { if (!cls2.isPrimitive()) { return setter1; } } else if (cls2.isPrimitive()) { return setter2; } if (cls1 == String.class) { if (cls2 != String.class) { return setter1; } } else if (cls2 == String.class) { return setter2; } return null; } /* /********************************************************** /* Annotations for Polymorphic Type handling /********************************************************** */ @Override public TypeResolverBuilder findTypeResolver(MapperConfig config, AnnotatedClass ac, JavaType baseType) { return _findTypeResolver(config, ac, baseType); } @Override public TypeResolverBuilder findPropertyTypeResolver(MapperConfig config, AnnotatedMember am, JavaType baseType) { /* As per definition of @JsonTypeInfo, should only apply to contents of container * (collection, map) types, not container types themselves: */ // 17-Apr-2016, tatu: For 2.7.4 make sure ReferenceType also included if (baseType.isContainerType() || baseType.isReferenceType()) { return null; } // No per-member type overrides (yet) return _findTypeResolver(config, am, baseType); } @Override public TypeResolverBuilder findPropertyContentTypeResolver(MapperConfig config, AnnotatedMember am, JavaType containerType) { /* First: let's ensure property is a container type: caller should have * verified but just to be sure */ if (containerType.getContentType() == null) { throw new IllegalArgumentException("Must call method with a container or reference type (got "+containerType+")"); } return _findTypeResolver(config, am, containerType); } @Override public List findSubtypes(Annotated a) { JsonSubTypes t = _findAnnotation(a, JsonSubTypes.class); if (t == null) return null; JsonSubTypes.Type[] types = t.value(); ArrayList result = new ArrayList(types.length); for (JsonSubTypes.Type type : types) { result.add(new NamedType(type.value(), type.name())); } return result; } @Override public String findTypeName(AnnotatedClass ac) { JsonTypeName tn = _findAnnotation(ac, JsonTypeName.class); return (tn == null) ? null : tn.value(); } @Override public Boolean isTypeId(AnnotatedMember member) { return _hasAnnotation(member, JsonTypeId.class); } /* /********************************************************** /* Annotations for Object Id handling /********************************************************** */ @Override public ObjectIdInfo findObjectIdInfo(Annotated ann) { JsonIdentityInfo info = _findAnnotation(ann, JsonIdentityInfo.class); if (info == null || info.generator() == ObjectIdGenerators.None.class) { return null; } // In future may need to allow passing namespace? PropertyName name = PropertyName.construct(info.property()); return new ObjectIdInfo(name, info.scope(), info.generator(), info.resolver()); } @Override public ObjectIdInfo findObjectReferenceInfo(Annotated ann, ObjectIdInfo objectIdInfo) { JsonIdentityReference ref = _findAnnotation(ann, JsonIdentityReference.class); if (ref == null) { return objectIdInfo; } if (objectIdInfo == null) { objectIdInfo = ObjectIdInfo.empty(); } return objectIdInfo.withAlwaysAsId(ref.alwaysAsId()); } /* /********************************************************** /* Serialization: general annotations /********************************************************** */ @Override public Object findSerializer(Annotated a) { JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); if (ann != null) { @SuppressWarnings("rawtypes") Class serClass = ann.using(); if (serClass != JsonSerializer.None.class) { return serClass; } } /* 18-Oct-2010, tatu: [JACKSON-351] @JsonRawValue handled just here, for now; * if we need to get raw indicator from other sources need to add * separate accessor within {@link AnnotationIntrospector} interface. */ JsonRawValue annRaw = _findAnnotation(a, JsonRawValue.class); if ((annRaw != null) && annRaw.value()) { // let's construct instance with nominal type: Class cls = a.getRawType(); return new RawSerializer(cls); } return null; } @Override public Object findKeySerializer(Annotated a) { JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); if (ann != null) { @SuppressWarnings("rawtypes") Class serClass = ann.keyUsing(); if (serClass != JsonSerializer.None.class) { return serClass; } } return null; } @Override public Object findContentSerializer(Annotated a) { JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); if (ann != null) { @SuppressWarnings("rawtypes") Class serClass = ann.contentUsing(); if (serClass != JsonSerializer.None.class) { return serClass; } } return null; } @Override public Object findNullSerializer(Annotated a) { JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); if (ann != null) { @SuppressWarnings("rawtypes") Class serClass = ann.nullsUsing(); if (serClass != JsonSerializer.None.class) { return serClass; } } return null; } @Override public JsonInclude.Value findPropertyInclusion(Annotated a) { JsonInclude inc = _findAnnotation(a, JsonInclude.class); JsonInclude.Value value = (inc == null) ? JsonInclude.Value.empty() : JsonInclude.Value.from(inc); // only consider deprecated variant if we didn't have non-deprecated one: if (value.getValueInclusion() == JsonInclude.Include.USE_DEFAULTS) { value = _refinePropertyInclusion(a, value); } return value; } @SuppressWarnings("deprecation") private JsonInclude.Value _refinePropertyInclusion(Annotated a, JsonInclude.Value value) { JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); if (ann != null) { switch (ann.include()) { case ALWAYS: return value.withValueInclusion(JsonInclude.Include.ALWAYS); case NON_NULL: return value.withValueInclusion(JsonInclude.Include.NON_NULL); case NON_DEFAULT: return value.withValueInclusion(JsonInclude.Include.NON_DEFAULT); case NON_EMPTY: return value.withValueInclusion(JsonInclude.Include.NON_EMPTY); case DEFAULT_INCLUSION: default: } } return value; } @Override public JsonSerialize.Typing findSerializationTyping(Annotated a) { JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); return (ann == null) ? null : ann.typing(); } @Override public Object findSerializationConverter(Annotated a) { JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); return (ann == null) ? null : _classIfExplicit(ann.converter(), Converter.None.class); } @Override public Object findSerializationContentConverter(AnnotatedMember a) { JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); return (ann == null) ? null : _classIfExplicit(ann.contentConverter(), Converter.None.class); } /* /********************************************************** /* Serialization: type refinements /********************************************************** */ @Override public JavaType refineSerializationType(final MapperConfig config, final Annotated a, final JavaType baseType) throws JsonMappingException { JavaType type = baseType; final TypeFactory tf = config.getTypeFactory(); final JsonSerialize jsonSer = _findAnnotation(a, JsonSerialize.class); // Ok: start by refining the main type itself; common to all types final Class serClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.as()); if (serClass != null) { if (type.hasRawClass(serClass)) { // 30-Nov-2015, tatu: As per [databind#1023], need to allow forcing of // static typing this way type = type.withStaticTyping(); } else { Class currRaw = type.getRawClass(); try { // 11-Oct-2015, tatu: For deser, we call `TypeFactory.constructSpecializedType()`, // may be needed here too in future? if (serClass.isAssignableFrom(currRaw)) { // common case type = tf.constructGeneralizedType(type, serClass); } else if (currRaw.isAssignableFrom(serClass)) { // specialization, ok as well type = tf.constructSpecializedType(type, serClass); } else if (_primitiveAndWrapper(currRaw, serClass)) { // 27-Apr-2017, tatu: [databind#1592] ignore primitive<->wrapper refinements type = type.withStaticTyping(); } else { throw new JsonMappingException(null, String.format("Cannot refine serialization type %s into %s; types not related", type, serClass.getName())); } } catch (IllegalArgumentException iae) { throw new JsonMappingException(null, String.format("Failed to widen type %s with annotation (value %s), from '%s': %s", type, serClass.getName(), a.getName(), iae.getMessage()), iae); } } } // Then further processing for container types // First, key type (for Maps, Map-like types): if (type.isMapLikeType()) { JavaType keyType = type.getKeyType(); final Class keyClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.keyAs()); if (keyClass != null) { if (keyType.hasRawClass(keyClass)) { keyType = keyType.withStaticTyping(); } else { Class currRaw = keyType.getRawClass(); try { // 19-May-2016, tatu: As per [databind#1231], [databind#1178] may need to actually // specialize (narrow) type sometimes, even if more commonly opposite // is needed. if (keyClass.isAssignableFrom(currRaw)) { // common case keyType = tf.constructGeneralizedType(keyType, keyClass); } else if (currRaw.isAssignableFrom(keyClass)) { // specialization, ok as well keyType = tf.constructSpecializedType(keyType, keyClass); } else if (_primitiveAndWrapper(currRaw, keyClass)) { // 27-Apr-2017, tatu: [databind#1592] ignore primitive<->wrapper refinements keyType = keyType.withStaticTyping(); } else { throw new JsonMappingException(null, String.format("Cannot refine serialization key type %s into %s; types not related", keyType, keyClass.getName())); } } catch (IllegalArgumentException iae) { throw new JsonMappingException(null, String.format("Failed to widen key type of %s with concrete-type annotation (value %s), from '%s': %s", type, keyClass.getName(), a.getName(), iae.getMessage()), iae); } } type = ((MapLikeType) type).withKeyType(keyType); } } JavaType contentType = type.getContentType(); if (contentType != null) { // collection[like], map[like], array, reference // And then value types for all containers: final Class contentClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.contentAs()); if (contentClass != null) { if (contentType.hasRawClass(contentClass)) { contentType = contentType.withStaticTyping(); } else { // 03-Apr-2016, tatu: As per [databind#1178], may need to actually // specialize (narrow) type sometimes, even if more commonly opposite // is needed. Class currRaw = contentType.getRawClass(); try { if (contentClass.isAssignableFrom(currRaw)) { // common case contentType = tf.constructGeneralizedType(contentType, contentClass); } else if (currRaw.isAssignableFrom(contentClass)) { // specialization, ok as well contentType = tf.constructSpecializedType(contentType, contentClass); } else if (_primitiveAndWrapper(currRaw, contentClass)) { // 27-Apr-2017, tatu: [databind#1592] ignore primitive<->wrapper refinements contentType = contentType.withStaticTyping(); } else { throw new JsonMappingException(null, String.format("Cannot refine serialization content type %s into %s; types not related", contentType, contentClass.getName())); } } catch (IllegalArgumentException iae) { // shouldn't really happen throw new JsonMappingException(null, String.format("Internal error: failed to refine value type of %s with concrete-type annotation (value %s), from '%s': %s", type, contentClass.getName(), a.getName(), iae.getMessage()), iae); } } type = type.withContentType(contentType); } } return type; } @Override @Deprecated // since 2.7 public Class findSerializationType(Annotated am) { return null; } @Override @Deprecated // since 2.7 public Class findSerializationKeyType(Annotated am, JavaType baseType) { return null; } @Override @Deprecated // since 2.7 public Class findSerializationContentType(Annotated am, JavaType baseType) { return null; } /* /********************************************************** /* Serialization: class annotations /********************************************************** */ @Override public String[] findSerializationPropertyOrder(AnnotatedClass ac) { JsonPropertyOrder order = _findAnnotation(ac, JsonPropertyOrder.class); return (order == null) ? null : order.value(); } @Override public Boolean findSerializationSortAlphabetically(Annotated ann) { return _findSortAlpha(ann); } private final Boolean _findSortAlpha(Annotated ann) { JsonPropertyOrder order = _findAnnotation(ann, JsonPropertyOrder.class); // 23-Jun-2015, tatu: as per [databind#840], let's only consider // `true` to have any significance. if ((order != null) && order.alphabetic()) { return Boolean.TRUE; } return null; } @Override public void findAndAddVirtualProperties(MapperConfig config, AnnotatedClass ac, List properties) { JsonAppend ann = _findAnnotation(ac, JsonAppend.class); if (ann == null) { return; } final boolean prepend = ann.prepend(); JavaType propType = null; // First: any attribute-backed properties? JsonAppend.Attr[] attrs = ann.attrs(); for (int i = 0, len = attrs.length; i < len; ++i) { if (propType == null) { propType = config.constructType(Object.class); } BeanPropertyWriter bpw = _constructVirtualProperty(attrs[i], config, ac, propType); if (prepend) { properties.add(i, bpw); } else { properties.add(bpw); } } // Then: general-purpose virtual properties? JsonAppend.Prop[] props = ann.props(); for (int i = 0, len = props.length; i < len; ++i) { BeanPropertyWriter bpw = _constructVirtualProperty(props[i], config, ac); if (prepend) { properties.add(i, bpw); } else { properties.add(bpw); } } } protected BeanPropertyWriter _constructVirtualProperty(JsonAppend.Attr attr, MapperConfig config, AnnotatedClass ac, JavaType type) { PropertyMetadata metadata = attr.required() ? PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL; // could add Index, Description in future, if those matter String attrName = attr.value(); // allow explicit renaming; if none, default to attribute name PropertyName propName = _propertyName(attr.propName(), attr.propNamespace()); if (!propName.hasSimpleName()) { propName = PropertyName.construct(attrName); } // now, then, we need a placeholder for member (no real Field/Method): AnnotatedMember member = new VirtualAnnotatedMember(ac, ac.getRawType(), attrName, type); // and with that and property definition SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(config, member, propName, metadata, attr.include()); // can construct the property writer return AttributePropertyWriter.construct(attrName, propDef, ac.getAnnotations(), type); } protected BeanPropertyWriter _constructVirtualProperty(JsonAppend.Prop prop, MapperConfig config, AnnotatedClass ac) { PropertyMetadata metadata = prop.required() ? PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL; PropertyName propName = _propertyName(prop.name(), prop.namespace()); JavaType type = config.constructType(prop.type()); // now, then, we need a placeholder for member (no real Field/Method): AnnotatedMember member = new VirtualAnnotatedMember(ac, ac.getRawType(), propName.getSimpleName(), type); // and with that and property definition SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(config, member, propName, metadata, prop.include()); Class implClass = prop.value(); HandlerInstantiator hi = config.getHandlerInstantiator(); VirtualBeanPropertyWriter bpw = (hi == null) ? null : hi.virtualPropertyWriterInstance(config, implClass); if (bpw == null) { bpw = (VirtualBeanPropertyWriter) ClassUtil.createInstance(implClass, config.canOverrideAccessModifiers()); } // one more thing: give it necessary contextual information return bpw.withConfig(config, ac, propDef, type); } /* /********************************************************** /* Serialization: property annotations /********************************************************** */ @Override public PropertyName findNameForSerialization(Annotated a) { JsonGetter jg = _findAnnotation(a, JsonGetter.class); if (jg != null) { return PropertyName.construct(jg.value()); } JsonProperty pann = _findAnnotation(a, JsonProperty.class); if (pann != null) { return PropertyName.construct(pann.value()); } if (_hasOneOf(a, ANNOTATIONS_TO_INFER_SER)) { return PropertyName.USE_DEFAULT; } return null; } @Override // since 2.9 public Boolean hasAsValue(Annotated a) { JsonValue ann = _findAnnotation(a, JsonValue.class); if (ann == null) { return null; } return ann.value(); } @Override // since 2.9 public Boolean hasAnyGetter(Annotated a) { JsonAnyGetter ann = _findAnnotation(a, JsonAnyGetter.class); if (ann == null) { return null; } return ann.enabled(); } @Override @Deprecated // since 2.9 public boolean hasAnyGetterAnnotation(AnnotatedMethod am) { // No dedicated disabling; regular @JsonIgnore used if needs to be ignored (handled separately) return _hasAnnotation(am, JsonAnyGetter.class); } @Override @Deprecated // since 2.9 public boolean hasAsValueAnnotation(AnnotatedMethod am) { JsonValue ann = _findAnnotation(am, JsonValue.class); // value of 'false' means disabled... return (ann != null) && ann.value(); } /* /********************************************************** /* Deserialization: general annotations /********************************************************** */ @Override public Object findDeserializer(Annotated a) { JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class); if (ann != null) { @SuppressWarnings("rawtypes") Class deserClass = ann.using(); if (deserClass != JsonDeserializer.None.class) { return deserClass; } } return null; } @Override public Object findKeyDeserializer(Annotated a) { JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class); if (ann != null) { Class deserClass = ann.keyUsing(); if (deserClass != KeyDeserializer.None.class) { return deserClass; } } return null; } @Override public Object findContentDeserializer(Annotated a) { JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class); if (ann != null) { @SuppressWarnings("rawtypes") Class deserClass = ann.contentUsing(); if (deserClass != JsonDeserializer.None.class) { return deserClass; } } return null; } @Override public Object findDeserializationConverter(Annotated a) { JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class); return (ann == null) ? null : _classIfExplicit(ann.converter(), Converter.None.class); } @Override public Object findDeserializationContentConverter(AnnotatedMember a) { JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class); return (ann == null) ? null : _classIfExplicit(ann.contentConverter(), Converter.None.class); } /* /********************************************************** /* Deserialization: type modifications /********************************************************** */ @Override public JavaType refineDeserializationType(final MapperConfig config, final Annotated a, final JavaType baseType) throws JsonMappingException { JavaType type = baseType; final TypeFactory tf = config.getTypeFactory(); final JsonDeserialize jsonDeser = _findAnnotation(a, JsonDeserialize.class); // Ok: start by refining the main type itself; common to all types final Class valueClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.as()); if ((valueClass != null) && !type.hasRawClass(valueClass) && !_primitiveAndWrapper(type, valueClass)) { try { type = tf.constructSpecializedType(type, valueClass); } catch (IllegalArgumentException iae) { throw new JsonMappingException(null, String.format("Failed to narrow type %s with annotation (value %s), from '%s': %s", type, valueClass.getName(), a.getName(), iae.getMessage()), iae); } } // Then further processing for container types // First, key type (for Maps, Map-like types): if (type.isMapLikeType()) { JavaType keyType = type.getKeyType(); final Class keyClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.keyAs()); if ((keyClass != null) && !_primitiveAndWrapper(keyType, keyClass)) { try { keyType = tf.constructSpecializedType(keyType, keyClass); type = ((MapLikeType) type).withKeyType(keyType); } catch (IllegalArgumentException iae) { throw new JsonMappingException(null, String.format("Failed to narrow key type of %s with concrete-type annotation (value %s), from '%s': %s", type, keyClass.getName(), a.getName(), iae.getMessage()), iae); } } } JavaType contentType = type.getContentType(); if (contentType != null) { // collection[like], map[like], array, reference // And then value types for all containers: final Class contentClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.contentAs()); if ((contentClass != null) && !_primitiveAndWrapper(contentType, contentClass)) { try { contentType = tf.constructSpecializedType(contentType, contentClass); type = type.withContentType(contentType); } catch (IllegalArgumentException iae) { throw new JsonMappingException(null, String.format("Failed to narrow value type of %s with concrete-type annotation (value %s), from '%s': %s", type, contentClass.getName(), a.getName(), iae.getMessage()), iae); } } } return type; } @Override @Deprecated // since 2.7 public Class findDeserializationContentType(Annotated am, JavaType baseContentType) { return null; } @Override @Deprecated // since 2.7 public Class findDeserializationType(Annotated am, JavaType baseType) { return null; } @Override @Deprecated // since 2.7 public Class findDeserializationKeyType(Annotated am, JavaType baseKeyType) { return null; } /* /********************************************************** /* Deserialization: Class annotations /********************************************************** */ @Override public Object findValueInstantiator(AnnotatedClass ac) { JsonValueInstantiator ann = _findAnnotation(ac, JsonValueInstantiator.class); // no 'null' marker yet, so: return (ann == null) ? null : ann.value(); } @Override public Class findPOJOBuilder(AnnotatedClass ac) { JsonDeserialize ann = _findAnnotation(ac, JsonDeserialize.class); return (ann == null) ? null : _classIfExplicit(ann.builder()); } @Override public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) { JsonPOJOBuilder ann = _findAnnotation(ac, JsonPOJOBuilder.class); return (ann == null) ? null : new JsonPOJOBuilder.Value(ann); } /* /********************************************************** /* Deserialization: property annotations /********************************************************** */ @Override public PropertyName findNameForDeserialization(Annotated a) { // @JsonSetter has precedence over @JsonProperty, being more specific // @JsonDeserialize implies that there is a property, but no name JsonSetter js = _findAnnotation(a, JsonSetter.class); if (js != null) { return PropertyName.construct(js.value()); } JsonProperty pann = _findAnnotation(a, JsonProperty.class); if (pann != null) { return PropertyName.construct(pann.value()); } if (_hasOneOf(a, ANNOTATIONS_TO_INFER_DESER)) { return PropertyName.USE_DEFAULT; } return null; } @Override public Boolean hasAnySetter(Annotated a) { JsonAnySetter ann = _findAnnotation(a, JsonAnySetter.class); return (ann == null) ? null : ann.enabled(); } @Override public JsonSetter.Value findSetterInfo(Annotated a) { return JsonSetter.Value.from(_findAnnotation(a, JsonSetter.class)); } @Override // since 2.9 public Boolean findMergeInfo(Annotated a) { JsonMerge ann = _findAnnotation(a, JsonMerge.class); return (ann == null) ? null : ann.value().asBoolean(); } @Override @Deprecated // since 2.9 public boolean hasAnySetterAnnotation(AnnotatedMethod am) { return _hasAnnotation(am, JsonAnySetter.class); } @Override @Deprecated // since 2.9 public boolean hasCreatorAnnotation(Annotated a) { /* No dedicated disabling; regular @JsonIgnore used if needs to be * ignored (and if so, is handled prior to this method getting called) */ JsonCreator ann = _findAnnotation(a, JsonCreator.class); if (ann != null) { return (ann.mode() != JsonCreator.Mode.DISABLED); } // 19-Apr-2016, tatu: As per [databind#1197], [databind#1122] (and some related), // may or may not consider it a creator if (_cfgConstructorPropertiesImpliesCreator ) { if (a instanceof AnnotatedConstructor) { if (_java7Helper != null) { Boolean b = _java7Helper.hasCreatorAnnotation(a); if (b != null) { return b.booleanValue(); } } } } return false; } @Override @Deprecated // since 2.9 public JsonCreator.Mode findCreatorBinding(Annotated a) { JsonCreator ann = _findAnnotation(a, JsonCreator.class); return (ann == null) ? null : ann.mode(); } @Override public JsonCreator.Mode findCreatorAnnotation(MapperConfig config, Annotated a) { JsonCreator ann = _findAnnotation(a, JsonCreator.class); if (ann != null) { return ann.mode(); } if (_cfgConstructorPropertiesImpliesCreator && config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES) ) { if (a instanceof AnnotatedConstructor) { if (_java7Helper != null) { Boolean b = _java7Helper.hasCreatorAnnotation(a); if ((b != null) && b.booleanValue()) { // 13-Sep-2016, tatu: Judgment call, but I don't think JDK ever implies // use of delegate; assumes as-properties implicitly return JsonCreator.Mode.PROPERTIES; } } } } return null; } /* /********************************************************** /* Helper methods /********************************************************** */ protected boolean _isIgnorable(Annotated a) { JsonIgnore ann = _findAnnotation(a, JsonIgnore.class); if (ann != null) { return ann.value(); } if (_java7Helper != null) { Boolean b = _java7Helper.findTransient(a); if (b != null) { return b.booleanValue(); } } return false; } protected Class _classIfExplicit(Class cls) { if (cls == null || ClassUtil.isBogusClass(cls)) { return null; } return cls; } protected Class _classIfExplicit(Class cls, Class implicit) { cls = _classIfExplicit(cls); return (cls == null || cls == implicit) ? null : cls; } protected PropertyName _propertyName(String localName, String namespace) { if (localName.isEmpty()) { return PropertyName.USE_DEFAULT; } if (namespace == null || namespace.isEmpty()) { return PropertyName.construct(localName); } return PropertyName.construct(localName, namespace); } protected PropertyName _findConstructorName(Annotated a) { if (a instanceof AnnotatedParameter) { AnnotatedParameter p = (AnnotatedParameter) a; AnnotatedWithParams ctor = p.getOwner(); if (ctor != null) { if (_java7Helper != null) { PropertyName name = _java7Helper.findConstructorName(p); if (name != null) { return name; } } } } return null; } /** * Helper method called to construct and initialize instance of {@link TypeResolverBuilder} * if given annotated element indicates one is needed. */ @SuppressWarnings("deprecation") protected TypeResolverBuilder _findTypeResolver(MapperConfig config, Annotated ann, JavaType baseType) { // First: maybe we have explicit type resolver? TypeResolverBuilder b; JsonTypeInfo info = _findAnnotation(ann, JsonTypeInfo.class); JsonTypeResolver resAnn = _findAnnotation(ann, JsonTypeResolver.class); if (resAnn != null) { if (info == null) { return null; } /* let's not try to force access override (would need to pass * settings through if we did, since that's not doable on some * platforms) */ b = config.typeResolverBuilderInstance(ann, resAnn.value()); } else { // if not, use standard one, if indicated by annotations if (info == null) { return null; } // bit special; must return 'marker' to block use of default typing: if (info.use() == JsonTypeInfo.Id.NONE) { return _constructNoTypeResolverBuilder(); } b = _constructStdTypeResolverBuilder(); } // Does it define a custom type id resolver? JsonTypeIdResolver idResInfo = _findAnnotation(ann, JsonTypeIdResolver.class); TypeIdResolver idRes = (idResInfo == null) ? null : config.typeIdResolverInstance(ann, idResInfo.value()); if (idRes != null) { idRes.init(baseType); } b = b.init(info.use(), idRes); /* 13-Aug-2011, tatu: One complication; external id * only works for properties; so if declared for a Class, we will need * to map it to "PROPERTY" instead of "EXTERNAL_PROPERTY" */ JsonTypeInfo.As inclusion = info.include(); if (inclusion == JsonTypeInfo.As.EXTERNAL_PROPERTY && (ann instanceof AnnotatedClass)) { inclusion = JsonTypeInfo.As.PROPERTY; } b = b.inclusion(inclusion); b = b.typeProperty(info.property()); Class defaultImpl = info.defaultImpl(); // 08-Dec-2014, tatu: To deprecate `JsonTypeInfo.None` we need to use other placeholder(s); // and since `java.util.Void` has other purpose (to indicate "deser as null"), we'll instead // use `JsonTypeInfo.class` itself. But any annotation type will actually do, as they have no // valid use (cannot instantiate as default) if (defaultImpl != JsonTypeInfo.None.class && !defaultImpl.isAnnotation()) { b = b.defaultImpl(defaultImpl); } b = b.typeIdVisibility(info.visible()); return b; } /** * Helper method for constructing standard {@link TypeResolverBuilder} * implementation. */ protected StdTypeResolverBuilder _constructStdTypeResolverBuilder() { return new StdTypeResolverBuilder(); } /** * Helper method for dealing with "no type info" marker; can't be null * (as it'd be replaced by default typing) */ protected StdTypeResolverBuilder _constructNoTypeResolverBuilder() { return StdTypeResolverBuilder.noTypeInfoBuilder(); } private boolean _primitiveAndWrapper(Class baseType, Class refinement) { if (baseType.isPrimitive()) { return baseType == ClassUtil.primitiveType(refinement); } if (refinement.isPrimitive()) { return refinement == ClassUtil.primitiveType(baseType); } return false; } private boolean _primitiveAndWrapper(JavaType baseType, Class refinement) { if (baseType.isPrimitive()) { return baseType.hasRawClass(ClassUtil.primitiveType(refinement)); } if (refinement.isPrimitive()) { return refinement == ClassUtil.primitiveType(baseType.getRawClass()); } return false; } } MemberKey.java000066400000000000000000000050441325620701100353700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.Constructor; import java.lang.reflect.Method; /** * Helper class needed to be able to efficiently access class * member functions ({@link Method}s and {@link Constructor}s) * in {@link java.util.Map}s. */ public final class MemberKey { final static Class[] NO_CLASSES = new Class[0]; final String _name; final Class[] _argTypes; public MemberKey(Method m) { this(m.getName(), m.getParameterTypes()); } public MemberKey(Constructor ctor) { this("", ctor.getParameterTypes()); } public MemberKey(String name, Class[] argTypes) { _name = name; _argTypes = (argTypes == null) ? NO_CLASSES : argTypes; } @Override public String toString() { return _name + "(" + _argTypes.length+"-args)"; } @Override public int hashCode() { return _name.hashCode() + _argTypes.length; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) { return false; } MemberKey other = (MemberKey) o; if (!_name.equals(other._name)) { return false; } Class[] otherArgs = other._argTypes; int len = _argTypes.length; if (otherArgs.length != len) { return false; } for (int i = 0; i < len; ++i) { Class type1 = otherArgs[i]; Class type2 = _argTypes[i]; if (type1 == type2) { continue; } /* 23-Feb-2009, tatu: Are there any cases where we would have to * consider some narrowing conversions or such? For now let's * assume exact type match is enough */ /* 07-Apr-2009, tatu: Indeed there are (see [JACKSON-97]). * This happens with generics when a bound is specified. * I hope this works; check here must be transitive */ /* 14-Oct-2014, tatu: No, doing that is wrong. Conflicts may (and will) be * handled at a later point; trying to change definition of equality * will just cause problems like [jackson-core#158] */ /* if (type1.isAssignableFrom(type2) || type2.isAssignableFrom(type1)) { continue; } */ return false; } return true; } } NopAnnotationIntrospector.java000066400000000000000000000021241325620701100407070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; /** * Dummy, "no-operation" implementation of {@link AnnotationIntrospector}. * Can be used as is to suppress handling of annotations; or as a basis * for simple configuration overrides (whether based on annotations or not). */ public abstract class NopAnnotationIntrospector extends AnnotationIntrospector implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Static immutable and shareable instance that can be used as * "null" introspector: one that never finds any annotation * information. */ public final static NopAnnotationIntrospector instance = new NopAnnotationIntrospector() { private static final long serialVersionUID = 1L; @Override public Version version() { return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION; } }; @Override public Version version() { return Version.unknownVersion(); } } ObjectIdInfo.java000066400000000000000000000053461325620701100360140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdResolver; import com.fasterxml.jackson.annotation.SimpleObjectIdResolver; import com.fasterxml.jackson.databind.PropertyName; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Container object that encapsulates information usually * derived from {@link JsonIdentityInfo} annotation or its * custom alternatives */ public class ObjectIdInfo { protected final PropertyName _propertyName; protected final Class> _generator; protected final Class _resolver; protected final Class _scope; protected final boolean _alwaysAsId; /** * @since 2.8.9 */ private final static ObjectIdInfo EMPTY = new ObjectIdInfo(PropertyName.NO_NAME, Object.class, null, false, null); public ObjectIdInfo(PropertyName name, Class scope, Class> gen, Class resolver) { this(name, scope, gen, false, resolver); } protected ObjectIdInfo(PropertyName prop, Class scope, Class> gen, boolean alwaysAsId) { this(prop, scope, gen, alwaysAsId, SimpleObjectIdResolver.class); } protected ObjectIdInfo(PropertyName prop, Class scope, Class> gen, boolean alwaysAsId, Class resolver) { _propertyName = prop; _scope = scope; _generator = gen; _alwaysAsId = alwaysAsId; if (resolver == null) { resolver = SimpleObjectIdResolver.class; } _resolver = resolver; } public static ObjectIdInfo empty() { return EMPTY; } public ObjectIdInfo withAlwaysAsId(boolean state) { if (_alwaysAsId == state) { return this; } return new ObjectIdInfo(_propertyName, _scope, _generator, state, _resolver); } public PropertyName getPropertyName() { return _propertyName; } public Class getScope() { return _scope; } public Class> getGeneratorType() { return _generator; } public Class getResolverType() { return _resolver; } public boolean getAlwaysAsId() { return _alwaysAsId; } @Override public String toString() { return "ObjectIdInfo: propName="+_propertyName +", scope="+ClassUtil.nameOf(_scope) +", generatorType="+ClassUtil.nameOf(_generator) +", alwaysAsId="+_alwaysAsId; } } POJOPropertiesCollector.java000066400000000000000000001221161325620701100402030ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.Modifier; import java.util.*; import com.fasterxml.jackson.annotation.JacksonInject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.util.BeanUtil; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Helper class used for aggregating information about all possible * properties of a POJO. */ public class POJOPropertiesCollector { /* /********************************************************** /* Configuration /********************************************************** */ /** * Configuration settings */ protected final MapperConfig _config; /** * True if introspection is done for serialization (giving * precedence for serialization annotations), or not (false, deserialization) */ protected final boolean _forSerialization; /** * @since 2.5 */ protected final boolean _stdBeanNaming; /** * Type of POJO for which properties are being collected. */ protected final JavaType _type; /** * Low-level introspected class information (methods, fields etc) */ protected final AnnotatedClass _classDef; protected final VisibilityChecker _visibilityChecker; protected final AnnotationIntrospector _annotationIntrospector; /** * @since 2.9 */ protected final boolean _useAnnotations; /** * Prefix used by auto-detected mutators ("setters"): usually "set", * but differs for builder objects ("with" by default). */ protected final String _mutatorPrefix; /* /********************************************************** /* Collected property information /********************************************************** */ /** * State flag we keep to indicate whether actual property information * has been collected or not. */ protected boolean _collected; /** * Set of logical property information collected so far. *

* Since 2.6, this has been constructed (more) lazily, to defer * throwing of exceptions for potential conflicts in cases where * this may not be an actual problem. */ protected LinkedHashMap _properties; protected LinkedList _creatorProperties; protected LinkedList _anyGetters; protected LinkedList _anySetters; protected LinkedList _anySetterField; /** * Method(s) marked with 'JsonValue' annotation *

* NOTE: before 2.9, was `AnnotatedMethod`; with 2.9 allows fields too */ protected LinkedList _jsonValueAccessors; /** * Lazily collected list of properties that can be implicitly * ignored during serialization; only updated when collecting * information for deserialization purposes */ protected HashSet _ignoredPropertyNames; /** * Lazily collected list of members that were annotated to * indicate that they represent mutators for deserializer * value injection. */ protected LinkedHashMap _injectables; /* /********************************************************** /* Life-cycle /********************************************************** */ protected POJOPropertiesCollector(MapperConfig config, boolean forSerialization, JavaType type, AnnotatedClass classDef, String mutatorPrefix) { _config = config; _stdBeanNaming = config.isEnabled(MapperFeature.USE_STD_BEAN_NAMING); _forSerialization = forSerialization; _type = type; _classDef = classDef; _mutatorPrefix = (mutatorPrefix == null) ? "set" : mutatorPrefix; if (config.isAnnotationProcessingEnabled()) { _useAnnotations = true; _annotationIntrospector = _config.getAnnotationIntrospector(); } else { _useAnnotations = false; _annotationIntrospector = AnnotationIntrospector.nopInstance(); } _visibilityChecker = _config.getDefaultVisibilityChecker(type.getRawClass(), classDef); } /* /********************************************************** /* Public API /********************************************************** */ public MapperConfig getConfig() { return _config; } public JavaType getType() { return _type; } public AnnotatedClass getClassDef() { return _classDef; } public AnnotationIntrospector getAnnotationIntrospector() { return _annotationIntrospector; } public List getProperties() { // make sure we return a copy, so caller can remove entries if need be: Map props = getPropertyMap(); return new ArrayList(props.values()); } public Map getInjectables() { if (!_collected) { collectAll(); } return _injectables; } @Deprecated // since 2.9 public AnnotatedMethod getJsonValueMethod() { AnnotatedMember m = getJsonValueAccessor(); if (m instanceof AnnotatedMethod) { return (AnnotatedMethod) m; } return null; } /** * @since 2.9 */ public AnnotatedMember getJsonValueAccessor() { if (!_collected) { collectAll(); } // If @JsonValue defined, must have a single one if (_jsonValueAccessors != null) { if (_jsonValueAccessors.size() > 1) { reportProblem("Multiple 'as-value' properties defined (%s vs %s)", _jsonValueAccessors.get(0), _jsonValueAccessors.get(1)); } // otherwise we won't greatly care return _jsonValueAccessors.get(0); } return null; } public AnnotatedMember getAnyGetter() { if (!_collected) { collectAll(); } if (_anyGetters != null) { if (_anyGetters.size() > 1) { reportProblem("Multiple 'any-getters' defined (%s vs %s)", _anyGetters.get(0), _anyGetters.get(1)); } return _anyGetters.getFirst(); } return null; } public AnnotatedMember getAnySetterField() { if (!_collected) { collectAll(); } if (_anySetterField != null) { if (_anySetterField.size() > 1) { reportProblem("Multiple 'any-setter' fields defined (%s vs %s)", _anySetterField.get(0), _anySetterField.get(1)); } return _anySetterField.getFirst(); } return null; } public AnnotatedMethod getAnySetterMethod() { if (!_collected) { collectAll(); } if (_anySetters != null) { if (_anySetters.size() > 1) { reportProblem("Multiple 'any-setter' methods defined (%s vs %s)", _anySetters.get(0), _anySetters.get(1)); } return _anySetters.getFirst(); } return null; } /** * Accessor for set of properties that are explicitly marked to be ignored * via per-property markers (but NOT class annotations). */ public Set getIgnoredPropertyNames() { return _ignoredPropertyNames; } /** * Accessor to find out whether type specified requires inclusion * of Object Identifier. */ public ObjectIdInfo getObjectIdInfo() { ObjectIdInfo info = _annotationIntrospector.findObjectIdInfo(_classDef); if (info != null) { // 2.1: may also have different defaults for refs: info = _annotationIntrospector.findObjectReferenceInfo(_classDef, info); } return info; } /** * Method for finding Class to use as POJO builder, if any. */ public Class findPOJOBuilderClass() { return _annotationIntrospector.findPOJOBuilder(_classDef); } // for unit tests: protected Map getPropertyMap() { if (!_collected) { collectAll(); } return _properties; } /* /********************************************************** /* Public API: main-level collection /********************************************************** */ /** * Internal method that will collect actual property information. * * @since 2.6 */ protected void collectAll() { LinkedHashMap props = new LinkedHashMap(); // First: gather basic data _addFields(props); _addMethods(props); // 25-Jan-2016, tatu: Avoid introspecting (constructor-)creators for non-static // inner classes, see [databind#1502] if (!_classDef.isNonStaticInnerClass()) { _addCreators(props); } _addInjectables(props); // Remove ignored properties, first; this MUST precede annotation merging // since logic relies on knowing exactly which accessor has which annotation _removeUnwantedProperties(props); // and then remove unneeded accessors (wrt read-only, read-write) _removeUnwantedAccessor(props); // Rename remaining properties _renameProperties(props); // then merge annotations, to simplify further processing // 26-Sep-2017, tatu: Before 2.9.2 was done earlier but that prevented some of // annotations from getting properly merged for (POJOPropertyBuilder property : props.values()) { property.mergeAnnotations(_forSerialization); } // And use custom naming strategy, if applicable... PropertyNamingStrategy naming = _findNamingStrategy(); if (naming != null) { _renameUsing(props, naming); } /* Sort by visibility (explicit over implicit); drop all but first * of member type (getter, setter etc) if there is visibility * difference */ for (POJOPropertyBuilder property : props.values()) { property.trimByVisibility(); } /* and, if required, apply wrapper name: note, MUST be done after * annotations are merged. */ if (_config.isEnabled(MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME)) { _renameWithWrappers(props); } // well, almost last: there's still ordering... _sortProperties(props); _properties = props; _collected = true; } /* /********************************************************** /* Overridable internal methods, adding members /********************************************************** */ /** * Method for collecting basic information on all fields found */ protected void _addFields(Map props) { final AnnotationIntrospector ai = _annotationIntrospector; /* 28-Mar-2013, tatu: For deserialization we may also want to remove * final fields, as often they won't make very good mutators... * (although, maybe surprisingly, JVM _can_ force setting of such fields!) */ final boolean pruneFinalFields = !_forSerialization && !_config.isEnabled(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS); final boolean transientAsIgnoral = _config.isEnabled(MapperFeature.PROPAGATE_TRANSIENT_MARKER); for (AnnotatedField f : _classDef.fields()) { String implName = ai.findImplicitPropertyName(f); // @JsonValue? if (Boolean.TRUE.equals(ai.hasAsValue(f))) { if (_jsonValueAccessors == null) { _jsonValueAccessors = new LinkedList<>(); } _jsonValueAccessors.add(f); continue; } // @JsonAnySetter? if (Boolean.TRUE.equals(ai.hasAnySetter(f))) { if (_anySetterField == null) { _anySetterField = new LinkedList(); } _anySetterField.add(f); continue; } if (implName == null) { implName = f.getName(); } PropertyName pn; if (_forSerialization) { /* 18-Aug-2011, tatu: As per existing unit tests, we should only * use serialization annotation (@JsonSerialize) when serializing * fields, and similarly for deserialize-only annotations... so * no fallbacks in this particular case. */ pn = ai.findNameForSerialization(f); } else { pn = ai.findNameForDeserialization(f); } boolean hasName = (pn != null); boolean nameExplicit = hasName; if (nameExplicit && pn.isEmpty()) { // empty String meaning "use default name", here just means "same as field name" pn = _propNameFromSimple(implName); nameExplicit = false; } // having explicit name means that field is visible; otherwise need to check the rules boolean visible = (pn != null); if (!visible) { visible = _visibilityChecker.isFieldVisible(f); } // and finally, may also have explicit ignoral boolean ignored = ai.hasIgnoreMarker(f); // 13-May-2015, tatu: Moved from earlier place (AnnotatedClass) in 2.6 if (f.isTransient()) { // 20-May-2016, tatu: as per [databind#1184] explicit annotation should override // "default" `transient` if (!hasName) { visible = false; if (transientAsIgnoral) { ignored = true; } } } /* [databind#190]: this is the place to prune final fields, if they are not * to be used as mutators. Must verify they are not explicitly included. * Also: if 'ignored' is set, need to included until a later point, to * avoid losing ignoral information. */ if (pruneFinalFields && (pn == null) && !ignored && Modifier.isFinal(f.getModifiers())) { continue; } _property(props, implName).addField(f, pn, nameExplicit, visible, ignored); } } /** * Method for collecting basic information on constructor(s) found */ protected void _addCreators(Map props) { // can be null if annotation processing is disabled... if (!_useAnnotations) { return; } for (AnnotatedConstructor ctor : _classDef.getConstructors()) { if (_creatorProperties == null) { _creatorProperties = new LinkedList(); } for (int i = 0, len = ctor.getParameterCount(); i < len; ++i) { _addCreatorParam(props, ctor.getParameter(i)); } } for (AnnotatedMethod factory : _classDef.getFactoryMethods()) { if (_creatorProperties == null) { _creatorProperties = new LinkedList(); } for (int i = 0, len = factory.getParameterCount(); i < len; ++i) { _addCreatorParam(props, factory.getParameter(i)); } } } /** * @since 2.4 */ protected void _addCreatorParam(Map props, AnnotatedParameter param) { // JDK 8, paranamer, Scala can give implicit name String impl = _annotationIntrospector.findImplicitPropertyName(param); if (impl == null) { impl = ""; } PropertyName pn = _annotationIntrospector.findNameForDeserialization(param); boolean expl = (pn != null && !pn.isEmpty()); if (!expl) { if (impl.isEmpty()) { // Important: if neither implicit nor explicit name, cannot make use of // this creator parameter -- may or may not be a problem, verified at a later point. return; } // Also: if this occurs, there MUST be explicit annotation on creator itself JsonCreator.Mode creatorMode = _annotationIntrospector.findCreatorAnnotation(_config, param.getOwner()); if ((creatorMode == null) || (creatorMode == JsonCreator.Mode.DISABLED)) { return; } pn = PropertyName.construct(impl); } // shouldn't need to worry about @JsonIgnore, since creators only added // if so annotated /* 13-May-2015, tatu: We should try to start with implicit name, similar to how * fields and methods work; but unlike those, we don't necessarily have * implicit name to use (pre-Java8 at least). So: */ POJOPropertyBuilder prop = (expl && impl.isEmpty()) ? _property(props, pn) : _property(props, impl); prop.addCtor(param, pn, expl, true, false); _creatorProperties.add(prop); } /** * Method for collecting basic information on all fields found */ protected void _addMethods(Map props) { final AnnotationIntrospector ai = _annotationIntrospector; for (AnnotatedMethod m : _classDef.memberMethods()) { /* For methods, handling differs between getters and setters; and * we will also only consider entries that either follow the bean * naming convention or are explicitly marked: just being visible * is not enough (unlike with fields) */ int argCount = m.getParameterCount(); if (argCount == 0) { // getters (including 'any getter') _addGetterMethod(props, m, ai); } else if (argCount == 1) { // setters _addSetterMethod(props, m, ai); } else if (argCount == 2) { // any getter? if (ai != null) { if (Boolean.TRUE.equals(ai.hasAnySetter(m))) { if (_anySetters == null) { _anySetters = new LinkedList(); } _anySetters.add(m); } } } } } protected void _addGetterMethod(Map props, AnnotatedMethod m, AnnotationIntrospector ai) { // Very first thing: skip if not returning any value if (!m.hasReturnType()) { return; } // any getter? // @JsonAnyGetter? if (Boolean.TRUE.equals(ai.hasAnyGetter(m))) { if (_anyGetters == null) { _anyGetters = new LinkedList(); } _anyGetters.add(m); return; } // @JsonValue? if (Boolean.TRUE.equals(ai.hasAsValue(m))) { if (_jsonValueAccessors == null) { _jsonValueAccessors = new LinkedList<>(); } _jsonValueAccessors.add(m); return; } String implName; // from naming convention boolean visible; PropertyName pn = ai.findNameForSerialization(m); boolean nameExplicit = (pn != null); if (!nameExplicit) { // no explicit name; must consider implicit implName = ai.findImplicitPropertyName(m); if (implName == null) { implName = BeanUtil.okNameForRegularGetter(m, m.getName(), _stdBeanNaming); } if (implName == null) { // if not, must skip implName = BeanUtil.okNameForIsGetter(m, m.getName(), _stdBeanNaming); if (implName == null) { return; } visible = _visibilityChecker.isIsGetterVisible(m); } else { visible = _visibilityChecker.isGetterVisible(m); } } else { // explicit indication of inclusion, but may be empty // we still need implicit name to link with other pieces implName = ai.findImplicitPropertyName(m); if (implName == null) { implName = BeanUtil.okNameForGetter(m, _stdBeanNaming); } // if not regular getter name, use method name as is if (implName == null) { implName = m.getName(); } if (pn.isEmpty()) { // !!! TODO: use PropertyName for implicit names too pn = _propNameFromSimple(implName); nameExplicit = false; } visible = true; } boolean ignore = ai.hasIgnoreMarker(m); _property(props, implName).addGetter(m, pn, nameExplicit, visible, ignore); } protected void _addSetterMethod(Map props, AnnotatedMethod m, AnnotationIntrospector ai) { String implName; // from naming convention boolean visible; PropertyName pn = (ai == null) ? null : ai.findNameForDeserialization(m); boolean nameExplicit = (pn != null); if (!nameExplicit) { // no explicit name; must follow naming convention implName = (ai == null) ? null : ai.findImplicitPropertyName(m); if (implName == null) { implName = BeanUtil.okNameForMutator(m, _mutatorPrefix, _stdBeanNaming); } if (implName == null) { // if not, must skip return; } visible = _visibilityChecker.isSetterVisible(m); } else { // explicit indication of inclusion, but may be empty // we still need implicit name to link with other pieces implName = (ai == null) ? null : ai.findImplicitPropertyName(m); if (implName == null) { implName = BeanUtil.okNameForMutator(m, _mutatorPrefix, _stdBeanNaming); } // if not regular getter name, use method name as is if (implName == null) { implName = m.getName(); } if (pn.isEmpty()) { // !!! TODO: use PropertyName for implicit names too pn = _propNameFromSimple(implName); nameExplicit = false; } visible = true; } boolean ignore = (ai == null) ? false : ai.hasIgnoreMarker(m); _property(props, implName).addSetter(m, pn, nameExplicit, visible, ignore); } protected void _addInjectables(Map props) { final AnnotationIntrospector ai = _annotationIntrospector; // first fields, then methods, to allow overriding for (AnnotatedField f : _classDef.fields()) { _doAddInjectable(ai.findInjectableValue(f), f); } for (AnnotatedMethod m : _classDef.memberMethods()) { // for now, only allow injection of a single arg (to be changed in future?) if (m.getParameterCount() != 1) { continue; } _doAddInjectable(ai.findInjectableValue(m), m); } } protected void _doAddInjectable(JacksonInject.Value injectable, AnnotatedMember m) { if (injectable == null) { return; } Object id = injectable.getId(); if (_injectables == null) { _injectables = new LinkedHashMap(); } AnnotatedMember prev = _injectables.put(id, m); if (prev != null) { // 12-Apr-2017, tatu: Let's allow masking of Field by Method if (prev.getClass() == m.getClass()) { String type = id.getClass().getName(); throw new IllegalArgumentException("Duplicate injectable value with id '" +String.valueOf(id)+"' (of type "+type+")"); } } } private PropertyName _propNameFromSimple(String simpleName) { return PropertyName.construct(simpleName, null); } /* /********************************************************** /* Internal methods; removing ignored properties /********************************************************** */ /** * Method called to get rid of candidate properties that are marked * as ignored. */ protected void _removeUnwantedProperties(Map props) { Iterator it = props.values().iterator(); while (it.hasNext()) { POJOPropertyBuilder prop = it.next(); // First: if nothing visible, just remove altogether if (!prop.anyVisible()) { it.remove(); continue; } // Otherwise, check ignorals if (prop.anyIgnorals()) { // first: if one or more ignorals, and no explicit markers, remove the whole thing if (!prop.isExplicitlyIncluded()) { it.remove(); _collectIgnorals(prop.getName()); continue; } // otherwise just remove ones marked to be ignored prop.removeIgnored(); if (!prop.couldDeserialize()) { _collectIgnorals(prop.getName()); } } } } /** * Method called to further get rid of unwanted individual accessors, * based on read/write settings and rules for "pulling in" accessors * (or not). */ protected void _removeUnwantedAccessor(Map props) { final boolean inferMutators = _config.isEnabled(MapperFeature.INFER_PROPERTY_MUTATORS); Iterator it = props.values().iterator(); while (it.hasNext()) { POJOPropertyBuilder prop = it.next(); // 26-Jan-2017, tatu: [databind#935]: need to denote removal of JsonProperty.Access acc = prop.removeNonVisible(inferMutators); if (acc == JsonProperty.Access.READ_ONLY) { _collectIgnorals(prop.getName()); } } } /** * Helper method called to add explicitly ignored properties to a list * of known ignored properties; this helps in proper reporting of * errors. */ private void _collectIgnorals(String name) { if (!_forSerialization) { if (_ignoredPropertyNames == null) { _ignoredPropertyNames = new HashSet(); } _ignoredPropertyNames.add(name); } } /* /********************************************************** /* Internal methods; renaming properties /********************************************************** */ protected void _renameProperties(Map props) { // With renaming need to do in phases: first, find properties to rename Iterator> it = props.entrySet().iterator(); LinkedList renamed = null; while (it.hasNext()) { Map.Entry entry = it.next(); POJOPropertyBuilder prop = entry.getValue(); Collection l = prop.findExplicitNames(); // no explicit names? Implicit one is fine as is if (l.isEmpty()) { continue; } it.remove(); // need to replace with one or more renamed if (renamed == null) { renamed = new LinkedList(); } // simple renaming? Just do it if (l.size() == 1) { PropertyName n = l.iterator().next(); renamed.add(prop.withName(n)); continue; } // but this may be problematic... renamed.addAll(prop.explode(l)); /* String newName = prop.findNewName(); if (newName != null) { if (renamed == null) { renamed = new LinkedList(); } prop = prop.withSimpleName(newName); renamed.add(prop); it.remove(); } */ } // and if any were renamed, merge back in... if (renamed != null) { for (POJOPropertyBuilder prop : renamed) { String name = prop.getName(); POJOPropertyBuilder old = props.get(name); if (old == null) { props.put(name, prop); } else { old.addAll(prop); } // replace the creatorProperty too, if there is one _updateCreatorProperty(prop, _creatorProperties); } } } protected void _renameUsing(Map propMap, PropertyNamingStrategy naming) { POJOPropertyBuilder[] props = propMap.values().toArray(new POJOPropertyBuilder[propMap.size()]); propMap.clear(); for (POJOPropertyBuilder prop : props) { PropertyName fullName = prop.getFullName(); String rename = null; // As per [databind#428] need to skip renaming if property has // explicitly defined name, unless feature is enabled if (!prop.isExplicitlyNamed() || _config.isEnabled(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING)) { if (_forSerialization) { if (prop.hasGetter()) { rename = naming.nameForGetterMethod(_config, prop.getGetter(), fullName.getSimpleName()); } else if (prop.hasField()) { rename = naming.nameForField(_config, prop.getField(), fullName.getSimpleName()); } } else { if (prop.hasSetter()) { rename = naming.nameForSetterMethod(_config, prop.getSetter(), fullName.getSimpleName()); } else if (prop.hasConstructorParameter()) { rename = naming.nameForConstructorParameter(_config, prop.getConstructorParameter(), fullName.getSimpleName()); } else if (prop.hasField()) { rename = naming.nameForField(_config, prop.getField(), fullName.getSimpleName()); } else if (prop.hasGetter()) { /* Plus, when getter-as-setter is used, need to convert that too.. * (should we verify that's enabled? For now, assume it's ok always) */ rename = naming.nameForGetterMethod(_config, prop.getGetter(), fullName.getSimpleName()); } } } final String simpleName; if (rename != null && !fullName.hasSimpleName(rename)) { prop = prop.withSimpleName(rename); simpleName = rename; } else { simpleName = fullName.getSimpleName(); } /* As per [JACKSON-687], need to consider case where there may already be * something in there... */ POJOPropertyBuilder old = propMap.get(simpleName); if (old == null) { propMap.put(simpleName, prop); } else { old.addAll(prop); } // replace the creatorProperty too, if there is one _updateCreatorProperty(prop, _creatorProperties); } } protected void _renameWithWrappers(Map props) { // 11-Sep-2012, tatu: To support 'MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME', // need another round of renaming... Iterator> it = props.entrySet().iterator(); LinkedList renamed = null; while (it.hasNext()) { Map.Entry entry = it.next(); POJOPropertyBuilder prop = entry.getValue(); AnnotatedMember member = prop.getPrimaryMember(); if (member == null) { continue; } PropertyName wrapperName = _annotationIntrospector.findWrapperName(member); // One trickier part (wrt [#24] of JAXB annotations: wrapper that // indicates use of actual property... But hopefully has been taken care // of previously if (wrapperName == null || !wrapperName.hasSimpleName()) { continue; } if (!wrapperName.equals(prop.getFullName())) { if (renamed == null) { renamed = new LinkedList(); } prop = prop.withName(wrapperName); renamed.add(prop); it.remove(); } } // and if any were renamed, merge back in... if (renamed != null) { for (POJOPropertyBuilder prop : renamed) { String name = prop.getName(); POJOPropertyBuilder old = props.get(name); if (old == null) { props.put(name, prop); } else { old.addAll(prop); } } } } /* /********************************************************** /* Overridable internal methods, sorting, other stuff /********************************************************** */ /* First, order by [JACKSON-90] (explicit ordering and/or alphabetic) * and then for [JACKSON-170] (implicitly order creator properties before others) */ protected void _sortProperties(Map props) { // Then how about explicit ordering? AnnotationIntrospector intr = _annotationIntrospector; Boolean alpha = intr.findSerializationSortAlphabetically((Annotated) _classDef); boolean sort; if (alpha == null) { sort = _config.shouldSortPropertiesAlphabetically(); } else { sort = alpha.booleanValue(); } String[] propertyOrder = intr.findSerializationPropertyOrder(_classDef); // no sorting? no need to shuffle, then if (!sort && (_creatorProperties == null) && (propertyOrder == null)) { return; } int size = props.size(); Map all; // Need to (re)sort alphabetically? if (sort) { all = new TreeMap(); } else { all = new LinkedHashMap(size+size); } for (POJOPropertyBuilder prop : props.values()) { all.put(prop.getName(), prop); } Map ordered = new LinkedHashMap(size+size); // Ok: primarily by explicit order if (propertyOrder != null) { for (String name : propertyOrder) { POJOPropertyBuilder w = all.get(name); if (w == null) { // will also allow use of "implicit" names for sorting for (POJOPropertyBuilder prop : props.values()) { if (name.equals(prop.getInternalName())) { w = prop; // plus re-map to external name, to avoid dups: name = prop.getName(); break; } } } if (w != null) { ordered.put(name, w); } } } // And secondly by sorting Creator properties before other unordered properties if (_creatorProperties != null) { /* As per [databind#311], this is bit delicate; but if alphabetic ordering * is mandated, at least ensure creator properties are in alphabetic * order. Related question of creator vs non-creator is punted for now, * so creator properties still fully predate non-creator ones. */ Collection cr; if (sort) { TreeMap sorted = new TreeMap(); for (POJOPropertyBuilder prop : _creatorProperties) { sorted.put(prop.getName(), prop); } cr = sorted.values(); } else { cr = _creatorProperties; } for (POJOPropertyBuilder prop : cr) { // 16-Jan-2016, tatu: Related to [databind#1317], make sure not to accidentally // add back pruned creator properties! String name = prop.getName(); if (all.containsKey(name)) { ordered.put(name, prop); } } } // And finally whatever is left (trying to put again will not change ordering) ordered.putAll(all); props.clear(); props.putAll(ordered); } /* /********************************************************** /* Internal methods; helpers /********************************************************** */ protected void reportProblem(String msg, Object... args) { if (args.length > 0) { msg = String.format(msg, args); } throw new IllegalArgumentException("Problem with definition of "+_classDef+": "+msg); } protected POJOPropertyBuilder _property(Map props, PropertyName name) { String simpleName = name.getSimpleName(); POJOPropertyBuilder prop = props.get(simpleName); if (prop == null) { prop = new POJOPropertyBuilder(_config, _annotationIntrospector, _forSerialization, name); props.put(simpleName, prop); } return prop; } // !!! TODO: deprecate, require use of PropertyName protected POJOPropertyBuilder _property(Map props, String implName) { POJOPropertyBuilder prop = props.get(implName); if (prop == null) { prop = new POJOPropertyBuilder(_config, _annotationIntrospector, _forSerialization, PropertyName.construct(implName)); props.put(implName, prop); } return prop; } private PropertyNamingStrategy _findNamingStrategy() { Object namingDef = _annotationIntrospector.findNamingStrategy(_classDef); if (namingDef == null) { return _config.getPropertyNamingStrategy(); } if (namingDef instanceof PropertyNamingStrategy) { return (PropertyNamingStrategy) namingDef; } /* Alas, there's no way to force return type of "either class * X or Y" -- need to throw an exception after the fact */ if (!(namingDef instanceof Class)) { throw new IllegalStateException("AnnotationIntrospector returned PropertyNamingStrategy definition of type " +namingDef.getClass().getName()+"; expected type PropertyNamingStrategy or Class instead"); } Class namingClass = (Class)namingDef; // 09-Nov-2015, tatu: Need to consider pseudo-value of STD, which means "use default" if (namingClass == PropertyNamingStrategy.class) { return null; } if (!PropertyNamingStrategy.class.isAssignableFrom(namingClass)) { throw new IllegalStateException("AnnotationIntrospector returned Class " +namingClass.getName()+"; expected Class"); } HandlerInstantiator hi = _config.getHandlerInstantiator(); if (hi != null) { PropertyNamingStrategy pns = hi.namingStrategyInstance(_config, _classDef, namingClass); if (pns != null) { return pns; } } return (PropertyNamingStrategy) ClassUtil.createInstance(namingClass, _config.canOverrideAccessModifiers()); } protected void _updateCreatorProperty(POJOPropertyBuilder prop, List creatorProperties) { if (creatorProperties != null) { for (int i = 0, len = creatorProperties.size(); i < len; ++i) { if (creatorProperties.get(i).getInternalName().equals(prop.getInternalName())) { creatorProperties.set(i, prop); break; } } } } } POJOPropertyBuilder.java000066400000000000000000001363531325620701100373430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.util.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.ConfigOverride; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Helper class used for aggregating information about a single * potential POJO property. */ public class POJOPropertyBuilder extends BeanPropertyDefinition implements Comparable { /** * Marker value used to denote that no reference-property information found for * this property * * @since 2.9 */ private final static AnnotationIntrospector.ReferenceProperty NOT_REFEFERENCE_PROP = AnnotationIntrospector.ReferenceProperty.managed(""); /** * Whether property is being composed for serialization * (true) or deserialization (false) */ protected final boolean _forSerialization; protected final MapperConfig _config; protected final AnnotationIntrospector _annotationIntrospector; /** * External name of logical property; may change with * renaming (by new instance being constructed using * a new name) */ protected final PropertyName _name; /** * Original internal name, derived from accessor, of this * property. Will not be changed by renaming. */ protected final PropertyName _internalName; protected Linked _fields; protected Linked _ctorParameters; protected Linked _getters; protected Linked _setters; protected transient PropertyMetadata _metadata; /** * Lazily accessed information about this property iff it is a forward or * back reference. * * @since 2.9 */ protected transient AnnotationIntrospector.ReferenceProperty _referenceInfo; public POJOPropertyBuilder(MapperConfig config, AnnotationIntrospector ai, boolean forSerialization, PropertyName internalName) { this(config, ai, forSerialization, internalName, internalName); } protected POJOPropertyBuilder(MapperConfig config, AnnotationIntrospector ai, boolean forSerialization, PropertyName internalName, PropertyName name) { _config = config; _annotationIntrospector = ai; _internalName = internalName; _name = name; _forSerialization = forSerialization; } // protected since 2.9 (was public before) protected POJOPropertyBuilder(POJOPropertyBuilder src, PropertyName newName) { _config = src._config; _annotationIntrospector = src._annotationIntrospector; _internalName = src._internalName; _name = newName; _fields = src._fields; _ctorParameters = src._ctorParameters; _getters = src._getters; _setters = src._setters; _forSerialization = src._forSerialization; } /* /********************************************************** /* Mutant factory methods /********************************************************** */ @Override public POJOPropertyBuilder withName(PropertyName newName) { return new POJOPropertyBuilder(this, newName); } @Override public POJOPropertyBuilder withSimpleName(String newSimpleName) { PropertyName newName = _name.withSimpleName(newSimpleName); return (newName == _name) ? this : new POJOPropertyBuilder(this, newName); } /* /********************************************************** /* Comparable implementation: sort alphabetically, except /* that properties with constructor parameters sorted /* before other properties /********************************************************** */ @Override public int compareTo(POJOPropertyBuilder other) { // first, if one has ctor params, that should come first: if (_ctorParameters != null) { if (other._ctorParameters == null) { return -1; } } else if (other._ctorParameters != null) { return 1; } /* otherwise sort by external name (including sorting of * ctor parameters) */ return getName().compareTo(other.getName()); } /* /********************************************************** /* BeanPropertyDefinition implementation, name/type /********************************************************** */ @Override public String getName() { return (_name == null) ? null : _name.getSimpleName(); } @Override public PropertyName getFullName() { return _name; } @Override public boolean hasName(PropertyName name) { return _name.equals(name); } @Override public String getInternalName() { return _internalName.getSimpleName(); } @Override public PropertyName getWrapperName() { /* 13-Mar-2013, tatu: Accessing via primary member SHOULD work, * due to annotation merging. However, I have seen some problems * with this access (for other annotations)... so if this should * occur, try commenting out full traversal code */ AnnotatedMember member = getPrimaryMember(); return (member == null || _annotationIntrospector == null) ? null : _annotationIntrospector.findWrapperName(member); /* return fromMemberAnnotations(new WithMember() { @Override public PropertyName withMember(AnnotatedMember member) { return _annotationIntrospector.findWrapperName(member); } }); */ } @Override public boolean isExplicitlyIncluded() { return _anyExplicits(_fields) || _anyExplicits(_getters) || _anyExplicits(_setters) // 16-Jan-2016, tatu: Creator names are special, in that name should exist too; // reason for this is [databind#1317]. Let's hope this works well, may need // to tweak further if this lowers visibility // || _anyExplicits(_ctorParameters) || _anyExplicitNames(_ctorParameters) ; } @Override public boolean isExplicitlyNamed() { return _anyExplicitNames(_fields) || _anyExplicitNames(_getters) || _anyExplicitNames(_setters) || _anyExplicitNames(_ctorParameters) ; } /* /********************************************************** /* Simple metadata /********************************************************** */ @Override public PropertyMetadata getMetadata() { if (_metadata == null) { final Boolean b = _findRequired(); final String desc = _findDescription(); final Integer idx = _findIndex(); final String def = _findDefaultValue(); if (b == null && idx == null && def == null) { _metadata = (desc == null) ? PropertyMetadata.STD_REQUIRED_OR_OPTIONAL : PropertyMetadata.STD_REQUIRED_OR_OPTIONAL.withDescription(desc); } else { _metadata = PropertyMetadata.construct(b, desc, idx, def); } if (!_forSerialization) { _metadata = _getSetterInfo(_metadata); } } return _metadata; } /** * Helper method that contains logic for accessing and merging all setter * information that we needed, regarding things like possible merging * of property value, and handling of incoming nulls. */ protected PropertyMetadata _getSetterInfo(PropertyMetadata metadata) { boolean needMerge = true; Nulls valueNulls = null; Nulls contentNulls = null; // Slightly confusing: first, annotations should be accessed via primary member // (mutator); but accessor is needed for actual merge operation. So: AnnotatedMember prim = getPrimaryMember(); AnnotatedMember acc = getAccessor(); if (prim != null) { // Ok, first: does property itself have something to say? if (_annotationIntrospector != null) { if (acc != null) { Boolean b = _annotationIntrospector.findMergeInfo(prim); if (b != null) { needMerge = false; if (b.booleanValue()) { metadata = metadata.withMergeInfo(PropertyMetadata.MergeInfo.createForPropertyOverride(acc)); } } } JsonSetter.Value setterInfo = _annotationIntrospector.findSetterInfo(prim); if (setterInfo != null) { valueNulls = setterInfo.nonDefaultValueNulls(); contentNulls = setterInfo.nonDefaultContentNulls(); } } // If not, config override? // 25-Oct-2016, tatu: Either this, or type of accessor... if (needMerge || (valueNulls == null) || (contentNulls == null)) { Class rawType = getRawPrimaryType(); ConfigOverride co = _config.getConfigOverride(rawType); JsonSetter.Value setterInfo = co.getSetterInfo(); if (setterInfo != null) { if (valueNulls == null) { valueNulls = setterInfo.nonDefaultValueNulls(); } if (contentNulls == null) { contentNulls = setterInfo.nonDefaultContentNulls(); } } if (needMerge && (acc != null)) { Boolean b = co.getMergeable(); if (b != null) { needMerge = false; if (b.booleanValue()) { metadata = metadata.withMergeInfo(PropertyMetadata.MergeInfo.createForTypeOverride(acc)); } } } } } if (needMerge || (valueNulls == null) || (contentNulls == null)) { JsonSetter.Value setterInfo = _config.getDefaultSetterInfo(); if (valueNulls == null) { valueNulls = setterInfo.nonDefaultValueNulls(); } if (contentNulls == null) { contentNulls = setterInfo.nonDefaultContentNulls(); } if (needMerge) { Boolean b = _config.getDefaultMergeable(); if (Boolean.TRUE.equals(b) && (acc != null)) { metadata = metadata.withMergeInfo(PropertyMetadata.MergeInfo.createForDefaults(acc)); } } } if ((valueNulls != null) || (contentNulls != null)) { metadata = metadata.withNulls(valueNulls, contentNulls); } return metadata; } /** * Type determined from the primary member for the property being built, * considering precedence according to whether we are processing serialization * or deserialization. */ @Override public JavaType getPrimaryType() { if (_forSerialization) { AnnotatedMember m = getGetter(); if (m == null) { m = getField(); if (m == null) { // 09-Feb-2017, tatu: Not sure if this or `null` but... return TypeFactory.unknownType(); } return m.getType(); } return m.getType(); } AnnotatedMember m = getConstructorParameter(); if (m == null) { m = getSetter(); // Important: can't try direct type access for setter; what we need is // type of the first parameter if (m != null) { return ((AnnotatedMethod) m).getParameterType(0); } m = getField(); } // for setterless properties, however, can further try getter if (m == null) { m = getGetter(); if (m == null) { return TypeFactory.unknownType(); } } return m.getType(); } @Override public Class getRawPrimaryType() { return getPrimaryType().getRawClass(); } /* /********************************************************** /* BeanPropertyDefinition implementation, accessor access /********************************************************** */ @Override public boolean hasGetter() { return _getters != null; } @Override public boolean hasSetter() { return _setters != null; } @Override public boolean hasField() { return _fields != null; } @Override public boolean hasConstructorParameter() { return _ctorParameters != null; } @Override public boolean couldDeserialize() { return (_ctorParameters != null) || (_setters != null) || (_fields != null); } @Override public boolean couldSerialize() { return (_getters != null) || (_fields != null); } @Override public AnnotatedMethod getGetter() { // Easy with zero or one getters... Linked curr = _getters; if (curr == null) { return null; } Linked next = curr.next; if (next == null) { return curr.value; } // But if multiple, verify that they do not conflict... for (; next != null; next = next.next) { /* [JACKSON-255] Allow masking, i.e. do not report exception if one * is in super-class from the other */ Class currClass = curr.value.getDeclaringClass(); Class nextClass = next.value.getDeclaringClass(); if (currClass != nextClass) { if (currClass.isAssignableFrom(nextClass)) { // next is more specific curr = next; continue; } if (nextClass.isAssignableFrom(currClass)) { // current more specific continue; } } /* 30-May-2014, tatu: Three levels of precedence: * * 1. Regular getters ("getX") * 2. Is-getters ("isX") * 3. Implicit, possible getters ("x") */ int priNext = _getterPriority(next.value); int priCurr = _getterPriority(curr.value); if (priNext != priCurr) { if (priNext < priCurr) { curr = next; } continue; } throw new IllegalArgumentException("Conflicting getter definitions for property \""+getName()+"\": " +curr.value.getFullName()+" vs "+next.value.getFullName()); } // One more thing; to avoid having to do it again... _getters = curr.withoutNext(); return curr.value; } @Override public AnnotatedMethod getSetter() { // Easy with zero or one getters... Linked curr = _setters; if (curr == null) { return null; } Linked next = curr.next; if (next == null) { return curr.value; } // But if multiple, verify that they do not conflict... for (; next != null; next = next.next) { // Allow masking, i.e. do not fail if one is in super-class from the other Class currClass = curr.value.getDeclaringClass(); Class nextClass = next.value.getDeclaringClass(); if (currClass != nextClass) { if (currClass.isAssignableFrom(nextClass)) { // next is more specific curr = next; continue; } if (nextClass.isAssignableFrom(currClass)) { // current more specific continue; } } AnnotatedMethod nextM = next.value; AnnotatedMethod currM = curr.value; /* 30-May-2014, tatu: Two levels of precedence: * * 1. Regular setters ("setX(...)") * 2. Implicit, possible setters ("x(...)") */ int priNext = _setterPriority(nextM); int priCurr = _setterPriority(currM); if (priNext != priCurr) { if (priNext < priCurr) { curr = next; } continue; } // 11-Dec-2015, tatu: As per [databind#1033] allow pluggable conflict resolution if (_annotationIntrospector != null) { AnnotatedMethod pref = _annotationIntrospector.resolveSetterConflict(_config, currM, nextM); // note: should be one of nextM/currM; but no need to check if (pref == currM) { continue; } if (pref == nextM) { curr = next; continue; } } throw new IllegalArgumentException(String.format( "Conflicting setter definitions for property \"%s\": %s vs %s", getName(), curr.value.getFullName(), next.value.getFullName())); } // One more thing; to avoid having to do it again... _setters = curr.withoutNext(); return curr.value; } @Override public AnnotatedField getField() { if (_fields == null) { return null; } // If multiple, verify that they do not conflict... AnnotatedField field = _fields.value; Linked next = _fields.next; for (; next != null; next = next.next) { AnnotatedField nextField = next.value; Class fieldClass = field.getDeclaringClass(); Class nextClass = nextField.getDeclaringClass(); if (fieldClass != nextClass) { if (fieldClass.isAssignableFrom(nextClass)) { // next is more specific field = nextField; continue; } if (nextClass.isAssignableFrom(fieldClass)) { // getter more specific continue; } } throw new IllegalArgumentException("Multiple fields representing property \""+getName()+"\": " +field.getFullName()+" vs "+nextField.getFullName()); } return field; } @Override public AnnotatedParameter getConstructorParameter() { if (_ctorParameters == null) { return null; } /* Hmmh. Checking for constructor parameters is trickier; for one, * we must allow creator and factory method annotations. * If this is the case, constructor parameter has the precedence. * * So, for now, just try finding the first constructor parameter; * if none, first factory method. And don't check for dups, if we must, * can start checking for them later on. */ Linked curr = _ctorParameters; do { if (curr.value.getOwner() instanceof AnnotatedConstructor) { return curr.value; } curr = curr.next; } while (curr != null); return _ctorParameters.value; } @Override public Iterator getConstructorParameters() { if (_ctorParameters == null) { return ClassUtil.emptyIterator(); } return new MemberIterator(_ctorParameters); } @Override public AnnotatedMember getPrimaryMember() { if (_forSerialization) { return getAccessor(); } AnnotatedMember m = getMutator(); // for setterless properties, however... if (m == null) { m = getAccessor(); } return m; } protected int _getterPriority(AnnotatedMethod m) { final String name = m.getName(); // [databind#238]: Also, regular getters have precedence over "is-getters" if (name.startsWith("get") && name.length() > 3) { // should we check capitalization? return 1; } if (name.startsWith("is") && name.length() > 2) { return 2; } return 3; } protected int _setterPriority(AnnotatedMethod m) { final String name = m.getName(); if (name.startsWith("set") && name.length() > 3) { // should we check capitalization? return 1; } return 2; } /* /********************************************************** /* Implementations of refinement accessors /********************************************************** */ @Override public Class[] findViews() { return fromMemberAnnotations(new WithMember[]>() { @Override public Class[] withMember(AnnotatedMember member) { return _annotationIntrospector.findViews(member); } }); } @Override public AnnotationIntrospector.ReferenceProperty findReferenceType() { // 30-Mar-2017, tatu: Access lazily but retain information since it needs // to be accessed multiple times during processing. AnnotationIntrospector.ReferenceProperty result = _referenceInfo; if (result != null) { if (result == NOT_REFEFERENCE_PROP) { return null; } return result; } result = fromMemberAnnotations(new WithMember() { @Override public AnnotationIntrospector.ReferenceProperty withMember(AnnotatedMember member) { return _annotationIntrospector.findReferenceType(member); } }); _referenceInfo = (result == null) ? NOT_REFEFERENCE_PROP : result; return result; } @Override public boolean isTypeId() { Boolean b = fromMemberAnnotations(new WithMember() { @Override public Boolean withMember(AnnotatedMember member) { return _annotationIntrospector.isTypeId(member); } }); return (b != null) && b.booleanValue(); } protected Boolean _findRequired() { return fromMemberAnnotations(new WithMember() { @Override public Boolean withMember(AnnotatedMember member) { return _annotationIntrospector.hasRequiredMarker(member); } }); } protected String _findDescription() { return fromMemberAnnotations(new WithMember() { @Override public String withMember(AnnotatedMember member) { return _annotationIntrospector.findPropertyDescription(member); } }); } protected Integer _findIndex() { return fromMemberAnnotations(new WithMember() { @Override public Integer withMember(AnnotatedMember member) { return _annotationIntrospector.findPropertyIndex(member); } }); } protected String _findDefaultValue() { return fromMemberAnnotations(new WithMember() { @Override public String withMember(AnnotatedMember member) { return _annotationIntrospector.findPropertyDefaultValue(member); } }); } @Override public ObjectIdInfo findObjectIdInfo() { return fromMemberAnnotations(new WithMember() { @Override public ObjectIdInfo withMember(AnnotatedMember member) { ObjectIdInfo info = _annotationIntrospector.findObjectIdInfo(member); if (info != null) { info = _annotationIntrospector.findObjectReferenceInfo(member, info); } return info; } }); } @Override public JsonInclude.Value findInclusion() { AnnotatedMember a = getAccessor(); // 16-Apr-2106, tatu: Let's include per-type default inclusion too // 17-Aug-2016, tatu: Do NOT include global, or per-type defaults, because // not all of this information (specifically, enclosing type's settings) // is available here JsonInclude.Value v = (_annotationIntrospector == null) ? null : _annotationIntrospector.findPropertyInclusion(a); return (v == null) ? JsonInclude.Value.empty() : v; } public JsonProperty.Access findAccess() { return fromMemberAnnotationsExcept(new WithMember() { @Override public JsonProperty.Access withMember(AnnotatedMember member) { return _annotationIntrospector.findPropertyAccess(member); } }, JsonProperty.Access.AUTO); } /* /********************************************************** /* Data aggregation /********************************************************** */ public void addField(AnnotatedField a, PropertyName name, boolean explName, boolean visible, boolean ignored) { _fields = new Linked(a, _fields, name, explName, visible, ignored); } public void addCtor(AnnotatedParameter a, PropertyName name, boolean explName, boolean visible, boolean ignored) { _ctorParameters = new Linked(a, _ctorParameters, name, explName, visible, ignored); } public void addGetter(AnnotatedMethod a, PropertyName name, boolean explName, boolean visible, boolean ignored) { _getters = new Linked(a, _getters, name, explName, visible, ignored); } public void addSetter(AnnotatedMethod a, PropertyName name, boolean explName, boolean visible, boolean ignored) { _setters = new Linked(a, _setters, name, explName, visible, ignored); } /** * Method for adding all property members from specified collector into * this collector. */ public void addAll(POJOPropertyBuilder src) { _fields = merge(_fields, src._fields); _ctorParameters = merge(_ctorParameters, src._ctorParameters); _getters= merge(_getters, src._getters); _setters = merge(_setters, src._setters); } private static Linked merge(Linked chain1, Linked chain2) { if (chain1 == null) { return chain2; } if (chain2 == null) { return chain1; } return chain1.append(chain2); } /* /********************************************************** /* Modifications /********************************************************** */ /** * Method called to remove all entries that are marked as * ignored. */ public void removeIgnored() { _fields = _removeIgnored(_fields); _getters = _removeIgnored(_getters); _setters = _removeIgnored(_setters); _ctorParameters = _removeIgnored(_ctorParameters); } /** * @param inferMutators Whether mutators can be "pulled in" by visible * accessors or not. */ public JsonProperty.Access removeNonVisible(boolean inferMutators) { /* 07-Jun-2015, tatu: With 2.6, we will allow optional definition * of explicit access type for property; if not "AUTO", it will * dictate how visibility checks are applied. */ JsonProperty.Access acc = findAccess(); if (acc == null) { acc = JsonProperty.Access.AUTO; } switch (acc) { case READ_ONLY: // Remove setters, creators for sure, but fields too if deserializing _setters = null; _ctorParameters = null; if (!_forSerialization) { _fields = null; } break; case READ_WRITE: // no trimming whatsoever? break; case WRITE_ONLY: // remove getters, definitely, but also fields if serializing _getters = null; if (_forSerialization) { _fields = null; } break; default: case AUTO: // the default case: base it on visibility _getters = _removeNonVisible(_getters); _ctorParameters = _removeNonVisible(_ctorParameters); if (!inferMutators || (_getters == null)) { _fields = _removeNonVisible(_fields); _setters = _removeNonVisible(_setters); } } return acc; } /** * Mutator that will simply drop any constructor parameters property may have. * * @since 2.5 */ public void removeConstructors() { _ctorParameters = null; } /** * Method called to trim unnecessary entries, such as implicit * getter if there is an explict one available. This is important * for later stages, to avoid unnecessary conflicts. */ public void trimByVisibility() { _fields = _trimByVisibility(_fields); _getters = _trimByVisibility(_getters); _setters = _trimByVisibility(_setters); _ctorParameters = _trimByVisibility(_ctorParameters); } @SuppressWarnings("unchecked") public void mergeAnnotations(boolean forSerialization) { if (forSerialization) { if (_getters != null) { AnnotationMap ann = _mergeAnnotations(0, _getters, _fields, _ctorParameters, _setters); _getters = _applyAnnotations(_getters, ann); } else if (_fields != null) { AnnotationMap ann = _mergeAnnotations(0, _fields, _ctorParameters, _setters); _fields = _applyAnnotations(_fields, ann); } } else { // for deserialization if (_ctorParameters != null) { AnnotationMap ann = _mergeAnnotations(0, _ctorParameters, _setters, _fields, _getters); _ctorParameters = _applyAnnotations(_ctorParameters, ann); } else if (_setters != null) { AnnotationMap ann = _mergeAnnotations(0, _setters, _fields, _getters); _setters = _applyAnnotations(_setters, ann); } else if (_fields != null) { AnnotationMap ann = _mergeAnnotations(0, _fields, _getters); _fields = _applyAnnotations(_fields, ann); } } } private AnnotationMap _mergeAnnotations(int index, Linked... nodes) { AnnotationMap ann = _getAllAnnotations(nodes[index]); while (++index < nodes.length) { if (nodes[index] != null) { return AnnotationMap.merge(ann, _mergeAnnotations(index, nodes)); } } return ann; } /** * Replacement, as per [databind#868], of simple access to annotations, which * does "deep merge" if an as necessary. *

     * nodes[index].value.getAllAnnotations()
     *
* * @since 2.6 */ private AnnotationMap _getAllAnnotations(Linked node) { AnnotationMap ann = node.value.getAllAnnotations(); if (node.next != null) { ann = AnnotationMap.merge(ann, _getAllAnnotations(node.next)); } return ann; } /** * Helper method to handle recursive merging of annotations within accessor class, * to ensure no annotations are accidentally dropped within chain when non-visible * and secondary accessors are pruned later on. *

* See [databind#868] for more information. * * @since 2.6 */ private Linked _applyAnnotations(Linked node, AnnotationMap ann) { @SuppressWarnings("unchecked") T value = (T) node.value.withAnnotations(ann); if (node.next != null) { node = node.withNext(_applyAnnotations(node.next, ann)); } return node.withValue(value); } private Linked _removeIgnored(Linked node) { if (node == null) { return node; } return node.withoutIgnored(); } private Linked _removeNonVisible(Linked node) { if (node == null) { return node; } return node.withoutNonVisible(); } private Linked _trimByVisibility(Linked node) { if (node == null) { return node; } return node.trimByVisibility(); } /* /********************************************************** /* Accessors for aggregate information /********************************************************** */ private boolean _anyExplicits(Linked n) { for (; n != null; n = n.next) { if (n.name != null && n.name.hasSimpleName()) { return true; } } return false; } private boolean _anyExplicitNames(Linked n) { for (; n != null; n = n.next) { if (n.name != null && n.isNameExplicit) { return true; } } return false; } public boolean anyVisible() { return _anyVisible(_fields) || _anyVisible(_getters) || _anyVisible(_setters) || _anyVisible(_ctorParameters) ; } private boolean _anyVisible(Linked n) { for (; n != null; n = n.next) { if (n.isVisible) { return true; } } return false; } public boolean anyIgnorals() { return _anyIgnorals(_fields) || _anyIgnorals(_getters) || _anyIgnorals(_setters) || _anyIgnorals(_ctorParameters) ; } private boolean _anyIgnorals(Linked n) { for (; n != null; n = n.next) { if (n.isMarkedIgnored) { return true; } } return false; } /** * Method called to find out set of explicit names for accessors * bound together due to implicit name. * * @since 2.4 */ public Set findExplicitNames() { Set renamed = null; renamed = _findExplicitNames(_fields, renamed); renamed = _findExplicitNames(_getters, renamed); renamed = _findExplicitNames(_setters, renamed); renamed = _findExplicitNames(_ctorParameters, renamed); if (renamed == null) { return Collections.emptySet(); } return renamed; } /** * Method called when a previous call to {@link #findExplicitNames} found * multiple distinct explicit names, and the property this builder represents * basically needs to be broken apart and replaced by a set of more than * one properties. * * @since 2.4 */ public Collection explode(Collection newNames) { HashMap props = new HashMap(); _explode(newNames, props, _fields); _explode(newNames, props, _getters); _explode(newNames, props, _setters); _explode(newNames, props, _ctorParameters); return props.values(); } @SuppressWarnings("unchecked") private void _explode(Collection newNames, Map props, Linked accessors) { final Linked firstAcc = accessors; // clumsy, part 1 for (Linked node = accessors; node != null; node = node.next) { PropertyName name = node.name; if (!node.isNameExplicit || name == null) { // no explicit name -- problem! // [databind#541] ... but only as long as it's visible if (!node.isVisible) { continue; } throw new IllegalStateException("Conflicting/ambiguous property name definitions (implicit name '" +_name+"'): found multiple explicit names: " +newNames+", but also implicit accessor: "+node); } POJOPropertyBuilder prop = props.get(name); if (prop == null) { prop = new POJOPropertyBuilder(_config, _annotationIntrospector, _forSerialization, _internalName, name); props.put(name, prop); } // ultra-clumsy, part 2 -- lambdas would be nice here if (firstAcc == _fields) { Linked n2 = (Linked) node; prop._fields = n2.withNext(prop._fields); } else if (firstAcc == _getters) { Linked n2 = (Linked) node; prop._getters = n2.withNext(prop._getters); } else if (firstAcc == _setters) { Linked n2 = (Linked) node; prop._setters = n2.withNext(prop._setters); } else if (firstAcc == _ctorParameters) { Linked n2 = (Linked) node; prop._ctorParameters = n2.withNext(prop._ctorParameters); } else { throw new IllegalStateException("Internal error: mismatched accessors, property: "+this); } } } private Set _findExplicitNames(Linked node, Set renamed) { for (; node != null; node = node.next) { /* 30-Mar-2014, tatu: Second check should not be needed, but seems like * removing it can cause nasty exceptions with certain version * combinations (2.4 databind, an older module). * So leaving it in for now until this is resolved * (or version beyond 2.4) */ if (!node.isNameExplicit || node.name == null) { continue; } if (renamed == null) { renamed = new HashSet(); } renamed.add(node.name); } return renamed; } // For trouble-shooting @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[Property '").append(_name) .append("'; ctors: ").append(_ctorParameters) .append(", field(s): ").append(_fields) .append(", getter(s): ").append(_getters) .append(", setter(s): ").append(_setters) ; sb.append("]"); return sb.toString(); } /* /********************************************************** /* Helper methods /********************************************************** */ /** * Helper method used for finding annotation values, from accessors * relevant to current usage (deserialization, serialization) */ protected T fromMemberAnnotations(WithMember func) { T result = null; if (_annotationIntrospector != null) { if (_forSerialization) { if (_getters != null) { result = func.withMember(_getters.value); } } else { if (_ctorParameters != null) { result = func.withMember(_ctorParameters.value); } if (result == null && _setters != null) { result = func.withMember(_setters.value); } } if (result == null && _fields != null) { result = func.withMember(_fields.value); } } return result; } protected T fromMemberAnnotationsExcept(WithMember func, T defaultValue) { if (_annotationIntrospector == null) { return null; } // NOTE: here we must ask ALL accessors, but the order varies between // serialization, deserialization if (_forSerialization) { if (_getters != null) { T result = func.withMember(_getters.value); if ((result != null) && (result != defaultValue)) { return result; } } if (_fields != null) { T result = func.withMember(_fields.value); if ((result != null) && (result != defaultValue)) { return result; } } if (_ctorParameters != null) { T result = func.withMember(_ctorParameters.value); if ((result != null) && (result != defaultValue)) { return result; } } if (_setters != null) { T result = func.withMember(_setters.value); if ((result != null) && (result != defaultValue)) { return result; } } return null; } if (_ctorParameters != null) { T result = func.withMember(_ctorParameters.value); if ((result != null) && (result != defaultValue)) { return result; } } if (_setters != null) { T result = func.withMember(_setters.value); if ((result != null) && (result != defaultValue)) { return result; } } if (_fields != null) { T result = func.withMember(_fields.value); if ((result != null) && (result != defaultValue)) { return result; } } if (_getters != null) { T result = func.withMember(_getters.value); if ((result != null) && (result != defaultValue)) { return result; } } return null; } /* /********************************************************** /* Helper classes /********************************************************** */ private interface WithMember { public T withMember(AnnotatedMember member); } /** * @since 2.5 */ protected static class MemberIterator implements Iterator { private Linked next; public MemberIterator(Linked first) { next = first; } @Override public boolean hasNext() { return (next != null); } @Override public T next() { if (next == null) throw new NoSuchElementException(); T result = next.value; next = next.next; return result; } @Override public void remove() { throw new UnsupportedOperationException(); } } /** * Node used for creating simple linked lists to efficiently store small sets * of things. */ protected final static class Linked { public final T value; public final Linked next; public final PropertyName name; public final boolean isNameExplicit; public final boolean isVisible; public final boolean isMarkedIgnored; public Linked(T v, Linked n, PropertyName name, boolean explName, boolean visible, boolean ignored) { value = v; next = n; // ensure that we'll never have missing names this.name = (name == null || name.isEmpty()) ? null : name; if (explName) { if (this.name == null) { // sanity check to catch internal problems throw new IllegalArgumentException("Cannot pass true for 'explName' if name is null/empty"); } // 03-Apr-2014, tatu: But how about name-space only override? // Probably should not be explicit? Or, need to merge somehow? if (!name.hasSimpleName()) { explName = false; } } isNameExplicit = explName; isVisible = visible; isMarkedIgnored = ignored; } public Linked withoutNext() { if (next == null) { return this; } return new Linked(value, null, name, isNameExplicit, isVisible, isMarkedIgnored); } public Linked withValue(T newValue) { if (newValue == value) { return this; } return new Linked(newValue, next, name, isNameExplicit, isVisible, isMarkedIgnored); } public Linked withNext(Linked newNext) { if (newNext == next) { return this; } return new Linked(value, newNext, name, isNameExplicit, isVisible, isMarkedIgnored); } public Linked withoutIgnored() { if (isMarkedIgnored) { return (next == null) ? null : next.withoutIgnored(); } if (next != null) { Linked newNext = next.withoutIgnored(); if (newNext != next) { return withNext(newNext); } } return this; } public Linked withoutNonVisible() { Linked newNext = (next == null) ? null : next.withoutNonVisible(); return isVisible ? withNext(newNext) : newNext; } /** * Method called to append given node(s) at the end of this * node chain. */ protected Linked append(Linked appendable) { if (next == null) { return withNext(appendable); } return withNext(next.append(appendable)); } public Linked trimByVisibility() { if (next == null) { return this; } Linked newNext = next.trimByVisibility(); if (name != null) { // this already has highest; how about next one? if (newNext.name == null) { // next one not, drop it return withNext(null); } // both have it, keep return withNext(newNext); } if (newNext.name != null) { // next one has higher, return it... return newNext; } // neither has explicit name; how about visibility? if (isVisible == newNext.isVisible) { // same; keep both in current order return withNext(newNext); } return isVisible ? withNext(null) : newNext; } @Override public String toString() { String msg = String.format("%s[visible=%b,ignore=%b,explicitName=%b]", value.toString(), isVisible, isMarkedIgnored, isNameExplicit); if (next != null) { msg = msg + ", "+next.toString(); } return msg; } } } SimpleMixInResolver.java000066400000000000000000000064071325620701100374340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.databind.type.ClassKey; /** * Simple implementation of {@link ClassIntrospector.MixInResolver} * that just uses a {@link java.util.Map} for containing mapping * from target to mix-in classes. *

* Implementation is only thread-safe after initialization (that is, * when underlying Map is not modified but only read). * * @since 2.6 */ public class SimpleMixInResolver implements ClassIntrospector.MixInResolver, java.io.Serializable { private static final long serialVersionUID = 1L; /** * External resolver that gets called before looking at any locally defined * mix-in target classes. */ protected final ClassIntrospector.MixInResolver _overrides; /** * Simple mix-in targets defined locally. */ protected Map> _localMixIns; public SimpleMixInResolver(ClassIntrospector.MixInResolver overrides) { _overrides = overrides; } protected SimpleMixInResolver(ClassIntrospector.MixInResolver overrides, Map> mixins) { _overrides = overrides; _localMixIns = mixins; } /** * Mutant factory for constructor a new resolver instance with given * mix-in resolver override. */ public SimpleMixInResolver withOverrides(ClassIntrospector.MixInResolver overrides) { return new SimpleMixInResolver(overrides, _localMixIns); } /** * Mutant factory method that constructs a new instance that has no locally * defined mix-in/target mappings. */ public SimpleMixInResolver withoutLocalDefinitions() { return new SimpleMixInResolver(_overrides, null); } public void setLocalDefinitions(Map, Class> sourceMixins) { if (sourceMixins == null || sourceMixins.isEmpty()) { _localMixIns = null; } else { Map> mixIns = new HashMap>(sourceMixins.size()); for (Map.Entry,Class> en : sourceMixins.entrySet()) { mixIns.put(new ClassKey(en.getKey()), en.getValue()); } _localMixIns = mixIns; } } public void addLocalDefinition(Class target, Class mixinSource) { if (_localMixIns == null) { _localMixIns = new HashMap>(); } _localMixIns.put(new ClassKey(target), mixinSource); } @Override public SimpleMixInResolver copy() { ClassIntrospector.MixInResolver overrides = (_overrides == null) ? null : _overrides.copy(); Map> mixIns = (_localMixIns == null) ? null : new HashMap>(_localMixIns); return new SimpleMixInResolver(overrides, mixIns); } @Override public Class findMixInClassFor(Class cls) { Class mixin = (_overrides == null) ? null : _overrides.findMixInClassFor(cls); if (mixin == null && (_localMixIns != null)) { mixin = _localMixIns.get(new ClassKey(cls)); } return mixin; } public int localSize() { return (_localMixIns == null) ? 0 : _localMixIns.size(); } } TypeResolutionContext.java000066400000000000000000000016271325620701100400650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.Type; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeBindings; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Interface that defines API used by members (like {@link AnnotatedMethod}) * to dynamically resolve types they have. * * @since 2.7 */ public interface TypeResolutionContext { public JavaType resolveType(Type t); public static class Basic implements TypeResolutionContext { private final TypeFactory _typeFactory; private final TypeBindings _bindings; public Basic(TypeFactory tf, TypeBindings b) { _typeFactory = tf; _bindings = b; } @Override public JavaType resolveType(Type type) { return _typeFactory.constructType(type, _bindings); } } } VirtualAnnotatedMember.java000066400000000000000000000062021325620701100401210ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Placeholder used by virtual properties as placeholder for * underlying {@link AnnotatedMember}. * * @since 2.5 */ public class VirtualAnnotatedMember extends AnnotatedMember implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final Class _declaringClass; /** * @since 2.8 with this signature; had _rawType earlier */ protected final JavaType _type; protected final String _name; /* /********************************************************** /* Life-cycle /********************************************************** */ public VirtualAnnotatedMember(TypeResolutionContext typeContext, Class declaringClass, String name, JavaType type) { super(typeContext, /* AnnotationMap*/ null); _declaringClass = declaringClass; _type = type; _name = name; } @Override public Annotated withAnnotations(AnnotationMap fallback) { return this; } /* /********************************************************** /* Annotated impl /********************************************************** */ @Override public Field getAnnotated() { return null; } @Override public int getModifiers() { return 0; } @Override public String getName() { return _name; } @Override public Class getRawType() { return _type.getRawClass(); } @Override public JavaType getType() { return _type; } /* /********************************************************** /* AnnotatedMember impl /********************************************************** */ @Override public Class getDeclaringClass() { return _declaringClass; } @Override public Member getMember() { return null; } @Override public void setValue(Object pojo, Object value) throws IllegalArgumentException { throw new IllegalArgumentException("Cannot set virtual property '"+_name+"'"); } @Override public Object getValue(Object pojo) throws IllegalArgumentException { throw new IllegalArgumentException("Cannot get virtual property '"+_name+"'"); } /* /********************************************************** /* Extended API, generic /********************************************************** */ public int getAnnotationCount() { return 0; } @Override public int hashCode() { return _name.hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; if (!ClassUtil.hasClass(o, getClass())) { return false; } VirtualAnnotatedMember other = (VirtualAnnotatedMember) o; return (other._declaringClass == _declaringClass) && other._name.equals(_name); } @Override public String toString() { return "[virtual "+getFullName()+"]"; } } VisibilityChecker.java000066400000000000000000000360441325620701100371300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; /** * Interface for object used for determine which property elements * (methods, fields, constructors) can be auto-detected, with respect * to their visibility modifiers. *

* Note on type declaration: funky recursive type is necessary to * support builder/fluent pattern. */ public interface VisibilityChecker> { // // Builder methods /** * Builder method that will return an instance that has same * settings as this instance has, except for values that * given annotation overrides. */ public T with(JsonAutoDetect ann); /** * Method that can be used for merging default values from `this` * instance with specified overrides; and either return `this` * if overrides had no effect (that is, result would be equal), * or a new instance with merged visibility settings. * * @since 2.9 */ public T withOverrides(JsonAutoDetect.Value vis); /** * Builder method that will create and return an instance that has specified * {@link Visibility} value to use for all property elements. * Typical usage would be something like: *

     *  mapper.setVisibilityChecker(
     *     mapper.getVisibilityChecker().with(Visibility.NONE));
     *
* (which would basically disable all auto-detection) */ public T with(Visibility v); /** * Builder method that will create and return an instance that has specified * {@link Visibility} value to use for specified property. * Typical usage would be: *
     *  mapper.setVisibilityChecker(
     *     mapper.getVisibilityChecker().withVisibility(JsonMethod.FIELD, Visibility.ANY));
     *
* (which would basically enable auto-detection for all member fields) */ public T withVisibility(PropertyAccessor method, Visibility v); /** * Builder method that will return a checker instance that has * specified minimum visibility level for regular ("getXxx") getters. */ public T withGetterVisibility(Visibility v); /** * Builder method that will return a checker instance that has * specified minimum visibility level for "is-getters" ("isXxx"). */ public T withIsGetterVisibility(Visibility v); /** * Builder method that will return a checker instance that has * specified minimum visibility level for setters. */ public T withSetterVisibility(Visibility v); /** * Builder method that will return a checker instance that has * specified minimum visibility level for creator methods * (constructors, factory methods) */ public T withCreatorVisibility(Visibility v); /** * Builder method that will return a checker instance that has * specified minimum visibility level for fields. */ public T withFieldVisibility(Visibility v); // // Accessors /** * Method for checking whether given method is auto-detectable * as regular getter, with respect to its visibility (not considering * method signature or name, just visibility) */ public boolean isGetterVisible(Method m); public boolean isGetterVisible(AnnotatedMethod m); /** * Method for checking whether given method is auto-detectable * as is-getter, with respect to its visibility (not considering * method signature or name, just visibility) */ public boolean isIsGetterVisible(Method m); public boolean isIsGetterVisible(AnnotatedMethod m); /** * Method for checking whether given method is auto-detectable * as setter, with respect to its visibility (not considering * method signature or name, just visibility) */ public boolean isSetterVisible(Method m); public boolean isSetterVisible(AnnotatedMethod m); /** * Method for checking whether given method is auto-detectable * as Creator, with respect to its visibility (not considering * method signature or name, just visibility) */ public boolean isCreatorVisible(Member m); public boolean isCreatorVisible(AnnotatedMember m); /** * Method for checking whether given field is auto-detectable * as property, with respect to its visibility (not considering * method signature or name, just visibility) */ public boolean isFieldVisible(Field f); public boolean isFieldVisible(AnnotatedField f); /* /******************************************************** /* Standard implementation suitable for basic use /******************************************************** */ /** * Default standard implementation is purely based on visibility * modifier of given class members, and its configured minimum * levels. * Implemented using "builder" (or "Fluent") pattern, whereas instances * are immutable, and configuration is achieved by chainable factory * methods. As a result, type is declared is funky recursive generic * type, to allow for sub-classing of build methods with property type * co-variance. */ public static class Std implements VisibilityChecker, java.io.Serializable { private static final long serialVersionUID = 1; /** * This is the canonical base instance, configured with default * visibility values */ protected final static Std DEFAULT = new Std( Visibility.PUBLIC_ONLY, // getter Visibility.PUBLIC_ONLY, // is-getter Visibility.ANY, // setter Visibility.ANY, // creator -- legacy, to support single-arg ctors Visibility.PUBLIC_ONLY // field ); protected final Visibility _getterMinLevel; protected final Visibility _isGetterMinLevel; protected final Visibility _setterMinLevel; protected final Visibility _creatorMinLevel; protected final Visibility _fieldMinLevel; public static Std defaultInstance() { return DEFAULT; } /** * Constructor used for building instance that has minumum visibility * levels as indicated by given annotation instance * * @param ann Annotations to use for determining minimum visibility levels */ public Std(JsonAutoDetect ann) { // let's combine checks for enabled/disabled, with minimum level checks: _getterMinLevel = ann.getterVisibility(); _isGetterMinLevel = ann.isGetterVisibility(); _setterMinLevel = ann.setterVisibility(); _creatorMinLevel = ann.creatorVisibility(); _fieldMinLevel = ann.fieldVisibility(); } /** * Constructor that allows directly specifying minimum visibility levels to use */ public Std(Visibility getter, Visibility isGetter, Visibility setter, Visibility creator, Visibility field) { _getterMinLevel = getter; _isGetterMinLevel = isGetter; _setterMinLevel = setter; _creatorMinLevel = creator; _fieldMinLevel = field; } /** * Constructor that will assign given visibility value for all * properties. * * @param v level to use for all property types */ public Std(Visibility v) { // typically we shouldn't get this value; but let's handle it if we do: if (v == Visibility.DEFAULT) { _getterMinLevel = DEFAULT._getterMinLevel; _isGetterMinLevel = DEFAULT._isGetterMinLevel; _setterMinLevel = DEFAULT._setterMinLevel; _creatorMinLevel = DEFAULT._creatorMinLevel; _fieldMinLevel = DEFAULT._fieldMinLevel; } else { _getterMinLevel = v; _isGetterMinLevel = v; _setterMinLevel = v; _creatorMinLevel = v; _fieldMinLevel = v; } } /** * @since 2.9 */ public static Std construct(JsonAutoDetect.Value vis) { return DEFAULT.withOverrides(vis); } /* /******************************************************** /* Builder/fluent methods for instantiating configured /* instances /******************************************************** */ protected Std _with(Visibility g, Visibility isG, Visibility s, Visibility cr, Visibility f) { if ((g == _getterMinLevel) && (isG == _isGetterMinLevel) && (s == _setterMinLevel) && (cr == _creatorMinLevel) && (f == _fieldMinLevel) ) { return this; } return new Std(g, isG, s, cr, f); } @Override public Std with(JsonAutoDetect ann) { Std curr = this; if (ann != null) { return _with( _defaultOrOverride(_getterMinLevel, ann.getterVisibility()), _defaultOrOverride(_isGetterMinLevel, ann.isGetterVisibility()), _defaultOrOverride(_setterMinLevel, ann.setterVisibility()), _defaultOrOverride(_creatorMinLevel, ann.creatorVisibility()), _defaultOrOverride(_fieldMinLevel, ann.fieldVisibility()) ); } return curr; } @Override // since 2.9 public Std withOverrides(JsonAutoDetect.Value vis) { Std curr = this; if (vis != null) { return _with( _defaultOrOverride(_getterMinLevel, vis.getGetterVisibility()), _defaultOrOverride(_isGetterMinLevel, vis.getIsGetterVisibility()), _defaultOrOverride(_setterMinLevel, vis.getSetterVisibility()), _defaultOrOverride(_creatorMinLevel, vis.getCreatorVisibility()), _defaultOrOverride(_fieldMinLevel, vis.getFieldVisibility()) ); } return curr; } private Visibility _defaultOrOverride(Visibility defaults, Visibility override) { if (override == Visibility.DEFAULT) { return defaults; } return override; } @Override public Std with(Visibility v) { if (v == Visibility.DEFAULT) { return DEFAULT; } return new Std(v); } @Override public Std withVisibility(PropertyAccessor method, Visibility v) { switch (method) { case GETTER: return withGetterVisibility(v); case SETTER: return withSetterVisibility(v); case CREATOR: return withCreatorVisibility(v); case FIELD: return withFieldVisibility(v); case IS_GETTER: return withIsGetterVisibility(v); case ALL: return with(v); //case NONE: default: // break; return this; } } @Override public Std withGetterVisibility(Visibility v) { if (v == Visibility.DEFAULT) v = DEFAULT._getterMinLevel; if (_getterMinLevel == v) return this; return new Std(v, _isGetterMinLevel, _setterMinLevel, _creatorMinLevel, _fieldMinLevel); } @Override public Std withIsGetterVisibility(Visibility v) { if (v == Visibility.DEFAULT) v = DEFAULT._isGetterMinLevel; if (_isGetterMinLevel == v) return this; return new Std(_getterMinLevel, v, _setterMinLevel, _creatorMinLevel, _fieldMinLevel); } @Override public Std withSetterVisibility(Visibility v) { if (v == Visibility.DEFAULT) v = DEFAULT._setterMinLevel; if (_setterMinLevel == v) return this; return new Std(_getterMinLevel, _isGetterMinLevel, v, _creatorMinLevel, _fieldMinLevel); } @Override public Std withCreatorVisibility(Visibility v) { if (v == Visibility.DEFAULT) v = DEFAULT._creatorMinLevel; if (_creatorMinLevel == v) return this; return new Std(_getterMinLevel, _isGetterMinLevel, _setterMinLevel, v, _fieldMinLevel); } @Override public Std withFieldVisibility(Visibility v) { if (v == Visibility.DEFAULT) v = DEFAULT._fieldMinLevel; if (_fieldMinLevel == v) return this; return new Std(_getterMinLevel, _isGetterMinLevel, _setterMinLevel, _creatorMinLevel, v); } /* /******************************************************** /* Public API impl /******************************************************** */ @Override public boolean isCreatorVisible(Member m) { return _creatorMinLevel.isVisible(m); } @Override public boolean isCreatorVisible(AnnotatedMember m) { return isCreatorVisible(m.getMember()); } @Override public boolean isFieldVisible(Field f) { return _fieldMinLevel.isVisible(f); } @Override public boolean isFieldVisible(AnnotatedField f) { return isFieldVisible(f.getAnnotated()); } @Override public boolean isGetterVisible(Method m) { return _getterMinLevel.isVisible(m); } @Override public boolean isGetterVisible(AnnotatedMethod m) { return isGetterVisible(m.getAnnotated()); } @Override public boolean isIsGetterVisible(Method m) { return _isGetterMinLevel.isVisible(m); } @Override public boolean isIsGetterVisible(AnnotatedMethod m) { return isIsGetterVisible(m.getAnnotated()); } @Override public boolean isSetterVisible(Method m) { return _setterMinLevel.isVisible(m); } @Override public boolean isSetterVisible(AnnotatedMethod m) { return isSetterVisible(m.getAnnotated()); } /* /******************************************************** /* Standard methods /******************************************************** */ @Override public String toString() { return String.format("[Visibility: getter=%s,isGetter=%s,setter=%s,creator=%s,field=%s]", _getterMinLevel, _isGetterMinLevel, _setterMinLevel, _creatorMinLevel, _fieldMinLevel); } } } WithMember.java000066400000000000000000000002101325620701100355410ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; public interface WithMember { public T withMember(AnnotatedMember member); } package-info.java000066400000000000000000000010771325620701100360360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/introspect/** * Functionality needed for Bean introspection, required for detecting * accessors and mutators for Beans, as well as locating and handling * method annotations. *

* Beyond collecting annotations, additional "method annotation inheritance" * is also supported: whereas regular JDK classes do not add annotations * from overridden methods in any situation. But code in this package does. * Similarly class-annotations are inherited properly from interfaces, in * addition to abstract and concrete classes. */ package com.fasterxml.jackson.databind.introspect; jsonFormatVisitors/000077500000000000000000000000001325620701100343355ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databindJsonAnyFormatVisitor.java000066400000000000000000000006001325620701100413060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; public interface JsonAnyFormatVisitor { /** * Default "empty" implementation, useful as the base to start on; * especially as it is guaranteed to implement all the method * of the interface, even if new methods are getting added. */ public static class Base implements JsonAnyFormatVisitor { } } JsonArrayFormatVisitor.java000066400000000000000000000036341325620701100416470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.SerializerProvider; public interface JsonArrayFormatVisitor extends JsonFormatVisitorWithSerializerProvider { /** * Visit method called for structured types, as well as possibly * for leaf types (especially if handled by custom serializers). * * @param handler Serializer used, to allow for further callbacks * @param elementType Type of elements in JSON array value */ void itemsFormat(JsonFormatVisitable handler, JavaType elementType) throws JsonMappingException; /** * Visit method that is called if the content type is a simple * scalar type like {@link JsonFormatTypes#STRING} (but not * for structured types like {@link JsonFormatTypes#OBJECT} since * they would be missing type information). */ void itemsFormat(JsonFormatTypes format) throws JsonMappingException; /** * Default "empty" implementation, useful as the base to start on; * especially as it is guaranteed to implement all the method * of the interface, even if new methods are getting added. */ public static class Base implements JsonArrayFormatVisitor { protected SerializerProvider _provider; public Base() { } public Base(SerializerProvider p) { _provider = p; } @Override public SerializerProvider getProvider() { return _provider; } @Override public void setProvider(SerializerProvider p) { _provider = p; } @Override public void itemsFormat(JsonFormatVisitable handler, JavaType elementType) throws JsonMappingException { } @Override public void itemsFormat(JsonFormatTypes format) throws JsonMappingException { } } } JsonBooleanFormatVisitor.java000066400000000000000000000007231325620701100421440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; public interface JsonBooleanFormatVisitor extends JsonValueFormatVisitor { /** * Default "empty" implementation, useful as the base to start on; * especially as it is guaranteed to implement all the method * of the interface, even if new methods are getting added. */ public static class Base extends JsonValueFormatVisitor.Base implements JsonBooleanFormatVisitor { } } JsonFormatTypes.java000066400000000000000000000012371325620701100403120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; public enum JsonFormatTypes { STRING, NUMBER, INTEGER, BOOLEAN, OBJECT, ARRAY, NULL, ANY; private static final Map _byLCName = new HashMap(); static { for (JsonFormatTypes t : values()) { _byLCName.put(t.name().toLowerCase(), t); } } @JsonValue public String value() { return name().toLowerCase(); } @JsonCreator public static JsonFormatTypes forValue(String s) { return _byLCName.get(s); } }JsonFormatVisitable.java000066400000000000000000000012121325620701100411210ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; /** * Interface {@link com.fasterxml.jackson.databind.JsonSerializer} implements * to allow for visiting type hierarchy. */ public interface JsonFormatVisitable { /** * Get the representation of the schema to which this serializer will conform. * * @param typeHint Type of element (entity like property) being visited */ public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException; } JsonFormatVisitorWithSerializerProvider.java000066400000000000000000000005131325620701100452420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitors/** * */ package com.fasterxml.jackson.databind.jsonFormatVisitors; import com.fasterxml.jackson.databind.SerializerProvider; /** * @author jphelan */ public interface JsonFormatVisitorWithSerializerProvider { public SerializerProvider getProvider(); public abstract void setProvider(SerializerProvider provider); } JsonFormatVisitorWrapper.java000066400000000000000000000110741325620701100422060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.SerializerProvider; /** * Interface for visitor callbacks, when type in question can be any of * legal JSON types. *

* In most cases it will make more sense to extend {@link JsonFormatVisitorWrapper.Base} * instead of directly implementing this interface. */ public interface JsonFormatVisitorWrapper extends JsonFormatVisitorWithSerializerProvider { /** * @param type Declared type of visited property (or List element) in Java */ public JsonObjectFormatVisitor expectObjectFormat(JavaType type) throws JsonMappingException; /** * @param type Declared type of visited property (or List element) in Java */ public JsonArrayFormatVisitor expectArrayFormat(JavaType type) throws JsonMappingException; /** * @param type Declared type of visited property (or List element) in Java */ public JsonStringFormatVisitor expectStringFormat(JavaType type) throws JsonMappingException; /** * @param type Declared type of visited property (or List element) in Java */ public JsonNumberFormatVisitor expectNumberFormat(JavaType type) throws JsonMappingException; /** * @param type Declared type of visited property (or List element) in Java */ public JsonIntegerFormatVisitor expectIntegerFormat(JavaType type) throws JsonMappingException; /** * @param type Declared type of visited property (or List element) in Java */ public JsonBooleanFormatVisitor expectBooleanFormat(JavaType type) throws JsonMappingException; /** * @param type Declared type of visited property (or List element) in Java */ public JsonNullFormatVisitor expectNullFormat(JavaType type) throws JsonMappingException; /** * @param type Declared type of visited property (or List element) in Java */ public JsonAnyFormatVisitor expectAnyFormat(JavaType type) throws JsonMappingException; /** * Method called when type is of Java {@link java.util.Map} type, and will * be serialized as a JSON Object. * * @since 2.2 */ public JsonMapFormatVisitor expectMapFormat(JavaType type) throws JsonMappingException; /** * Empty "no-op" implementation of {@link JsonFormatVisitorWrapper}, suitable for * sub-classing. Does implement {@link #setProvider(SerializerProvider)} and * {@link #getProvider()} as expected; other methods simply return null * and do nothing. * * @since 2.5 */ public static class Base implements JsonFormatVisitorWrapper { protected SerializerProvider _provider; public Base() { } public Base(SerializerProvider p) { _provider = p; } @Override public SerializerProvider getProvider() { return _provider; } @Override public void setProvider(SerializerProvider p) { _provider = p; } @Override public JsonObjectFormatVisitor expectObjectFormat(JavaType type) throws JsonMappingException { return null; } @Override public JsonArrayFormatVisitor expectArrayFormat(JavaType type) throws JsonMappingException { return null; } @Override public JsonStringFormatVisitor expectStringFormat(JavaType type) throws JsonMappingException { return null; } @Override public JsonNumberFormatVisitor expectNumberFormat(JavaType type) throws JsonMappingException { return null; } @Override public JsonIntegerFormatVisitor expectIntegerFormat(JavaType type) throws JsonMappingException { return null; } @Override public JsonBooleanFormatVisitor expectBooleanFormat(JavaType type) throws JsonMappingException { return null; } @Override public JsonNullFormatVisitor expectNullFormat(JavaType type) throws JsonMappingException { return null; } @Override public JsonAnyFormatVisitor expectAnyFormat(JavaType type) throws JsonMappingException { return null; } @Override public JsonMapFormatVisitor expectMapFormat(JavaType type) throws JsonMappingException { return null; } } } JsonIntegerFormatVisitor.java000066400000000000000000000016411325620701100421620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; import com.fasterxml.jackson.core.JsonParser; public interface JsonIntegerFormatVisitor extends JsonValueFormatVisitor { /** * Method called to provide more exact type of number being serialized * (regardless of logical type, which may be {@link java.util.Date} or * {@link java.lang.Enum}, in addition to actual numeric types like * {@link java.lang.Integer}). */ public void numberType(JsonParser.NumberType type); /** * Default "empty" implementation, useful as the base to start on; * especially as it is guaranteed to implement all the method * of the interface, even if new methods are getting added. */ public static class Base extends JsonValueFormatVisitor.Base implements JsonIntegerFormatVisitor { @Override public void numberType(JsonParser.NumberType type) { } } } JsonMapFormatVisitor.java000066400000000000000000000031251325620701100413010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.SerializerProvider; public interface JsonMapFormatVisitor extends JsonFormatVisitorWithSerializerProvider { /** * Visit method called to indicate type of keys of the Map type * being visited */ public void keyFormat(JsonFormatVisitable handler, JavaType keyType) throws JsonMappingException; /** * Visit method called after {@link #keyFormat} to allow visiting of * the value type */ public void valueFormat(JsonFormatVisitable handler, JavaType valueType) throws JsonMappingException; /** * Default "empty" implementation, useful as the base to start on; * especially as it is guaranteed to implement all the method * of the interface, even if new methods are getting added. */ public static class Base implements JsonMapFormatVisitor { protected SerializerProvider _provider; public Base() { } public Base(SerializerProvider p) { _provider = p; } @Override public SerializerProvider getProvider() { return _provider; } @Override public void setProvider(SerializerProvider p) { _provider = p; } @Override public void keyFormat(JsonFormatVisitable handler, JavaType keyType) throws JsonMappingException { } @Override public void valueFormat(JsonFormatVisitable handler, JavaType valueType) throws JsonMappingException { } } } JsonNullFormatVisitor.java000066400000000000000000000006021325620701100414730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; public interface JsonNullFormatVisitor { /** * Default "empty" implementation, useful as the base to start on; * especially as it is guaranteed to implement all the method * of the interface, even if new methods are getting added. */ public static class Base implements JsonNullFormatVisitor { } } JsonNumberFormatVisitor.java000066400000000000000000000016371325620701100420220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; import com.fasterxml.jackson.core.JsonParser; public interface JsonNumberFormatVisitor extends JsonValueFormatVisitor { /** * Method called to provide more exact type of number being serialized * (regardless of logical type, which may be {@link java.util.Date} or * {@link java.lang.Enum}, in addition to actual numeric types like * {@link java.lang.Integer}). */ public void numberType(JsonParser.NumberType type); /** * Default "empty" implementation, useful as the base to start on; * especially as it is guaranteed to implement all the method * of the interface, even if new methods are getting added. */ public static class Base extends JsonValueFormatVisitor.Base implements JsonNumberFormatVisitor { @Override public void numberType(JsonParser.NumberType type) { } } } JsonObjectFormatVisitor.java000066400000000000000000000047021325620701100417740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.SerializerProvider; /** * Visitor called when properties of a type that maps to JSON Object * are being visited: this usually means POJOs, but sometimes other * types use it too (like {@link java.util.EnumMap}). */ public interface JsonObjectFormatVisitor extends JsonFormatVisitorWithSerializerProvider { /** * Callback method called when a POJO property is being traversed. */ public void property(BeanProperty writer) throws JsonMappingException; /** * Callback method called when a non-POJO property (typically something * like an Enum entry of {@link java.util.EnumMap} type) is being * traversed. With POJOs, {@link #property(BeanProperty)} is called instead. */ public void property(String name, JsonFormatVisitable handler, JavaType propertyTypeHint) throws JsonMappingException; public void optionalProperty(BeanProperty writer) throws JsonMappingException; public void optionalProperty(String name, JsonFormatVisitable handler, JavaType propertyTypeHint) throws JsonMappingException; /** * Default "empty" implementation, useful as the base to start on; * especially as it is guaranteed to implement all the method * of the interface, even if new methods are getting added. */ public static class Base implements JsonObjectFormatVisitor { protected SerializerProvider _provider; public Base() { } public Base(SerializerProvider p) { _provider = p; } @Override public SerializerProvider getProvider() { return _provider; } @Override public void setProvider(SerializerProvider p) { _provider = p; } @Override public void property(BeanProperty prop) throws JsonMappingException { } @Override public void property(String name, JsonFormatVisitable handler, JavaType propertyTypeHint) throws JsonMappingException { } @Override public void optionalProperty(BeanProperty prop) throws JsonMappingException { } @Override public void optionalProperty(String name, JsonFormatVisitable handler, JavaType propertyTypeHint) throws JsonMappingException { } } } JsonStringFormatVisitor.java000066400000000000000000000007221325620701100420320ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; public interface JsonStringFormatVisitor extends JsonValueFormatVisitor { /** * Default "empty" implementation, useful as the base to start on; * especially as it is guaranteed to implement all the method * of the interface, even if new methods are getting added. */ public static class Base extends JsonValueFormatVisitor.Base implements JsonStringFormatVisitor { } } JsonValueFormat.java000066400000000000000000000043651325620701100402670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; import com.fasterxml.jackson.annotation.JsonValue; /** * This enum represents the encoded format for a jsonSchema value type * @author jphelan * */ public enum JsonValueFormat { /** * This is a CSS color (like "#FF0000" or "red"), based on CSS 2.1 [W3C.CR-CSS21-20070719]. */ COLOR("color"), /** * This SHOULD be a date in the format of YYYY-MM-DD. It is recommended that you use the "date-time" format instead of "date" unless you need to transfer only the date part. */ DATE("date"), /** * This SHOULD be a date in ISO 8601 format of YYYY-MM- DDThh:mm:ssZ in UTC time. This is the recommended form of date/ timestamp. */ DATE_TIME("date-time"), /** * This SHOULD be an email address. */ EMAIL("email"), /** * This SHOULD be a host-name. */ HOST_NAME("host-name"), /** * This SHOULD be an ip version 4 address. */ IP_ADDRESS("ip-address"), /** * This SHOULD be an ip version 6 address. */ IPV6("ipv6"), /** * This SHOULD be a phone number (format MAY follow E.123). */ PHONE("phone"), /** * A regular expression, following the regular expression * specification from ECMA 262/Perl 5. */ REGEX("regex"), /** * This is a CSS style definition (like "color: red; background- * color:#FFF"), based on CSS 2.1 [W3C.CR-CSS21-20070719]. */ STYLE("style"), /** * This SHOULD be a time in the format of hh:mm:ss. It is * recommended that you use the "date-time" format instead of "time" * unless you need to transfer only the time part. */ TIME("time"), /** * This value SHOULD be a URI.. */ URI("uri"), /** * This SHOULD be the difference, measured in milliseconds, between the specified time and midnight, 00:00 of January 1, 1970 UTC. The value SHOULD be a number (integer or float). */ UTC_MILLISEC("utc-millisec"), ; private final String _desc; private JsonValueFormat(String desc) { _desc = desc; } @Override @JsonValue // since 2.7 public String toString() { return _desc; } } JsonValueFormatVisitor.java000066400000000000000000000015341325620701100416420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitorspackage com.fasterxml.jackson.databind.jsonFormatVisitors; import java.util.Set; public interface JsonValueFormatVisitor { /** * Method called to indicate configured format for value type being visited. */ void format(JsonValueFormat format); /** * Method called to indicate enumerated (String) values type being visited * can take as values. */ void enumTypes(Set enums); /** * Default "empty" implementation, useful as the base to start on; * especially as it is guaranteed to implement all the method * of the interface, even if new methods are getting added. */ public static class Base implements JsonValueFormatVisitor { @Override public void format(JsonValueFormat format) { } @Override public void enumTypes(Set enums) { } } } package-info.java000066400000000000000000000011661325620701100375300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitors/** * Classes used for exposing logical structure of POJOs as Jackson * sees it, and exposed via * {@link com.fasterxml.jackson.databind.ObjectMapper#acceptJsonFormatVisitor(Class, JsonFormatVisitorWrapper)} * and * {@link com.fasterxml.jackson.databind.ObjectMapper#acceptJsonFormatVisitor(com.fasterxml.jackson.databind.JavaType, JsonFormatVisitorWrapper)} * methods. *

* The main entrypoint for code, then, is {@link com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper} and other * types are recursively needed during traversal. */ package com.fasterxml.jackson.databind.jsonFormatVisitors; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonschema/000077500000000000000000000000001325620701100326615ustar00rootroot00000000000000JsonSchema.java000066400000000000000000000050261325620701100355020ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonschemapackage com.fasterxml.jackson.databind.jsonschema; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; /** * Container for a logical JSON Schema instance. * Internally schema data is stored as a JSON Tree * (instance of {@link JsonNode} is the root * of schema document) * * @author Ryan Heaton * @see JSON Schema * * @deprecated Since 2.2, we recommend use of external * JSON Schema generator module */ @Deprecated public class JsonSchema { private final ObjectNode schema; /** * Main constructor for schema instances. *

* This is the creator constructor used by Jackson itself when * deserializing instances. It is so-called delegating creator, * meaning that its argument will be bound by Jackson before * constructor gets called. */ @JsonCreator public JsonSchema(ObjectNode schema) { this.schema = schema; } /** * Method for accessing root JSON object of the contained schema. *

* Note: this method is specified with {@link JsonValue} annotation * to represent serialization to use; same as if explicitly * serializing returned object. * * @return Root node of the schema tree */ @JsonValue public ObjectNode getSchemaNode() { return schema; } @Override public String toString() { return this.schema.toString(); } @Override public int hashCode() { return schema.hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (!(o instanceof JsonSchema)) return false; JsonSchema other = (JsonSchema) o; if (schema == null) { return other.schema == null; } return schema.equals(other.schema); } /** * Get the default schema node. * * @return The default schema node. */ public static JsonNode getDefaultSchemaNode() { ObjectNode objectNode = JsonNodeFactory.instance.objectNode(); objectNode.put("type", "any"); // "required" is false by default, no need to include //objectNode.put("required", false); return objectNode; } } JsonSerializableSchema.java000066400000000000000000000045561325620701100400400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonschemapackage com.fasterxml.jackson.databind.jsonschema; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Retention; import java.lang.annotation.ElementType; import java.lang.annotation.Target; import com.fasterxml.jackson.annotation.JacksonAnnotation; /** * Annotation that can be used to define JSON Schema definition for * the annotated class. *

* Note that annotation is often not needed: for example, regular * Jackson beans that Jackson can introspect can be used without * annotations, to produce JSON schema definition. * * @author Ryan Heaton * @author Tatu Saloranta */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation public @interface JsonSerializableSchema { /** * Marker value used to indicate that property has "no value"; * needed because annotations cannot have null as default * value. */ public final static String NO_VALUE = "##irrelevant"; /** * Property that can be used to indicate id of the type when * generating JSON Schema; empty String indicates that no id * is defined. */ public String id() default ""; /** * The schema type for this JsonSerializable instance. * Possible values: "string", "number", "boolean", "object", "array", "null", "any" * * @return The schema type for this JsonSerializable instance. */ public String schemaType() default "any"; /** * If the schema type is "object", JSON definition of properties of the object as * a String. * * @return The node representing the schema properties, or "##irrelevant" if irrelevant. * * @deprecated (since 2.1) -- support will be dropped in future, since JSON-as-String is * fundamentally bad way for customizing anything. No direct replacements offered. */ @Deprecated public String schemaObjectPropertiesDefinition() default NO_VALUE; /** * If the schema type if "array", JSON definition of the schema for item types contained. * * @return The schema for the items in the array, or "##irrelevant" if irrelevant. * * @deprecated (since 2.1) -- support will be dropped in future, since JSON-as-String is * fundamentally bad way for customizing anything. No direct replacements offered. */ @Deprecated public String schemaItemDefinition() default NO_VALUE; } SchemaAware.java000066400000000000000000000022671325620701100356340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonschemapackage com.fasterxml.jackson.databind.jsonschema; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.SerializerProvider; import java.lang.reflect.Type; /** * Marker interface for schema-aware serializers. */ public interface SchemaAware { /** * Get the representation of the schema to which this serializer will conform. * * @param provider The serializer provider. * @param typeHint A hint about the type. * @return Json-schema for this serializer. */ public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException; /** * Get the representation of the schema to which this serializer will conform. * * @param provider The serializer provider. * @param isOptional Is the type optional * @param typeHint A hint about the type. * @return Json-schema for this serializer. */ public JsonNode getSchema(SerializerProvider provider, Type typeHint, boolean isOptional) throws JsonMappingException; } package-info.java000066400000000000000000000002761325620701100357760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsonschema/** * Classes needed for JSON schema support (currently just ability * to generate schemas using serialization part of data mapping) */ package com.fasterxml.jackson.databind.jsonschema; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/000077500000000000000000000000001325620701100324025ustar00rootroot00000000000000NamedType.java000066400000000000000000000025451325620701100350620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; /** * Simple container class for types with optional logical name, used * as external identifier */ public final class NamedType implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final Class _class; protected final int _hashCode; protected String _name; public NamedType(Class c) { this(c, null); } public NamedType(Class c, String name) { _class = c; _hashCode = c.getName().hashCode(); setName(name); } public Class getType() { return _class; } public String getName() { return _name; } public void setName(String name) { _name = (name == null || name.length() == 0) ? null : name; } public boolean hasName() { return _name != null; } /** * Equality is defined based on class only, not on name */ @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; return _class == ((NamedType) o)._class; } @Override public int hashCode() { return _hashCode; } @Override public String toString() { return "[NamedType, class "+_class.getName()+", name: " +(_name == null ? "null" :("'"+_name+"'"))+"]"; } } SubtypeResolver.java000066400000000000000000000126651325620701100363550ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.Collection; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; /** * Helper object used for handling registration on resolving of super-types * to sub-types. */ public abstract class SubtypeResolver { /* /********************************************************** /* Methods for registering external subtype definitions /********************************************************** */ /** * Method for registering specified subtypes (possibly including type * names); for type entries without name, non-qualified class name * as used as name (unless overridden by annotation). */ public abstract void registerSubtypes(NamedType... types); public abstract void registerSubtypes(Class... classes); /** * @since 2.9 */ public abstract void registerSubtypes(Collection> subtypes); /* /********************************************************** /* Subtype resolution /********************************************************** */ /** * Method for finding out all reachable subtypes for a property specified * by given element (method or field), * such that access is by type, * typically needed for serialization (converting from type to type name). * * @param baseType Effective property base type to use; may differ from * actual type of property; for structured types it is content (value) type and NOT * structured type. * * @since 2.6 */ public Collection collectAndResolveSubtypesByClass(MapperConfig config, AnnotatedMember property, JavaType baseType) { // for backwards compatibility... return collectAndResolveSubtypes(property, config, config.getAnnotationIntrospector(), baseType); } /** * Method for finding out all reachable subtypes for given type, * such that access is by type, * typically needed for serialization (converting from type to type name). * * @param baseType Effective property base type to use; may differ from * actual type of property; for structured types it is content (value) type and NOT * structured type. * * @since 2.6 */ public Collection collectAndResolveSubtypesByClass(MapperConfig config, AnnotatedClass baseType) { // for backwards compatibility... return collectAndResolveSubtypes(baseType, config, config.getAnnotationIntrospector()); } /** * Method for finding out all reachable subtypes for a property specified * by given element (method or field), * such that access is by type id, * typically needed for deserialization (converting from type id to type). * * @param baseType Effective property base type to use; may differ from * actual type of property; for structured types it is content (value) type and NOT * structured type. * * @since 2.6 */ public Collection collectAndResolveSubtypesByTypeId(MapperConfig config, AnnotatedMember property, JavaType baseType) { // for backwards compatibility... return collectAndResolveSubtypes(property, config, config.getAnnotationIntrospector(), baseType); } /** * Method for finding out all reachable subtypes for given type, * such that access is by type id, * typically needed for deserialization (converting from type id to type). * * @param baseType Effective property base type to use; may differ from * actual type of property; for structured types it is content (value) type and NOT * structured type. * * @since 2.6 */ public Collection collectAndResolveSubtypesByTypeId(MapperConfig config, AnnotatedClass baseType) { // for backwards compatibility... return collectAndResolveSubtypes(baseType, config, config.getAnnotationIntrospector()); } /* /********************************************************** /* Deprecated methods /********************************************************** */ /** * @deprecated Since 2.6 Use either * {@link #collectAndResolveSubtypesByClass(MapperConfig, AnnotatedMember, JavaType)} * or {@link #collectAndResolveSubtypesByTypeId(MapperConfig, AnnotatedMember, JavaType)} * instead. */ @Deprecated public Collection collectAndResolveSubtypes(AnnotatedMember property, MapperConfig config, AnnotationIntrospector ai, JavaType baseType) { return collectAndResolveSubtypesByClass(config, property, baseType); } /** * @deprecated Since 2.6 Use either * {@link #collectAndResolveSubtypesByClass(MapperConfig, AnnotatedClass)} * or {@link #collectAndResolveSubtypesByTypeId(MapperConfig, AnnotatedClass)} * instead. */ @Deprecated public Collection collectAndResolveSubtypes(AnnotatedClass baseType, MapperConfig config, AnnotationIntrospector ai) { return collectAndResolveSubtypesByClass(config, baseType); } } TypeDeserializer.java000066400000000000000000000147011325620701100364550ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; /** * Interface for deserializing type information from JSON content, to * type-safely deserialize data into correct polymorphic instance * (when type inclusion has been enabled for type handled). *

* Separate deserialization methods are needed because serialized * form for inclusion mechanism {@link As#PROPERTY} * is slighty different if value is not expressed as JSON Object: * and as such both type deserializer and serializer need to * JSON Object form (array, object or other (== scalar)) being used. */ public abstract class TypeDeserializer { /* /********************************************************** /* Initialization /********************************************************** */ /** * Method called to create contextual version, to be used for * values of given property. This may be the type itself * (as is the case for bean properties), or values contained * (for {@link java.util.Collection} or {@link java.util.Map} * valued properties). */ public abstract TypeDeserializer forProperty(BeanProperty prop); /* /********************************************************** /* Introspection /********************************************************** */ /** * Accessor for type information inclusion method * that deserializer uses; indicates how type information * is (expected to be) embedded in JSON input. */ public abstract As getTypeInclusion(); /** * Name of property that contains type information, if * property-based inclusion is used. */ public abstract String getPropertyName(); /** * Accessor for object that handles conversions between * types and matching type ids. */ public abstract TypeIdResolver getTypeIdResolver(); /** * Accessor for "default implementation" type; optionally defined * class to use in cases where type id is not * accessible for some reason (either missing, or cannot be * resolved) */ public abstract Class getDefaultImpl(); /* /********************************************************** /* Type deserialization methods /********************************************************** */ /** * Method called to let this type deserializer handle * deserialization of "typed" object, when value itself * is serialized as JSON Object (regardless of Java type). * Method needs to figure out intended * polymorphic type, locate {@link JsonDeserializer} to use, and * call it with JSON data to deserializer (which does not contain * type information). */ public abstract Object deserializeTypedFromObject(JsonParser p, DeserializationContext ctxt) throws IOException; /** * Method called to let this type deserializer handle * deserialization of "typed" object, when value itself * is serialized as JSON Array (regardless of Java type). * Method needs to figure out intended * polymorphic type, locate {@link JsonDeserializer} to use, and * call it with JSON data to deserializer (which does not contain * type information). */ public abstract Object deserializeTypedFromArray(JsonParser p, DeserializationContext ctxt) throws IOException; /** * Method called to let this type deserializer handle * deserialization of "typed" object, when value itself * is serialized as a scalar JSON value (something other * than Array or Object), regardless of Java type. * Method needs to figure out intended * polymorphic type, locate {@link JsonDeserializer} to use, and * call it with JSON data to deserializer (which does not contain * type information). */ public abstract Object deserializeTypedFromScalar(JsonParser p, DeserializationContext ctxt) throws IOException; /** * Method called to let this type deserializer handle * deserialization of "typed" object, when value itself * may have been serialized using any kind of JSON value * (Array, Object, scalar). Should only be called if JSON * serialization is polymorphic (not Java type); for example when * using JSON node representation, or "untyped" Java object * (which may be Map, Collection, wrapper/primitive etc). */ public abstract Object deserializeTypedFromAny(JsonParser p, DeserializationContext ctxt) throws IOException; /* /********************************************************** /* Shared helper methods /********************************************************** */ /** * Helper method used to check if given parser might be pointing to * a "natural" value, and one that would be acceptable as the * result value (compatible with declared base type) */ public static Object deserializeIfNatural(JsonParser p, DeserializationContext ctxt, JavaType baseType) throws IOException { return deserializeIfNatural(p, ctxt, baseType.getRawClass()); } @SuppressWarnings("incomplete-switch") public static Object deserializeIfNatural(JsonParser p, DeserializationContext ctxt, Class base) throws IOException { JsonToken t = p.getCurrentToken(); if (t == null) { return null; } switch (t) { case VALUE_STRING: if (base.isAssignableFrom(String.class)) { return p.getText(); } break; case VALUE_NUMBER_INT: if (base.isAssignableFrom(Integer.class)) { return p.getIntValue(); } break; case VALUE_NUMBER_FLOAT: if (base.isAssignableFrom(Double.class)) { return Double.valueOf(p.getDoubleValue()); } break; case VALUE_TRUE: if (base.isAssignableFrom(Boolean.class)) { return Boolean.TRUE; } break; case VALUE_FALSE: if (base.isAssignableFrom(Boolean.class)) { return Boolean.FALSE; } break; } return null; } } TypeIdResolver.java000066400000000000000000000070451325620701100361140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.DatabindContext; import com.fasterxml.jackson.databind.JavaType; /** * Interface that defines standard API for converting types * to type identifiers and vice versa. Used by type resolvers * ({@link com.fasterxml.jackson.databind.jsontype.TypeSerializer}, * {@link com.fasterxml.jackson.databind.jsontype.TypeDeserializer}) for converting * between type and matching id; id is stored in JSON and needed for * creating instances of proper subtypes when deserializing values. *

* NOTE: it is strongly recommended that developers always extend * abstract base class {@link com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase} * instead of directly implementing this interface; this helps prevent * breakage in case new methds need to be added in this interface (something * we try to avoid doing; but which may be necessary in some cases). */ public interface TypeIdResolver { /* /********************************************************** /* Initialization/configuration methods /********************************************************** */ /** * Method that will be called once before any type resolution calls; * used to initialize instance with configuration. This is necessary * since instances may be created via reflection, without ability to * call specific constructor to pass in configuration settings. * * @param baseType Base type for which this id resolver instance is * used */ public void init(JavaType baseType); /* /********************************************************** /* Conversions between types and type ids /********************************************************** */ /** * Method called to serialize type of the type of given value * as a String to include in serialized JSON content. */ public String idFromValue(Object value); /** * Alternative method used for determining type from combination of * value and type, using suggested type (that serializer provides) * and possibly value of that type. Most common implementation will * use suggested type as is. */ public String idFromValueAndType(Object value, Class suggestedType); /** * Method that can be called to figure out type id to use for instances * of base type (declared type of property). This is usually only used * for fallback handling, for cases where real type information is not * available for some reason. */ public String idFromBaseType(); /** * Method called to resolve type from given type identifier. * * @since 2.5 (throws clause added in 2.8) */ public JavaType typeFromId(DatabindContext context, String id) throws IOException; /** * Method called for error-reporting and diagnostics purposes. * * @since 2.7 -- but since 2.5 has existed in {@link com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase} */ public String getDescForKnownTypeIds(); /* /********************************************************** /* Accessors for metadata /********************************************************** */ /** * Accessor for mechanism that this resolver uses for determining * type id from type. Mostly informational; not required to be called * or used. */ public JsonTypeInfo.Id getMechanism(); } TypeResolverBuilder.java000066400000000000000000000134641325620701100371500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.Collection; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.SerializationConfig; /** * Interface that defines builders that are configured based on * annotations (like {@link com.fasterxml.jackson.annotation.JsonTypeInfo} or JAXB annotations), * and produce type serializers and deserializers used for * handling type information embedded in JSON to allow for safe * polymorphic type handling. *

* Builder is first initialized by calling {@link #init} method, and then * configured using 'set' methods like {@link #inclusion}. * Finally, after calling all configuration methods, * {@link #buildTypeSerializer} or {@link #buildTypeDeserializer} * will be called to get actual type resolver constructed * and used for resolving types for configured base type and its * subtypes. *

* Note that instances are used for two related but distinct use cases: *

    *
  • To create builders to use with explicit type information * inclusion (usually via @JsonTypeInfo annotation) *
  • *
  • To create builders when "default typing" is used; if so, type information * is automatically included for certain kind of types, regardless of annotations *
  • *
* Important distinction between the cases is that in first case, calls to * create builders are only made when builders are certainly needed; whereas * in second case builder has to first verify whether type information is * applicable for given type, and if not, just return null to indicate this. */ public interface TypeResolverBuilder> { /* /********************************************************** /* Accessors /********************************************************** */ /** * Accessor for currently configured default type; implementation * class that may be used in case no valid type information is * available during type resolution */ public Class getDefaultImpl(); /* /********************************************************** /* Actual builder methods /********************************************************** */ /** * Method for building type serializer based on current configuration * of this builder. * * @param baseType Base type that constructed resolver will * handle; super type of all types it will be used for. */ public TypeSerializer buildTypeSerializer(SerializationConfig config, JavaType baseType, Collection subtypes); /** * Method for building type deserializer based on current configuration * of this builder. * * @param baseType Base type that constructed resolver will * handle; super type of all types it will be used for. * @param subtypes Known subtypes of the base type. */ public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, JavaType baseType, Collection subtypes); /* /********************************************************** /* Initialization method(s) that must be called before other /* configuration /********************************************************** */ /** * Initialization method that is called right after constructing * the builder instance. * * @param idType Which type metadata is used * @param res (optional) Custom type id resolver used, if any * * @return Resulting builder instance (usually this builder, * but not necessarily) */ public T init(JsonTypeInfo.Id idType, TypeIdResolver res); /* /********************************************************** /* Methods for configuring resolver to build /********************************************************** */ /** * Method for specifying mechanism to use for including type metadata * in JSON. * If not explicitly called, setting defaults to * {@link As#PROPERTY}. * * @param includeAs Mechanism used for including type metadata in JSON * * @return Resulting builder instance (usually this builder, * but may be a newly constructed instance for immutable builders} */ public T inclusion(As includeAs); /** * Method for specifying name of property used for including type * information. Not used for all inclusion mechanisms; * usually only used with {@link As#PROPERTY}. *

* If not explicitly called, name of property to use is based on * defaults for {@link com.fasterxml.jackson.annotation.JsonTypeInfo.Id} configured. * * @param propName Name of JSON property to use for including * type information * * @return Resulting builder instance (usually this builder, * but may be a newly constructed instance for immutable builders} */ public T typeProperty(String propName); /** * Method for specifying default implementation to use if type id * is either not available, or cannot be resolved. * * @return Resulting builder instance (usually this builder, * but may be a newly constructed instance for immutable builders} */ public T defaultImpl(Class defaultImpl); /** * Method for specifying whether type id should be visible to * {@link com.fasterxml.jackson.databind.JsonDeserializer}s or not. * * @return Resulting builder instance (usually this builder, * but may be a newly constructed instance for immutable builders} * * @since 2.0 */ public T typeIdVisibility(boolean isVisible); } TypeSerializer.java000066400000000000000000000270021325620701100361420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.core.util.VersionUtil; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; /** * Interface for serializing type information regarding instances of specified * base type (super class), so that exact subtype can be properly deserialized * later on. These instances are to be called by regular * {@link com.fasterxml.jackson.databind.JsonSerializer}s using proper contextual * calls, to add type information using mechanism type serializer was * configured with. *

* NOTE: version 2.9 contains significant attempt at simplifying interface, * as well as giving format implementation (via {@link JsonGenerator}) more * control over actual serialization details. */ public abstract class TypeSerializer { /* /********************************************************** /* Initialization /********************************************************** */ /** * Method called to create contextual version, to be used for * values of given property. This may be the type itself * (as is the case for bean properties), or values contained * (for {@link java.util.Collection} or {@link java.util.Map} * valued properties). * * @since 2.0 */ public abstract TypeSerializer forProperty(BeanProperty prop); /* /********************************************************** /* Introspection /********************************************************** */ /** * Accessor for type information inclusion method * that serializer uses; indicates how type information * is embedded in resulting JSON. */ public abstract JsonTypeInfo.As getTypeInclusion(); /** * Name of property that contains type information, if * property-based inclusion is used. */ public abstract String getPropertyName(); /** * Accessor for object that handles conversions between * types and matching type ids. */ public abstract TypeIdResolver getTypeIdResolver(); /* /********************************************************** /* Type serialization methods: new (2.9) /********************************************************** */ /** * Factory method for constructing type id value object to pass to * {@link #writeTypePrefix}. */ public WritableTypeId typeId(Object value, JsonToken valueShape) { WritableTypeId typeIdDef = new WritableTypeId(value, valueShape); switch (getTypeInclusion()) { case EXISTING_PROPERTY: typeIdDef.include = WritableTypeId.Inclusion.PAYLOAD_PROPERTY; typeIdDef.asProperty = getPropertyName(); break; case EXTERNAL_PROPERTY: typeIdDef.include = WritableTypeId.Inclusion.PARENT_PROPERTY; typeIdDef.asProperty = getPropertyName(); break; case PROPERTY: typeIdDef.include = WritableTypeId.Inclusion.METADATA_PROPERTY; typeIdDef.asProperty = getPropertyName(); break; case WRAPPER_ARRAY: typeIdDef.include = WritableTypeId.Inclusion.WRAPPER_ARRAY; break; case WRAPPER_OBJECT: typeIdDef.include = WritableTypeId.Inclusion.WRAPPER_OBJECT; break; default: VersionUtil.throwInternal(); } return typeIdDef; } public WritableTypeId typeId(Object value, JsonToken valueShape, Object id) { WritableTypeId typeId = typeId(value, valueShape); typeId.id = id; return typeId; } public WritableTypeId typeId(Object value, Class typeForId, JsonToken valueShape) { WritableTypeId typeId = typeId(value, valueShape); typeId.forValueType = typeForId; return typeId; } /** * Method called to write initial part of type information for given * value, along with possible wrapping to use: details are specified * by `typeId` argument. * * @param g Generator to use for outputting type id and possible wrapping * @param typeId Details of what type id is to be written, how. * * @since 2.9 */ public abstract WritableTypeId writeTypePrefix(JsonGenerator g, WritableTypeId typeId) throws IOException; /** * @since 2.9 */ public abstract WritableTypeId writeTypeSuffix(JsonGenerator g, WritableTypeId typeId) throws IOException; /* /********************************************************** /* Legacy type serialization methods /********************************************************** */ /** * Method called to write initial part of type information for given * value, when it will be output as scalar JSON value (not as JSON * Object or Array). * This means that the context after call cannot be that of JSON Object; * it may be Array or root context. * * @param value Value that will be serialized, for which type information is * to be written * @param g Generator to use for writing type information */ @Deprecated // since 2.9 public void writeTypePrefixForScalar(Object value, JsonGenerator g) throws IOException { writeTypePrefix(g, typeId(value, JsonToken.VALUE_STRING)); } /** * Method called to write initial part of type information for given * value, when it will be output as JSON Object value (not as JSON * Array or scalar). * This means that context after call must be JSON Object, meaning that * caller can then proceed to output field entries. * * @param value Value that will be serialized, for which type information is * to be written * @param g Generator to use for writing type information */ @Deprecated // since 2.9 public void writeTypePrefixForObject(Object value, JsonGenerator g) throws IOException { writeTypePrefix(g, typeId(value, JsonToken.START_OBJECT)); } /** * Method called to write initial part of type information for given * value, when it will be output as JSON Array value (not as JSON * Object or scalar). * This means that context after call must be JSON Array, that is, there * must be an open START_ARRAY to write contents in. * * @param value Value that will be serialized, for which type information is * to be written * @param g Generator to use for writing type information */ @Deprecated // since 2.9 public void writeTypePrefixForArray(Object value, JsonGenerator g) throws IOException { writeTypePrefix(g, typeId(value, JsonToken.START_ARRAY)); } /** * Method called after value has been serialized, to close any scopes opened * by earlier matching call to {@link #writeTypePrefixForScalar}. * Actual action to take may depend on various factors, but has to match with * action {@link #writeTypePrefixForScalar} did (close array or object; or do nothing). */ @Deprecated // since 2.9 public void writeTypeSuffixForScalar(Object value, JsonGenerator g) throws IOException { _writeLegacySuffix(g, typeId(value, JsonToken.VALUE_STRING)); } /** * Method called after value has been serialized, to close any scopes opened * by earlier matching call to {@link #writeTypePrefixForObject}. * It needs to write closing END_OBJECT marker, and any other decoration * that needs to be matched. */ @Deprecated // since 2.9 public void writeTypeSuffixForObject(Object value, JsonGenerator g) throws IOException { _writeLegacySuffix(g, typeId(value, JsonToken.START_OBJECT)); } /** * Method called after value has been serialized, to close any scopes opened * by earlier matching call to {@link #writeTypeSuffixForScalar}. * It needs to write closing END_ARRAY marker, and any other decoration * that needs to be matched. */ @Deprecated // since 2.9 public void writeTypeSuffixForArray(Object value, JsonGenerator g) throws IOException { _writeLegacySuffix(g, typeId(value, JsonToken.START_ARRAY)); } /** * Alternative version of the prefix-for-scalar method, which is given * actual type to use (instead of using exact type of the value); typically * a super type of actual value type */ @Deprecated // since 2.9 public void writeTypePrefixForScalar(Object value, JsonGenerator g, Class type) throws IOException { writeTypePrefix(g, typeId(value, type, JsonToken.VALUE_STRING)); } /** * Alternative version of the prefix-for-object method, which is given * actual type to use (instead of using exact type of the value); typically * a super type of actual value type */ @Deprecated // since 2.9 public void writeTypePrefixForObject(Object value, JsonGenerator g, Class type) throws IOException { writeTypePrefix(g, typeId(value, type, JsonToken.START_OBJECT)); } /** * Alternative version of the prefix-for-array method, which is given * actual type to use (instead of using exact type of the value); typically * a super type of actual value type */ @Deprecated // since 2.9 public void writeTypePrefixForArray(Object value, JsonGenerator g, Class type) throws IOException { writeTypePrefix(g, typeId(value, type, JsonToken.START_ARRAY)); } /* /********************************************************** /* Type serialization methods with type id override /********************************************************** */ @Deprecated // since 2.9 public void writeCustomTypePrefixForScalar(Object value, JsonGenerator g, String typeId) throws IOException { writeTypePrefix(g, typeId(value, JsonToken.VALUE_STRING, typeId)); } @Deprecated // since 2.9 public void writeCustomTypePrefixForObject(Object value, JsonGenerator g, String typeId) throws IOException { writeTypePrefix(g, typeId(value, JsonToken.START_OBJECT, typeId)); } @Deprecated // since 2.9 public void writeCustomTypePrefixForArray(Object value, JsonGenerator g, String typeId) throws IOException { writeTypePrefix(g, typeId(value, JsonToken.START_ARRAY, typeId)); } @Deprecated // since 2.9 public void writeCustomTypeSuffixForScalar(Object value, JsonGenerator g, String typeId) throws IOException { _writeLegacySuffix(g, typeId(value, JsonToken.VALUE_STRING, typeId)); } @Deprecated // since 2.9 public void writeCustomTypeSuffixForObject(Object value, JsonGenerator g, String typeId) throws IOException { _writeLegacySuffix(g, typeId(value, JsonToken.START_OBJECT, typeId)); } @Deprecated // since 2.9 public void writeCustomTypeSuffixForArray(Object value, JsonGenerator g, String typeId) throws IOException { _writeLegacySuffix(g, typeId(value, JsonToken.START_ARRAY, typeId)); } /** * Helper method needed for backwards compatibility: since original type id * can not be routed through completely, we have to reverse-engineer likely * setting before calling suffix. * * @since 2.9 */ protected final void _writeLegacySuffix(JsonGenerator g, WritableTypeId typeId) throws IOException { // most likely logic within generator is this: typeId.wrapperWritten = !g.canWriteTypeId(); writeTypeSuffix(g, typeId); } } jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/000077500000000000000000000000001325620701100333435ustar00rootroot00000000000000AsArrayTypeDeserializer.java000066400000000000000000000143001325620701100406740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.util.JsonParserSequence; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Type deserializer used with {@link As#WRAPPER_ARRAY} * inclusion mechanism. Simple since JSON structure used is always * the same, regardless of structure used for actual value: wrapping * is done using a 2-element JSON Array where type id is the first * element, and actual object data as second element. */ public class AsArrayTypeDeserializer extends TypeDeserializerBase implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * @since 2.8 */ public AsArrayTypeDeserializer(JavaType bt, TypeIdResolver idRes, String typePropertyName, boolean typeIdVisible, JavaType defaultImpl) { super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl); } public AsArrayTypeDeserializer(AsArrayTypeDeserializer src, BeanProperty property) { super(src, property); } @Override public TypeDeserializer forProperty(BeanProperty prop) { // usually if it's null: return (prop == _property) ? this : new AsArrayTypeDeserializer(this, prop); } @Override public As getTypeInclusion() { return As.WRAPPER_ARRAY; } /** * Method called when actual object is serialized as JSON Array. */ @Override public Object deserializeTypedFromArray(JsonParser jp, DeserializationContext ctxt) throws IOException { return _deserialize(jp, ctxt); } /** * Method called when actual object is serialized as JSON Object */ @Override public Object deserializeTypedFromObject(JsonParser jp, DeserializationContext ctxt) throws IOException { return _deserialize(jp, ctxt); } @Override public Object deserializeTypedFromScalar(JsonParser jp, DeserializationContext ctxt) throws IOException { return _deserialize(jp, ctxt); } @Override public Object deserializeTypedFromAny(JsonParser jp, DeserializationContext ctxt) throws IOException { return _deserialize(jp, ctxt); } /* /*************************************************************** /* Internal methods /*************************************************************** */ /** * Method that handles type information wrapper, locates actual * subtype deserializer to use, and calls it to do actual * deserialization. */ @SuppressWarnings("resource") protected Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 02-Aug-2013, tatu: May need to use native type ids if (p.canReadTypeId()) { Object typeId = p.getTypeId(); if (typeId != null) { return _deserializeWithNativeTypeId(p, ctxt, typeId); } } boolean hadStartArray = p.isExpectedStartArrayToken(); String typeId = _locateTypeId(p, ctxt); JsonDeserializer deser = _findDeserializer(ctxt, typeId); // Minor complication: we may need to merge type id in? if (_typeIdVisible // 06-Oct-2014, tatu: To fix [databind#408], must distinguish between // internal and external properties // TODO: but does it need to be injected in external case? Why not? && !_usesExternalId() && p.getCurrentToken() == JsonToken.START_OBJECT) { // but what if there's nowhere to add it in? Error? Or skip? For now, skip. TokenBuffer tb = new TokenBuffer(null, false); tb.writeStartObject(); // recreate START_OBJECT tb.writeFieldName(_typePropertyName); tb.writeString(typeId); // 02-Jul-2016, tatu: Depending on for JsonParserSequence is initialized it may // try to access current token; ensure there isn't one p.clearCurrentToken(); p = JsonParserSequence.createFlattened(false, tb.asParser(p), p); p.nextToken(); } Object value = deser.deserialize(p, ctxt); // And then need the closing END_ARRAY if (hadStartArray && p.nextToken() != JsonToken.END_ARRAY) { ctxt.reportWrongTokenException(baseType(), JsonToken.END_ARRAY, "expected closing END_ARRAY after type information and deserialized value"); // 05-May-2016, tatu: Not 100% what to do if exception is stored for // future, and not thrown immediately: should probably skip until END_ARRAY // ... but for now, fall through } return value; } protected String _locateTypeId(JsonParser p, DeserializationContext ctxt) throws IOException { if (!p.isExpectedStartArrayToken()) { // Need to allow even more customized handling, if something unexpected seen... // but should there be a way to limit this to likely success cases? if (_defaultImpl != null) { return _idResolver.idFromBaseType(); } ctxt.reportWrongTokenException(baseType(), JsonToken.START_ARRAY, "need JSON Array to contain As.WRAPPER_ARRAY type information for class "+baseTypeName()); return null; } // And then type id as a String JsonToken t = p.nextToken(); if (t == JsonToken.VALUE_STRING) { String result = p.getText(); p.nextToken(); return result; } if (_defaultImpl != null) { return _idResolver.idFromBaseType(); } ctxt.reportWrongTokenException(baseType(), JsonToken.VALUE_STRING, "need JSON String that contains type id (for subtype of %s)", baseTypeName()); return null; } /** * @since 2.5 */ protected boolean _usesExternalId() { return false; } } AsArrayTypeSerializer.java000066400000000000000000000014511325620701100403660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; /** * Type serializer that will embed type information in an array, * as the first element, and actual value as the second element. */ public class AsArrayTypeSerializer extends TypeSerializerBase { public AsArrayTypeSerializer(TypeIdResolver idRes, BeanProperty property) { super(idRes, property); } @Override public AsArrayTypeSerializer forProperty(BeanProperty prop) { return (_property == prop) ? this : new AsArrayTypeSerializer(_idResolver, prop); } @Override public As getTypeInclusion() { return As.WRAPPER_ARRAY; } } AsExistingPropertyTypeSerializer.java000066400000000000000000000017041325620701100426500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; /** * Type serializer used with {@link As#EXISTING_PROPERTY} inclusion mechanism. * Expects type information to be a well-defined property on all sub-classes. */ public class AsExistingPropertyTypeSerializer extends AsPropertyTypeSerializer { public AsExistingPropertyTypeSerializer(TypeIdResolver idRes, BeanProperty property, String propName) { super(idRes, property, propName); } @Override public AsExistingPropertyTypeSerializer forProperty(BeanProperty prop) { return (_property == prop) ? this : new AsExistingPropertyTypeSerializer(_idResolver, prop, _typePropertyName); } @Override public As getTypeInclusion() { return As.EXISTING_PROPERTY; } } AsExternalTypeDeserializer.java000066400000000000000000000034031325620701100414020ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; /** * Type deserializer used with {@link As#EXTERNAL_PROPERTY} inclusion mechanism. * Actual implementation may look bit strange since it depends on comprehensive * pre-processing done by {@link com.fasterxml.jackson.databind.deser.BeanDeserializer} * to basically transform external type id into structure that looks more like * "wrapper-array" style inclusion. This intermediate form is chosen to allow * supporting all possible JSON structures. */ public class AsExternalTypeDeserializer extends AsArrayTypeDeserializer { private static final long serialVersionUID = 1L; /** * @since 2.8 */ public AsExternalTypeDeserializer(JavaType bt, TypeIdResolver idRes, String typePropertyName, boolean typeIdVisible, JavaType defaultImpl) { super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl); } public AsExternalTypeDeserializer(AsExternalTypeDeserializer src, BeanProperty property) { super(src, property); } @Override public TypeDeserializer forProperty(BeanProperty prop) { if (prop == _property) { // usually if it's null return this; } return new AsExternalTypeDeserializer(this, prop); } @Override public As getTypeInclusion() { return As.EXTERNAL_PROPERTY; } // yes, very important distinction... @Override protected boolean _usesExternalId() { return true; } } AsExternalTypeSerializer.java000066400000000000000000000055241325620701100410770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; /** * Type serializer that preferably embeds type information as an "external" * type property; embedded in enclosing JSON object. * Note that this serializer should only be used when value is being output * at JSON Object context; otherwise it cannot work reliably, and will have * to revert operation similar to {@link AsPropertyTypeSerializer}. *

* Note that implementation of serialization is bit cumbersome as we must * serialized external type id AFTER object; this because callback only * occurs after field name has been written. *

* Also note that this type of type id inclusion will NOT try to make use * of native Type Ids, even if those exist. */ public class AsExternalTypeSerializer extends TypeSerializerBase { protected final String _typePropertyName; public AsExternalTypeSerializer(TypeIdResolver idRes, BeanProperty property, String propName) { super(idRes, property); _typePropertyName = propName; } @Override public AsExternalTypeSerializer forProperty(BeanProperty prop) { return (_property == prop) ? this : new AsExternalTypeSerializer(_idResolver, prop, _typePropertyName); } @Override public String getPropertyName() { return _typePropertyName; } @Override public As getTypeInclusion() { return As.EXTERNAL_PROPERTY; } /* /********************************************************** /* Helper methods /********************************************************** */ // nothing to wrap it with: protected final void _writeScalarPrefix(Object value, JsonGenerator g) throws IOException { } protected final void _writeObjectPrefix(Object value, JsonGenerator g) throws IOException { g.writeStartObject(); } protected final void _writeArrayPrefix(Object value, JsonGenerator g) throws IOException { g.writeStartArray(); } protected final void _writeScalarSuffix(Object value, JsonGenerator g, String typeId) throws IOException { if (typeId != null) { g.writeStringField(_typePropertyName, typeId); } } protected final void _writeObjectSuffix(Object value, JsonGenerator g, String typeId) throws IOException { g.writeEndObject(); if (typeId != null) { g.writeStringField(_typePropertyName, typeId); } } protected final void _writeArraySuffix(Object value, JsonGenerator g, String typeId) throws IOException { g.writeEndArray(); if (typeId != null) { g.writeStringField(_typePropertyName, typeId); } } } AsPropertyTypeDeserializer.java000066400000000000000000000200551325620701100414460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.util.JsonParserSequence; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Type deserializer used with {@link As#PROPERTY} * inclusion mechanism. * Uses regular form (additional key/value entry before actual data) * when typed object is expressed as JSON Object; otherwise behaves similar to how * {@link As#WRAPPER_ARRAY} works. * Latter is used if JSON representation is polymorphic */ public class AsPropertyTypeDeserializer extends AsArrayTypeDeserializer { private static final long serialVersionUID = 1L; protected final As _inclusion; /** * @since 2.8 */ public AsPropertyTypeDeserializer(JavaType bt, TypeIdResolver idRes, String typePropertyName, boolean typeIdVisible, JavaType defaultImpl) { this(bt, idRes, typePropertyName, typeIdVisible, defaultImpl, As.PROPERTY); } /** * @since 2.8 */ public AsPropertyTypeDeserializer(JavaType bt, TypeIdResolver idRes, String typePropertyName, boolean typeIdVisible, JavaType defaultImpl, As inclusion) { super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl); _inclusion = inclusion; } public AsPropertyTypeDeserializer(AsPropertyTypeDeserializer src, BeanProperty property) { super(src, property); _inclusion = src._inclusion; } @Override public TypeDeserializer forProperty(BeanProperty prop) { return (prop == _property) ? this : new AsPropertyTypeDeserializer(this, prop); } @Override public As getTypeInclusion() { return _inclusion; } /** * This is the trickiest thing to handle, since property we are looking * for may be anywhere... */ @Override @SuppressWarnings("resource") public Object deserializeTypedFromObject(JsonParser p, DeserializationContext ctxt) throws IOException { // 02-Aug-2013, tatu: May need to use native type ids if (p.canReadTypeId()) { Object typeId = p.getTypeId(); if (typeId != null) { return _deserializeWithNativeTypeId(p, ctxt, typeId); } } // but first, sanity check to ensure we have START_OBJECT or FIELD_NAME JsonToken t = p.getCurrentToken(); if (t == JsonToken.START_OBJECT) { t = p.nextToken(); } else if (/*t == JsonToken.START_ARRAY ||*/ t != JsonToken.FIELD_NAME) { /* This is most likely due to the fact that not all Java types are * serialized as JSON Objects; so if "as-property" inclusion is requested, * serialization of things like Lists must be instead handled as if * "as-wrapper-array" was requested. * But this can also be due to some custom handling: so, if "defaultImpl" * is defined, it will be asked to handle this case. */ return _deserializeTypedUsingDefaultImpl(p, ctxt, null); } // Ok, let's try to find the property. But first, need token buffer... TokenBuffer tb = null; for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String name = p.getCurrentName(); p.nextToken(); // to point to the value if (name.equals(_typePropertyName)) { // gotcha! return _deserializeTypedForId(p, ctxt, tb); } if (tb == null) { tb = new TokenBuffer(p, ctxt); } tb.writeFieldName(name); tb.copyCurrentStructure(p); } return _deserializeTypedUsingDefaultImpl(p, ctxt, tb); } @SuppressWarnings("resource") protected Object _deserializeTypedForId(JsonParser p, DeserializationContext ctxt, TokenBuffer tb) throws IOException { String typeId = p.getText(); JsonDeserializer deser = _findDeserializer(ctxt, typeId); if (_typeIdVisible) { // need to merge id back in JSON input? if (tb == null) { tb = new TokenBuffer(p, ctxt); } tb.writeFieldName(p.getCurrentName()); tb.writeString(typeId); } if (tb != null) { // need to put back skipped properties? // 02-Jul-2016, tatu: Depending on for JsonParserSequence is initialized it may // try to access current token; ensure there isn't one p.clearCurrentToken(); p = JsonParserSequence.createFlattened(false, tb.asParser(p), p); } // Must point to the next value; tb had no current, jp pointed to VALUE_STRING: p.nextToken(); // to skip past String value // deserializer should take care of closing END_OBJECT as well return deser.deserialize(p, ctxt); } // off-lined to keep main method lean and mean... @SuppressWarnings("resource") protected Object _deserializeTypedUsingDefaultImpl(JsonParser p, DeserializationContext ctxt, TokenBuffer tb) throws IOException { // May have default implementation to use JsonDeserializer deser = _findDefaultImplDeserializer(ctxt); if (deser == null) { // or, perhaps we just bumped into a "natural" value (boolean/int/double/String)? Object result = TypeDeserializer.deserializeIfNatural(p, ctxt, _baseType); if (result != null) { return result; } // or, something for which "as-property" won't work, changed into "wrapper-array" type: if (p.isExpectedStartArrayToken()) { return super.deserializeTypedFromAny(p, ctxt); } if (p.hasToken(JsonToken.VALUE_STRING)) { if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { String str = p.getText().trim(); if (str.isEmpty()) { return null; } } } String msg = String.format("missing type id property '%s'", _typePropertyName); // even better, may know POJO property polymorphic value would be assigned to if (_property != null) { msg = String.format("%s (for POJO property '%s')", msg, _property.getName()); } JavaType t = _handleMissingTypeId(ctxt, msg); if (t == null) { // 09-Mar-2017, tatu: Is this the right thing to do? return null; } // ... would this actually work? deser = ctxt.findContextualValueDeserializer(t, _property); } if (tb != null) { tb.writeEndObject(); p = tb.asParser(p); // must move to point to the first token: p.nextToken(); } return deser.deserialize(p, ctxt); } /* Also need to re-route "unknown" version. Need to think * this through bit more in future, but for now this does address issue and has * no negative side effects (at least within existing unit test suite). */ @Override public Object deserializeTypedFromAny(JsonParser p, DeserializationContext ctxt) throws IOException { /* Sometimes, however, we get an array wrapper; specifically * when an array or list has been serialized with type information. */ if (p.getCurrentToken() == JsonToken.START_ARRAY) { return super.deserializeTypedFromArray(p, ctxt); } return deserializeTypedFromObject(p, ctxt); } // These are fine from base class: //public Object deserializeTypedFromArray(JsonParser jp, DeserializationContext ctxt) //public Object deserializeTypedFromScalar(JsonParser jp, DeserializationContext ctxt) } AsPropertyTypeSerializer.java000066400000000000000000000023351325620701100411360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; /** * Type serializer that preferably embeds type information as an additional * JSON Object property, if possible (when resulting serialization would * use JSON Object). If this is not possible (for JSON Arrays, scalars), * uses a JSON Array wrapper (similar to how * {@link As#WRAPPER_ARRAY} always works) as a fallback. */ public class AsPropertyTypeSerializer extends AsArrayTypeSerializer { protected final String _typePropertyName; public AsPropertyTypeSerializer(TypeIdResolver idRes, BeanProperty property, String propName) { super(idRes, property); _typePropertyName = propName; } @Override public AsPropertyTypeSerializer forProperty(BeanProperty prop) { return (_property == prop) ? this : new AsPropertyTypeSerializer(this._idResolver, prop, this._typePropertyName); } @Override public String getPropertyName() { return _typePropertyName; } @Override public As getTypeInclusion() { return As.PROPERTY; } } AsWrapperTypeDeserializer.java000066400000000000000000000117371325620701100412510ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.util.JsonParserSequence; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Type deserializer used with {@link As#WRAPPER_OBJECT} * inclusion mechanism. Simple since JSON structure used is always * the same, regardless of structure used for actual value: wrapping * is done using a single-element JSON Object where type id is the key, * and actual object data as the value. */ public class AsWrapperTypeDeserializer extends TypeDeserializerBase implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * @since 2.8 */ public AsWrapperTypeDeserializer(JavaType bt, TypeIdResolver idRes, String typePropertyName, boolean typeIdVisible, JavaType defaultImpl) { super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl); } protected AsWrapperTypeDeserializer(AsWrapperTypeDeserializer src, BeanProperty property) { super(src, property); } @Override public TypeDeserializer forProperty(BeanProperty prop) { return (prop == _property) ? this : new AsWrapperTypeDeserializer(this, prop); } @Override public As getTypeInclusion() { return As.WRAPPER_OBJECT; } /** * Deserializing type id enclosed using WRAPPER_OBJECT style is straightforward */ @Override public Object deserializeTypedFromObject(JsonParser jp, DeserializationContext ctxt) throws IOException { return _deserialize(jp, ctxt); } @Override public Object deserializeTypedFromArray(JsonParser jp, DeserializationContext ctxt) throws IOException { return _deserialize(jp, ctxt); } @Override public Object deserializeTypedFromScalar(JsonParser jp, DeserializationContext ctxt) throws IOException { return _deserialize(jp, ctxt); } @Override public Object deserializeTypedFromAny(JsonParser jp, DeserializationContext ctxt) throws IOException { return _deserialize(jp, ctxt); } /* /*************************************************************** /* Internal methods /*************************************************************** */ /** * Method that handles type information wrapper, locates actual * subtype deserializer to use, and calls it to do actual * deserialization. */ @SuppressWarnings("resource") protected Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 02-Aug-2013, tatu: May need to use native type ids if (p.canReadTypeId()) { Object typeId = p.getTypeId(); if (typeId != null) { return _deserializeWithNativeTypeId(p, ctxt, typeId); } } // first, sanity checks JsonToken t = p.getCurrentToken(); if (t == JsonToken.START_OBJECT) { // should always get field name, but just in case... if (p.nextToken() != JsonToken.FIELD_NAME) { ctxt.reportWrongTokenException(baseType(), JsonToken.FIELD_NAME, "need JSON String that contains type id (for subtype of "+baseTypeName()+")"); } } else if (t != JsonToken.FIELD_NAME) { ctxt.reportWrongTokenException(baseType(), JsonToken.START_OBJECT, "need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName()); } final String typeId = p.getText(); JsonDeserializer deser = _findDeserializer(ctxt, typeId); p.nextToken(); // Minor complication: we may need to merge type id in? if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) { // but what if there's nowhere to add it in? Error? Or skip? For now, skip. TokenBuffer tb = new TokenBuffer(null, false); tb.writeStartObject(); // recreate START_OBJECT tb.writeFieldName(_typePropertyName); tb.writeString(typeId); // 02-Jul-2016, tatu: Depending on for JsonParserSequence is initialized it may // try to access current token; ensure there isn't one p.clearCurrentToken(); p = JsonParserSequence.createFlattened(false, tb.asParser(p), p); p.nextToken(); } Object value = deser.deserialize(p, ctxt); // And then need the closing END_OBJECT if (p.nextToken() != JsonToken.END_OBJECT) { ctxt.reportWrongTokenException(baseType(), JsonToken.END_OBJECT, "expected closing END_OBJECT after type information and deserialized value"); } return value; } } AsWrapperTypeSerializer.java000066400000000000000000000035371325620701100407370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Type wrapper that tries to use an extra JSON Object, with a single * entry that has type name as key, to serialize type information. * If this is not possible (value is serialize as array or primitive), * will use {@link As#WRAPPER_ARRAY} mechanism as fallback: that is, * just use a wrapping array with type information as the first element * and value as second. */ public class AsWrapperTypeSerializer extends TypeSerializerBase { public AsWrapperTypeSerializer(TypeIdResolver idRes, BeanProperty property) { super(idRes, property); } @Override public AsWrapperTypeSerializer forProperty(BeanProperty prop) { return (_property == prop) ? this : new AsWrapperTypeSerializer(_idResolver, prop); } @Override public As getTypeInclusion() { return As.WRAPPER_OBJECT; } /* /********************************************************** /* Internal helper methods /********************************************************** */ /** * Helper method used to ensure that intended type id is output as something that is valid: * currently only used to ensure that `null` output is converted to an empty String. * * @since 2.6 */ protected String _validTypeId(String typeId) { return ClassUtil.nonNullString(typeId); } // @since 2.9 protected final void _writeTypeId(JsonGenerator g, String typeId) throws IOException { if (typeId != null) { g.writeTypeId(typeId); } } } ClassNameIdResolver.java000066400000000000000000000117511325620701100400010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; /** * {@link com.fasterxml.jackson.databind.jsontype.TypeIdResolver} implementation * that converts between fully-qualified * Java class names and (JSON) Strings. */ public class ClassNameIdResolver extends TypeIdResolverBase { private final static String JAVA_UTIL_PKG = "java.util."; public ClassNameIdResolver(JavaType baseType, TypeFactory typeFactory) { super(baseType, typeFactory); } @Override public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.CLASS; } public void registerSubtype(Class type, String name) { // not used with class name - based resolvers } @Override public String idFromValue(Object value) { return _idFrom(value, value.getClass(), _typeFactory); } @Override public String idFromValueAndType(Object value, Class type) { return _idFrom(value, type, _typeFactory); } @Override public JavaType typeFromId(DatabindContext context, String id) throws IOException { return _typeFromId(id, context); } protected JavaType _typeFromId(String id, DatabindContext ctxt) throws IOException { JavaType t = ctxt.resolveSubType(_baseType, id); if (t == null) { if (ctxt instanceof DeserializationContext) { // First: we may have problem handlers that can deal with it? return ((DeserializationContext) ctxt).handleUnknownTypeId(_baseType, id, this, "no such class found"); } // ... meaning that we really should never get here. } return t; } /* /********************************************************** /* Internal methods /********************************************************** */ protected String _idFrom(Object value, Class cls, TypeFactory typeFactory) { // Need to ensure that "enum subtypes" work too if (Enum.class.isAssignableFrom(cls)) { if (!cls.isEnum()) { // means that it's sub-class of base enum, so: cls = cls.getSuperclass(); } } String str = cls.getName(); if (str.startsWith(JAVA_UTIL_PKG)) { // 25-Jan-2009, tatu: There are some internal classes that we cannot access as is. // We need better mechanism; for now this has to do... // Enum sets and maps are problematic since we MUST know type of // contained enums, to be able to deserialize. // In addition, EnumSet is not a concrete type either if (value instanceof EnumSet) { // Regular- and JumboEnumSet... Class enumClass = ClassUtil.findEnumType((EnumSet) value); // not optimal: but EnumSet is not a customizable type so this is sort of ok str = typeFactory.constructCollectionType(EnumSet.class, enumClass).toCanonical(); } else if (value instanceof EnumMap) { Class enumClass = ClassUtil.findEnumType((EnumMap) value); Class valueClass = Object.class; // not optimal: but EnumMap is not a customizable type so this is sort of ok str = typeFactory.constructMapType(EnumMap.class, enumClass, valueClass).toCanonical(); } // 10-Jan-2018, tatu: Up until 2.9.4 we used to have other conversions for `Collections.xxx()` // and `Arrays.asList(...)`; but it was changed to be handled on receiving end instead } else if (str.indexOf('$') >= 0) { /* Other special handling may be needed for inner classes, * The best way to handle would be to find 'hidden' constructor; pass parent * value etc (which is actually done for non-anonymous static classes!), * but that is just not possible due to various things. So, we will instead * try to generalize type into something we will be more likely to be able * construct. */ Class outer = ClassUtil.getOuterClass(cls); if (outer != null) { // one more check: let's actually not worry if the declared static type is // non-static as well; if so, deserializer does have a chance at figuring it all out. Class staticType = _baseType.getRawClass(); if (ClassUtil.getOuterClass(staticType) == null) { // Is this always correct? Seems like it should be... cls = _baseType.getRawClass(); str = cls.getName(); } } } return str; } @Override public String getDescForKnownTypeIds() { return "class name used as type id"; } } MinimalClassNameIdResolver.java000066400000000000000000000044051325620701100413060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.DatabindContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; public class MinimalClassNameIdResolver extends ClassNameIdResolver { /** * Package name of the base class, to be used for determining common * prefix that can be omitted from included type id. * Does not include the trailing dot. */ protected final String _basePackageName; /** * Same as {@link #_basePackageName}, but includes trailing dot. */ protected final String _basePackagePrefix; protected MinimalClassNameIdResolver(JavaType baseType, TypeFactory typeFactory) { super(baseType, typeFactory); String base = baseType.getRawClass().getName(); int ix = base.lastIndexOf('.'); if (ix < 0) { // can this ever occur? _basePackageName = ""; _basePackagePrefix = "."; } else { _basePackagePrefix = base.substring(0, ix+1); _basePackageName = base.substring(0, ix); } } @Override public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.MINIMAL_CLASS; } @Override public String idFromValue(Object value) { String n = value.getClass().getName(); if (n.startsWith(_basePackagePrefix)) { // note: we will leave the leading dot in there return n.substring(_basePackagePrefix.length()-1); } return n; } @Override protected JavaType _typeFromId(String id, DatabindContext ctxt) throws IOException { if (id.startsWith(".")) { StringBuilder sb = new StringBuilder(id.length() + _basePackageName.length()); if (_basePackageName.length() == 0) { // no package; must remove leading '.' from id sb.append(id.substring(1)); } else { // otherwise just concatenate package, with leading-dot-partial name sb.append(_basePackageName).append(id); } id = sb.toString(); } return super._typeFromId(id, ctxt); } } StdSubtypeResolver.java000066400000000000000000000304201325620701100377560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.lang.reflect.Modifier; import java.util.*; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.SubtypeResolver; /** * Standard {@link SubtypeResolver} implementation. */ public class StdSubtypeResolver extends SubtypeResolver implements java.io.Serializable { private static final long serialVersionUID = 1L; protected LinkedHashSet _registeredSubtypes; public StdSubtypeResolver() { } /* /********************************************************** /* Subtype registration /********************************************************** */ @Override public void registerSubtypes(NamedType... types) { if (_registeredSubtypes == null) { _registeredSubtypes = new LinkedHashSet(); } for (NamedType type : types) { _registeredSubtypes.add(type); } } @Override public void registerSubtypes(Class... classes) { NamedType[] types = new NamedType[classes.length]; for (int i = 0, len = classes.length; i < len; ++i) { types[i] = new NamedType(classes[i]); } registerSubtypes(types); } @Override // since 2.9 public void registerSubtypes(Collection> subtypes) { int len = subtypes.size(); NamedType[] types = new NamedType[len]; int i = 0; for (Class subtype : subtypes) { types[i++] = new NamedType(subtype); } registerSubtypes(types); } /* /********************************************************** /* Resolution by class (serialization) /********************************************************** */ @Override public Collection collectAndResolveSubtypesByClass(MapperConfig config, AnnotatedMember property, JavaType baseType) { final AnnotationIntrospector ai = config.getAnnotationIntrospector(); // for backwards compatibility, must allow null here: Class rawBase = (baseType == null) ? property.getRawType() : baseType.getRawClass(); HashMap collected = new HashMap(); // start with registered subtypes (which have precedence) if (_registeredSubtypes != null) { for (NamedType subtype : _registeredSubtypes) { // is it a subtype of root type? if (rawBase.isAssignableFrom(subtype.getType())) { // yes AnnotatedClass curr = AnnotatedClassResolver.resolveWithoutSuperTypes(config, subtype.getType()); _collectAndResolve(curr, subtype, config, ai, collected); } } } // then annotated types for property itself if (property != null) { Collection st = ai.findSubtypes(property); if (st != null) { for (NamedType nt : st) { AnnotatedClass ac = AnnotatedClassResolver.resolveWithoutSuperTypes(config, nt.getType()); _collectAndResolve(ac, nt, config, ai, collected); } } } NamedType rootType = new NamedType(rawBase, null); AnnotatedClass ac = AnnotatedClassResolver.resolveWithoutSuperTypes(config, rawBase); // and finally subtypes via annotations from base type (recursively) _collectAndResolve(ac, rootType, config, ai, collected); return new ArrayList(collected.values()); } @Override public Collection collectAndResolveSubtypesByClass(MapperConfig config, AnnotatedClass type) { final AnnotationIntrospector ai = config.getAnnotationIntrospector(); HashMap subtypes = new HashMap(); // then consider registered subtypes (which have precedence over annotations) if (_registeredSubtypes != null) { Class rawBase = type.getRawType(); for (NamedType subtype : _registeredSubtypes) { // is it a subtype of root type? if (rawBase.isAssignableFrom(subtype.getType())) { // yes AnnotatedClass curr = AnnotatedClassResolver.resolveWithoutSuperTypes(config, subtype.getType()); _collectAndResolve(curr, subtype, config, ai, subtypes); } } } // and then check subtypes via annotations from base type (recursively) NamedType rootType = new NamedType(type.getRawType(), null); _collectAndResolve(type, rootType, config, ai, subtypes); return new ArrayList(subtypes.values()); } /* /********************************************************** /* Resolution by class (deserialization) /********************************************************** */ @Override public Collection collectAndResolveSubtypesByTypeId(MapperConfig config, AnnotatedMember property, JavaType baseType) { final AnnotationIntrospector ai = config.getAnnotationIntrospector(); Class rawBase = baseType.getRawClass(); // Need to keep track of classes that have been handled already Set> typesHandled = new HashSet>(); Map byName = new LinkedHashMap(); // start with lowest-precedence, which is from type hierarchy NamedType rootType = new NamedType(rawBase, null); AnnotatedClass ac = AnnotatedClassResolver.resolveWithoutSuperTypes(config, rawBase); _collectAndResolveByTypeId(ac, rootType, config, typesHandled, byName); // then with definitions from property if (property != null) { Collection st = ai.findSubtypes(property); if (st != null) { for (NamedType nt : st) { ac = AnnotatedClassResolver.resolveWithoutSuperTypes(config, nt.getType()); _collectAndResolveByTypeId(ac, nt, config, typesHandled, byName); } } } // and finally explicit type registrations (highest precedence) if (_registeredSubtypes != null) { for (NamedType subtype : _registeredSubtypes) { // is it a subtype of root type? if (rawBase.isAssignableFrom(subtype.getType())) { // yes AnnotatedClass curr = AnnotatedClassResolver.resolveWithoutSuperTypes(config, subtype.getType()); _collectAndResolveByTypeId(curr, subtype, config, typesHandled, byName); } } } return _combineNamedAndUnnamed(rawBase, typesHandled, byName); } @Override public Collection collectAndResolveSubtypesByTypeId(MapperConfig config, AnnotatedClass baseType) { final Class rawBase = baseType.getRawType(); Set> typesHandled = new HashSet>(); Map byName = new LinkedHashMap(); NamedType rootType = new NamedType(rawBase, null); _collectAndResolveByTypeId(baseType, rootType, config, typesHandled, byName); if (_registeredSubtypes != null) { for (NamedType subtype : _registeredSubtypes) { // is it a subtype of root type? if (rawBase.isAssignableFrom(subtype.getType())) { // yes AnnotatedClass curr = AnnotatedClassResolver.resolveWithoutSuperTypes(config, subtype.getType()); _collectAndResolveByTypeId(curr, subtype, config, typesHandled, byName); } } } return _combineNamedAndUnnamed(rawBase, typesHandled, byName); } /* /********************************************************** /* Internal methods /********************************************************** */ /** * Method called to find subtypes for a specific type (class), using * type (class) as the unique key (in case of conflicts). */ protected void _collectAndResolve(AnnotatedClass annotatedType, NamedType namedType, MapperConfig config, AnnotationIntrospector ai, HashMap collectedSubtypes) { if (!namedType.hasName()) { String name = ai.findTypeName(annotatedType); if (name != null) { namedType = new NamedType(namedType.getType(), name); } } // First things first: is base type itself included? if (collectedSubtypes.containsKey(namedType)) { // if so, no recursion; however, may need to update name? if (namedType.hasName()) { NamedType prev = collectedSubtypes.get(namedType); if (!prev.hasName()) { collectedSubtypes.put(namedType, namedType); } } return; } // if it wasn't, add and check subtypes recursively collectedSubtypes.put(namedType, namedType); Collection st = ai.findSubtypes(annotatedType); if (st != null && !st.isEmpty()) { for (NamedType subtype : st) { AnnotatedClass subtypeClass = AnnotatedClassResolver.resolveWithoutSuperTypes(config, subtype.getType()); _collectAndResolve(subtypeClass, subtype, config, ai, collectedSubtypes); } } } /** * Method called to find subtypes for a specific type (class), using * type id as the unique key (in case of conflicts). */ protected void _collectAndResolveByTypeId(AnnotatedClass annotatedType, NamedType namedType, MapperConfig config, Set> typesHandled, Map byName) { final AnnotationIntrospector ai = config.getAnnotationIntrospector(); if (!namedType.hasName()) { String name = ai.findTypeName(annotatedType); if (name != null) { namedType = new NamedType(namedType.getType(), name); } } if (namedType.hasName()) { byName.put(namedType.getName(), namedType); } // only check subtypes if this type hadn't yet been handled if (typesHandled.add(namedType.getType())) { Collection st = ai.findSubtypes(annotatedType); if (st != null && !st.isEmpty()) { for (NamedType subtype : st) { AnnotatedClass subtypeClass = AnnotatedClassResolver.resolveWithoutSuperTypes(config, subtype.getType()); _collectAndResolveByTypeId(subtypeClass, subtype, config, typesHandled, byName); } } } } /** * Helper method used for merging explicitly named types and handled classes * without explicit names. */ protected Collection _combineNamedAndUnnamed(Class rawBase, Set> typesHandled, Map byName) { ArrayList result = new ArrayList(byName.values()); // Ok, so... we will figure out which classes have no explicitly assigned name, // by removing Classes from Set. And for remaining classes, add an anonymous // marker for (NamedType t : byName.values()) { typesHandled.remove(t.getType()); } for (Class cls : typesHandled) { // 27-Apr-2017, tatu: [databind#1616] Do not add base type itself unless // it is concrete (or has explicit type name) if ((cls == rawBase) && Modifier.isAbstract(cls.getModifiers())) { continue; } result.add(new NamedType(cls)); } return result; } } StdTypeResolverBuilder.java000066400000000000000000000213171325620701100405600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.util.Collection; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.NoClass; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.jsontype.*; /** * Default {@link TypeResolverBuilder} implementation. */ public class StdTypeResolverBuilder implements TypeResolverBuilder { // Configuration settings: protected JsonTypeInfo.Id _idType; protected JsonTypeInfo.As _includeAs; protected String _typeProperty; /** * Whether type id should be exposed to deserializers or not */ protected boolean _typeIdVisible = false; /** * Default class to use in case type information is not available * or is broken. */ protected Class _defaultImpl; // Objects protected TypeIdResolver _customIdResolver; /* /********************************************************** /* Construction, initialization, actual building /********************************************************** */ public StdTypeResolverBuilder() { } /** * @since 2.9 */ protected StdTypeResolverBuilder(JsonTypeInfo.Id idType, JsonTypeInfo.As idAs, String propName) { _idType = idType; _includeAs = idAs; _typeProperty = propName; } public static StdTypeResolverBuilder noTypeInfoBuilder() { return new StdTypeResolverBuilder().init(JsonTypeInfo.Id.NONE, null); } @Override public StdTypeResolverBuilder init(JsonTypeInfo.Id idType, TypeIdResolver idRes) { // sanity checks if (idType == null) { throw new IllegalArgumentException("idType cannot be null"); } _idType = idType; _customIdResolver = idRes; // Let's also initialize property name as per idType default _typeProperty = idType.getDefaultPropertyName(); return this; } @Override public TypeSerializer buildTypeSerializer(SerializationConfig config, JavaType baseType, Collection subtypes) { if (_idType == JsonTypeInfo.Id.NONE) { return null; } // 03-Oct-2016, tatu: As per [databind#1395] better prevent use for primitives, // regardless of setting if (baseType.isPrimitive()) { return null; } TypeIdResolver idRes = idResolver(config, baseType, subtypes, true, false); switch (_includeAs) { case WRAPPER_ARRAY: return new AsArrayTypeSerializer(idRes, null); case PROPERTY: return new AsPropertyTypeSerializer(idRes, null, _typeProperty); case WRAPPER_OBJECT: return new AsWrapperTypeSerializer(idRes, null); case EXTERNAL_PROPERTY: return new AsExternalTypeSerializer(idRes, null, _typeProperty); case EXISTING_PROPERTY: // as per [#528] return new AsExistingPropertyTypeSerializer(idRes, null, _typeProperty); } throw new IllegalStateException("Do not know how to construct standard type serializer for inclusion type: "+_includeAs); } // as per [#368] // removed when fix [#528] //private IllegalArgumentException _noExisting() { // return new IllegalArgumentException("Inclusion type "+_includeAs+" not yet supported"); //} @Override public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, JavaType baseType, Collection subtypes) { if (_idType == JsonTypeInfo.Id.NONE) { return null; } // 03-Oct-2016, tatu: As per [databind#1395] better prevent use for primitives, // regardless of setting if (baseType.isPrimitive()) { return null; } TypeIdResolver idRes = idResolver(config, baseType, subtypes, false, true); JavaType defaultImpl; if (_defaultImpl == null) { defaultImpl = null; } else { // 20-Mar-2016, tatu: It is important to do specialization go through // TypeFactory to ensure proper resolution; with 2.7 and before, direct // call to JavaType was used, but that cannot work reliably with 2.7 // 20-Mar-2016, tatu: Can finally add a check for type compatibility BUT // if so, need to add explicit checks for marker types. Not ideal, but // seems like a reasonable compromise. if ((_defaultImpl == Void.class) || (_defaultImpl == NoClass.class)) { defaultImpl = config.getTypeFactory().constructType(_defaultImpl); } else { defaultImpl = config.getTypeFactory() .constructSpecializedType(baseType, _defaultImpl); } } // First, method for converting type info to type id: switch (_includeAs) { case WRAPPER_ARRAY: return new AsArrayTypeDeserializer(baseType, idRes, _typeProperty, _typeIdVisible, defaultImpl); case PROPERTY: case EXISTING_PROPERTY: // as per [#528] same class as PROPERTY return new AsPropertyTypeDeserializer(baseType, idRes, _typeProperty, _typeIdVisible, defaultImpl, _includeAs); case WRAPPER_OBJECT: return new AsWrapperTypeDeserializer(baseType, idRes, _typeProperty, _typeIdVisible, defaultImpl); case EXTERNAL_PROPERTY: return new AsExternalTypeDeserializer(baseType, idRes, _typeProperty, _typeIdVisible, defaultImpl); } throw new IllegalStateException("Do not know how to construct standard type serializer for inclusion type: "+_includeAs); } /* /********************************************************** /* Construction, configuration /********************************************************** */ @Override public StdTypeResolverBuilder inclusion(JsonTypeInfo.As includeAs) { if (includeAs == null) { throw new IllegalArgumentException("includeAs cannot be null"); } _includeAs = includeAs; return this; } /** * Method for constructing an instance with specified type property name * (property name to use for type id when using "as-property" inclusion). */ @Override public StdTypeResolverBuilder typeProperty(String typeIdPropName) { // ok to have null/empty; will restore to use defaults if (typeIdPropName == null || typeIdPropName.length() == 0) { typeIdPropName = _idType.getDefaultPropertyName(); } _typeProperty = typeIdPropName; return this; } @Override public StdTypeResolverBuilder defaultImpl(Class defaultImpl) { _defaultImpl = defaultImpl; return this; } @Override public StdTypeResolverBuilder typeIdVisibility(boolean isVisible) { _typeIdVisible = isVisible; return this; } /* /********************************************************** /* Accessors /********************************************************** */ @Override public Class getDefaultImpl() { return _defaultImpl; } public String getTypeProperty() { return _typeProperty; } public boolean isTypeIdVisible() { return _typeIdVisible; } /* /********************************************************** /* Internal methods /********************************************************** */ /** * Helper method that will either return configured custom * type id resolver, or construct a standard resolver * given configuration. */ protected TypeIdResolver idResolver(MapperConfig config, JavaType baseType, Collection subtypes, boolean forSer, boolean forDeser) { // Custom id resolver? if (_customIdResolver != null) { return _customIdResolver; } if (_idType == null) throw new IllegalStateException("Cannot build, 'init()' not yet called"); switch (_idType) { case CLASS: return new ClassNameIdResolver(baseType, config.getTypeFactory()); case MINIMAL_CLASS: return new MinimalClassNameIdResolver(baseType, config.getTypeFactory()); case NAME: return TypeNameIdResolver.construct(config, baseType, subtypes, forSer, forDeser); case NONE: // hmmh. should never get this far with 'none' return null; case CUSTOM: // need custom resolver... } throw new IllegalStateException("Do not know how to construct standard type id resolver for idType: "+_idType); } } SubTypeValidator.java000066400000000000000000000125061325620701100373740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.util.Collections; import java.util.HashSet; import java.util.Set; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; /** * Helper class used to encapsulate rules that determine subtypes that * are invalid to use, even with default typing, mostly due to security * concerns. * Used by BeanDeserializerFacotry * * @since 2.8.11 */ public class SubTypeValidator { protected final static String PREFIX_SPRING = "org.springframework."; protected final static String PREFIX_C3P0 = "com.mchange.v2.c3p0."; /** * Set of well-known "nasty classes", deserialization of which is considered dangerous * and should (and is) prevented by default. */ protected final static Set DEFAULT_NO_DESER_CLASS_NAMES; static { Set s = new HashSet(); // Courtesy of [https://github.com/kantega/notsoserial]: // (and wrt [databind#1599]) s.add("org.apache.commons.collections.functors.InvokerTransformer"); s.add("org.apache.commons.collections.functors.InstantiateTransformer"); s.add("org.apache.commons.collections4.functors.InvokerTransformer"); s.add("org.apache.commons.collections4.functors.InstantiateTransformer"); s.add("org.codehaus.groovy.runtime.ConvertedClosure"); s.add("org.codehaus.groovy.runtime.MethodClosure"); s.add("org.springframework.beans.factory.ObjectFactory"); s.add("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); s.add("org.apache.xalan.xsltc.trax.TemplatesImpl"); // [databind#1680]: may or may not be problem, take no chance s.add("com.sun.rowset.JdbcRowSetImpl"); // [databind#1737]; JDK provided s.add("java.util.logging.FileHandler"); s.add("java.rmi.server.UnicastRemoteObject"); // [databind#1737]; 3rd party //s.add("org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor"); // deprecated by [databind#1855] s.add("org.springframework.beans.factory.config.PropertyPathFactoryBean"); // s.add("com.mchange.v2.c3p0.JndiRefForwardingDataSource"); // deprecated by [databind#1931] // s.add("com.mchange.v2.c3p0.WrapperConnectionPoolDataSource"); // - "" - // [databind#1855]: more 3rd party s.add("org.apache.tomcat.dbcp.dbcp2.BasicDataSource"); s.add("com.sun.org.apache.bcel.internal.util.ClassLoader"); // [databind#1899]: more 3rd party s.add("org.hibernate.jmx.StatisticsService"); s.add("org.apache.ibatis.datasource.jndi.JndiDataSourceFactory"); DEFAULT_NO_DESER_CLASS_NAMES = Collections.unmodifiableSet(s); } /** * Set of class names of types that are never to be deserialized. */ protected Set _cfgIllegalClassNames = DEFAULT_NO_DESER_CLASS_NAMES; private final static SubTypeValidator instance = new SubTypeValidator(); protected SubTypeValidator() { } public static SubTypeValidator instance() { return instance; } public void validateSubType(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { // There are certain nasty classes that could cause problems, mostly // via default typing -- catch them here. final Class raw = type.getRawClass(); String full = raw.getName(); main_check: do { if (_cfgIllegalClassNames.contains(full)) { break; } // 18-Dec-2017, tatu: As per [databind#1855], need bit more sophisticated handling // for some Spring framework types // 05-Jan-2017, tatu: ... also, only applies to classes, not interfaces if (raw.isInterface()) { ; } else if (full.startsWith(PREFIX_SPRING)) { for (Class cls = raw; (cls != null) && (cls != Object.class); cls = cls.getSuperclass()){ String name = cls.getSimpleName(); // looking for "AbstractBeanFactoryPointcutAdvisor" but no point to allow any is there? if ("AbstractPointcutAdvisor".equals(name) // ditto for "FileSystemXmlApplicationContext": block all ApplicationContexts || "AbstractApplicationContext".equals(name)) { break main_check; } } } else if (full.startsWith(PREFIX_C3P0)) { // [databind#1737]; more 3rd party // s.add("com.mchange.v2.c3p0.JndiRefForwardingDataSource"); // s.add("com.mchange.v2.c3p0.WrapperConnectionPoolDataSource"); // [databind#1931]; more 3rd party // com.mchange.v2.c3p0.ComboPooledDataSource // com.mchange.v2.c3p0.debug.AfterCloseLoggingComboPooledDataSource if (full.endsWith("DataSource")) { break main_check; } } return; } while (false); ctxt.reportBadTypeDefinition(beanDesc, "Illegal type (%s) to deserialize: prevented for security reasons", full); } } TypeDeserializerBase.java000066400000000000000000000270271325620701100402160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.deser.std.NullifyingDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Base class for all standard Jackson {@link TypeDeserializer}s. */ public abstract class TypeDeserializerBase extends TypeDeserializer implements java.io.Serializable { private static final long serialVersionUID = 1; protected final TypeIdResolver _idResolver; protected final JavaType _baseType; /** * Property that contains value for which type information * is included; null if value is a root value. * Note that this value is not assigned during construction * but only when {@link #forProperty} is called to create * a copy. */ protected final BeanProperty _property; /** * Type to use as the default implementation, if type id is * missing or cannot be resolved. */ protected final JavaType _defaultImpl; /** * Name of type property used; needed for non-property versions too, * in cases where type id is to be exposed as part of JSON. */ protected final String _typePropertyName; protected final boolean _typeIdVisible; /** * For efficient operation we will lazily build mappings from type ids * to actual deserializers, once needed. */ protected final Map> _deserializers; protected JsonDeserializer _defaultImplDeserializer; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @since 2.8 */ protected TypeDeserializerBase(JavaType baseType, TypeIdResolver idRes, String typePropertyName, boolean typeIdVisible, JavaType defaultImpl) { _baseType = baseType; _idResolver = idRes; _typePropertyName = ClassUtil.nonNullString(typePropertyName); _typeIdVisible = typeIdVisible; // defaults are fine, although shouldn't need much concurrency _deserializers = new ConcurrentHashMap>(16, 0.75f, 2); _defaultImpl = defaultImpl; _property = null; } protected TypeDeserializerBase(TypeDeserializerBase src, BeanProperty property) { _baseType = src._baseType; _idResolver = src._idResolver; _typePropertyName = src._typePropertyName; _typeIdVisible = src._typeIdVisible; _deserializers = src._deserializers; _defaultImpl = src._defaultImpl; _defaultImplDeserializer = src._defaultImplDeserializer; _property = property; } @Override public abstract TypeDeserializer forProperty(BeanProperty prop); /* /********************************************************** /* Accessors /********************************************************** */ @Override public abstract JsonTypeInfo.As getTypeInclusion(); public String baseTypeName() { return _baseType.getRawClass().getName(); } @Override public final String getPropertyName() { return _typePropertyName; } @Override public TypeIdResolver getTypeIdResolver() { return _idResolver; } @Override public Class getDefaultImpl() { return ClassUtil.rawClass(_defaultImpl); } /** * @since 2.9 */ public JavaType baseType() { return _baseType; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append('[').append(getClass().getName()); sb.append("; base-type:").append(_baseType); sb.append("; id-resolver: ").append(_idResolver); sb.append(']'); return sb.toString(); } /* /********************************************************** /* Helper methods for sub-classes /********************************************************** */ protected final JsonDeserializer _findDeserializer(DeserializationContext ctxt, String typeId) throws IOException { JsonDeserializer deser = _deserializers.get(typeId); if (deser == null) { /* As per [databind#305], need to provide contextual info. But for * backwards compatibility, let's start by only supporting this * for base class, not via interface. Later on we can add this * to the interface, assuming deprecation at base class helps. */ JavaType type = _idResolver.typeFromId(ctxt, typeId); if (type == null) { // use the default impl if no type id available: deser = _findDefaultImplDeserializer(ctxt); if (deser == null) { // 10-May-2016, tatu: We may get some help... JavaType actual = _handleUnknownTypeId(ctxt, typeId); if (actual == null) { // what should this be taken to mean? // TODO: try to figure out something better return null; } // ... would this actually work? deser = ctxt.findContextualValueDeserializer(actual, _property); } } else { /* 16-Dec-2010, tatu: Since nominal type we get here has no (generic) type parameters, * we actually now need to explicitly narrow from base type (which may have parameterization) * using raw type. * * One complication, though; cannot change 'type class' (simple type to container); otherwise * we may try to narrow a SimpleType (Object.class) into MapType (Map.class), losing actual * type in process (getting SimpleType of Map.class which will not work as expected) */ if ((_baseType != null) && _baseType.getClass() == type.getClass()) { /* 09-Aug-2015, tatu: Not sure if the second part of the check makes sense; * but it appears to check that JavaType impl class is the same which is * important for some reason? * Disabling the check will break 2 Enum-related tests. */ // 19-Jun-2016, tatu: As per [databind#1270] we may actually get full // generic type with custom type resolvers. If so, should try to retain them. // Whether this is sufficient to avoid problems remains to be seen, but for // now it should improve things. if (!type.hasGenericTypes()) { type = ctxt.getTypeFactory().constructSpecializedType(_baseType, type.getRawClass()); } } deser = ctxt.findContextualValueDeserializer(type, _property); } _deserializers.put(typeId, deser); } return deser; } protected final JsonDeserializer _findDefaultImplDeserializer(DeserializationContext ctxt) throws IOException { /* 06-Feb-2013, tatu: As per [databind#148], consider default implementation value of * {@link java.lang.Void} to mean "serialize as null"; as well as DeserializationFeature * to do swift mapping to null */ if (_defaultImpl == null) { if (!ctxt.isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) { return NullifyingDeserializer.instance; } return null; } Class raw = _defaultImpl.getRawClass(); if (ClassUtil.isBogusClass(raw)) { return NullifyingDeserializer.instance; } synchronized (_defaultImpl) { if (_defaultImplDeserializer == null) { _defaultImplDeserializer = ctxt.findContextualValueDeserializer( _defaultImpl, _property); } return _defaultImplDeserializer; } } /** * Helper method called when {@link JsonParser} indicates that it can use * so-called native type ids. Assumption from there is that only native * type ids are to be used. * * @since 2.3 */ @Deprecated protected Object _deserializeWithNativeTypeId(JsonParser jp, DeserializationContext ctxt) throws IOException { return _deserializeWithNativeTypeId(jp, ctxt, jp.getTypeId()); } /** * Helper method called when {@link JsonParser} indicates that it can use * so-called native type ids, and such type id has been found. * * @since 2.4 */ protected Object _deserializeWithNativeTypeId(JsonParser jp, DeserializationContext ctxt, Object typeId) throws IOException { JsonDeserializer deser; if (typeId == null) { /* 04-May-2014, tatu: Should error be obligatory, or should there be another method * for "try to deserialize with native tpye id"? */ deser = _findDefaultImplDeserializer(ctxt); if (deser == null) { return ctxt.reportInputMismatch(baseType(), "No (native) type id found when one was expected for polymorphic type handling"); } } else { String typeIdStr = (typeId instanceof String) ? (String) typeId : String.valueOf(typeId); deser = _findDeserializer(ctxt, typeIdStr); } return deser.deserialize(jp, ctxt); } /** * Helper method called when given type id cannot be resolved into * concrete deserializer either directly (using given {@link TypeIdResolver}), * or using default type. * Default implementation simply throws a {@link com.fasterxml.jackson.databind.JsonMappingException} to * indicate the problem; sub-classes may choose * * @return If it is possible to resolve type id into a {@link JsonDeserializer} * should return that deserializer; otherwise throw an exception to indicate * the problem. * * @since 2.8 */ protected JavaType _handleUnknownTypeId(DeserializationContext ctxt, String typeId) throws IOException { String extraDesc = _idResolver.getDescForKnownTypeIds(); if (extraDesc == null) { extraDesc = "type ids are not statically known"; } else { extraDesc = "known type ids = " + extraDesc; } if (_property != null) { extraDesc = String.format("%s (for POJO property '%s')", extraDesc, _property.getName()); } return ctxt.handleUnknownTypeId(_baseType, typeId, _idResolver, extraDesc); } /** * @since 2.9 */ protected JavaType _handleMissingTypeId(DeserializationContext ctxt, String extraDesc) throws IOException { return ctxt.handleMissingTypeId(_baseType, _idResolver, extraDesc); } } TypeIdResolverBase.java000066400000000000000000000047531325620701100376530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.io.IOException; import com.fasterxml.jackson.databind.DatabindContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Partial base implementation of {@link TypeIdResolver}: all custom implementations * are strongly recommended to extend this class, instead of directly * implementing {@link TypeIdResolver}. * Note that ALL sub-class need to re-implement * {@link #typeFromId(DatabindContext, String)} method; otherwise implementation * will not work. *

* Note that instances created to be constructed from annotations * ({@link com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver}) * are always created using no-arguments constructor; protected constructor * is only used sub-classes. */ public abstract class TypeIdResolverBase implements TypeIdResolver { protected final TypeFactory _typeFactory; /** * Common base type for all polymorphic instances handled. */ protected final JavaType _baseType; protected TypeIdResolverBase() { this(null, null); } protected TypeIdResolverBase(JavaType baseType, TypeFactory typeFactory) { _baseType = baseType; _typeFactory = typeFactory; } // Standard type id resolvers do not need this: only useful for custom ones. @Override public void init(JavaType bt) { } @Override public String idFromBaseType() { /* By default we will just defer to regular handling, handing out the * base type; and since there is no value, must just pass null here * assuming that implementations can deal with it. * Alternative would be to pass a bogus Object, but that does not seem right. */ return idFromValueAndType(null, _baseType.getRawClass()); } @Override public JavaType typeFromId(DatabindContext context, String id) throws IOException { // 22-Dec-2015, tatu: Must be overridden by sub-classes, so let's throw // an exception if not throw new IllegalStateException("Sub-class "+getClass().getName()+" MUST implement " +"`typeFromId(DatabindContext,String)"); } /** * Helper method used to get a simple description of all known type ids, * for use in error messages. */ @Override public String getDescForKnownTypeIds() { return null; } } TypeNameIdResolver.java000066400000000000000000000132421325620701100376520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.util.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DatabindContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.jsontype.NamedType; public class TypeNameIdResolver extends TypeIdResolverBase { protected final MapperConfig _config; /** * Mappings from class name to type id, used for serialization */ protected final Map _typeToId; /** * Mappings from type id to JavaType, used for deserialization */ protected final Map _idToType; protected TypeNameIdResolver(MapperConfig config, JavaType baseType, Map typeToId, Map idToType) { super(baseType, config.getTypeFactory()); _config = config; _typeToId = typeToId; _idToType = idToType; } public static TypeNameIdResolver construct(MapperConfig config, JavaType baseType, Collection subtypes, boolean forSer, boolean forDeser) { // sanity check if (forSer == forDeser) throw new IllegalArgumentException(); Map typeToId = null; Map idToType = null; if (forSer) { typeToId = new HashMap(); } if (forDeser) { idToType = new HashMap(); // 14-Apr-2016, tatu: Apparently needed for special case of `defaultImpl`; // see [databind#1198] for details. typeToId = new TreeMap(); } if (subtypes != null) { for (NamedType t : subtypes) { /* no name? Need to figure out default; for now, let's just * use non-qualified class name */ Class cls = t.getType(); String id = t.hasName() ? t.getName() : _defaultTypeId(cls); if (forSer) { typeToId.put(cls.getName(), id); } if (forDeser) { // One more problem; sometimes we have same name for multiple types; // if so, use most specific JavaType prev = idToType.get(id); if (prev != null) { // Can only override if more specific if (cls.isAssignableFrom(prev.getRawClass())) { // nope, more generic (or same) continue; } } idToType.put(id, config.constructType(cls)); } } } return new TypeNameIdResolver(config, baseType, typeToId, idToType); } @Override public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.NAME; } @Override public String idFromValue(Object value) { return idFromClass(value.getClass()); } protected String idFromClass(Class clazz) { if (clazz == null) { return null; } Class cls = _typeFactory.constructType(clazz).getRawClass(); final String key = cls.getName(); String name; synchronized (_typeToId) { name = _typeToId.get(key); if (name == null) { // 24-Feb-2011, tatu: As per [JACKSON-498], may need to dynamically look up name // can either throw an exception, or use default name... if (_config.isAnnotationProcessingEnabled()) { BeanDescription beanDesc = _config.introspectClassAnnotations(cls); name = _config.getAnnotationIntrospector().findTypeName(beanDesc.getClassInfo()); } if (name == null) { // And if still not found, let's choose default? name = _defaultTypeId(cls); } _typeToId.put(key, name); } } return name; } @Override public String idFromValueAndType(Object value, Class type) { /* 18-Jan-2013, tatu: We may be called with null value occasionally * it seems; nothing much we can figure out that way. */ if (value == null) { return idFromClass(type); } return idFromValue(value); } @Override public JavaType typeFromId(DatabindContext context, String id) { return _typeFromId(id); } protected JavaType _typeFromId(String id) { /* Now: if no type is found, should we try to locate it by * some other means? (specifically, if in same package as base type, * could just try Class.forName) * For now let's not add any such workarounds; can add if need be */ return _idToType.get(id); } @Override public String getDescForKnownTypeIds() { return new TreeSet(_idToType.keySet()).toString(); } @Override public String toString() { return String.format("[%s; id-to-type=%s]", getClass().getName(), _idToType); } /* /********************************************************* /* Helper methods /********************************************************* */ /** * If no name was explicitly given for a class, we will just * use non-qualified class name */ protected static String _defaultTypeId(Class cls) { String n = cls.getName(); int ix = n.lastIndexOf('.'); return (ix < 0) ? n : n.substring(ix+1); } } TypeSerializerBase.java000066400000000000000000000060711325620701100377010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/implpackage com.fasterxml.jackson.databind.jsontype.impl; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; public abstract class TypeSerializerBase extends TypeSerializer { protected final TypeIdResolver _idResolver; protected final BeanProperty _property; protected TypeSerializerBase(TypeIdResolver idRes, BeanProperty property) { _idResolver = idRes; _property = property; } /* /********************************************************** /* Base implementations, simple accessors /********************************************************** */ @Override public abstract JsonTypeInfo.As getTypeInclusion(); @Override public String getPropertyName() { return null; } @Override public TypeIdResolver getTypeIdResolver() { return _idResolver; } @Override public WritableTypeId writeTypePrefix(JsonGenerator g, WritableTypeId idMetadata) throws IOException { _generateTypeId(idMetadata); return g.writeTypePrefix(idMetadata); } @Override public WritableTypeId writeTypeSuffix(JsonGenerator g, WritableTypeId idMetadata) throws IOException { return g.writeTypeSuffix(idMetadata); } /** * Helper method that will generate type id to use, if not already passed. * * @since 2.9 */ protected void _generateTypeId(WritableTypeId idMetadata) { Object id = idMetadata.id; if (id == null) { final Object value = idMetadata.forValue; Class typeForId = idMetadata.forValueType; if (typeForId == null) { id = idFromValue(value); } else { id = idFromValueAndType(value, typeForId); } idMetadata.id = id; } } /* /********************************************************** /* Helper methods for subclasses /********************************************************** */ protected String idFromValue(Object value) { String id = _idResolver.idFromValue(value); if (id == null) { handleMissingId(value); } return id; } protected String idFromValueAndType(Object value, Class type) { String id = _idResolver.idFromValueAndType(value, type); if (id == null) { handleMissingId(value); } return id; } // As per [databind#633], maybe better just not do anything... protected void handleMissingId(Object value) { /* String typeDesc = ClassUtil.classNameOf(value, "NULL"); throw new IllegalArgumentException("Cannot resolve type id for " +typeDesc+" (using "+_idResolver.getClass().getName()+")"); */ } } package-info.java000066400000000000000000000004051325620701100364520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/** * Package that contains standard implementations for * {@link com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder} * and * {@link com.fasterxml.jackson.databind.jsontype.TypeIdResolver}. */ package com.fasterxml.jackson.databind.jsontype.impl; package-info.java000066400000000000000000000005771325620701100355230ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/jsontype/** * Package that contains interfaces that define how to implement * functionality for dynamically resolving type during deserialization. * This is needed for complete handling of polymorphic types, where * actual type cannot be determined statically (declared type is * a supertype of actual polymorphic serialized types). */ package com.fasterxml.jackson.databind.jsontype; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/module/000077500000000000000000000000001325620701100320145ustar00rootroot00000000000000SimpleAbstractTypeResolver.java000066400000000000000000000073721325620701100401120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.lang.reflect.Modifier; import java.util.*; import com.fasterxml.jackson.databind.AbstractTypeResolver; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.ClassKey; /** * Simple {@link AbstractTypeResolver} implementation, which is * based on static mapping from abstract super types into * sub types (concrete or abstract), but retaining generic * parameterization. * Can be used for things like specifying which implementation of * {@link java.util.Collection} to use: *

 *  SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver();
 *  // To make all properties declared as Collection, List, to LinkedList
 *  resolver.addMapping(Collection.class, LinkedList.class);
 *  resolver.addMapping(List.class, LinkedList.class);
 *
* Can also be used as an alternative to per-class annotations when defining * concrete implementations; however, only works with abstract types (since * this is only called for abstract types) */ public class SimpleAbstractTypeResolver extends AbstractTypeResolver implements java.io.Serializable { private static final long serialVersionUID = 8635483102371490919L; /** * Mappings from super types to subtypes */ protected final HashMap> _mappings = new HashMap>(); /** * Method for adding a mapping from super type to specific subtype. * Arguments will be checked by method, to ensure that superType * is abstract (since resolver is never called for concrete classes); * as well as to ensure that there is supertype/subtype relationship * (to ensure there won't be cycles during resolution). * * @param superType Abstract type to resolve * @param subType Sub-class of superType, to map superTo to * * @return This resolver, to allow chaining of initializations */ public SimpleAbstractTypeResolver addMapping(Class superType, Class subType) { // Sanity checks, just in case someone tries to force typing... if (superType == subType) { throw new IllegalArgumentException("Cannot add mapping from class to itself"); } if (!superType.isAssignableFrom(subType)) { throw new IllegalArgumentException("Cannot add mapping from class "+superType.getName() +" to "+subType.getName()+", as latter is not a subtype of former"); } if (!Modifier.isAbstract(superType.getModifiers())) { throw new IllegalArgumentException("Cannot add mapping from class "+superType.getName() +" since it is not abstract"); } _mappings.put(new ClassKey(superType), subType); return this; } @Override public JavaType findTypeMapping(DeserializationConfig config, JavaType type) { // this is the main mapping base, so let's Class src = type.getRawClass(); Class dst = _mappings.get(new ClassKey(src)); if (dst == null) { return null; } // 09-Aug-2015, tatu: Instead of direct call via JavaType, better use TypeFactory return config.getTypeFactory().constructSpecializedType(type, dst); } @Override @Deprecated public JavaType resolveAbstractType(DeserializationConfig config, JavaType type){ // never materialize anything, so: return null; } @Override public JavaType resolveAbstractType(DeserializationConfig config, BeanDescription typeDesc) { // never materialize anything, so: return null; } } SimpleDeserializers.java000066400000000000000000000142471325620701100365670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.Deserializers; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.type.*; /** * Simple implementation {@link Deserializers} which allows registration of * deserializers based on raw (type erased class). * It can work well for basic bean and scalar type deserializers, but is not * a good fit for handling generic types (like {@link Map}s and {@link Collection}s * or array types). *

* Unlike {@link SimpleSerializers}, this class does not currently support generic mappings; * all mappings must be to exact declared deserialization type. */ public class SimpleDeserializers implements Deserializers, java.io.Serializable { private static final long serialVersionUID = 1L; protected HashMap> _classMappings = null; /** * Flag to help find "generic" enum deserializer, if one has been registered. * * @since 2.3 */ protected boolean _hasEnumDeserializer = false; /* /********************************************************** /* Life-cycle, construction and configuring /********************************************************** */ public SimpleDeserializers() { } /** * @since 2.1 */ public SimpleDeserializers(Map,JsonDeserializer> desers) { addDeserializers(desers); } public void addDeserializer(Class forClass, JsonDeserializer deser) { ClassKey key = new ClassKey(forClass); if (_classMappings == null) { _classMappings = new HashMap>(); } _classMappings.put(key, deser); // [Issue#227]: generic Enum deserializer? if (forClass == Enum.class) { _hasEnumDeserializer = true; } } /** * @since 2.1 */ @SuppressWarnings("unchecked") public void addDeserializers(Map,JsonDeserializer> desers) { for (Map.Entry,JsonDeserializer> entry : desers.entrySet()) { Class cls = entry.getKey(); // what a mess... nominal generics safety... JsonDeserializer deser = (JsonDeserializer) entry.getValue(); addDeserializer((Class) cls, deser); } } /* /********************************************************** /* Serializers implementation /********************************************************** */ @Override public JsonDeserializer findArrayDeserializer(ArrayType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { return _find(type); } @Override public JsonDeserializer findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { return _find(type); } @Override public JsonDeserializer findCollectionDeserializer(CollectionType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { return _find(type); } @Override public JsonDeserializer findCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { return _find(type); } @Override public JsonDeserializer findEnumDeserializer(Class type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { if (_classMappings == null) { return null; } JsonDeserializer deser = _classMappings.get(new ClassKey(type)); if (deser == null) { if (_hasEnumDeserializer && type.isEnum()) { deser = _classMappings.get(new ClassKey(Enum.class)); } } return deser; } @Override public JsonDeserializer findTreeNodeDeserializer(Class nodeType, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { if (_classMappings == null) { return null; } return _classMappings.get(new ClassKey(nodeType)); } @Override public JsonDeserializer findReferenceDeserializer(ReferenceType refType, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer contentTypeDeserializer, JsonDeserializer contentDeserializer) throws JsonMappingException { // 21-Oct-2015, tatu: Unlikely this will really get used (reference types need more // work, simple registration probably not sufficient). But whatever. return _find(refType); } @Override public JsonDeserializer findMapDeserializer(MapType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { return _find(type); } @Override public JsonDeserializer findMapLikeDeserializer(MapLikeType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { return _find(type); } private final JsonDeserializer _find(JavaType type) { if (_classMappings == null) { return null; } return _classMappings.get(new ClassKey(type.getRawClass())); } } SimpleKeyDeserializers.java000066400000000000000000000037371325620701100372420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.util.Collection; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.KeyDeserializers; import com.fasterxml.jackson.databind.type.ClassKey; /** * Simple implementation {@link KeyDeserializers} which allows registration of * deserializers based on raw (type erased class). * It can work well for basic bean and scalar type deserializers, but is not * a good fit for handling generic types (like {@link Map}s and {@link Collection}s * or array types). *

* Unlike {@link SimpleSerializers}, this class does not currently support generic mappings; * all mappings must be to exact declared deserialization type. */ public class SimpleKeyDeserializers implements KeyDeserializers, java.io.Serializable // since 2.1 { private static final long serialVersionUID = 1L; protected HashMap _classMappings = null; /* /********************************************************** /* Life-cycle, construction and configuring /********************************************************** */ public SimpleKeyDeserializers() { } public SimpleKeyDeserializers addDeserializer(Class forClass, KeyDeserializer deser) { if (_classMappings == null) { _classMappings = new HashMap(); } _classMappings.put(new ClassKey(forClass), deser); return this; } /* /********************************************************** /* Serializers implementation /********************************************************** */ @Override public KeyDeserializer findKeyDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) { if (_classMappings == null) { return null; } return _classMappings.get(new ClassKey(type.getRawClass())); } } SimpleModule.java000066400000000000000000000432001325620701100351760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; /** * Vanilla {@link Module} implementation that allows registration * of serializers and deserializers, bean serializer * and deserializer modifiers, registration of subtypes and mix-ins * as well as some other commonly * needed aspects (addition of custom {@link AbstractTypeResolver}s, * {@link com.fasterxml.jackson.databind.deser.ValueInstantiator}s). *

* NOTE: although it is not expected that sub-types should need to * override {@link #setupModule(SetupContext)} method, if they choose * to do so they MUST call super.setupModule(context); * to ensure that registration works as expected. *

* WARNING: when registering {@link JsonSerializer}s and {@link JsonDeserializer}s, * only type erased {@code Class} is compared: this means that usually you should * NOT use this implementation for registering structured types such as * {@link java.util.Collection}s or {@link java.util.Map}s: this because parametric * type information will not be considered and you may end up having "wrong" handler * for your type. * What you need to do, instead, is to implement {@link com.fasterxml.jackson.databind.deser.Deserializers} * and/or {@link com.fasterxml.jackson.databind.ser.Serializers} callbacks to match full type * signatures (with {@link JavaType}). */ public class SimpleModule extends com.fasterxml.jackson.databind.Module implements java.io.Serializable { private static final long serialVersionUID = 1L; // 2.5.0 protected final String _name; protected final Version _version; protected SimpleSerializers _serializers = null; protected SimpleDeserializers _deserializers = null; protected SimpleSerializers _keySerializers = null; protected SimpleKeyDeserializers _keyDeserializers = null; /** * Lazily-constructed resolver used for storing mappings from * abstract classes to more specific implementing classes * (which may be abstract or concrete) */ protected SimpleAbstractTypeResolver _abstractTypes = null; /** * Lazily-constructed resolver used for storing mappings from * abstract classes to more specific implementing classes * (which may be abstract or concrete) */ protected SimpleValueInstantiators _valueInstantiators = null; /** * @since 2.2 */ protected BeanDeserializerModifier _deserializerModifier = null; /** * @since 2.2 */ protected BeanSerializerModifier _serializerModifier = null; /** * Lazily-constructed map that contains mix-in definitions, indexed * by target class, value being mix-in to apply. */ protected HashMap, Class> _mixins = null; /** * Set of subtypes to register, if any. */ protected LinkedHashSet _subtypes = null; /** * @since 2.3 */ protected PropertyNamingStrategy _namingStrategy = null; /* /********************************************************** /* Life-cycle: creation /********************************************************** */ /** * Constructors that should only be used for non-reusable * convenience modules used by app code: "real" modules should * use actual name and version number information. */ public SimpleModule() { // can't chain when making reference to 'this' // note: generate different name for direct instantiation, sub-classing _name = (getClass() == SimpleModule.class) ? "SimpleModule-"+System.identityHashCode(this) : getClass().getName(); _version = Version.unknownVersion(); } /** * Convenience constructor that will default version to * {@link Version#unknownVersion()}. */ public SimpleModule(String name) { this(name, Version.unknownVersion()); } /** * Convenience constructor that will use specified Version, * including name from {@link Version#getArtifactId()} */ public SimpleModule(Version version) { _name = version.getArtifactId(); _version = version; } /** * Constructor to use for actual reusable modules. * ObjectMapper may use name as identifier to notice attempts * for multiple registrations of the same module (although it * does not have to). * * @param name Unique name of the module * @param version Version of the module */ public SimpleModule(String name, Version version) { _name = name; _version = version; } /** * @since 2.1 */ public SimpleModule(String name, Version version, Map,JsonDeserializer> deserializers) { this(name, version, deserializers, null); } /** * @since 2.1 */ public SimpleModule(String name, Version version, List> serializers) { this(name, version, null, serializers); } /** * @since 2.1 */ public SimpleModule(String name, Version version, Map,JsonDeserializer> deserializers, List> serializers) { _name = name; _version = version; if (deserializers != null) { _deserializers = new SimpleDeserializers(deserializers); } if (serializers != null) { _serializers = new SimpleSerializers(serializers); } } /** * Since instances are likely to be custom, implementation returns * null if (but only if!) this class is directly instantiated; * but class name (default impl) for sub-classes. */ @Override public Object getTypeId() { if (getClass() == SimpleModule.class) { return null; } return super.getTypeId(); } /* /********************************************************** /* Simple setters to allow overriding /********************************************************** */ /** * Resets all currently configured serializers. */ public void setSerializers(SimpleSerializers s) { _serializers = s; } /** * Resets all currently configured deserializers. */ public void setDeserializers(SimpleDeserializers d) { _deserializers = d; } /** * Resets all currently configured key serializers. */ public void setKeySerializers(SimpleSerializers ks) { _keySerializers = ks; } /** * Resets all currently configured key deserializers. */ public void setKeyDeserializers(SimpleKeyDeserializers kd) { _keyDeserializers = kd; } /** * Resets currently configured abstract type mappings */ public void setAbstractTypes(SimpleAbstractTypeResolver atr) { _abstractTypes = atr; } /** * Resets all currently configured value instantiators */ public void setValueInstantiators(SimpleValueInstantiators svi) { _valueInstantiators = svi; } /** * @since 2.2 */ public SimpleModule setDeserializerModifier(BeanDeserializerModifier mod) { _deserializerModifier = mod; return this; } /** * @since 2.2 */ public SimpleModule setSerializerModifier(BeanSerializerModifier mod) { _serializerModifier = mod; return this; } /** * @since 2.3 */ protected SimpleModule setNamingStrategy(PropertyNamingStrategy naming) { _namingStrategy = naming; return this; } /* /********************************************************** /* Configuration methods, adding serializers /********************************************************** */ /** * Method for adding serializer to handle type that the serializer claims to handle * (see {@link JsonSerializer#handledType()}). *

* WARNING! Type matching only uses type-erased {@code Class} and should NOT * be used when registering serializers for generic types like * {@link java.util.Collection} and {@link java.util.Map}. */ public SimpleModule addSerializer(JsonSerializer ser) { _checkNotNull(ser, "serializer"); if (_serializers == null) { _serializers = new SimpleSerializers(); } _serializers.addSerializer(ser); return this; } /** * Method for adding serializer to handle values of specific type. *

* WARNING! Type matching only uses type-erased {@code Class} and should NOT * be used when registering serializers for generic types like * {@link java.util.Collection} and {@link java.util.Map}. */ public SimpleModule addSerializer(Class type, JsonSerializer ser) { _checkNotNull(type, "type to register serializer for"); _checkNotNull(ser, "serializer"); if (_serializers == null) { _serializers = new SimpleSerializers(); } _serializers.addSerializer(type, ser); return this; } public SimpleModule addKeySerializer(Class type, JsonSerializer ser) { _checkNotNull(type, "type to register key serializer for"); _checkNotNull(ser, "key serializer"); if (_keySerializers == null) { _keySerializers = new SimpleSerializers(); } _keySerializers.addSerializer(type, ser); return this; } /* /********************************************************** /* Configuration methods, adding deserializers /********************************************************** */ /** * Method for adding deserializer to handle specified type. *

* WARNING! Type matching only uses type-erased {@code Class} and should NOT * be used when registering serializers for generic types like * {@link java.util.Collection} and {@link java.util.Map}. */ public SimpleModule addDeserializer(Class type, JsonDeserializer deser) { _checkNotNull(type, "type to register deserializer for"); _checkNotNull(deser, "deserializer"); if (_deserializers == null) { _deserializers = new SimpleDeserializers(); } _deserializers.addDeserializer(type, deser); return this; } public SimpleModule addKeyDeserializer(Class type, KeyDeserializer deser) { _checkNotNull(type, "type to register key deserializer for"); _checkNotNull(deser, "key deserializer"); if (_keyDeserializers == null) { _keyDeserializers = new SimpleKeyDeserializers(); } _keyDeserializers.addDeserializer(type, deser); return this; } /* /********************************************************** /* Configuration methods, type mapping /********************************************************** */ /** * Lazily-constructed resolver used for storing mappings from * abstract classes to more specific implementing classes * (which may be abstract or concrete) */ public SimpleModule addAbstractTypeMapping(Class superType, Class subType) { _checkNotNull(superType, "abstract type to map"); _checkNotNull(subType, "concrete type to map to"); if (_abstractTypes == null) { _abstractTypes = new SimpleAbstractTypeResolver(); } // note: addMapping() will verify arguments _abstractTypes = _abstractTypes.addMapping(superType, subType); return this; } /** * Method for adding set of subtypes to be registered with * {@link ObjectMapper} * this is an alternative to using annotations in super type to indicate subtypes. */ public SimpleModule registerSubtypes(Class ... subtypes) { if (_subtypes == null) { _subtypes = new LinkedHashSet<>(); } for (Class subtype : subtypes) { _checkNotNull(subtype, "subtype to register"); _subtypes.add(new NamedType(subtype)); } return this; } /** * Method for adding set of subtypes (along with type name to use) to be registered with * {@link ObjectMapper} * this is an alternative to using annotations in super type to indicate subtypes. */ public SimpleModule registerSubtypes(NamedType ... subtypes) { if (_subtypes == null) { _subtypes = new LinkedHashSet<>(); } for (NamedType subtype : subtypes) { _checkNotNull(subtype, "subtype to register"); _subtypes.add(subtype); } return this; } /** * Method for adding set of subtypes (along with type name to use) to be registered with * {@link ObjectMapper} * this is an alternative to using annotations in super type to indicate subtypes. * * @since 2.9 */ public SimpleModule registerSubtypes(Collection> subtypes) { if (_subtypes == null) { _subtypes = new LinkedHashSet<>(); } for (Class subtype : subtypes) { _checkNotNull(subtype, "subtype to register"); _subtypes.add(new NamedType(subtype)); } return this; } /* /********************************************************** /* Configuration methods, add other handlers /********************************************************** */ /** * Method for registering {@link ValueInstantiator} to use when deserializing * instances of type beanType. *

* Instantiator is * registered when module is registered for ObjectMapper. */ public SimpleModule addValueInstantiator(Class beanType, ValueInstantiator inst) { _checkNotNull(beanType, "class to register value instantiator for"); _checkNotNull(inst, "value instantiator"); if (_valueInstantiators == null) { _valueInstantiators = new SimpleValueInstantiators(); } _valueInstantiators = _valueInstantiators.addValueInstantiator(beanType, inst); return this; } /** * Method for specifying that annotations define by mixinClass * should be "mixed in" with annotations that targetType * has (as if they were directly included on it!). *

* Mix-in annotations are * registered when module is registered for ObjectMapper. */ public SimpleModule setMixInAnnotation(Class targetType, Class mixinClass) { _checkNotNull(targetType, "target type"); _checkNotNull(mixinClass, "mixin class"); if (_mixins == null) { _mixins = new HashMap, Class>(); } _mixins.put(targetType, mixinClass); return this; } /* /********************************************************** /* Module impl /********************************************************** */ @Override public String getModuleName() { return _name; } /** * Standard implementation handles registration of all configured * customizations: it is important that sub-classes call this * implementation (usually before additional custom logic) * if they choose to override it; otherwise customizations * will not be registered. */ @Override public void setupModule(SetupContext context) { if (_serializers != null) { context.addSerializers(_serializers); } if (_deserializers != null) { context.addDeserializers(_deserializers); } if (_keySerializers != null) { context.addKeySerializers(_keySerializers); } if (_keyDeserializers != null) { context.addKeyDeserializers(_keyDeserializers); } if (_abstractTypes != null) { context.addAbstractTypeResolver(_abstractTypes); } if (_valueInstantiators != null) { context.addValueInstantiators(_valueInstantiators); } if (_deserializerModifier != null) { context.addBeanDeserializerModifier(_deserializerModifier); } if (_serializerModifier != null) { context.addBeanSerializerModifier(_serializerModifier); } if (_subtypes != null && _subtypes.size() > 0) { context.registerSubtypes(_subtypes.toArray(new NamedType[_subtypes.size()])); } if (_namingStrategy != null) { context.setNamingStrategy(_namingStrategy); } if (_mixins != null) { for (Map.Entry,Class> entry : _mixins.entrySet()) { context.setMixInAnnotations(entry.getKey(), entry.getValue()); } } } @Override public Version version() { return _version; } /* /********************************************************** /* Helper methods /********************************************************** */ /** * @since 2.9 */ protected void _checkNotNull(Object thingy, String type) { if (thingy == null) { throw new IllegalArgumentException(String.format( "Cannot pass `null` as %s", type)); } } } SimpleSerializers.java000066400000000000000000000210511325620701100362450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.Serializers; import com.fasterxml.jackson.databind.type.ArrayType; import com.fasterxml.jackson.databind.type.ClassKey; import com.fasterxml.jackson.databind.type.CollectionLikeType; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.MapLikeType; import com.fasterxml.jackson.databind.type.MapType; /** * Simple implementation {@link Serializers} which allows registration of * serializers based on raw (type erased class). * It can work well for basic bean and scalar type serializers, but is not * a good fit for handling generic types (like {@link Map}s and {@link Collection}s). *

* Type registrations are assumed to be general; meaning that registration of serializer * for a super type will also be used for handling subtypes, unless an exact match * is found first. As an example, handler for {@link CharSequence} would also be used * serializing {@link StringBuilder} instances, unless a direct mapping was found. */ public class SimpleSerializers extends Serializers.Base implements java.io.Serializable { private static final long serialVersionUID = 8531646511998456779L; /** * Class-based mappings that are used both for exact and * sub-class matches. */ protected HashMap> _classMappings = null; /** * Interface-based matches. */ protected HashMap> _interfaceMappings = null; /** * Flag to help find "generic" enum serializer, if one has been registered. * * @since 2.3 */ protected boolean _hasEnumSerializer = false; /* /********************************************************** /* Life-cycle, construction and configuring /********************************************************** */ public SimpleSerializers() { } /** * @since 2.1 */ public SimpleSerializers(List> sers) { addSerializers(sers); } /** * Method for adding given serializer for type that {@link JsonSerializer#handledType} * specifies (which MUST return a non-null class; and can NOT be {@link Object}, as a * sanity check). * For serializers that do not declare handled type, use the variant that takes * two arguments. * * @param ser */ public void addSerializer(JsonSerializer ser) { // Interface to match? Class cls = ser.handledType(); if (cls == null || cls == Object.class) { throw new IllegalArgumentException("JsonSerializer of type "+ser.getClass().getName() +" does not define valid handledType() -- must either register with method that takes type argument " +" or make serializer extend 'com.fasterxml.jackson.databind.ser.std.StdSerializer'"); } _addSerializer(cls, ser); } public void addSerializer(Class type, JsonSerializer ser) { _addSerializer(type, ser); } /** * @since 2.1 */ public void addSerializers(List> sers) { for (JsonSerializer ser : sers) { addSerializer(ser); } } /* /********************************************************** /* Serializers implementation /********************************************************** */ @Override public JsonSerializer findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc) { Class cls = type.getRawClass(); ClassKey key = new ClassKey(cls); JsonSerializer ser = null; // First: direct match? if (cls.isInterface()) { if (_interfaceMappings != null) { ser = _interfaceMappings.get(key); if (ser != null) { return ser; } } } else { if (_classMappings != null) { ser = _classMappings.get(key); if (ser != null) { return ser; } // [Issue#227]: Handle registration of plain `Enum` serializer if (_hasEnumSerializer && type.isEnumType()) { key.reset(Enum.class); ser = _classMappings.get(key); if (ser != null) { return ser; } } // If not direct match, maybe super-class match? for (Class curr = cls; (curr != null); curr = curr.getSuperclass()) { key.reset(curr); ser = _classMappings.get(key); if (ser != null) { return ser; } } } } // No direct match? How about super-interfaces? if (_interfaceMappings != null) { ser = _findInterfaceMapping(cls, key); if (ser != null) { return ser; } // still no matches? Maybe interfaces of super classes if (!cls.isInterface()) { while ((cls = cls.getSuperclass()) != null) { ser = _findInterfaceMapping(cls, key); if (ser != null) { return ser; } } } } return null; } @Override public JsonSerializer findArraySerializer(SerializationConfig config, ArrayType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { return findSerializer(config, type, beanDesc); } @Override public JsonSerializer findCollectionSerializer(SerializationConfig config, CollectionType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { return findSerializer(config, type, beanDesc); } @Override public JsonSerializer findCollectionLikeSerializer(SerializationConfig config, CollectionLikeType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { return findSerializer(config, type, beanDesc); } @Override public JsonSerializer findMapSerializer(SerializationConfig config, MapType type, BeanDescription beanDesc, JsonSerializer keySerializer, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { return findSerializer(config, type, beanDesc); } @Override public JsonSerializer findMapLikeSerializer(SerializationConfig config, MapLikeType type, BeanDescription beanDesc, JsonSerializer keySerializer, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { return findSerializer(config, type, beanDesc); } /* /********************************************************** /* Internal methods /********************************************************** */ protected JsonSerializer _findInterfaceMapping(Class cls, ClassKey key) { for (Class iface : cls.getInterfaces()) { key.reset(iface); JsonSerializer ser = _interfaceMappings.get(key); if (ser != null) { return ser; } ser = _findInterfaceMapping(iface, key); if (ser != null) { return ser; } } return null; } protected void _addSerializer(Class cls, JsonSerializer ser) { ClassKey key = new ClassKey(cls); // Interface or class type? if (cls.isInterface()) { if (_interfaceMappings == null) { _interfaceMappings = new HashMap>(); } _interfaceMappings.put(key, ser); } else { // nope, class: if (_classMappings == null) { _classMappings = new HashMap>(); } _classMappings.put(key, ser); if (cls == Enum.class) { _hasEnumSerializer = true; } } } } SimpleValueInstantiators.java000066400000000000000000000031321325620701100376100ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.util.HashMap; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.deser.ValueInstantiators; import com.fasterxml.jackson.databind.type.ClassKey; public class SimpleValueInstantiators extends ValueInstantiators.Base implements java.io.Serializable { private static final long serialVersionUID = -8929386427526115130L; /** * Mappings from raw (type-erased, i.e. non-generic) types * to matching {@link ValueInstantiator} instances. */ protected HashMap _classMappings; /* /********************************************************** /* Life-cycle, construction and configuring /********************************************************** */ public SimpleValueInstantiators() { _classMappings = new HashMap(); } public SimpleValueInstantiators addValueInstantiator(Class forType, ValueInstantiator inst) { _classMappings.put(new ClassKey(forType), inst); return this; } @Override public ValueInstantiator findValueInstantiator(DeserializationConfig config, BeanDescription beanDesc, ValueInstantiator defaultInstantiator) { ValueInstantiator inst = _classMappings.get(new ClassKey(beanDesc.getBeanClass())); return (inst == null) ? defaultInstantiator : inst; } } package-info.java000066400000000000000000000012201325620701100351170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/module/** * Package that contains classes and interfaces to help implement * custom extension {@link com.fasterxml.jackson.databind.Module}s * (which are registered using * {@link com.fasterxml.jackson.databind.ObjectMapper#registerModule}. *

* Note that classes in the package only support registering * handlers for non-generic types (types without type * parameterization) -- hence "simple" -- which works for * many cases, but not all. So if you will need to register * handlers for generic types, you will usually need to either * sub-class handlers, or implement/extend base types directly. */ package com.fasterxml.jackson.databind.module; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/node/000077500000000000000000000000001325620701100314545ustar00rootroot00000000000000ArrayNode.java000066400000000000000000000551231325620701100341320ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.util.RawValue; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.List; /** * Node class that represents Arrays mapped from JSON content. *

* Note: class was final temporarily for Jackson 2.2. */ public class ArrayNode extends ContainerNode { private final List _children; public ArrayNode(JsonNodeFactory nf) { super(nf); _children = new ArrayList(); } /** * @since 2.8 */ public ArrayNode(JsonNodeFactory nf, int capacity) { super(nf); _children = new ArrayList(capacity); } /** * @since 2.7 */ public ArrayNode(JsonNodeFactory nf, List children) { super(nf); _children = children; } @Override protected JsonNode _at(JsonPointer ptr) { return get(ptr.getMatchingIndex()); } // note: co-variant to allow caller-side type safety @SuppressWarnings("unchecked") @Override public ArrayNode deepCopy() { ArrayNode ret = new ArrayNode(_nodeFactory); for (JsonNode element: _children) ret._children.add(element.deepCopy()); return ret; } /* /********************************************************** /* Overrides for JsonSerializable.Base /********************************************************** */ @Override public boolean isEmpty(SerializerProvider serializers) { return _children.isEmpty(); } /* /********************************************************** /* Implementation of core JsonNode API /********************************************************** */ @Override public JsonNodeType getNodeType() { return JsonNodeType.ARRAY; } @Override public boolean isArray() { return true; } @Override public JsonToken asToken() { return JsonToken.START_ARRAY; } @Override public int size() { return _children.size(); } @Override public Iterator elements() { return _children.iterator(); } @Override public JsonNode get(int index) { if (index >= 0 && index < _children.size()) { return _children.get(index); } return null; } @Override public JsonNode get(String fieldName) { return null; } @Override public JsonNode path(String fieldName) { return MissingNode.getInstance(); } @Override public JsonNode path(int index) { if (index >= 0 && index < _children.size()) { return _children.get(index); } return MissingNode.getInstance(); } @Override public boolean equals(Comparator comparator, JsonNode o) { if (!(o instanceof ArrayNode)) { return false; } ArrayNode other = (ArrayNode) o; final int len = _children.size(); if (other.size() != len) { return false; } List l1 = _children; List l2 = other._children; for (int i = 0; i < len; ++i) { if (!l1.get(i).equals(comparator, l2.get(i))) { return false; } } return true; } /* /********************************************************** /* Public API, serialization /********************************************************** */ @Override public void serialize(JsonGenerator f, SerializerProvider provider) throws IOException { final List c = _children; final int size = c.size(); f.writeStartArray(size); for (int i = 0; i < size; ++i) { // we'll typically have array list // For now, assuming it's either BaseJsonNode, JsonSerializable JsonNode n = c.get(i); ((BaseJsonNode) n).serialize(f, provider); } f.writeEndArray(); } @Override public void serializeWithType(JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(this, JsonToken.START_ARRAY)); for (JsonNode n : _children) { ((BaseJsonNode)n).serialize(g, provider); } typeSer.writeTypeSuffix(g, typeIdDef); } /* /********************************************************** /* Public API, finding value nodes /********************************************************** */ @Override public JsonNode findValue(String fieldName) { for (JsonNode node : _children) { JsonNode value = node.findValue(fieldName); if (value != null) { return value; } } return null; } @Override public List findValues(String fieldName, List foundSoFar) { for (JsonNode node : _children) { foundSoFar = node.findValues(fieldName, foundSoFar); } return foundSoFar; } @Override public List findValuesAsText(String fieldName, List foundSoFar) { for (JsonNode node : _children) { foundSoFar = node.findValuesAsText(fieldName, foundSoFar); } return foundSoFar; } @Override public ObjectNode findParent(String fieldName) { for (JsonNode node : _children) { JsonNode parent = node.findParent(fieldName); if (parent != null) { return (ObjectNode) parent; } } return null; } @Override public List findParents(String fieldName, List foundSoFar) { for (JsonNode node : _children) { foundSoFar = node.findParents(fieldName, foundSoFar); } return foundSoFar; } /* /********************************************************** /* Extended ObjectNode API, accessors /********************************************************** */ /** * Method that will set specified field, replacing old value, * if any. * * @param value to set field to; if null, will be converted * to a {@link NullNode} first (to remove field entry, call * {@link #remove} instead) * * @return Old value of the field, if any; null if there was no * old value. */ public JsonNode set(int index, JsonNode value) { if (value == null) { // let's not store 'raw' nulls but nodes value = nullNode(); } if (index < 0 || index >= _children.size()) { throw new IndexOutOfBoundsException("Illegal index "+ index +", array size "+size()); } return _children.set(index, value); } /** * Method for adding specified node at the end of this array. * * @return This node, to allow chaining */ public ArrayNode add(JsonNode value) { if (value == null) { // let's not store 'raw' nulls but nodes value = nullNode(); } _add(value); return this; } /** * Method for adding all child nodes of given Array, appending to * child nodes this array contains * * @param other Array to add contents from * * @return This node (to allow chaining) */ public ArrayNode addAll(ArrayNode other) { _children.addAll(other._children); return this; } /** * Method for adding given nodes as child nodes of this array node. * * @param nodes Nodes to add * * @return This node (to allow chaining) */ public ArrayNode addAll(Collection nodes) { _children.addAll(nodes); return this; } /** * Method for inserting specified child node as an element * of this Array. If index is 0 or less, it will be inserted as * the first element; if >= size(), appended at the end, and otherwise * inserted before existing element in specified index. * No exceptions are thrown for any index. * * @return This node (to allow chaining) */ public ArrayNode insert(int index, JsonNode value) { if (value == null) { value = nullNode(); } _insert(index, value); return this; } /** * Method for removing an entry from this ArrayNode. * Will return value of the entry at specified index, if entry existed; * null if not. * * @return Node removed, if any; null if none */ public JsonNode remove(int index) { if (index >= 0 && index < _children.size()) { return _children.remove(index); } return null; } /** * Method for removing all elements of this array, leaving the * array empty. * * @return This node (to allow chaining) */ @Override public ArrayNode removeAll() { _children.clear(); return this; } /* /********************************************************** /* Extended ObjectNode API, mutators, generic; addXxx()/insertXxx() /********************************************************** */ /** * Method that will construct an ArrayNode and add it at the end * of this array node. * * @return Newly constructed ArrayNode */ public ArrayNode addArray() { ArrayNode n = arrayNode(); _add(n); return n; } /** * Method that will construct an ObjectNode and add it at the end * of this array node. * * @return Newly constructed ObjectNode */ public ObjectNode addObject() { ObjectNode n = objectNode(); _add(n); return n; } /** * Method that will construct a POJONode and add it at the end * of this array node. * * @return This array node, to allow chaining */ public ArrayNode addPOJO(Object value) { if (value == null) { addNull(); } else { _add(pojoNode(value)); } return this; } /** * @return This array node, to allow chaining * * @since 2.6 */ public ArrayNode addRawValue(RawValue raw) { if (raw == null) { addNull(); } else { _add(rawValueNode(raw)); } return this; } /** * Method that will add a null value at the end of this array node. * * @return This array node, to allow chaining */ public ArrayNode addNull() { _add(nullNode()); return this; } /** * Method for adding specified number at the end of this array. * * @return This array node, to allow chaining */ public ArrayNode add(int v) { _add(numberNode(v)); return this; } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This array node, to allow chaining */ public ArrayNode add(Integer value) { if (value == null) { return addNull(); } return _add(numberNode(value.intValue())); } /** * Method for adding specified number at the end of this array. * * @return This array node, to allow chaining */ public ArrayNode add(long v) { return _add(numberNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This array node, to allow chaining */ public ArrayNode add(Long value) { if (value == null) { return addNull(); } return _add(numberNode(value.longValue())); } /** * Method for adding specified number at the end of this array. * * @return This array node, to allow chaining */ public ArrayNode add(float v) { return _add(numberNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This array node, to allow chaining */ public ArrayNode add(Float value) { if (value == null) { return addNull(); } return _add(numberNode(value.floatValue())); } /** * Method for adding specified number at the end of this array. * * @return This array node, to allow chaining */ public ArrayNode add(double v) { return _add(numberNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This array node, to allow chaining */ public ArrayNode add(Double value) { if (value == null) { return addNull(); } return _add(numberNode(value.doubleValue())); } /** * Method for adding specified number at the end of this array. * * @return This array node, to allow chaining */ public ArrayNode add(BigDecimal v) { if (v == null) { return addNull(); } return _add(numberNode(v)); } /** * Method for adding specified number at the end of this array. * * @return This array node, to allow chaining * * @since 2.9 */ public ArrayNode add(BigInteger v) { if (v == null) { return addNull(); } return _add(numberNode(v)); } /** * Method for adding specified String value at the end of this array. * * @return This array node, to allow chaining */ public ArrayNode add(String v) { if (v == null) { return addNull(); } return _add(textNode(v)); } /** * Method for adding specified boolean value at the end of this array. * * @return This array node, to allow chaining */ public ArrayNode add(boolean v) { return _add(booleanNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This array node, to allow chaining */ public ArrayNode add(Boolean value) { if (value == null) { return addNull(); } return _add(booleanNode(value.booleanValue())); } /** * Method for adding specified binary value at the end of this array * (note: when serializing as JSON, will be output Base64 encoded) * * @return This array node, to allow chaining */ public ArrayNode add(byte[] v) { if (v == null) { return addNull(); } return _add(binaryNode(v)); } /** * Method for creating an array node, inserting it at the * specified point in the array, * and returning the newly created array * (note: NOT 'this' array) */ public ArrayNode insertArray(int index) { ArrayNode n = arrayNode(); _insert(index, n); return n; } /** * Method for creating an {@link ObjectNode}, appending it at the end * of this array, and returning the newly created node * (note: NOT 'this' array) * * @return Newly constructed ObjectNode */ public ObjectNode insertObject(int index) { ObjectNode n = objectNode(); _insert(index, n); return n; } /** * Method that will construct a POJONode and * insert it at specified position in this array. * * @return This array node, to allow chaining */ public ArrayNode insertPOJO(int index, Object value) { if (value == null) { return insertNull(index); } return _insert(index, pojoNode(value)); } /** * Method that will insert a null value * at specified position in this array. * * @return This array node, to allow chaining */ public ArrayNode insertNull(int index) { _insert(index, nullNode()); return this; } /** * Method that will insert specified numeric value * at specified position in this array. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, int v) { _insert(index, numberNode(v)); return this; } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, Integer value) { if (value == null) { insertNull(index); } else { _insert(index, numberNode(value.intValue())); } return this; } /** * Method that will insert specified numeric value * at specified position in this array. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, long v) { return _insert(index, numberNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, Long value) { if (value == null) { return insertNull(index); } return _insert(index, numberNode(value.longValue())); } /** * Method that will insert specified numeric value * at specified position in this array. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, float v) { return _insert(index, numberNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, Float value) { if (value == null) { return insertNull(index); } return _insert(index, numberNode(value.floatValue())); } /** * Method that will insert specified numeric value * at specified position in this array. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, double v) { return _insert(index, numberNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, Double value) { if (value == null) { return insertNull(index); } return _insert(index, numberNode(value.doubleValue())); } /** * Method that will insert specified numeric value * at specified position in this array. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, BigDecimal v) { if (v == null) { return insertNull(index); } return _insert(index, numberNode(v)); } /** * Method that will insert specified numeric value * at specified position in this array. * * @return This array node, to allow chaining * * @since 2.9 */ public ArrayNode insert(int index, BigInteger v) { if (v == null) { return insertNull(index); } return _insert(index, numberNode(v)); } /** * Method that will insert specified String * at specified position in this array. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, String v) { if (v == null) { return insertNull(index); } return _insert(index, textNode(v)); } /** * Method that will insert specified String * at specified position in this array. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, boolean v) { return _insert(index, booleanNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This array node, to allow chaining */ public ArrayNode insert(int index, Boolean value) { if (value == null) { return insertNull(index); } return _insert(index, booleanNode(value.booleanValue())); } /** * Method that will insert specified binary value * at specified position in this array * (note: when written as JSON, will be Base64 encoded) * * @return This array node, to allow chaining */ public ArrayNode insert(int index, byte[] v) { if (v == null) { return insertNull(index); } return _insert(index, binaryNode(v)); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof ArrayNode) { return _children.equals(((ArrayNode) o)._children); } return false; } /** * @since 2.3 */ protected boolean _childrenEqual(ArrayNode other) { return _children.equals(other._children); } @Override public int hashCode() { return _children.hashCode(); } @Override public String toString() { StringBuilder sb = new StringBuilder(16 + (size() << 4)); sb.append('['); for (int i = 0, len = _children.size(); i < len; ++i) { if (i > 0) { sb.append(','); } sb.append(_children.get(i).toString()); } sb.append(']'); return sb.toString(); } /* /********************************************************** /* Internal methods (overridable) /********************************************************** */ protected ArrayNode _add(JsonNode node) { _children.add(node); return this; } protected ArrayNode _insert(int index, JsonNode node) { if (index < 0) { _children.add(0, node); } else if (index >= _children.size()) { _children.add(node); } else { _children.add(index, node); } return this; } } BaseJsonNode.java000066400000000000000000000057771325620701100345720ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonSerializable; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * Abstract base class common to all standard {@link JsonNode} * implementations. * The main addition here is that we declare that sub-classes must * implement {@link JsonSerializable}. * This simplifies object mapping aspects a bit, as no external serializers are needed. */ public abstract class BaseJsonNode extends JsonNode implements JsonSerializable { protected BaseJsonNode() { } /* /********************************************************** /* Basic definitions for non-container types /********************************************************** */ @Override public final JsonNode findPath(String fieldName) { JsonNode value = findValue(fieldName); if (value == null) { return MissingNode.getInstance(); } return value; } // Also, force (re)definition (2.7) @Override public abstract int hashCode(); /* /********************************************************** /* Support for traversal-as-stream /********************************************************** */ @Override public JsonParser traverse() { return new TreeTraversingParser(this); } @Override public JsonParser traverse(ObjectCodec codec) { return new TreeTraversingParser(this, codec); } /** * Method that can be used for efficient type detection * when using stream abstraction for traversing nodes. * Will return the first {@link JsonToken} that equivalent * stream event would produce (for most nodes there is just * one token but for structured/container types multiple) */ @Override public abstract JsonToken asToken(); /** * Returns code that identifies type of underlying numeric * value, if (and only if) node is a number node. */ @Override public JsonParser.NumberType numberType() { // most types non-numeric, so: return null; } /* /********************************************************** /* JsonSerializable /********************************************************** */ /** * Method called to serialize node instances using given generator. */ @Override public abstract void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException; /** * Type information is needed, even if JsonNode instances are "plain" JSON, * since they may be mixed with other types. */ @Override public abstract void serializeWithType(JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) throws IOException, JsonProcessingException; } BigIntegerNode.java000066400000000000000000000065321325620701100350730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.SerializerProvider; /** * Numeric node that contains simple 64-bit integer values. */ public class BigIntegerNode extends NumericNode { private final static BigInteger MIN_INTEGER = BigInteger.valueOf(Integer.MIN_VALUE); private final static BigInteger MAX_INTEGER = BigInteger.valueOf(Integer.MAX_VALUE); private final static BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE); private final static BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE); final protected BigInteger _value; /* /********************************************************** /* Construction /********************************************************** */ public BigIntegerNode(BigInteger v) { _value = v; } public static BigIntegerNode valueOf(BigInteger v) { return new BigIntegerNode(v); } /* /********************************************************** /* Overrridden JsonNode methods /********************************************************** */ @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_INT; } @Override public JsonParser.NumberType numberType() { return JsonParser.NumberType.BIG_INTEGER; } @Override public boolean isIntegralNumber() { return true; } @Override public boolean isBigInteger() { return true; } @Override public boolean canConvertToInt() { return (_value.compareTo(MIN_INTEGER) >= 0) && (_value.compareTo(MAX_INTEGER) <= 0); } @Override public boolean canConvertToLong() { return (_value.compareTo(MIN_LONG) >= 0) && (_value.compareTo(MAX_LONG) <= 0); } @Override public Number numberValue() { return _value; } @Override public short shortValue() { return _value.shortValue(); } @Override public int intValue() { return _value.intValue(); } @Override public long longValue() { return _value.longValue(); } @Override public BigInteger bigIntegerValue() { return _value; } @Override public float floatValue() { return _value.floatValue(); } @Override public double doubleValue() { return _value.doubleValue(); } @Override public BigDecimal decimalValue() { return new BigDecimal(_value); } /* /********************************************************** /* General type coercions /********************************************************** */ @Override public String asText() { return _value.toString(); } @Override public boolean asBoolean(boolean defaultValue) { return !BigInteger.ZERO.equals(_value); } @Override public final void serialize(JsonGenerator jg, SerializerProvider provider) throws IOException, JsonProcessingException { jg.writeNumber(_value); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (!(o instanceof BigIntegerNode)) { return false; } return ((BigIntegerNode) o)._value.equals(_value); } @Override public int hashCode() { return _value.hashCode(); } } BinaryNode.java000066400000000000000000000060121325620701100342710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import java.util.Arrays; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.SerializerProvider; /** * Value node that contains Base64 encoded binary value, which will be * output and stored as Json String value. */ public class BinaryNode extends ValueNode { final static BinaryNode EMPTY_BINARY_NODE = new BinaryNode(new byte[0]); protected final byte[] _data; public BinaryNode(byte[] data) { _data = data; } public BinaryNode(byte[] data, int offset, int length) { if (offset == 0 && length == data.length) { _data = data; } else { _data = new byte[length]; System.arraycopy(data, offset, _data, 0, length); } } public static BinaryNode valueOf(byte[] data) { if (data == null) { return null; } if (data.length == 0) { return EMPTY_BINARY_NODE; } return new BinaryNode(data); } public static BinaryNode valueOf(byte[] data, int offset, int length) { if (data == null) { return null; } if (length == 0) { return EMPTY_BINARY_NODE; } return new BinaryNode(data, offset, length); } @Override public JsonNodeType getNodeType() { return JsonNodeType.BINARY; } @Override public JsonToken asToken() { /* No distinct type; could use one for textual values, * but given that it's not in text form at this point, * embedded-object is closest */ return JsonToken.VALUE_EMBEDDED_OBJECT; } /** *

* Note: caller is not to modify returned array in any way, since * it is not a copy but reference to the underlying byte array. */ @Override public byte[] binaryValue() { return _data; } /** * Hmmh. This is not quite as efficient as using {@link #serialize}, * but will work correctly. */ @Override public String asText() { return Base64Variants.getDefaultVariant().encode(_data, false); } @Override public final void serialize(JsonGenerator jg, SerializerProvider provider) throws IOException, JsonProcessingException { jg.writeBinary(provider.getConfig().getBase64Variant(), _data, 0, _data.length); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (!(o instanceof BinaryNode)) { return false; } return Arrays.equals(((BinaryNode) o)._data, _data); } @Override public int hashCode() { return (_data == null) ? -1 : _data.length; } /** * Different from other values, since contents need to be surrounded * by (double) quotes. */ @Override public String toString() { return Base64Variants.getDefaultVariant().encode(_data, true); } } BooleanNode.java000066400000000000000000000047171325620701100344360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.SerializerProvider; /** * This concrete value class is used to contain boolean (true / false) * values. Only two instances are ever created, to minimize memory * usage. */ public class BooleanNode extends ValueNode { // // Just need two instances... public final static BooleanNode TRUE = new BooleanNode(true); public final static BooleanNode FALSE = new BooleanNode(false); private final boolean _value; /** *

* NOTE: visibility raised to `protected` in 2.9.3 to allow custom subtypes. */ protected BooleanNode(boolean v) { _value = v; } public static BooleanNode getTrue() { return TRUE; } public static BooleanNode getFalse() { return FALSE; } public static BooleanNode valueOf(boolean b) { return b ? TRUE : FALSE; } @Override public JsonNodeType getNodeType() { return JsonNodeType.BOOLEAN; } @Override public JsonToken asToken() { return _value ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE; } @Override public boolean booleanValue() { return _value; } @Override public String asText() { return _value ? "true" : "false"; } @Override public boolean asBoolean() { return _value; } @Override public boolean asBoolean(boolean defaultValue) { return _value; } @Override public int asInt(int defaultValue) { return _value ? 1 : 0; } @Override public long asLong(long defaultValue) { return _value ? 1L : 0L; } @Override public double asDouble(double defaultValue) { return _value ? 1.0 : 0.0; } @Override public final void serialize(JsonGenerator g, SerializerProvider provider) throws IOException { g.writeBoolean(_value); } @Override public int hashCode() { return _value ? 3 : 1; } @Override public boolean equals(Object o) { /* 11-Mar-2013, tatu: Apparently ClassLoaders can manage to load * different instances, rendering identity comparisons broken. * So let's use value instead. */ if (o == this) return true; if (o == null) return false; if (!(o instanceof BooleanNode)) { return false; } return (_value == ((BooleanNode) o)._value); } } ContainerNode.java000066400000000000000000000116751325620701100350020ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.util.RawValue; /** * This intermediate base class is used for all container nodes, * specifically, array and object nodes. */ public abstract class ContainerNode> extends BaseJsonNode implements JsonNodeCreator { /** * We will keep a reference to the Object (usually TreeMapper) * that can construct instances of nodes to add to this container * node. */ protected final JsonNodeFactory _nodeFactory; protected ContainerNode(JsonNodeFactory nc) { _nodeFactory = nc; } // all containers are mutable: can't define: // @Override public abstract T deepCopy(); @Override public abstract JsonToken asToken(); @Override public String asText() { return ""; } /* /********************************************************** /* Methods reset as abstract to force real implementation /********************************************************** */ @Override public abstract int size(); @Override public abstract JsonNode get(int index); @Override public abstract JsonNode get(String fieldName); /* /********************************************************** /* JsonNodeCreator implementation, just dispatch to /* the real creator /********************************************************** */ /** * Factory method that constructs and returns an empty {@link ArrayNode} * Construction is done using registered {@link JsonNodeFactory}. */ @Override public final ArrayNode arrayNode() { return _nodeFactory.arrayNode(); } /** * Factory method that constructs and returns an {@link ArrayNode} with an initial capacity * Construction is done using registered {@link JsonNodeFactory} * @param capacity the initial capacity of the ArrayNode */ @Override public final ArrayNode arrayNode(int capacity) { return _nodeFactory.arrayNode(capacity); } /** * Factory method that constructs and returns an empty {@link ObjectNode} * Construction is done using registered {@link JsonNodeFactory}. */ @Override public final ObjectNode objectNode() { return _nodeFactory.objectNode(); } @Override public final NullNode nullNode() { return _nodeFactory.nullNode(); } @Override public final BooleanNode booleanNode(boolean v) { return _nodeFactory.booleanNode(v); } @Override public final NumericNode numberNode(byte v) { return _nodeFactory.numberNode(v); } @Override public final NumericNode numberNode(short v) { return _nodeFactory.numberNode(v); } @Override public final NumericNode numberNode(int v) { return _nodeFactory.numberNode(v); } @Override public final NumericNode numberNode(long v) { return _nodeFactory.numberNode(v); } @Override public final NumericNode numberNode(float v) { return _nodeFactory.numberNode(v); } @Override public final NumericNode numberNode(double v) { return _nodeFactory.numberNode(v); } @Override public final ValueNode numberNode(BigInteger v) { return _nodeFactory.numberNode(v); } @Override public final ValueNode numberNode(BigDecimal v) { return (_nodeFactory.numberNode(v)); } @Override public final ValueNode numberNode(Byte v) { return _nodeFactory.numberNode(v); } @Override public final ValueNode numberNode(Short v) { return _nodeFactory.numberNode(v); } @Override public final ValueNode numberNode(Integer v) { return _nodeFactory.numberNode(v); } @Override public final ValueNode numberNode(Long v) { return _nodeFactory.numberNode(v); } @Override public final ValueNode numberNode(Float v) { return _nodeFactory.numberNode(v); } @Override public final ValueNode numberNode(Double v) { return _nodeFactory.numberNode(v); } @Override public final TextNode textNode(String text) { return _nodeFactory.textNode(text); } @Override public final BinaryNode binaryNode(byte[] data) { return _nodeFactory.binaryNode(data); } @Override public final BinaryNode binaryNode(byte[] data, int offset, int length) { return _nodeFactory.binaryNode(data, offset, length); } @Override public final ValueNode pojoNode(Object pojo) { return _nodeFactory.pojoNode(pojo); } @Override public final ValueNode rawValueNode(RawValue value) { return _nodeFactory.rawValueNode(value); } /* /********************************************************** /* Common mutators /********************************************************** */ /** * Method for removing all children container has (if any) * * @return Container node itself (to allow method call chaining) */ public abstract T removeAll(); } DecimalNode.java000066400000000000000000000073651325620701100344170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; /** * Numeric node that contains values that do not fit in simple * integer (int, long) or floating point (double) values. */ public class DecimalNode extends NumericNode { public static final DecimalNode ZERO = new DecimalNode(BigDecimal.ZERO); private final static BigDecimal MIN_INTEGER = BigDecimal.valueOf(Integer.MIN_VALUE); private final static BigDecimal MAX_INTEGER = BigDecimal.valueOf(Integer.MAX_VALUE); private final static BigDecimal MIN_LONG = BigDecimal.valueOf(Long.MIN_VALUE); private final static BigDecimal MAX_LONG = BigDecimal.valueOf(Long.MAX_VALUE); final protected BigDecimal _value; /* /********************************************************** /* Construction /********************************************************** */ public DecimalNode(BigDecimal v) { _value = v; } public static DecimalNode valueOf(BigDecimal d) { return new DecimalNode(d); } /* /********************************************************** /* BaseJsonNode extended API /********************************************************** */ @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_FLOAT; } @Override public JsonParser.NumberType numberType() { return JsonParser.NumberType.BIG_DECIMAL; } /* /********************************************************** /* Overrridden JsonNode methods /********************************************************** */ @Override public boolean isFloatingPointNumber() { return true; } @Override public boolean isBigDecimal() { return true; } @Override public boolean canConvertToInt() { return (_value.compareTo(MIN_INTEGER) >= 0) && (_value.compareTo(MAX_INTEGER) <= 0); } @Override public boolean canConvertToLong() { return (_value.compareTo(MIN_LONG) >= 0) && (_value.compareTo(MAX_LONG) <= 0); } @Override public Number numberValue() { return _value; } @Override public short shortValue() { return _value.shortValue(); } @Override public int intValue() { return _value.intValue(); } @Override public long longValue() { return _value.longValue(); } @Override public BigInteger bigIntegerValue() { return _value.toBigInteger(); } @Override public float floatValue() { return _value.floatValue(); } @Override public double doubleValue() { return _value.doubleValue(); } @Override public BigDecimal decimalValue() { return _value; } @Override public String asText() { return _value.toString(); } @Override public final void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { // 07-Jul-2013, tatu: Should be handled by propagating setting to JsonGenerator // so this should not be needed: /* if (provider.isEnabled(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN)) { if (!(jgen instanceof TokenBuffer)) { // [Issue#232] jgen.writeNumber(((BigDecimal) _value).toPlainString()); return; } } */ jgen.writeNumber(_value); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof DecimalNode) { return ((DecimalNode) o)._value.compareTo(_value) == 0; } return false; } @Override public int hashCode() { return Double.valueOf(doubleValue()).hashCode(); } } DoubleNode.java000066400000000000000000000065011325620701100342620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.NumberOutput; import com.fasterxml.jackson.databind.SerializerProvider; /** * Numeric node that contains 64-bit ("double precision") * floating point values simple 32-bit integer values. */ public class DoubleNode extends NumericNode { protected final double _value; /* /********************************************************** /* Construction /********************************************************** */ public DoubleNode(double v) { _value = v; } public static DoubleNode valueOf(double v) { return new DoubleNode(v); } /* /********************************************************** /* BaseJsonNode extended API /********************************************************** */ @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_FLOAT; } @Override public JsonParser.NumberType numberType() { return JsonParser.NumberType.DOUBLE; } /* /********************************************************** /* Overrridden JsonNode methods /********************************************************** */ @Override public boolean isFloatingPointNumber() { return true; } @Override public boolean isDouble() { return true; } @Override public boolean canConvertToInt() { return (_value >= Integer.MIN_VALUE && _value <= Integer.MAX_VALUE); } @Override public boolean canConvertToLong() { return (_value >= Long.MIN_VALUE && _value <= Long.MAX_VALUE); } @Override public Number numberValue() { return Double.valueOf(_value); } @Override public short shortValue() { return (short) _value; } @Override public int intValue() { return (int) _value; } @Override public long longValue() { return (long) _value; } @Override public float floatValue() { return (float) _value; } @Override public double doubleValue() { return _value; } @Override public BigDecimal decimalValue() { return BigDecimal.valueOf(_value); } @Override public BigInteger bigIntegerValue() { return decimalValue().toBigInteger(); } @Override public String asText() { return NumberOutput.toString(_value); } // @since 2.9 @Override public boolean isNaN() { return Double.isNaN(_value) || Double.isInfinite(_value); } @Override public final void serialize(JsonGenerator g, SerializerProvider provider) throws IOException { g.writeNumber(_value); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof DoubleNode) { // We must account for NaNs: NaN does not equal NaN, therefore we have // to use Double.compare(). final double otherValue = ((DoubleNode) o)._value; return Double.compare(_value, otherValue) == 0; } return false; } @Override public int hashCode() { // same as hashCode Double.class uses long l = Double.doubleToLongBits(_value); return ((int) l) ^ (int) (l >> 32); } } FloatNode.java000066400000000000000000000062771325620701100341270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.NumberOutput; import com.fasterxml.jackson.databind.SerializerProvider; /** * JsonNode implementation for efficiently containing 32-bit * `float` values. * * @since 2.2 */ public class FloatNode extends NumericNode { protected final float _value; /* /********************************************************** /* Construction /********************************************************** */ public FloatNode(float v) { _value = v; } public static FloatNode valueOf(float v) { return new FloatNode(v); } /* /********************************************************** /* BaseJsonNode extended API /********************************************************** */ @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_FLOAT; } @Override public JsonParser.NumberType numberType() { return JsonParser.NumberType.FLOAT; } /* /********************************************************** /* Overrridden JsonNode methods /********************************************************** */ @Override public boolean isFloatingPointNumber() { return true; } @Override public boolean isFloat() { return true; } @Override public boolean canConvertToInt() { return (_value >= Integer.MIN_VALUE && _value <= Integer.MAX_VALUE); } @Override public boolean canConvertToLong() { return (_value >= Long.MIN_VALUE && _value <= Long.MAX_VALUE); } @Override public Number numberValue() { return Float.valueOf(_value); } @Override public short shortValue() { return (short) _value; } @Override public int intValue() { return (int) _value; } @Override public long longValue() { return (long) _value; } @Override public float floatValue() { return _value; } @Override public double doubleValue() { return _value; } @Override public BigDecimal decimalValue() { return BigDecimal.valueOf(_value); } @Override public BigInteger bigIntegerValue() { return decimalValue().toBigInteger(); } @Override public String asText() { return NumberOutput.toString(_value); } // @since 2.9 @Override public boolean isNaN() { return Float.isNaN(_value) || Float.isInfinite(_value); } @Override public final void serialize(JsonGenerator g, SerializerProvider provider) throws IOException { g.writeNumber(_value); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof FloatNode) { // We must account for NaNs: NaN does not equal NaN, therefore we have // to use Double.compare(). final float otherValue = ((FloatNode) o)._value; return Float.compare(_value, otherValue) == 0; } return false; } @Override public int hashCode() { return Float.floatToIntBits(_value); } } IntNode.java000066400000000000000000000065051325620701100336060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.NumberOutput; import com.fasterxml.jackson.databind.SerializerProvider; /** * Numeric node that contains simple 32-bit integer values. */ public class IntNode extends NumericNode { // // // Let's cache small set of common value final static int MIN_CANONICAL = -1; final static int MAX_CANONICAL = 10; private final static IntNode[] CANONICALS; static { int count = MAX_CANONICAL - MIN_CANONICAL + 1; CANONICALS = new IntNode[count]; for (int i = 0; i < count; ++i) { CANONICALS[i] = new IntNode(MIN_CANONICAL + i); } } /** * Integer value this node contains */ protected final int _value; /* ************************************************ * Construction ************************************************ */ public IntNode(int v) { _value = v; } public static IntNode valueOf(int i) { if (i > MAX_CANONICAL || i < MIN_CANONICAL) return new IntNode(i); return CANONICALS[i - MIN_CANONICAL]; } /* /********************************************************** /* BaseJsonNode extended API /********************************************************** */ @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_INT; } @Override public JsonParser.NumberType numberType() { return JsonParser.NumberType.INT; } /* /********************************************************** /* Overrridden JsonNode methods /********************************************************** */ @Override public boolean isIntegralNumber() { return true; } @Override public boolean isInt() { return true; } @Override public boolean canConvertToInt() { return true; } @Override public boolean canConvertToLong() { return true; } @Override public Number numberValue() { return Integer.valueOf(_value); } @Override public short shortValue() { return (short) _value; } @Override public int intValue() { return _value; } @Override public long longValue() { return (long) _value; } @Override public float floatValue() { return (float) _value; } @Override public double doubleValue() { return (double) _value; } @Override public BigDecimal decimalValue() { return BigDecimal.valueOf(_value); } @Override public BigInteger bigIntegerValue() { return BigInteger.valueOf(_value); } @Override public String asText() { return NumberOutput.toString(_value); } @Override public boolean asBoolean(boolean defaultValue) { return _value != 0; } @Override public final void serialize(JsonGenerator jg, SerializerProvider provider) throws IOException, JsonProcessingException { jg.writeNumber(_value); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof IntNode) { return ((IntNode) o)._value == _value; } return false; } @Override public int hashCode() { return _value; } } JsonNodeCreator.java000066400000000000000000000043221325620701100353000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.databind.util.RawValue; /** * Interface that defines common "creator" functionality implemented * both by {@link JsonNodeFactory} and {@link ContainerNode} (that is, * JSON Object and Array nodes). * * @since 2.3 */ public interface JsonNodeCreator { // Enumerated/singleton types public ValueNode booleanNode(boolean v); public ValueNode nullNode(); // Numeric types public ValueNode numberNode(byte v); public ValueNode numberNode(Byte value); public ValueNode numberNode(short v); public ValueNode numberNode(Short value); public ValueNode numberNode(int v); public ValueNode numberNode(Integer value); public ValueNode numberNode(long v); public ValueNode numberNode(Long value); public ValueNode numberNode(BigInteger v); public ValueNode numberNode(float v); public ValueNode numberNode(Float value); public ValueNode numberNode(double v); public ValueNode numberNode(Double value); public ValueNode numberNode(BigDecimal v); // Textual nodes public ValueNode textNode(String text); // Other value (non-structured) nodes public ValueNode binaryNode(byte[] data); public ValueNode binaryNode(byte[] data, int offset, int length); public ValueNode pojoNode(Object pojo); /** * Factory method to use for adding "raw values"; pre-encoded values * that are included exactly as-is when node is serialized. * This may be used, for example, to include fully serialized JSON * sub-trees. * Note that the concept may not work with all backends, and since * no translation of any kinds is done it will not work when converting * between data formats. * * @since 2.6 */ public ValueNode rawValueNode(RawValue value); // Structured nodes: // (bit unkosher, due to forward references... but has to do for now) public ArrayNode arrayNode(); /** * Factory method for constructing a JSON Array node with an initial capacity * * @since 2.8 */ public ArrayNode arrayNode(int capacity); public ObjectNode objectNode(); } JsonNodeFactory.java000066400000000000000000000265151325620701100353200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.databind.util.RawValue; /** * Base class that specifies methods for getting access to * Node instances (newly constructed, or shared, depending * on type), as well as basic implementation of the methods. * Designed to be sub-classed if extended functionality (additions * to behavior of node types, mostly) is needed. */ public class JsonNodeFactory implements java.io.Serializable, // since 2.1 JsonNodeCreator // since 2.3 { // with 2.2 private static final long serialVersionUID = 1L; private final boolean _cfgBigDecimalExact; private static final JsonNodeFactory decimalsNormalized = new JsonNodeFactory(false); private static final JsonNodeFactory decimalsAsIs = new JsonNodeFactory(true); /** * Default singleton instance that construct "standard" node instances: * given that this class is stateless, a globally shared singleton * can be used. */ public final static JsonNodeFactory instance = decimalsNormalized; /** * Main constructor * *

The only argument to this constructor is a boolean telling whether * {@link DecimalNode} instances must be built with exact representations of * {@link BigDecimal} instances.

* *

This has quite an influence since, for instance, a BigDecimal (and, * therefore, a DecimalNode) constructed from input string {@code "1.0"} and * another constructed with input string {@code "1.00"} will not be * equal, since their scale differs (1 in the first case, 2 in the second * case).

* *

Note that setting the argument to {@code true} does not * guarantee a strict inequality between JSON representations: input texts * {@code "0.1"} and {@code "1e-1"}, for instance, yield two equivalent * BigDecimal instances since they have the same scale (1).

* *

The no-arg constructor (and the default {@link #instance}) calls this * constructor with {@code false} as an argument.

* * @param bigDecimalExact see description * * @see BigDecimal */ public JsonNodeFactory(boolean bigDecimalExact) { _cfgBigDecimalExact = bigDecimalExact; } /** * Default constructor * *

This calls {@link #JsonNodeFactory(boolean)} with {@code false} * as an argument.

*/ protected JsonNodeFactory() { this(false); } /** * Return a factory instance with the desired behavior for BigDecimals *

See {@link #JsonNodeFactory(boolean)} for a full description.

* * @param bigDecimalExact see description * @return a factory instance */ public static JsonNodeFactory withExactBigDecimals(boolean bigDecimalExact) { return bigDecimalExact ? decimalsAsIs : decimalsNormalized; } /* /********************************************************** /* Factory methods for literal values /********************************************************** */ /** * Factory method for getting an instance of JSON boolean value * (either literal 'true' or 'false') */ @Override public BooleanNode booleanNode(boolean v) { return v ? BooleanNode.getTrue() : BooleanNode.getFalse(); } /** * Factory method for getting an instance of JSON null node (which * represents literal null value) */ @Override public NullNode nullNode() { return NullNode.getInstance(); } /* /********************************************************** /* Factory methods for numeric values /********************************************************** */ /** * Factory method for getting an instance of JSON numeric value * that expresses given 8-bit value */ @Override public NumericNode numberNode(byte v) { return IntNode.valueOf(v); } /** * Alternate factory method that will handle wrapper value, which may * be null. * Due to possibility of null, returning type is not guaranteed to be * {@link NumericNode}, but just {@link ValueNode}. */ @Override public ValueNode numberNode(Byte value) { return (value == null) ? nullNode() : IntNode.valueOf(value.intValue()); } /** * Factory method for getting an instance of JSON numeric value * that expresses given 16-bit integer value */ @Override public NumericNode numberNode(short v) { return ShortNode.valueOf(v); } /** * Alternate factory method that will handle wrapper value, which may * be null. * Due to possibility of null, returning type is not guaranteed to be * {@link NumericNode}, but just {@link ValueNode}. */ @Override public ValueNode numberNode(Short value) { return (value == null) ? nullNode() : ShortNode.valueOf(value); } /** * Factory method for getting an instance of JSON numeric value * that expresses given 32-bit integer value */ @Override public NumericNode numberNode(int v) { return IntNode.valueOf(v); } /** * Alternate factory method that will handle wrapper value, which may * be null. * Due to possibility of null, returning type is not guaranteed to be * {@link NumericNode}, but just {@link ValueNode}. */ @Override public ValueNode numberNode(Integer value) { return (value == null) ? nullNode() : IntNode.valueOf(value.intValue()); } /** * Factory method for getting an instance of JSON numeric value * that expresses given 64-bit integer value */ @Override public NumericNode numberNode(long v) { return LongNode.valueOf(v); } /** * Alternate factory method that will handle wrapper value, which may be null. * Due to possibility of null, returning type is not guaranteed to be * {@link NumericNode}, but just {@link ValueNode}. */ @Override public ValueNode numberNode(Long v) { if (v == null) { return nullNode(); } return LongNode.valueOf(v.longValue()); } /** * Factory method for getting an instance of JSON numeric value * that expresses given unlimited range integer value */ @Override public ValueNode numberNode(BigInteger v) { if (v == null) { return nullNode(); } return BigIntegerNode.valueOf(v); } /** * Factory method for getting an instance of JSON numeric value * that expresses given 32-bit floating point value */ @Override public NumericNode numberNode(float v) { return FloatNode.valueOf((float) v); } /** * Alternate factory method that will handle wrapper value, which may * be null. * Due to possibility of null, returning type is not guaranteed to be * {@link NumericNode}, but just {@link ValueNode}. */ @Override public ValueNode numberNode(Float value) { return (value == null) ? nullNode() : FloatNode.valueOf(value.floatValue()); } /** * Factory method for getting an instance of JSON numeric value * that expresses given 64-bit floating point value */ @Override public NumericNode numberNode(double v) { return DoubleNode.valueOf(v); } /** * Alternate factory method that will handle wrapper value, which may * be null. * Due to possibility of null, returning type is not guaranteed to be * {@link NumericNode}, but just {@link ValueNode}. */ @Override public ValueNode numberNode(Double value) { return (value == null) ? nullNode() : DoubleNode.valueOf(value.doubleValue()); } /** * Factory method for getting an instance of JSON numeric value * that expresses given unlimited precision floating point value * *

In the event that the factory has been built to normalize decimal * values, the BigDecimal argument will be stripped off its trailing zeroes, * using {@link BigDecimal#stripTrailingZeros()}.

* * @see #JsonNodeFactory(boolean) */ @Override public ValueNode numberNode(BigDecimal v) { if (v == null) { return nullNode(); } /* * If the user wants the exact representation of this big decimal, * return the value directly */ if (_cfgBigDecimalExact) return DecimalNode.valueOf(v); /* * If the user has asked to strip trailing zeroes, however, there is * this bug to account for: * * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6480539 * * In short: zeroes are never stripped out of 0! We therefore _have_ * to compare with BigDecimal.ZERO... */ return v.compareTo(BigDecimal.ZERO) == 0 ? DecimalNode.ZERO : DecimalNode.valueOf(v.stripTrailingZeros()); } /* /********************************************************** /* Factory methods for textual values /********************************************************** */ /** * Factory method for constructing a node that represents JSON * String value */ @Override public TextNode textNode(String text) { return TextNode.valueOf(text); } /** * Factory method for constructing a node that represents given * binary data, and will get serialized as equivalent base64-encoded * String value */ @Override public BinaryNode binaryNode(byte[] data) { return BinaryNode.valueOf(data); } /** * Factory method for constructing a node that represents given * binary data, and will get serialized as equivalent base64-encoded * String value */ @Override public BinaryNode binaryNode(byte[] data, int offset, int length) { return BinaryNode.valueOf(data, offset, length); } /* /********************************************************** /* Factory method for structured values /********************************************************** */ /** * Factory method for constructing an empty JSON Array node */ @Override public ArrayNode arrayNode() { return new ArrayNode(this); } /** * Factory method for constructing a JSON Array node with an initial capacity * * @since 2.8 */ @Override public ArrayNode arrayNode(int capacity) { return new ArrayNode(this, capacity); } /** * Factory method for constructing an empty JSON Object ("struct") node */ @Override public ObjectNode objectNode() { return new ObjectNode(this); } /** * Factory method for constructing a wrapper for POJO * ("Plain Old Java Object") objects; these will get serialized * using data binding, usually as JSON Objects, but in some * cases as JSON Strings or other node types. */ @Override public ValueNode pojoNode(Object pojo) { return new POJONode(pojo); } @Override public ValueNode rawValueNode(RawValue value) { return new POJONode(value); } /* /********************************************************** /* Helper methods /********************************************************** */ protected boolean _inIntRange(long l) { int i = (int) l; long l2 = (long) i; return (l2 == l); } } JsonNodeType.java000066400000000000000000000010701325620701100346170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; /** * Enumeration of JSON types. * Covers all JSON types defined by RFC 4627 (array, boolean, * null, number, object and string) but also Jackson-specific types: binary, * missing and POJO; although does not distinguish between more granular * types. * * @see BinaryNode * @see MissingNode * @see POJONode * * @since 2.2 */ public enum JsonNodeType { ARRAY, BINARY, BOOLEAN, MISSING, NULL, NUMBER, OBJECT, POJO, STRING } LongNode.java000066400000000000000000000052401325620701100337460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.NumberOutput; import com.fasterxml.jackson.databind.SerializerProvider; /** * Numeric node that contains simple 64-bit integer values. */ public class LongNode extends NumericNode { protected final long _value; /* ************************************************ * Construction ************************************************ */ public LongNode(long v) { _value = v; } public static LongNode valueOf(long l) { return new LongNode(l); } /* ************************************************ * Overrridden JsonNode methods ************************************************ */ @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_INT; } @Override public JsonParser.NumberType numberType() { return JsonParser.NumberType.LONG; } @Override public boolean isIntegralNumber() { return true; } @Override public boolean isLong() { return true; } @Override public boolean canConvertToInt() { return (_value >= Integer.MIN_VALUE && _value <= Integer.MAX_VALUE); } @Override public boolean canConvertToLong() { return true; } @Override public Number numberValue() { return Long.valueOf(_value); } @Override public short shortValue() { return (short) _value; } @Override public int intValue() { return (int) _value; } @Override public long longValue() { return _value; } @Override public float floatValue() { return _value; } @Override public double doubleValue() { return _value; } @Override public BigDecimal decimalValue() { return BigDecimal.valueOf(_value); } @Override public BigInteger bigIntegerValue() { return BigInteger.valueOf(_value); } @Override public String asText() { return NumberOutput.toString(_value); } @Override public boolean asBoolean(boolean defaultValue) { return _value != 0; } @Override public final void serialize(JsonGenerator jg, SerializerProvider provider) throws IOException, JsonProcessingException { jg.writeNumber(_value); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof LongNode) { return ((LongNode) o)._value == _value; } return false; } @Override public int hashCode() { return ((int) _value) ^ (int) (_value >> 32); } } MissingNode.java000066400000000000000000000065261325620701100344700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * This singleton node class is generated to denote "missing nodes" * along paths that do not exist. For example, if a path via * element of an array is requested for an element outside range * of elements in the array; or for a non-array value, result * will be reference to this node. *

* In most respects this placeholder node will act as {@link NullNode}; * for example, for purposes of value conversions, value is considered * to be null and represented as value zero when used for numeric * conversions. */ public final class MissingNode extends ValueNode { private final static MissingNode instance = new MissingNode(); /** *

* NOTE: visibility raised to `protected` in 2.9.3 to allow custom subtypes. */ protected MissingNode() { } @Override public boolean isMissingNode() { return true; } // Immutable: no need to copy @SuppressWarnings("unchecked") @Override public T deepCopy() { return (T) this; } public static MissingNode getInstance() { return instance; } @Override public JsonNodeType getNodeType() { return JsonNodeType.MISSING; } @Override public JsonToken asToken() { return JsonToken.NOT_AVAILABLE; } @Override public String asText() { return ""; } @Override public String asText(String defaultValue) { return defaultValue; } // // Note: not a numeric node, hence default 'asXxx()' are fine: /* public int asInt(int defaultValue); public long asLong(long defaultValue); public double asDouble(double defaultValue); public boolean asBoolean(boolean defaultValue); */ @Override public final void serialize(JsonGenerator jg, SerializerProvider provider) throws IOException, JsonProcessingException { /* Nothing to output... should we signal an error tho? * Chances are, this is an erroneous call. For now, let's * not do that; serialize as explicit null. Why? Because we * cannot just omit a value as JSON Object field name may have * been written out. */ jg.writeNull(); } @Override public void serializeWithType(JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException, JsonProcessingException { g.writeNull(); } @Override public boolean equals(Object o) { /* Hmmh. Since there's just a singleton instance, this * fails in all cases but with identity comparison. * However: if this placeholder value was to be considered * similar to SQL NULL, it shouldn't even equal itself? * That might cause problems when dealing with collections * like Sets... so for now, let's let identity comparison * return true. */ return (o == this); } @Override public String toString() { // toString() should never return null return ""; } @Override public int hashCode() { return JsonNodeType.MISSING.ordinal(); } } NodeCursor.java000066400000000000000000000151401325620701100343240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JsonNode; /** * Helper class used by {@link TreeTraversingParser} to keep track * of current location within traversed JSON tree. */ abstract class NodeCursor extends JsonStreamContext { /** * Parent cursor of this cursor, if any; null for root * cursors. */ protected final NodeCursor _parent; /** * Current field name */ protected String _currentName; /** * @since 2.5 */ protected java.lang.Object _currentValue; public NodeCursor(int contextType, NodeCursor p) { super(); _type = contextType; _index = -1; _parent = p; } /* /********************************************************** /* JsonStreamContext impl /********************************************************** */ // note: co-variant return type @Override public final NodeCursor 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 JsonNode 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 NodeCursor iterateChildren() { JsonNode 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(n, this); } if (n.isObject()) { return new ObjectCursor(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 NodeCursor { protected JsonNode _node; protected boolean _done = false; public RootCursor(JsonNode n, NodeCursor 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 JsonNode currentNode() { return _node; } @Override public boolean currentHasChildren() { return false; } } /** * Cursor used for traversing non-empty JSON Array nodes */ protected final static class ArrayCursor extends NodeCursor { protected Iterator _contents; protected JsonNode _currentNode; public ArrayCursor(JsonNode n, NodeCursor 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 JsonNode currentNode() { return _currentNode; } @Override public boolean currentHasChildren() { // note: ONLY to be called for container nodes return ((ContainerNode) currentNode()).size() > 0; } } /** * Cursor used for traversing non-empty JSON Object nodes */ protected final static class ObjectCursor extends NodeCursor { protected Iterator> _contents; protected Map.Entry _current; protected boolean _needEntry; public ObjectCursor(JsonNode n, NodeCursor p) { super(JsonStreamContext.TYPE_OBJECT, p); _contents = ((ObjectNode) 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 JsonNode currentNode() { return (_current == null) ? null : _current.getValue(); } @Override public boolean currentHasChildren() { // note: ONLY to be called for container nodes return ((ContainerNode) currentNode()).size() > 0; } } } NullNode.java000066400000000000000000000030561325620701100337640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.SerializerProvider; /** * This singleton value class is used to contain explicit JSON null * value. */ public final class NullNode extends ValueNode { // // Just need a fly-weight singleton public final static NullNode instance = new NullNode(); /** *

* NOTE: visibility raised to `protected` in 2.9.3 to allow custom subtypes. */ protected NullNode() { } public static NullNode getInstance() { return instance; } @Override public JsonNodeType getNodeType() { return JsonNodeType.NULL; } @Override public JsonToken asToken() { return JsonToken.VALUE_NULL; } @Override public String asText(String defaultValue) { return defaultValue; } @Override public String asText() { return "null"; } // as with MissingNode, not considered number node; hence defaults are returned if provided /* public int asInt(int defaultValue); public long asLong(long defaultValue); public double asDouble(double defaultValue); public boolean asBoolean(boolean defaultValue); */ @Override public final void serialize(JsonGenerator g, SerializerProvider provider) throws IOException { provider.defaultSerializeNull(g); } @Override public boolean equals(Object o) { return (o == this); } @Override public int hashCode() { return JsonNodeType.NULL.ordinal(); } } NumericNode.java000066400000000000000000000041651325620701100344560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.JsonParser; /** * Intermediate value node used for numeric nodes. */ public abstract class NumericNode extends ValueNode { protected NumericNode() { } @Override public final JsonNodeType getNodeType() { return JsonNodeType.NUMBER; } // // // Let's re-abstract so sub-classes handle them @Override public abstract JsonParser.NumberType numberType(); @Override public abstract Number numberValue(); @Override public abstract int intValue(); @Override public abstract long longValue(); @Override public abstract double doubleValue(); @Override public abstract BigDecimal decimalValue(); @Override public abstract BigInteger bigIntegerValue(); @Override public abstract boolean canConvertToInt(); @Override public abstract boolean canConvertToLong(); /* /********************************************************** /* General type coercions /********************************************************** */ @Override public abstract String asText(); @Override public final int asInt() { return intValue(); } @Override public final int asInt(int defaultValue) { return intValue(); } @Override public final long asLong() { return longValue(); } @Override public final long asLong(long defaultValue) { return longValue(); } @Override public final double asDouble() { return doubleValue(); } @Override public final double asDouble(double defaultValue) { return doubleValue(); } /* /********************************************************** /* Other /********************************************************** */ /** * Convenience method for checking whether this node is a * {@link FloatNode} or {@link DoubleNode} that contains * "not-a-number" (NaN) value. * * @since 2.9 */ public boolean isNaN() { return false; } } ObjectNode.java000066400000000000000000000645151325620701100342670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.util.RawValue; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; /** * Node that maps to JSON Object structures in JSON content. *

* Note: class was final temporarily for Jackson 2.2. */ public class ObjectNode extends ContainerNode { // Note: LinkedHashMap for backwards compatibility protected final Map _children; public ObjectNode(JsonNodeFactory nc) { super(nc); _children = new LinkedHashMap(); } /** * @since 2.4 */ public ObjectNode(JsonNodeFactory nc, Map kids) { super(nc); _children = kids; } @Override protected JsonNode _at(JsonPointer ptr) { return get(ptr.getMatchingProperty()); } /* Question: should this delegate to `JsonNodeFactory`? It does not absolutely * have to, as long as sub-types override the method but... */ // note: co-variant for type safety @SuppressWarnings("unchecked") @Override public ObjectNode deepCopy() { ObjectNode ret = new ObjectNode(_nodeFactory); for (Map.Entry entry: _children.entrySet()) ret._children.put(entry.getKey(), entry.getValue().deepCopy()); return ret; } /* /********************************************************** /* Overrides for JsonSerializable.Base /********************************************************** */ @Override public boolean isEmpty(SerializerProvider serializers) { return _children.isEmpty(); } /* /********************************************************** /* Implementation of core JsonNode API /********************************************************** */ @Override public JsonNodeType getNodeType() { return JsonNodeType.OBJECT; } @Override public final boolean isObject() { return true; } @Override public JsonToken asToken() { return JsonToken.START_OBJECT; } @Override public int size() { return _children.size(); } @Override public Iterator elements() { return _children.values().iterator(); } @Override public JsonNode get(int index) { return null; } @Override public JsonNode get(String fieldName) { return _children.get(fieldName); } @Override public Iterator fieldNames() { return _children.keySet().iterator(); } @Override public JsonNode path(int index) { return MissingNode.getInstance(); } @Override public JsonNode path(String fieldName) { JsonNode n = _children.get(fieldName); if (n != null) { return n; } return MissingNode.getInstance(); } /** * Method to use for accessing all fields (with both names * and values) of this JSON Object. */ @Override public Iterator> fields() { return _children.entrySet().iterator(); } @Override public ObjectNode with(String propertyName) { JsonNode n = _children.get(propertyName); if (n != null) { if (n instanceof ObjectNode) { return (ObjectNode) n; } throw new UnsupportedOperationException("Property '" + propertyName + "' has value that is not of type ObjectNode (but " + n .getClass().getName() + ")"); } ObjectNode result = objectNode(); _children.put(propertyName, result); return result; } @Override public ArrayNode withArray(String propertyName) { JsonNode n = _children.get(propertyName); if (n != null) { if (n instanceof ArrayNode) { return (ArrayNode) n; } throw new UnsupportedOperationException("Property '" + propertyName + "' has value that is not of type ArrayNode (but " + n .getClass().getName() + ")"); } ArrayNode result = arrayNode(); _children.put(propertyName, result); return result; } @Override public boolean equals(Comparator comparator, JsonNode o) { if (!(o instanceof ObjectNode)) { return false; } ObjectNode other = (ObjectNode) o; Map m1 = _children; Map m2 = other._children; final int len = m1.size(); if (m2.size() != len) { return false; } for (Map.Entry entry : m1.entrySet()) { JsonNode v2 = m2.get(entry.getKey()); if ((v2 == null) || !entry.getValue().equals(comparator, v2)) { return false; } } return true; } /* /********************************************************** /* Public API, finding value nodes /********************************************************** */ @Override public JsonNode findValue(String fieldName) { for (Map.Entry entry : _children.entrySet()) { if (fieldName.equals(entry.getKey())) { return entry.getValue(); } JsonNode value = entry.getValue().findValue(fieldName); if (value != null) { return value; } } return null; } @Override public List findValues(String fieldName, List foundSoFar) { for (Map.Entry entry : _children.entrySet()) { if (fieldName.equals(entry.getKey())) { if (foundSoFar == null) { foundSoFar = new ArrayList(); } foundSoFar.add(entry.getValue()); } else { // only add children if parent not added foundSoFar = entry.getValue().findValues(fieldName, foundSoFar); } } return foundSoFar; } @Override public List findValuesAsText(String fieldName, List foundSoFar) { for (Map.Entry entry : _children.entrySet()) { if (fieldName.equals(entry.getKey())) { if (foundSoFar == null) { foundSoFar = new ArrayList(); } foundSoFar.add(entry.getValue().asText()); } else { // only add children if parent not added foundSoFar = entry.getValue().findValuesAsText(fieldName, foundSoFar); } } return foundSoFar; } @Override public ObjectNode findParent(String fieldName) { for (Map.Entry entry : _children.entrySet()) { if (fieldName.equals(entry.getKey())) { return this; } JsonNode value = entry.getValue().findParent(fieldName); if (value != null) { return (ObjectNode) value; } } return null; } @Override public List findParents(String fieldName, List foundSoFar) { for (Map.Entry entry : _children.entrySet()) { if (fieldName.equals(entry.getKey())) { if (foundSoFar == null) { foundSoFar = new ArrayList(); } foundSoFar.add(this); } else { // only add children if parent not added foundSoFar = entry.getValue() .findParents(fieldName, foundSoFar); } } return foundSoFar; } /* /********************************************************** /* Public API, serialization /********************************************************** */ /** * Method that can be called to serialize this node and * all of its descendants using specified JSON generator. */ @Override public void serialize(JsonGenerator g, SerializerProvider provider) throws IOException { @SuppressWarnings("deprecation") boolean trimEmptyArray = (provider != null) && !provider.isEnabled(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS); g.writeStartObject(this); for (Map.Entry en : _children.entrySet()) { /* 17-Feb-2009, tatu: Can we trust that all nodes will always * extend BaseJsonNode? Or if not, at least implement * JsonSerializable? Let's start with former, change if * we must. */ BaseJsonNode value = (BaseJsonNode) en.getValue(); // as per [databind#867], see if WRITE_EMPTY_JSON_ARRAYS feature is disabled, // if the feature is disabled, then should not write an empty array // to the output, so continue to the next element in the iteration if (trimEmptyArray && value.isArray() && value.isEmpty(provider)) { continue; } g.writeFieldName(en.getKey()); value.serialize(g, provider); } g.writeEndObject(); } @Override public void serializeWithType(JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { @SuppressWarnings("deprecation") boolean trimEmptyArray = (provider != null) && !provider.isEnabled(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS); WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(this, JsonToken.START_OBJECT)); for (Map.Entry en : _children.entrySet()) { BaseJsonNode value = (BaseJsonNode) en.getValue(); // check if WRITE_EMPTY_JSON_ARRAYS feature is disabled, // if the feature is disabled, then should not write an empty array // to the output, so continue to the next element in the iteration if (trimEmptyArray && value.isArray() && value.isEmpty(provider)) { continue; } g.writeFieldName(en.getKey()); value.serialize(g, provider); } typeSer.writeTypeSuffix(g, typeIdDef); } /* /********************************************************** /* Extended ObjectNode API, mutators, since 2.1 /********************************************************** */ /** * Method that will set specified field, replacing old value, if any. * Note that this is identical to {@link #replace(String, JsonNode)}, * except for return value. *

* NOTE: added to replace those uses of {@link #put(String, JsonNode)} * where chaining with 'this' is desired. * * @param value to set field to; if null, will be converted * to a {@link NullNode} first (to remove field entry, call * {@link #remove} instead) * * @return This node after adding/replacing property value (to allow chaining) * * @since 2.1 */ public JsonNode set(String fieldName, JsonNode value) { if (value == null) { value = nullNode(); } _children.put(fieldName, value); return this; } /** * Method for adding given properties to this object node, overriding * any existing values for those properties. * * @param properties Properties to add * * @return This node after adding/replacing property values (to allow chaining) * * @since 2.1 */ public JsonNode setAll(Map properties) { for (Map.Entry en : properties.entrySet()) { JsonNode n = en.getValue(); if (n == null) { n = nullNode(); } _children.put(en.getKey(), n); } return this; } /** * Method for adding all properties of the given Object, overriding * any existing values for those properties. * * @param other Object of which properties to add to this object * * @return This node after addition (to allow chaining) * * @since 2.1 */ public JsonNode setAll(ObjectNode other) { _children.putAll(other._children); return this; } /** * Method for replacing value of specific property with passed * value, and returning value (or null if none). * * @param fieldName Property of which value to replace * @param value Value to set property to, replacing old value if any * * @return Old value of the property; null if there was no such property * with value * * @since 2.1 */ public JsonNode replace(String fieldName, JsonNode value) { if (value == null) { // let's not store 'raw' nulls but nodes value = nullNode(); } return _children.put(fieldName, value); } /** * Method for removing field entry from this ObjectNode, and * returning instance after removal. * * @return This node after removing entry (if any) * * @since 2.1 */ public JsonNode without(String fieldName) { _children.remove(fieldName); return this; } /** * Method for removing specified field properties out of * this ObjectNode. * * @param fieldNames Names of fields to remove * * @return This node after removing entries * * @since 2.1 */ public ObjectNode without(Collection fieldNames) { _children.keySet().removeAll(fieldNames); return this; } /* /********************************************************** /* Extended ObjectNode API, mutators, generic /********************************************************** */ /** * Method that will set specified field, replacing old value, if any. * * @param value to set field to; if null, will be converted * to a {@link NullNode} first (to remove field entry, call * {@link #remove} instead) * * @return Old value of the field, if any; null if there was no * old value. * * @deprecated Since 2.4 use either {@link #set(String,JsonNode)} or {@link #replace(String,JsonNode)}, */ @Deprecated public JsonNode put(String fieldName, JsonNode value) { if (value == null) { // let's not store 'raw' nulls but nodes value = nullNode(); } return _children.put(fieldName, value); } /** * Method for removing field entry from this ObjectNode. * Will return value of the field, if such field existed; * null if not. * * @return Value of specified field, if it existed; null if not */ public JsonNode remove(String fieldName) { return _children.remove(fieldName); } /** * Method for removing specified field properties out of * this ObjectNode. * * @param fieldNames Names of fields to remove * * @return This node after removing entries */ public ObjectNode remove(Collection fieldNames) { _children.keySet().removeAll(fieldNames); return this; } /** * Method for removing all field properties, such that this * ObjectNode will contain no properties after call. * * @return This node after removing all entries */ @Override public ObjectNode removeAll() { _children.clear(); return this; } /** * Method for adding given properties to this object node, overriding * any existing values for those properties. * * @param properties Properties to add * * @return This node after adding/replacing property values (to allow chaining) * * @deprecated Since 2.4 use {@link #setAll(Map)}, */ @Deprecated public JsonNode putAll(Map properties) { return setAll(properties); } /** * Method for adding all properties of the given Object, overriding * any existing values for those properties. * * @param other Object of which properties to add to this object * * @return This node (to allow chaining) * * @deprecated Since 2.4 use {@link #setAll(ObjectNode)}, */ @Deprecated public JsonNode putAll(ObjectNode other) { return setAll(other); } /** * Method for removing all field properties out of this ObjectNode * except for ones specified in argument. * * @param fieldNames Fields to retain in this ObjectNode * * @return This node (to allow call chaining) */ public ObjectNode retain(Collection fieldNames) { _children.keySet().retainAll(fieldNames); return this; } /** * Method for removing all field properties out of this ObjectNode * except for ones specified in argument. * * @param fieldNames Fields to retain in this ObjectNode * * @return This node (to allow call chaining) */ public ObjectNode retain(String... fieldNames) { return retain(Arrays.asList(fieldNames)); } /* /********************************************************** /* Extended ObjectNode API, mutators, typed /********************************************************** */ /** * Method that will construct an ArrayNode and add it as a * field of this ObjectNode, replacing old value, if any. *

* NOTE: Unlike all put(...) methods, return value * is NOT this ObjectNode, but the * newly created ArrayNode instance. * * @return Newly constructed ArrayNode (NOT the old value, * which could be of any type) */ public ArrayNode putArray(String fieldName) { ArrayNode n = arrayNode(); _put(fieldName, n); return n; } /** * Method that will construct an ObjectNode and add it as a * field of this ObjectNode, replacing old value, if any. *

* NOTE: Unlike all put(...) methods, return value * is NOT this ObjectNode, but the * newly created ObjectNode instance. * * @return Newly constructed ObjectNode (NOT the old value, * which could be of any type) */ public ObjectNode putObject(String fieldName) { ObjectNode n = objectNode(); _put(fieldName, n); return n; } /** * @return This node (to allow chaining) */ public ObjectNode putPOJO(String fieldName, Object pojo) { return _put(fieldName, pojoNode(pojo)); } /** * @since 2.6 */ public ObjectNode putRawValue(String fieldName, RawValue raw) { return _put(fieldName, rawValueNode(raw)); } /** * @return This node (to allow chaining) */ public ObjectNode putNull(String fieldName) { _children.put(fieldName, nullNode()); return this; } /** * Method for setting value of a field to specified numeric value. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, short v) { return _put(fieldName, numberNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, Short v) { return _put(fieldName, (v == null) ? nullNode() : numberNode(v.shortValue())); } /** * Method for setting value of a field to specified numeric value. * The underlying {@link JsonNode} that will be added is constructed * using {@link JsonNodeFactory#numberNode(int)}, and may be * "smaller" (like {@link ShortNode}) in cases where value fits within * range of a smaller integral numeric value. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, int v) { return _put(fieldName, numberNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, Integer v) { return _put(fieldName, (v == null) ? nullNode() : numberNode(v.intValue())); } /** * Method for setting value of a field to specified numeric value. * The underlying {@link JsonNode} that will be added is constructed * using {@link JsonNodeFactory#numberNode(long)}, and may be * "smaller" (like {@link IntNode}) in cases where value fits within * range of a smaller integral numeric value. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, long v) { return _put(fieldName, numberNode(v)); } /** * Method for setting value of a field to specified numeric value. * The underlying {@link JsonNode} that will be added is constructed * using {@link JsonNodeFactory#numberNode(Long)}, and may be * "smaller" (like {@link IntNode}) in cases where value fits within * range of a smaller integral numeric value. *

* Note that this is alternative to {@link #put(String, long)} needed to avoid * bumping into NPE issues with auto-unboxing. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, Long v) { return _put(fieldName, (v == null) ? nullNode() : numberNode(v.longValue())); } /** * Method for setting value of a field to specified numeric value. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, float v) { return _put(fieldName, numberNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, Float v) { return _put(fieldName, (v == null) ? nullNode() : numberNode(v.floatValue())); } /** * Method for setting value of a field to specified numeric value. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, double v) { return _put(fieldName, numberNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, Double v) { return _put(fieldName, (v == null) ? nullNode() : numberNode(v.doubleValue())); } /** * Method for setting value of a field to specified numeric value. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, BigDecimal v) { return _put(fieldName, (v == null) ? nullNode() : numberNode(v)); } /** * Method for setting value of a field to specified numeric value. * * @return This node (to allow chaining) * * @since 2.9 */ public ObjectNode put(String fieldName, BigInteger v) { return _put(fieldName, (v == null) ? nullNode() : numberNode(v)); } /** * Method for setting value of a field to specified String value. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, String v) { return _put(fieldName, (v == null) ? nullNode() : textNode(v)); } /** * Method for setting value of a field to specified String value. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, boolean v) { return _put(fieldName, booleanNode(v)); } /** * Alternative method that we need to avoid bumping into NPE issues * with auto-unboxing. * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, Boolean v) { return _put(fieldName, (v == null) ? nullNode() : booleanNode(v.booleanValue())); } /** * Method for setting value of a field to specified binary value * * @return This node (to allow chaining) */ public ObjectNode put(String fieldName, byte[] v) { return _put(fieldName, (v == null) ? nullNode() : binaryNode(v)); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof ObjectNode) { return _childrenEqual((ObjectNode) o); } return false; } /** * @since 2.3 */ protected boolean _childrenEqual(ObjectNode other) { return _children.equals(other._children); } @Override public int hashCode() { return _children.hashCode(); } @Override public String toString() { StringBuilder sb = new StringBuilder(32 + (size() << 4)); sb.append("{"); int count = 0; for (Map.Entry en : _children.entrySet()) { if (count > 0) { sb.append(","); } ++count; TextNode.appendQuoted(sb, en.getKey()); sb.append(':'); sb.append(en.getValue().toString()); } sb.append("}"); return sb.toString(); } /* /********************************************************** /* Internal methods (overridable) /********************************************************** */ protected ObjectNode _put(String fieldName, JsonNode value) { _children.put(fieldName, value); return this; } } POJONode.java000066400000000000000000000111041325620701100336120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JsonSerializable; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.util.RawValue; /** * Value node that contains a wrapped POJO, to be serialized as * a JSON constructed through data mapping (usually done by * calling {@link com.fasterxml.jackson.databind.ObjectMapper}). */ public class POJONode extends ValueNode { protected final Object _value; public POJONode(Object v) { _value = v; } /* /********************************************************** /* Base class overrides /********************************************************** */ @Override public JsonNodeType getNodeType() { return JsonNodeType.POJO; } @Override public JsonToken asToken() { return JsonToken.VALUE_EMBEDDED_OBJECT; } /** * As it is possible that some implementations embed byte[] as POJONode * (despite optimal being {@link BinaryNode}), let's add support for exposing * binary data here too. */ @Override public byte[] binaryValue() throws IOException { if (_value instanceof byte[]) { return (byte[]) _value; } return super.binaryValue(); } /* /********************************************************** /* General type coercions /********************************************************** */ @Override public String asText() { return (_value == null) ? "null" : _value.toString(); } @Override public String asText(String defaultValue) { return (_value == null) ? defaultValue : _value.toString(); } @Override public boolean asBoolean(boolean defaultValue) { if (_value != null && _value instanceof Boolean) { return ((Boolean) _value).booleanValue(); } return defaultValue; } @Override public int asInt(int defaultValue) { if (_value instanceof Number) { return ((Number) _value).intValue(); } return defaultValue; } @Override public long asLong(long defaultValue) { if (_value instanceof Number) { return ((Number) _value).longValue(); } return defaultValue; } @Override public double asDouble(double defaultValue) { if (_value instanceof Number) { return ((Number) _value).doubleValue(); } return defaultValue; } /* /********************************************************** /* Public API, serialization /********************************************************** */ @Override public final void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException { if (_value == null) { serializers.defaultSerializeNull(gen); } else if (_value instanceof JsonSerializable) { ((JsonSerializable) _value).serialize(gen, serializers); } else { gen.writeObject(_value); } } /* /********************************************************** /* Extended API /********************************************************** */ /** * Method that can be used to access the POJO this node wraps. */ public Object getPojo() { return _value; } /* /********************************************************** /* Overridden standard methods /********************************************************** */ @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof POJONode) { return _pojoEquals((POJONode) o); } return false; } /** * @since 2.3 */ protected boolean _pojoEquals(POJONode other) { if (_value == null) { return other._value == null; } return _value.equals(other._value); } @Override public int hashCode() { return _value.hashCode(); } @Override public String toString() { // [databind#743]: Let's try indicating content type, for debugging purposes if (_value instanceof byte[]) { return String.format("(binary value of %d bytes)", ((byte[]) _value).length); } if (_value instanceof RawValue) { return String.format("(raw value '%s')", ((RawValue) _value).toString()); } return String.valueOf(_value); } } ShortNode.java000066400000000000000000000051151325620701100341470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.NumberOutput; import com.fasterxml.jackson.databind.SerializerProvider; /** * Numeric node that contains simple 16-bit integer values. */ public class ShortNode extends NumericNode { protected final short _value; /* ************************************************ * Construction ************************************************ */ public ShortNode(short v) { _value = v; } public static ShortNode valueOf(short l) { return new ShortNode(l); } /* ************************************************ * Overridden JsonNode methods ************************************************ */ @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_INT; } @Override public JsonParser.NumberType numberType() { return JsonParser.NumberType.INT; } // should be SHORT @Override public boolean isIntegralNumber() { return true; } @Override public boolean isShort() { return true; } @Override public boolean canConvertToInt() { return true; } @Override public boolean canConvertToLong() { return true; } @Override public Number numberValue() { return Short.valueOf(_value); } @Override public short shortValue() { return _value; } @Override public int intValue() { return _value; } @Override public long longValue() { return _value; } @Override public float floatValue() { return _value; } @Override public double doubleValue() { return _value; } @Override public BigDecimal decimalValue() { return BigDecimal.valueOf(_value); } @Override public BigInteger bigIntegerValue() { return BigInteger.valueOf(_value); } @Override public String asText() { return NumberOutput.toString(_value); } @Override public boolean asBoolean(boolean defaultValue) { return _value != 0; } @Override public final void serialize(JsonGenerator jg, SerializerProvider provider) throws IOException, JsonProcessingException { jg.writeNumber(_value); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof ShortNode) { return ((ShortNode) o)._value == _value; } return false; } @Override public int hashCode() { return _value; } } TextNode.java000066400000000000000000000117021325620701100337730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.CharTypes; import com.fasterxml.jackson.core.io.NumberInput; import com.fasterxml.jackson.core.util.ByteArrayBuilder; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.exc.InvalidFormatException; /** * Value node that contains a text value. */ public class TextNode extends ValueNode { final static TextNode EMPTY_STRING_NODE = new TextNode(""); protected final String _value; public TextNode(String v) { _value = v; } /** * Factory method that should be used to construct instances. * For some common cases, can reuse canonical instances: currently * this is the case for empty Strings, in future possible for * others as well. If null is passed, will return null. * * @return Resulting {@link TextNode} object, if v * is NOT null; null if it is. */ public static TextNode valueOf(String v) { if (v == null) { return null; } if (v.length() == 0) { return EMPTY_STRING_NODE; } return new TextNode(v); } @Override public JsonNodeType getNodeType() { return JsonNodeType.STRING; } @Override public JsonToken asToken() { return JsonToken.VALUE_STRING; } @Override public String textValue() { return _value; } /** * Method for accessing textual contents assuming they were * base64 encoded; if so, they are decoded and resulting binary * data is returned. */ @SuppressWarnings("resource") public byte[] getBinaryValue(Base64Variant b64variant) throws IOException { final String str = _value.trim(); ByteArrayBuilder builder = new ByteArrayBuilder(4 + ((str.length() * 3) << 2)); try { b64variant.decode(str, builder); } catch (IllegalArgumentException e) { throw InvalidFormatException.from(null, String.format( "Cannot access contents of TextNode as binary due to broken Base64 encoding: %s", e.getMessage()), str, byte[].class); } return builder.toByteArray(); } @Override public byte[] binaryValue() throws IOException { return getBinaryValue(Base64Variants.getDefaultVariant()); } /* /********************************************************** /* General type coercions /********************************************************** */ @Override public String asText() { return _value; } @Override public String asText(String defaultValue) { return (_value == null) ? defaultValue : _value; } // note: neither fast nor elegant, but these work for now: @Override public boolean asBoolean(boolean defaultValue) { if (_value != null) { String v = _value.trim(); if ("true".equals(v)) { return true; } if ("false".equals(v)) { return false; } } return defaultValue; } @Override public int asInt(int defaultValue) { return NumberInput.parseAsInt(_value, defaultValue); } @Override public long asLong(long defaultValue) { return NumberInput.parseAsLong(_value, defaultValue); } @Override public double asDouble(double defaultValue) { return NumberInput.parseAsDouble(_value, defaultValue); } /* /********************************************************** /* Serialization /********************************************************** */ @Override public final void serialize(JsonGenerator g, SerializerProvider provider) throws IOException { if (_value == null) { g.writeNull(); } else { g.writeString(_value); } } /* /********************************************************** /* Overridden standard methods /********************************************************** */ @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof TextNode) { return ((TextNode) o)._value.equals(_value); } return false; } @Override public int hashCode() { return _value.hashCode(); } /** * Different from other values, Strings need quoting */ @Override public String toString() { int len = _value.length(); len = len + 2 + (len >> 4); StringBuilder sb = new StringBuilder(len); appendQuoted(sb, _value); return sb.toString(); } protected static void appendQuoted(StringBuilder sb, String content) { sb.append('"'); CharTypes.appendQuoted(sb, content); sb.append('"'); } } TreeTraversingParser.java000066400000000000000000000274301325620701100363670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; 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.databind.JsonNode; /** * Facade over {@link JsonNode} 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 TreeTraversingParser extends ParserMinimalBase { /* /********************************************************** /* Configuration /********************************************************** */ protected ObjectCodec _objectCodec; /** * Traversal context within tree */ protected NodeCursor _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 TreeTraversingParser(JsonNode n) { this(n, null); } public TreeTraversingParser(JsonNode n, ObjectCodec codec) { super(0); _objectCodec = codec; if (n.isArray()) { _nextToken = JsonToken.START_ARRAY; _nodeCursor = new NodeCursor.ArrayCursor(n, null); } else if (n.isObject()) { _nextToken = JsonToken.START_OBJECT; _nodeCursor = new NodeCursor.ObjectCursor(n, null); } else { // value node _nodeCursor = new NodeCursor.RootCursor(n, null); } } @Override public void setCodec(ObjectCodec c) { _objectCodec = c; } @Override public ObjectCodec getCodec() { return _objectCodec; } @Override public Version version() { return com.fasterxml.jackson.databind.cfg.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, JsonParseException { 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, JsonParseException @Override public JsonParser skipChildren() throws IOException, JsonParseException { 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: return currentNode().textValue(); case VALUE_NUMBER_INT: case VALUE_NUMBER_FLOAT: return String.valueOf(currentNode().numberValue()); case VALUE_EMBEDDED_OBJECT: JsonNode n = currentNode(); if (n != null && n.isBinary()) { // this will convert it to base64 return n.asText(); } default: return (_currToken == null) ? null : _currToken.asString(); } } @Override public char[] getTextCharacters() throws IOException, JsonParseException { return getText().toCharArray(); } @Override public int getTextLength() throws IOException, JsonParseException { return getText().length(); } @Override public int getTextOffset() throws IOException, JsonParseException { 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, JsonParseException @Override public NumberType getNumberType() throws IOException, JsonParseException { JsonNode n = currentNumericNode(); return (n == null) ? null : n.numberType(); } @Override public BigInteger getBigIntegerValue() throws IOException, JsonParseException { return currentNumericNode().bigIntegerValue(); } @Override public BigDecimal getDecimalValue() throws IOException, JsonParseException { return currentNumericNode().decimalValue(); } @Override public double getDoubleValue() throws IOException, JsonParseException { return currentNumericNode().doubleValue(); } @Override public float getFloatValue() throws IOException, JsonParseException { return (float) currentNumericNode().doubleValue(); } @Override public long getLongValue() throws IOException, JsonParseException { return currentNumericNode().longValue(); } @Override public int getIntValue() throws IOException, JsonParseException { return currentNumericNode().intValue(); } @Override public Number getNumberValue() throws IOException, JsonParseException { return currentNumericNode().numberValue(); } @Override public Object getEmbeddedObject() { if (!_closed) { JsonNode n = currentNode(); if (n != null) { if (n.isPojo()) { return ((POJONode) n).getPojo(); } if (n.isBinary()) { return ((BinaryNode) n).binaryValue(); } } } return null; } @Override public boolean isNaN() { if (!_closed) { JsonNode n = currentNode(); if (n instanceof NumericNode) { return ((NumericNode) n).isNaN(); } } return false; } /* /********************************************************** /* Public API, typed binary (base64) access /********************************************************** */ @Override public byte[] getBinaryValue(Base64Variant b64variant) throws IOException, JsonParseException { // Multiple possibilities... JsonNode n = currentNode(); if (n != null) { // binary node? byte[] data = n.binaryValue(); // (or TextNode, which can also convert automatically!) if (data != null) { return data; } // Or maybe byte[] as POJO? if (n.isPojo()) { Object ob = ((POJONode) n).getPojo(); if (ob instanceof byte[]) { return (byte[]) ob; } } } // otherwise return null to mark we have no binary content return null; } @Override public int readBinaryValue(Base64Variant b64variant, OutputStream out) throws IOException, JsonParseException { byte[] data = getBinaryValue(b64variant); if (data != null) { out.write(data, 0, data.length); return data.length; } return 0; } /* /********************************************************** /* Internal methods /********************************************************** */ protected JsonNode currentNode() { if (_closed || _nodeCursor == null) { return null; } return _nodeCursor.currentNode(); } protected JsonNode currentNumericNode() throws JsonParseException { JsonNode n = currentNode(); if (n == null || !n.isNumber()) { JsonToken t = (n == null) ? null : n.asToken(); throw _constructError("Current token ("+t+") not numeric, cannot use numeric value accessors"); } return n; } @Override protected void _handleEOF() throws JsonParseException { _throwInternal(); // should never get called } } ValueNode.java000066400000000000000000000066411325620701100341310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import java.util.List; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * This intermediate base class is used for all leaf nodes, that is, * all non-container (array or object) nodes, except for the * "missing node". */ public abstract class ValueNode extends BaseJsonNode { protected ValueNode() { } @Override protected JsonNode _at(JsonPointer ptr) { // will only allow direct matches, but no traversal through // (base class checks for direct match) return MissingNode.getInstance(); } /** * All current value nodes are immutable, so we can just return * them as is. */ @SuppressWarnings("unchecked") @Override public T deepCopy() { return (T) this; } @Override public abstract JsonToken asToken(); @Override public void serializeWithType(JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(this, asToken())); serialize(g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } /* /********************************************************************** /* Base impls for standard methods /********************************************************************** */ @Override public String toString() { return asText(); } /* ********************************************************************** * Navigation methods ********************************************************************** */ @Override public final JsonNode get(int index) { return null; } @Override public final JsonNode path(int index) { return MissingNode.getInstance(); } @Override public final boolean has(int index) { return false; } @Override public final boolean hasNonNull(int index) { return false; } @Override public final JsonNode get(String fieldName) { return null; } @Override public final JsonNode path(String fieldName) { return MissingNode.getInstance(); } @Override public final boolean has(String fieldName) { return false; } @Override public final boolean hasNonNull(String fieldName) { return false; } /* ********************************************************************** * Find methods: all "leaf" nodes return the same for these ********************************************************************** */ @Override public final JsonNode findValue(String fieldName) { return null; } // note: co-variant return type @Override public final ObjectNode findParent(String fieldName) { return null; } @Override public final List findValues(String fieldName, List foundSoFar) { return foundSoFar; } @Override public final List findValuesAsText(String fieldName, List foundSoFar) { return foundSoFar; } @Override public final List findParents(String fieldName, List foundSoFar) { return foundSoFar; } } package-info.java000066400000000000000000000005331325620701100345650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/node/** * Contains concrete {@link com.fasterxml.jackson.databind.JsonNode} implementations * Jackson uses for the Tree model. * These classes are public since concrete type will be needed * for most operations that modify node trees. For read-only access concrete * types are usually not needed. */ package com.fasterxml.jackson.databind.node; package-info.java000066400000000000000000000063671325620701100336530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/** Basic data binding (mapping) functionality that allows for reading JSON content into Java Objects (POJOs) and JSON Trees ({@link com.fasterxml.jackson.databind.JsonNode}), as well as writing Java Objects and trees as JSON. Reading and writing (as well as related additional functionality) is accessed through {@link com.fasterxml.jackson.databind.ObjectMapper}, {@link com.fasterxml.jackson.databind.ObjectReader} and {@link com.fasterxml.jackson.databind.ObjectWriter} classes. In addition to reading and writing JSON content, it is also possible to use the general databinding functionality for many other data formats, using Jackson extension modules that provide such support: if so, you typically simply construct an {@link com.fasterxml.jackson.databind.ObjectMapper} with different underlying streaming parser, generator implementation.

The main starting point for operations is {@link com.fasterxml.jackson.databind.ObjectMapper}, which can be used either directly (via multiple overloaded readValue, readTree, writeValue and writeTree methods, or it can be used as a configurable factory for constructing fully immutable, thread-safe and reusable {@link com.fasterxml.jackson.databind.ObjectReader} and {@link com.fasterxml.jackson.databind.ObjectWriter} objects.

In addition to simple reading and writing of JSON as POJOs or JSON trees (represented as {@link com.fasterxml.jackson.databind.JsonNode}, and configurability needed to change aspects of reading/writing, mapper contains additional functionality such as:

  • Value conversions using {@link com.fasterxml.jackson.databind.ObjectMapper#convertValue(Object, Class)}, {@link com.fasterxml.jackson.databind.ObjectMapper#valueToTree(Object)} and {@link com.fasterxml.jackson.databind.ObjectMapper#treeToValue(com.fasterxml.jackson.core.TreeNode, Class)} methods.
  • Type introspection needed for things like generation of Schemas (like JSON Schema, Avro Schema, or protoc definitions), using {@link com.fasterxml.jackson.databind.ObjectMapper#acceptJsonFormatVisitor(Class, com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper)} (note: actual handles are usually provided by various Jackson modules: mapper simply initiates calling of callbacks, based on serializers registered)

Simplest usage is of form:

  final ObjectMapper mapper = new ObjectMapper(); // can use static singleton, inject: just make sure to reuse!
  MyValue value = new MyValue();
  // ... and configure
  File newState = new File("my-stuff.json");
  mapper.writeValue(newState, value); // writes JSON serialization of MyValue instance
  // or, read
  MyValue older = mapper.readValue(new File("my-older-stuff.json"), MyValue.class);

  // Or if you prefer JSON Tree representation:
  JsonNode root = mapper.readTree(newState);
  // and find values by, for example, using a {@link com.fasterxml.jackson.core.JsonPointer} expression:
  int age = root.at("/personal/age").getValueAsInt(); 

For more usage, refer to {@link com.fasterxml.jackson.databind.ObjectMapper}, {@link com.fasterxml.jackson.databind.ObjectReader} and {@link com.fasterxml.jackson.databind.ObjectWriter} Javadocs. */ package com.fasterxml.jackson.databind; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/000077500000000000000000000000001325620701100313205ustar00rootroot00000000000000AnyGetterWriter.java000066400000000000000000000072271325620701100352130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.Map; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.ser.std.MapSerializer; /** * Class similar to {@link BeanPropertyWriter}, but that will be used * for serializing {@link com.fasterxml.jackson.annotation.JsonAnyGetter} annotated * (Map) properties */ public class AnyGetterWriter { protected final BeanProperty _property; /** * Method (or field) that represents the "any getter" */ protected final AnnotatedMember _accessor; protected JsonSerializer _serializer; protected MapSerializer _mapSerializer; @SuppressWarnings("unchecked") public AnyGetterWriter(BeanProperty property, AnnotatedMember accessor, JsonSerializer serializer) { _accessor = accessor; _property = property; _serializer = (JsonSerializer) serializer; if (serializer instanceof MapSerializer) { _mapSerializer = (MapSerializer) serializer; } } /** * @since 2.8.3 */ public void fixAccess(SerializationConfig config) { _accessor.fixAccess( config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } public void getAndSerialize(Object bean, JsonGenerator gen, SerializerProvider provider) throws Exception { Object value = _accessor.getValue(bean); if (value == null) { return; } if (!(value instanceof Map)) { provider.reportBadDefinition(_property.getType(), String.format( "Value returned by 'any-getter' %s() not java.util.Map but %s", _accessor.getName(), value.getClass().getName())); } // 23-Feb-2015, tatu: Nasty, but has to do (for now) if (_mapSerializer != null) { _mapSerializer.serializeFields((Map) value, gen, provider); return; } _serializer.serialize(value, gen, provider); } /** * @since 2.3 */ public void getAndFilter(Object bean, JsonGenerator gen, SerializerProvider provider, PropertyFilter filter) throws Exception { Object value = _accessor.getValue(bean); if (value == null) { return; } if (!(value instanceof Map)) { provider.reportBadDefinition(_property.getType(), String.format("Value returned by 'any-getter' (%s()) not java.util.Map but %s", _accessor.getName(), value.getClass().getName())); } // 19-Oct-2014, tatu: Should we try to support @JsonInclude options here? if (_mapSerializer != null) { _mapSerializer.serializeFilteredAnyProperties(provider, gen, bean,(Map) value, filter, null); return; } // ... not sure how custom handler would do it _serializer.serialize(value, gen, provider); } // Note: NOT part of ResolvableSerializer... @SuppressWarnings("unchecked") public void resolve(SerializerProvider provider) throws JsonMappingException { // 05-Sep-2013, tatu: I _think_ this can be considered a primary property... if (_serializer instanceof ContextualSerializer) { JsonSerializer ser = provider.handlePrimaryContextualization(_serializer, _property); _serializer = (JsonSerializer) ser; if (ser instanceof MapSerializer) { _mapSerializer = (MapSerializer) ser; } } } } BasicSerializerFactory.java000066400000000000000000001514341325620701100365170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.math.BigDecimal; import java.math.BigInteger; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig; import com.fasterxml.jackson.databind.ext.OptionalHandlerFactory; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.impl.*; import com.fasterxml.jackson.databind.ser.std.*; import com.fasterxml.jackson.databind.type.*; import com.fasterxml.jackson.databind.util.*; /** * Factory class that can provide serializers for standard JDK classes, * as well as custom classes that extend standard classes or implement * one of "well-known" interfaces (such as {@link java.util.Collection}). *

* Since all the serializers are eagerly instantiated, and there is * no additional introspection or customizability of these types, * this factory is essentially stateless. */ @SuppressWarnings("serial") public abstract class BasicSerializerFactory extends SerializerFactory implements java.io.Serializable { /* /********************************************************** /* Configuration, lookup tables/maps /********************************************************** */ /** * Since these are all JDK classes, we shouldn't have to worry * about ClassLoader used to load them. Rather, we can just * use the class name, and keep things simple and efficient. */ protected final static HashMap> _concrete; /** * Actually it may not make much sense to eagerly instantiate all * kinds of serializers: so this Map actually contains class references, * not instances */ protected final static HashMap>> _concreteLazy; static { HashMap>> concLazy = new HashMap>>(); HashMap> concrete = new HashMap>(); /* String and string-like types (note: date types explicitly * not included -- can use either textual or numeric serialization) */ concrete.put(String.class.getName(), new StringSerializer()); final ToStringSerializer sls = ToStringSerializer.instance; concrete.put(StringBuffer.class.getName(), sls); concrete.put(StringBuilder.class.getName(), sls); concrete.put(Character.class.getName(), sls); concrete.put(Character.TYPE.getName(), sls); // Primitives/wrappers for primitives (primitives needed for Beans) NumberSerializers.addAll(concrete); concrete.put(Boolean.TYPE.getName(), new BooleanSerializer(true)); concrete.put(Boolean.class.getName(), new BooleanSerializer(false)); // Other numbers, more complicated concrete.put(BigInteger.class.getName(), new NumberSerializer(BigInteger.class)); concrete.put(BigDecimal.class.getName(),new NumberSerializer(BigDecimal.class)); // Other discrete non-container types: // First, Date/Time zoo: concrete.put(Calendar.class.getName(), CalendarSerializer.instance); concrete.put(java.util.Date.class.getName(), DateSerializer.instance); // And then other standard non-structured JDK types for (Map.Entry,Object> en : StdJdkSerializers.all()) { Object value = en.getValue(); if (value instanceof JsonSerializer) { concrete.put(en.getKey().getName(), (JsonSerializer) value); } else { @SuppressWarnings("unchecked") Class> cls = (Class>) value; concLazy.put(en.getKey().getName(), cls); } } // Jackson-specific type(s) // (Q: can this ever be sub-classed?) concLazy.put(TokenBuffer.class.getName(), TokenBufferSerializer.class); _concrete = concrete; _concreteLazy = concLazy; } /* /********************************************************** /* Configuration /********************************************************** */ /** * Configuration settings for this factory; immutable instance (just like this * factory), new version created via copy-constructor (fluent-style) */ protected final SerializerFactoryConfig _factoryConfig; /* /********************************************************** /* Life cycle /********************************************************** */ /** * We will provide default constructor to allow sub-classing, * but make it protected so that no non-singleton instances of * the class will be instantiated. */ protected BasicSerializerFactory(SerializerFactoryConfig config) { _factoryConfig = (config == null) ? new SerializerFactoryConfig() : config; } /** * Method for getting current {@link SerializerFactoryConfig}. *

* Note that since instances are immutable, you can NOT change settings * by accessing an instance and calling methods: this will simply create * new instance of config object. */ public SerializerFactoryConfig getFactoryConfig() { return _factoryConfig; } /** * Method used for creating a new instance of this factory, but with different * configuration. Reason for specifying factory method (instead of plain constructor) * is to allow proper sub-classing of factories. *

* Note that custom sub-classes generally must override implementation * of this method, as it usually requires instantiating a new instance of * factory type. Check out javadocs for * {@link com.fasterxml.jackson.databind.ser.BeanSerializerFactory} for more details. */ public abstract SerializerFactory withConfig(SerializerFactoryConfig config); /** * Convenience method for creating a new factory instance with an additional * serializer provider. */ @Override public final SerializerFactory withAdditionalSerializers(Serializers additional) { return withConfig(_factoryConfig.withAdditionalSerializers(additional)); } /** * Convenience method for creating a new factory instance with an additional * key serializer provider. */ @Override public final SerializerFactory withAdditionalKeySerializers(Serializers additional) { return withConfig(_factoryConfig.withAdditionalKeySerializers(additional)); } /** * Convenience method for creating a new factory instance with additional bean * serializer modifier. */ @Override public final SerializerFactory withSerializerModifier(BeanSerializerModifier modifier) { return withConfig(_factoryConfig.withSerializerModifier(modifier)); } /* /********************************************************** /* SerializerFactory impl /********************************************************** */ // Implemented by sub-classes @Override public abstract JsonSerializer createSerializer(SerializerProvider prov, JavaType type) throws JsonMappingException; @Override @SuppressWarnings("unchecked") public JsonSerializer createKeySerializer(SerializationConfig config, JavaType keyType, JsonSerializer defaultImpl) { // We should not need any member method info; at most class annotations for Map type // ... at least, not here. BeanDescription beanDesc = config.introspectClassAnnotations(keyType.getRawClass()); JsonSerializer ser = null; // Minor optimization: to avoid constructing beanDesc, bail out if none registered if (_factoryConfig.hasKeySerializers()) { // Only thing we have here are module-provided key serializers: for (Serializers serializers : _factoryConfig.keySerializers()) { ser = serializers.findSerializer(config, keyType, beanDesc); if (ser != null) { break; } } } if (ser == null) { ser = defaultImpl; if (ser == null) { ser = StdKeySerializers.getStdKeySerializer(config, keyType.getRawClass(), false); // As per [databind#47], also need to support @JsonValue if (ser == null) { beanDesc = config.introspect(keyType); AnnotatedMember am = beanDesc.findJsonValueAccessor(); if (am != null) { final Class rawType = am.getRawType(); JsonSerializer delegate = StdKeySerializers.getStdKeySerializer(config, rawType, true); if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(am.getMember(), config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } ser = new JsonValueSerializer(am, delegate); } else { ser = StdKeySerializers.getFallbackKeySerializer(config, keyType.getRawClass()); } } } } // [databind#120]: Allow post-processing if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { ser = mod.modifyKeySerializer(config, keyType, beanDesc, ser); } } return (JsonSerializer) ser; } /** * Method called to construct a type serializer for values with given declared * base type. This is called for values other than those of bean property * types. */ @Override public TypeSerializer createTypeSerializer(SerializationConfig config, JavaType baseType) { BeanDescription bean = config.introspectClassAnnotations(baseType.getRawClass()); AnnotatedClass ac = bean.getClassInfo(); AnnotationIntrospector ai = config.getAnnotationIntrospector(); TypeResolverBuilder b = ai.findTypeResolver(config, ac, baseType); /* Ok: if there is no explicit type info handler, we may want to * use a default. If so, config object knows what to use. */ Collection subtypes = null; if (b == null) { b = config.getDefaultTyper(baseType); } else { subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByClass(config, ac); } if (b == null) { return null; } // 10-Jun-2015, tatu: Since not created for Bean Property, no need for post-processing // wrt EXTERNAL_PROPERTY return b.buildTypeSerializer(config, baseType, subtypes); } /* /********************************************************** /* Additional API for other core classes /********************************************************** */ protected abstract Iterable customSerializers(); /* /********************************************************** /* Overridable secondary serializer accessor methods /********************************************************** */ /** * Method that will use fast lookup (and identity comparison) methods to * see if we know serializer to use for given type. */ protected final JsonSerializer findSerializerByLookup(JavaType type, SerializationConfig config, BeanDescription beanDesc, boolean staticTyping) { Class raw = type.getRawClass(); String clsName = raw.getName(); JsonSerializer ser = _concrete.get(clsName); if (ser == null) { Class> serClass = _concreteLazy.get(clsName); if (serClass != null) { // 07-Jan-2017, tatu: Should never fail (since we control constructors), // but if it does will throw `IllegalArgumentException` with description, // which we could catch, re-title. return ClassUtil.createInstance(serClass, false); } } return ser; } /** * Method called to see if one of primary per-class annotations * (or related, like implementing of {@link JsonSerializable}) * determines the serializer to use. *

* Currently handles things like: *

    *
  • If type implements {@link JsonSerializable}, use that *
  • *
  • If type has {@link com.fasterxml.jackson.annotation.JsonValue} annotation (or equivalent), build serializer * based on that property *
  • *
* * @since 2.0 */ protected final JsonSerializer findSerializerByAnnotations(SerializerProvider prov, JavaType type, BeanDescription beanDesc) throws JsonMappingException { Class raw = type.getRawClass(); // First: JsonSerializable? if (JsonSerializable.class.isAssignableFrom(raw)) { return SerializableSerializer.instance; } // Second: @JsonValue for any type AnnotatedMember valueAccessor = beanDesc.findJsonValueAccessor(); if (valueAccessor != null) { if (prov.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(valueAccessor.getMember(), prov.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } JsonSerializer ser = findSerializerFromAnnotation(prov, valueAccessor); return new JsonValueSerializer(valueAccessor, ser); } // No well-known annotations... return null; } /** * Method for checking if we can determine serializer to use based on set of * known primary types, checking for set of known base types (exact matches * having been compared against with findSerializerByLookup). * This does not include "secondary" interfaces, but * mostly concrete or abstract base classes. */ protected final JsonSerializer findSerializerByPrimaryType(SerializerProvider prov, JavaType type, BeanDescription beanDesc, boolean staticTyping) throws JsonMappingException { Class raw = type.getRawClass(); // Then check for optional/external serializers JsonSerializer ser = findOptionalStdSerializer(prov, type, beanDesc, staticTyping); if (ser != null) { return ser; } if (Calendar.class.isAssignableFrom(raw)) { return CalendarSerializer.instance; } if (java.util.Date.class.isAssignableFrom(raw)) { return DateSerializer.instance; } if (Map.Entry.class.isAssignableFrom(raw)) { // 18-Oct-2015, tatu: With 2.7, need to dig type info: JavaType mapEntryType = type.findSuperType(Map.Entry.class); // 28-Apr-2015, tatu: TypeFactory does it all for us already so JavaType kt = mapEntryType.containedTypeOrUnknown(0); JavaType vt = mapEntryType.containedTypeOrUnknown(1); return buildMapEntrySerializer(prov, type, beanDesc, staticTyping, kt, vt); } if (ByteBuffer.class.isAssignableFrom(raw)) { return new ByteBufferSerializer(); } if (InetAddress.class.isAssignableFrom(raw)) { return new InetAddressSerializer(); } if (InetSocketAddress.class.isAssignableFrom(raw)) { return new InetSocketAddressSerializer(); } if (TimeZone.class.isAssignableFrom(raw)) { return new TimeZoneSerializer(); } if (java.nio.charset.Charset.class.isAssignableFrom(raw)) { return ToStringSerializer.instance; } if (Number.class.isAssignableFrom(raw)) { // 21-May-2014, tatu: Couple of alternatives actually JsonFormat.Value format = beanDesc.findExpectedFormat(null); if (format != null) { switch (format.getShape()) { case STRING: return ToStringSerializer.instance; case OBJECT: // need to bail out to let it be serialized as POJO case ARRAY: // or, I guess ARRAY; otherwise no point in speculating return null; default: } } return NumberSerializer.instance; } if (Enum.class.isAssignableFrom(raw)) { return buildEnumSerializer(prov.getConfig(), type, beanDesc); } return null; } /** * Overridable method called after checking all other types. * * @since 2.2 */ protected JsonSerializer findOptionalStdSerializer(SerializerProvider prov, JavaType type, BeanDescription beanDesc, boolean staticTyping) throws JsonMappingException { return OptionalHandlerFactory.instance.findSerializer(prov.getConfig(), type, beanDesc); } /** * Reflection-based serialized find method, which checks if * given class implements one of recognized "add-on" interfaces. * Add-on here means a role that is usually or can be a secondary * trait: for example, * bean classes may implement {@link Iterable}, but their main * function is usually something else. The reason for */ protected final JsonSerializer findSerializerByAddonType(SerializationConfig config, JavaType javaType, BeanDescription beanDesc, boolean staticTyping) throws JsonMappingException { Class rawType = javaType.getRawClass(); if (Iterator.class.isAssignableFrom(rawType)) { JavaType[] params = config.getTypeFactory().findTypeParameters(javaType, Iterator.class); JavaType vt = (params == null || params.length != 1) ? TypeFactory.unknownType() : params[0]; return buildIteratorSerializer(config, javaType, beanDesc, staticTyping, vt); } if (Iterable.class.isAssignableFrom(rawType)) { JavaType[] params = config.getTypeFactory().findTypeParameters(javaType, Iterable.class); JavaType vt = (params == null || params.length != 1) ? TypeFactory.unknownType() : params[0]; return buildIterableSerializer(config, javaType, beanDesc, staticTyping, vt); } if (CharSequence.class.isAssignableFrom(rawType)) { return ToStringSerializer.instance; } return null; } /** * Helper method called to check if a class or method * has an annotation * (@link com.fasterxml.jackson.databind.annotation.JsonSerialize#using) * that tells the class to use for serialization. * Returns null if no such annotation found. */ @SuppressWarnings("unchecked") protected JsonSerializer findSerializerFromAnnotation(SerializerProvider prov, Annotated a) throws JsonMappingException { Object serDef = prov.getAnnotationIntrospector().findSerializer(a); if (serDef == null) { return null; } JsonSerializer ser = prov.serializerInstance(a, serDef); // One more thing however: may need to also apply a converter: return (JsonSerializer) findConvertingSerializer(prov, a, ser); } /** * Helper method that will check whether given annotated entity (usually class, * but may also be a property accessor) indicates that a {@link Converter} is to * be used; and if so, to construct and return suitable serializer for it. * If not, will simply return given serializer as is. */ protected JsonSerializer findConvertingSerializer(SerializerProvider prov, Annotated a, JsonSerializer ser) throws JsonMappingException { Converter conv = findConverter(prov, a); if (conv == null) { return ser; } JavaType delegateType = conv.getOutputType(prov.getTypeFactory()); return new StdDelegatingSerializer(conv, delegateType, ser); } protected Converter findConverter(SerializerProvider prov, Annotated a) throws JsonMappingException { Object convDef = prov.getAnnotationIntrospector().findSerializationConverter(a); if (convDef == null) { return null; } return prov.converterInstance(a, convDef); } /* /********************************************************** /* Factory methods, container types: /********************************************************** */ /** * @since 2.1 */ protected JsonSerializer buildContainerSerializer(SerializerProvider prov, JavaType type, BeanDescription beanDesc, boolean staticTyping) throws JsonMappingException { final SerializationConfig config = prov.getConfig(); /* [databind#23], 15-Mar-2013, tatu: must force static handling of root value type, * with just one important exception: if value type is "untyped", let's * leave it as is; no clean way to make it work. */ if (!staticTyping && type.useStaticType()) { if (!type.isContainerType() || !type.getContentType().isJavaLangObject()) { staticTyping = true; } } // Let's see what we can learn about element/content/value type, type serializer for it: JavaType elementType = type.getContentType(); TypeSerializer elementTypeSerializer = createTypeSerializer(config, elementType); // if elements have type serializer, cannot force static typing: if (elementTypeSerializer != null) { staticTyping = false; } JsonSerializer elementValueSerializer = _findContentSerializer(prov, beanDesc.getClassInfo()); if (type.isMapLikeType()) { // implements java.util.Map MapLikeType mlt = (MapLikeType) type; /* 29-Sep-2012, tatu: This is actually too early to (try to) find * key serializer from property annotations, and can lead to caching * issues (see [databind#75]). Instead, must be done from 'createContextual()' call. * But we do need to check class annotations. */ JsonSerializer keySerializer = _findKeySerializer(prov, beanDesc.getClassInfo()); if (mlt.isTrueMapType()) { return buildMapSerializer(prov, (MapType) mlt, beanDesc, staticTyping, keySerializer, elementTypeSerializer, elementValueSerializer); } // With Map-like, just 2 options: (1) Custom, (2) Annotations JsonSerializer ser = null; MapLikeType mlType = (MapLikeType) type; for (Serializers serializers : customSerializers()) { // (1) Custom ser = serializers.findMapLikeSerializer(config, mlType, beanDesc, keySerializer, elementTypeSerializer, elementValueSerializer); if (ser != null) { break; } } if (ser == null) { // (2) Annotations-based ones: ser = findSerializerByAnnotations(prov, type, beanDesc); } if (ser != null) { if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { ser = mod.modifyMapLikeSerializer(config, mlType, beanDesc, ser); } } } return ser; } if (type.isCollectionLikeType()) { CollectionLikeType clt = (CollectionLikeType) type; if (clt.isTrueCollectionType()) { return buildCollectionSerializer(prov, (CollectionType) clt, beanDesc, staticTyping, elementTypeSerializer, elementValueSerializer); } // With Map-like, just 2 options: (1) Custom, (2) Annotations JsonSerializer ser = null; CollectionLikeType clType = (CollectionLikeType) type; for (Serializers serializers : customSerializers()) { // (1) Custom ser = serializers.findCollectionLikeSerializer(config, clType, beanDesc, elementTypeSerializer, elementValueSerializer); if (ser != null) { break; } } if (ser == null) { // (2) Annotations-based ones: ser = findSerializerByAnnotations(prov, type, beanDesc); } if (ser != null) { if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { ser = mod.modifyCollectionLikeSerializer(config, clType, beanDesc, ser); } } } return ser; } if (type.isArrayType()) { return buildArraySerializer(prov, (ArrayType) type, beanDesc, staticTyping, elementTypeSerializer, elementValueSerializer); } return null; } /** * Helper method that handles configuration details when constructing serializers for * {@link java.util.List} types that support efficient by-index access * * @since 2.1 */ protected JsonSerializer buildCollectionSerializer(SerializerProvider prov, CollectionType type, BeanDescription beanDesc, boolean staticTyping, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) throws JsonMappingException { SerializationConfig config = prov.getConfig(); JsonSerializer ser = null; // Order of lookups: // 1. Custom serializers // 2. Annotations (@JsonValue, @JsonDeserialize) // 3. Defaults for (Serializers serializers : customSerializers()) { // (1) Custom ser = serializers.findCollectionSerializer(config, type, beanDesc, elementTypeSerializer, elementValueSerializer); if (ser != null) { break; } } if (ser == null) { ser = findSerializerByAnnotations(prov, type, beanDesc); // (2) Annotations if (ser == null) { // We may also want to use serialize Collections "as beans", if (and only if) // this is specified with `@JsonFormat(shape=Object)` JsonFormat.Value format = beanDesc.findExpectedFormat(null); if ((format != null) && format.getShape() == JsonFormat.Shape.OBJECT) { return null; } Class raw = type.getRawClass(); if (EnumSet.class.isAssignableFrom(raw)) { // this may or may not be available (Class doesn't; type of field/method does) JavaType enumType = type.getContentType(); // and even if nominally there is something, only use if it really is enum if (!enumType.isEnumType()) { enumType = null; } ser = buildEnumSetSerializer(enumType); } else { Class elementRaw = type.getContentType().getRawClass(); if (isIndexedList(raw)) { if (elementRaw == String.class) { // [JACKSON-829] Must NOT use if we have custom serializer if (ClassUtil.isJacksonStdImpl(elementValueSerializer)) { ser = IndexedStringListSerializer.instance; } } else { ser = buildIndexedListSerializer(type.getContentType(), staticTyping, elementTypeSerializer, elementValueSerializer); } } else if (elementRaw == String.class) { // [JACKSON-829] Must NOT use if we have custom serializer if (ClassUtil.isJacksonStdImpl(elementValueSerializer)) { ser = StringCollectionSerializer.instance; } } if (ser == null) { ser = buildCollectionSerializer(type.getContentType(), staticTyping, elementTypeSerializer, elementValueSerializer); } } } } // [databind#120]: Allow post-processing if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { ser = mod.modifyCollectionSerializer(config, type, beanDesc, ser); } } return ser; } /* /********************************************************** /* Factory methods, for Collections /********************************************************** */ protected boolean isIndexedList(Class cls) { return RandomAccess.class.isAssignableFrom(cls); } public ContainerSerializer buildIndexedListSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts, JsonSerializer valueSerializer) { return new IndexedListSerializer(elemType, staticTyping, vts, valueSerializer); } public ContainerSerializer buildCollectionSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts, JsonSerializer valueSerializer) { return new CollectionSerializer(elemType, staticTyping, vts, valueSerializer); } public JsonSerializer buildEnumSetSerializer(JavaType enumType) { return new EnumSetSerializer(enumType); } /* /********************************************************** /* Factory methods, for Maps /********************************************************** */ /** * Helper method that handles configuration details when constructing serializers for * {@link java.util.Map} types. */ protected JsonSerializer buildMapSerializer(SerializerProvider prov, MapType type, BeanDescription beanDesc, boolean staticTyping, JsonSerializer keySerializer, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) throws JsonMappingException { // [databind#467]: This is where we could allow serialization "as POJO": But! It's // nasty to undo, and does not apply on per-property basis. So, hardly optimal JsonFormat.Value format = beanDesc.findExpectedFormat(null); if ((format != null) && format.getShape() == JsonFormat.Shape.OBJECT) { return null; } JsonSerializer ser = null; // Order of lookups: // 1. Custom serializers // 2. Annotations (@JsonValue, @JsonDeserialize) // 3. Defaults final SerializationConfig config = prov.getConfig(); for (Serializers serializers : customSerializers()) { // (1) Custom ser = serializers.findMapSerializer(config, type, beanDesc, keySerializer, elementTypeSerializer, elementValueSerializer); if (ser != null) { break; } } if (ser == null) { ser = findSerializerByAnnotations(prov, type, beanDesc); // (2) Annotations if (ser == null) { Object filterId = findFilterId(config, beanDesc); // 01-May-2016, tatu: Which base type to use here gets tricky, since // most often it ought to be `Map` or `EnumMap`, but due to abstract // mapping it will more likely be concrete type like `HashMap`. // So, for time being, just pass `Map.class` JsonIgnoreProperties.Value ignorals = config.getDefaultPropertyIgnorals(Map.class, beanDesc.getClassInfo()); Set ignored = (ignorals == null) ? null : ignorals.findIgnoredForSerialization(); MapSerializer mapSer = MapSerializer.construct(ignored, type, staticTyping, elementTypeSerializer, keySerializer, elementValueSerializer, filterId); ser = _checkMapContentInclusion(prov, beanDesc, mapSer); } } // [databind#120]: Allow post-processing if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { ser = mod.modifyMapSerializer(config, type, beanDesc, ser); } } return ser; } /** * Helper method that does figures out content inclusion value to use, if any, * and construct re-configured {@link MapSerializer} appropriately. * * @since 2.9 */ @SuppressWarnings("deprecation") protected MapSerializer _checkMapContentInclusion(SerializerProvider prov, BeanDescription beanDesc, MapSerializer mapSer) throws JsonMappingException { final JavaType contentType = mapSer.getContentType(); JsonInclude.Value inclV = _findInclusionWithContent(prov, beanDesc, contentType, Map.class); // Need to support global legacy setting, for now: JsonInclude.Include incl = (inclV == null) ? JsonInclude.Include.USE_DEFAULTS : inclV.getContentInclusion(); if (incl == JsonInclude.Include.USE_DEFAULTS || incl == JsonInclude.Include.ALWAYS) { if (!prov.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES)) { return mapSer.withContentInclusion(null, true); } return mapSer; } // NOTE: mostly copied from `PropertyBuilder`; would be nice to refactor // but code is not identical nor are these types related Object valueToSuppress; boolean suppressNulls = true; // almost always, but possibly not with CUSTOM switch (incl) { case NON_DEFAULT: valueToSuppress = BeanUtil.getDefaultValue(contentType); if (valueToSuppress != null) { if (valueToSuppress.getClass().isArray()) { valueToSuppress = ArrayBuilders.getArrayComparator(valueToSuppress); } } break; case NON_ABSENT: // new with 2.6, to support Guava/JDK8 Optionals // and for referential types, also "empty", which in their case means "absent" valueToSuppress = contentType.isReferenceType() ? MapSerializer.MARKER_FOR_EMPTY : null; break; case NON_EMPTY: valueToSuppress = MapSerializer.MARKER_FOR_EMPTY; break; case CUSTOM: // new with 2.9 valueToSuppress = prov.includeFilterInstance(null, inclV.getContentFilter()); if (valueToSuppress == null) { // is this legal? suppressNulls = true; } else { suppressNulls = prov.includeFilterSuppressNulls(valueToSuppress); } break; case NON_NULL: default: // should not matter but... valueToSuppress = null; break; } return mapSer.withContentInclusion(valueToSuppress, suppressNulls); } /** * @since 2.9 */ protected JsonSerializer buildMapEntrySerializer(SerializerProvider prov, JavaType type, BeanDescription beanDesc, boolean staticTyping, JavaType keyType, JavaType valueType) throws JsonMappingException { // [databind#865]: Allow serialization "as POJO" -- note: to undo, declare // serialization as `Shape.NATURAL` instead; that's JSON Object too. JsonFormat.Value formatOverride = prov.getDefaultPropertyFormat(Map.Entry.class); JsonFormat.Value formatFromAnnotation = beanDesc.findExpectedFormat(null); JsonFormat.Value format = JsonFormat.Value.merge(formatFromAnnotation, formatOverride); if (format.getShape() == JsonFormat.Shape.OBJECT) { return null; } MapEntrySerializer ser = new MapEntrySerializer(valueType, keyType, valueType, staticTyping, createTypeSerializer(prov.getConfig(), valueType), null); final JavaType contentType = ser.getContentType(); JsonInclude.Value inclV = _findInclusionWithContent(prov, beanDesc, contentType, Map.Entry.class); // Need to support global legacy setting, for now: JsonInclude.Include incl = (inclV == null) ? JsonInclude.Include.USE_DEFAULTS : inclV.getContentInclusion(); if (incl == JsonInclude.Include.USE_DEFAULTS || incl == JsonInclude.Include.ALWAYS) { return ser; } // NOTE: mostly copied from `PropertyBuilder`; would be nice to refactor // but code is not identical nor are these types related Object valueToSuppress; boolean suppressNulls = true; // almost always, but possibly not with CUSTOM switch (incl) { case NON_DEFAULT: valueToSuppress = BeanUtil.getDefaultValue(contentType); if (valueToSuppress != null) { if (valueToSuppress.getClass().isArray()) { valueToSuppress = ArrayBuilders.getArrayComparator(valueToSuppress); } } break; case NON_ABSENT: valueToSuppress = contentType.isReferenceType() ? MapSerializer.MARKER_FOR_EMPTY : null; break; case NON_EMPTY: valueToSuppress = MapSerializer.MARKER_FOR_EMPTY; break; case CUSTOM: valueToSuppress = prov.includeFilterInstance(null, inclV.getContentFilter()); if (valueToSuppress == null) { // is this legal? suppressNulls = true; } else { suppressNulls = prov.includeFilterSuppressNulls(valueToSuppress); } break; case NON_NULL: default: // should not matter but... valueToSuppress = null; break; } return ser.withContentInclusion(valueToSuppress, suppressNulls); } /** * Helper method used for finding inclusion definitions for structured * container types like Maps and referential types * (like AtomicReference). * * @param contentType Declared full content type of container * @param configType Raw base type under which `configOverride`, if any, needs to be defined */ protected JsonInclude.Value _findInclusionWithContent(SerializerProvider prov, BeanDescription beanDesc, JavaType contentType, Class configType) throws JsonMappingException { final SerializationConfig config = prov.getConfig(); // Defaulting gets complicated because we might have two distinct // axis to consider: Container type itself , and then value (content) type. // Start with Container-defaults, then use more-specific value override, if any. // Start by getting global setting, overridden by Map-type-override JsonInclude.Value inclV = beanDesc.findPropertyInclusion(config.getDefaultPropertyInclusion()); inclV = config.getDefaultPropertyInclusion(configType, inclV); // and then merge content-type overrides, if any. But note that there's // content-to-value inclusion shift we have to do JsonInclude.Value valueIncl = config.getDefaultPropertyInclusion(contentType.getRawClass(), null); if (valueIncl != null) { switch (valueIncl.getValueInclusion()) { case USE_DEFAULTS: break; case CUSTOM: inclV = inclV.withContentFilter(valueIncl.getContentFilter()); break; default: inclV = inclV.withContentInclusion(valueIncl.getValueInclusion()); } } return inclV; } /* /********************************************************** /* Factory methods, for Arrays /********************************************************** */ /** * Helper method that handles configuration details when constructing serializers for * Object[] (and subtypes, except for String). */ protected JsonSerializer buildArraySerializer(SerializerProvider prov, ArrayType type, BeanDescription beanDesc, boolean staticTyping, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) throws JsonMappingException { // 25-Jun-2015, tatu: Note that unlike with Collection(Like) and Map(Like) types, array // types cannot be annotated (in theory I guess we could have mix-ins but... ?) // so we need not do primary annotation lookup here. // So all we need is (1) Custom, (2) Default array serializers SerializationConfig config = prov.getConfig(); JsonSerializer ser = null; for (Serializers serializers : customSerializers()) { // (1) Custom ser = serializers.findArraySerializer(config, type, beanDesc, elementTypeSerializer, elementValueSerializer); if (ser != null) { break; } } if (ser == null) { Class raw = type.getRawClass(); // Important: do NOT use standard serializers if non-standard element value serializer specified if (elementValueSerializer == null || ClassUtil.isJacksonStdImpl(elementValueSerializer)) { if (String[].class == raw) { ser = StringArraySerializer.instance; } else { // other standard types? ser = StdArraySerializers.findStandardImpl(raw); } } if (ser == null) { ser = new ObjectArraySerializer(type.getContentType(), staticTyping, elementTypeSerializer, elementValueSerializer); } } // [databind#120]: Allow post-processing if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { ser = mod.modifyArraySerializer(config, type, beanDesc, ser); } } return ser; } /* /********************************************************** /* Factory methods for Reference types /* (demoted from BeanSF down here in 2.9) /********************************************************** */ /** * @since 2.7 */ public JsonSerializer findReferenceSerializer(SerializerProvider prov, ReferenceType refType, BeanDescription beanDesc, boolean staticTyping) throws JsonMappingException { JavaType contentType = refType.getContentType(); TypeSerializer contentTypeSerializer = contentType.getTypeHandler(); final SerializationConfig config = prov.getConfig(); if (contentTypeSerializer == null) { contentTypeSerializer = createTypeSerializer(config, contentType); } JsonSerializer contentSerializer = contentType.getValueHandler(); for (Serializers serializers : customSerializers()) { JsonSerializer ser = serializers.findReferenceSerializer(config, refType, beanDesc, contentTypeSerializer, contentSerializer); if (ser != null) { return ser; } } if (refType.isTypeOrSubTypeOf(AtomicReference.class)) { return buildAtomicReferenceSerializer(prov, refType, beanDesc, staticTyping, contentTypeSerializer, contentSerializer); } return null; } protected JsonSerializer buildAtomicReferenceSerializer(SerializerProvider prov, ReferenceType refType, BeanDescription beanDesc, boolean staticTyping, TypeSerializer contentTypeSerializer, JsonSerializer contentSerializer) throws JsonMappingException { final JavaType contentType = refType.getReferencedType(); JsonInclude.Value inclV = _findInclusionWithContent(prov, beanDesc, contentType, AtomicReference.class); // Need to support global legacy setting, for now: JsonInclude.Include incl = (inclV == null) ? JsonInclude.Include.USE_DEFAULTS : inclV.getContentInclusion(); Object valueToSuppress; boolean suppressNulls; if (incl == JsonInclude.Include.USE_DEFAULTS || incl == JsonInclude.Include.ALWAYS) { valueToSuppress = null; suppressNulls = false; } else { suppressNulls = true; switch (incl) { case NON_DEFAULT: valueToSuppress = BeanUtil.getDefaultValue(contentType); if (valueToSuppress != null) { if (valueToSuppress.getClass().isArray()) { valueToSuppress = ArrayBuilders.getArrayComparator(valueToSuppress); } } break; case NON_ABSENT: valueToSuppress = contentType.isReferenceType() ? MapSerializer.MARKER_FOR_EMPTY : null; break; case NON_EMPTY: valueToSuppress = MapSerializer.MARKER_FOR_EMPTY; break; case CUSTOM: valueToSuppress = prov.includeFilterInstance(null, inclV.getContentFilter()); if (valueToSuppress == null) { // is this legal? suppressNulls = true; } else { suppressNulls = prov.includeFilterSuppressNulls(valueToSuppress); } break; case NON_NULL: default: // should not matter but... valueToSuppress = null; break; } } AtomicReferenceSerializer ser = new AtomicReferenceSerializer(refType, staticTyping, contentTypeSerializer, contentSerializer); return ser.withContentInclusion(valueToSuppress, suppressNulls); } /* /********************************************************** /* Factory methods, for non-container types /********************************************************** */ /** * @since 2.5 */ protected JsonSerializer buildIteratorSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc, boolean staticTyping, JavaType valueType) throws JsonMappingException { return new IteratorSerializer(valueType, staticTyping, createTypeSerializer(config, valueType)); } /** * @since 2.5 */ protected JsonSerializer buildIterableSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc, boolean staticTyping, JavaType valueType) throws JsonMappingException { return new IterableSerializer(valueType, staticTyping, createTypeSerializer(config, valueType)); } protected JsonSerializer buildEnumSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc) throws JsonMappingException { /* As per [databind#24], may want to use alternate shape, serialize as JSON Object. * Challenge here is that EnumSerializer does not know how to produce * POJO style serialization, so we must handle that special case separately; * otherwise pass it to EnumSerializer. */ JsonFormat.Value format = beanDesc.findExpectedFormat(null); if (format != null && format.getShape() == JsonFormat.Shape.OBJECT) { // one special case: suppress serialization of "getDeclaringClass()"... ((BasicBeanDescription) beanDesc).removeProperty("declaringClass"); // returning null will mean that eventually BeanSerializer gets constructed return null; } @SuppressWarnings("unchecked") Class> enumClass = (Class>) type.getRawClass(); JsonSerializer ser = EnumSerializer.construct(enumClass, config, beanDesc, format); // [databind#120]: Allow post-processing if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { ser = mod.modifyEnumSerializer(config, type, beanDesc, ser); } } return ser; } /* /********************************************************** /* Other helper methods /********************************************************** */ /** * Helper method called to try to find whether there is an annotation in the * class that indicates key serializer to use. * If so, will try to instantiate key serializer and return it; otherwise returns null. */ protected JsonSerializer _findKeySerializer(SerializerProvider prov, Annotated a) throws JsonMappingException { AnnotationIntrospector intr = prov.getAnnotationIntrospector(); Object serDef = intr.findKeySerializer(a); if (serDef != null) { return prov.serializerInstance(a, serDef); } return null; } /** * Helper method called to try to find whether there is an annotation in the * class that indicates content ("value") serializer to use. * If so, will try to instantiate value serializer and return it; otherwise returns null. */ protected JsonSerializer _findContentSerializer(SerializerProvider prov, Annotated a) throws JsonMappingException { AnnotationIntrospector intr = prov.getAnnotationIntrospector(); Object serDef = intr.findContentSerializer(a); if (serDef != null) { return prov.serializerInstance(a, serDef); } return null; } /** * Method called to find filter that is configured to be used with bean * serializer being built, if any. */ protected Object findFilterId(SerializationConfig config, BeanDescription beanDesc) { return config.getAnnotationIntrospector().findFilterId((Annotated)beanDesc.getClassInfo()); } /** * Helper method to check whether global settings and/or class * annotations for the bean class indicate that static typing * (declared types) should be used for properties. * (instead of dynamic runtime types). * * @since 2.1 (earlier had variant with additional 'property' parameter) */ protected boolean usesStaticTyping(SerializationConfig config, BeanDescription beanDesc, TypeSerializer typeSer) { /* 16-Aug-2010, tatu: If there is a (value) type serializer, we cannot force * static typing; that would make it impossible to handle expected subtypes */ if (typeSer != null) { return false; } AnnotationIntrospector intr = config.getAnnotationIntrospector(); JsonSerialize.Typing t = intr.findSerializationTyping(beanDesc.getClassInfo()); if (t != null && t != JsonSerialize.Typing.DEFAULT_TYPING) { return (t == JsonSerialize.Typing.STATIC); } return config.isEnabled(MapperFeature.USE_STATIC_TYPING); } // Commented out in 2.9 /* protected Class _verifyAsClass(Object src, String methodName, Class noneClass) { if (src == null) { return null; } if (!(src instanceof Class)) { throw new IllegalStateException("AnnotationIntrospector."+methodName+"() returned value of type "+src.getClass().getName()+": expected type JsonSerializer or Class instead"); } Class cls = (Class) src; if (cls == noneClass || ClassUtil.isBogusClass(cls)) { return null; } return cls; } */ } BeanPropertyFilter.java000066400000000000000000000073651325620701100356770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.node.ObjectNode; /** * Interface that defines API for filter objects use (as configured * using {@link com.fasterxml.jackson.annotation.JsonFilter}) * for filtering bean properties to serialize. *

* Starting with version 2.3 this class is deprecated; use * {@link PropertyFilter} instead. * * @deprecated Since 2.3: use {@link PropertyFilter} instead. */ @Deprecated public interface BeanPropertyFilter { /** * Method called by {@link BeanSerializer} to let filter decide what to do with * given bean property value: the usual choices are to either filter out (i.e. * do nothing) or write using given {@link BeanPropertyWriter}, although filters * can choose other to do something different altogether. *

* Typical implementation is something like: *

     * if (include(writer)) {
     *      writer.serializeAsField(pojo, jgen, prov);
     * }
     *
* * @param pojo Object that contains property value to serialize * @param jgen Generator use for serializing value * @param prov Provider that can be used for accessing dynamic aspects of serialization * processing * @param writer Default bean property serializer to use */ public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider prov, BeanPropertyWriter writer) throws Exception; /** * Method called by {@link BeanSerializer} to let the filter determine whether, and in what * form the given property exist within the parent, or root, schema. Filters can omit * adding the property to the node, or choose the form of the schema value for the property. *

* Typical implementation is something like: *

     * if (include(writer)) {
     *      writer.depositSchemaProperty(propertiesNode, provider);
     * }
     *
* * @param writer Bean property writer to use to create schema value * @param propertiesNode Node which the given property would exist within * @param provider Provider that can be used for accessing dynamic aspects of serialization * processing * * @since 2.1 * @deprecated Since 2.3: new code should use the alternative depositSchemaProperty * method */ @Deprecated public void depositSchemaProperty(BeanPropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException; /** * Method called by {@link BeanSerializer} to let the filter determine whether, and in what * form the given property exist within the parent, or root, schema. Filters can omit * adding the property to the node, or choose the form of the schema value for the property *

* Typical implementation is something like: *

     * if (include(writer)) {
     *      writer.depositSchemaProperty(objectVisitor, provider);
     * }
     *
* * @param writer Bean property serializer to use to create schema value * @param objectVisitor JsonObjectFormatVisitor which should be aware of * the property's existence * @param provider Provider that can be used for accessing dynamic aspects of serialization * processing * * @since 2.1 */ public void depositSchemaProperty(BeanPropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException; } BeanPropertyWriter.java000066400000000000000000001025541325620701100357220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.HashMap; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.jsonschema.SchemaAware; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; import com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter; import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; import com.fasterxml.jackson.databind.util.Annotations; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Base bean property handler class, which implements common parts of * reflection-based functionality for accessing a property value and serializing * it. *

* Note that current design tries to keep instances immutable (semi-functional * style); mostly because these instances are exposed to application code and * this is to reduce likelihood of data corruption and synchronization issues. */ @JacksonStdImpl // since 2.6. NOTE: sub-classes typically are not public class BeanPropertyWriter extends PropertyWriter // which extends // `ConcreteBeanPropertyBase` implements java.io.Serializable // since 2.6 { // As of 2.7 private static final long serialVersionUID = 1L; /** * Marker object used to indicate "do not serialize if empty" */ public final static Object MARKER_FOR_EMPTY = JsonInclude.Include.NON_EMPTY; /* /*********************************************************** /* Basic property metadata: name, type, other /*********************************************************** */ /** * Logical name of the property; will be used as the field name under which * value for the property is written. *

* NOTE: do NOT change name of this field; it is accessed by Afterburner * module (until 2.4; not directly from 2.5) ALSO NOTE: ... and while it * really ought to be `SerializableString`, changing that is also * binary-incompatible change. So nope. */ protected final SerializedString _name; /** * Wrapper name to use for this element, if any * * @since 2.2 */ protected final PropertyName _wrapperName; /** * Type property is declared to have, either in class definition or * associated annotations. */ protected final JavaType _declaredType; /** * Type to use for locating serializer; normally same as return type of the * accessor method, but may be overridden by annotations. */ protected final JavaType _cfgSerializationType; /** * Base type of the property, if the declared type is "non-trivial"; meaning * it is either a structured type (collection, map, array), or * parameterized. Used to retain type information about contained type, * which is mostly necessary if type meta-data is to be included. */ protected JavaType _nonTrivialBaseType; /** * Annotations from context (most often, class that declares property, or in * case of sub-class serializer, from that sub-class) *

* NOTE: transient just to support JDK serializability; Annotations do not * serialize. At all. */ protected final transient Annotations _contextAnnotations; /* /*********************************************************** /* Settings for accessing property value to serialize /*********************************************************** */ /** * Member (field, method) that represents property and allows access to * associated annotations. */ protected final AnnotatedMember _member; /** * Accessor method used to get property value, for method-accessible * properties. Null if and only if {@link #_field} is null. *

* `transient` (and non-final) only to support JDK serializability. */ protected transient Method _accessorMethod; /** * Field that contains the property value for field-accessible properties. * Null if and only if {@link #_accessorMethod} is null. *

* `transient` (and non-final) only to support JDK serializability. */ protected transient Field _field; /* /*********************************************************** /* Serializers needed /*********************************************************** */ /** * Serializer to use for writing out the value: null if it cannot be known * statically; non-null if it can. */ protected JsonSerializer _serializer; /** * Serializer used for writing out null values, if any: if null, null values * are to be suppressed. */ protected JsonSerializer _nullSerializer; /** * If property being serialized needs type information to be included this * is the type serializer to use. Declared type (possibly augmented with * annotations) of property is used for determining exact mechanism to use * (compared to actual runtime type used for serializing actual state). */ protected TypeSerializer _typeSerializer; /** * In case serializer is not known statically (i.e. _serializer * is null), we will use a lookup structure for storing dynamically resolved * mapping from type(s) to serializer(s). */ protected transient PropertySerializerMap _dynamicSerializers; /* /*********************************************************** /* Filtering /*********************************************************** */ /** * Whether null values are to be suppressed (nothing written out if value is * null) or not. Note that this is a configuration value during * construction, and actual handling relies on setting (or not) of * {@link #_nullSerializer}. */ protected final boolean _suppressNulls; /** * Value that is considered default value of the property; used for * default-value-suppression if enabled. */ protected final Object _suppressableValue; /** * Alternate set of property writers used when view-based filtering is * available for the Bean. */ protected final Class[] _includeInViews; /* /********************************************************** /* Opaqueinternal data that bean serializer factory and /* bean serializers can add. /********************************************************** */ protected transient HashMap _internalSettings; /* /*********************************************************** /* Construction, configuration /*********************************************************** */ /** * @since 2.9 (added `includeInViews` since 2.8) */ @SuppressWarnings("unchecked") public BeanPropertyWriter(BeanPropertyDefinition propDef, AnnotatedMember member, Annotations contextAnnotations, JavaType declaredType, JsonSerializer ser, TypeSerializer typeSer, JavaType serType, boolean suppressNulls, Object suppressableValue, Class[] includeInViews) { super(propDef); _member = member; _contextAnnotations = contextAnnotations; _name = new SerializedString(propDef.getName()); _wrapperName = propDef.getWrapperName(); _declaredType = declaredType; _serializer = (JsonSerializer) ser; _dynamicSerializers = (ser == null) ? PropertySerializerMap .emptyForProperties() : null; _typeSerializer = typeSer; _cfgSerializationType = serType; if (member instanceof AnnotatedField) { _accessorMethod = null; _field = (Field) member.getMember(); } else if (member instanceof AnnotatedMethod) { _accessorMethod = (Method) member.getMember(); _field = null; } else { // 01-Dec-2014, tatu: Used to be illegal, but now explicitly allowed // for virtual props _accessorMethod = null; _field = null; } _suppressNulls = suppressNulls; _suppressableValue = suppressableValue; // this will be resolved later on, unless nulls are to be suppressed _nullSerializer = null; _includeInViews = includeInViews; } @Deprecated // Since 2.9 public BeanPropertyWriter(BeanPropertyDefinition propDef, AnnotatedMember member, Annotations contextAnnotations, JavaType declaredType, JsonSerializer ser, TypeSerializer typeSer, JavaType serType, boolean suppressNulls, Object suppressableValue) { this(propDef, member, contextAnnotations, declaredType, ser, typeSer, serType, suppressNulls, suppressableValue, null); } /** * Constructor that may be of use to virtual properties, when there is need * for the zero-arg ("default") constructor, and actual initialization is * done after constructor call. * * @since 2.5 */ protected BeanPropertyWriter() { super(PropertyMetadata.STD_REQUIRED_OR_OPTIONAL); _member = null; _contextAnnotations = null; _name = null; _wrapperName = null; _includeInViews = null; _declaredType = null; _serializer = null; _dynamicSerializers = null; _typeSerializer = null; _cfgSerializationType = null; _accessorMethod = null; _field = null; _suppressNulls = false; _suppressableValue = null; _nullSerializer = null; } /** * "Copy constructor" to be used by filtering sub-classes */ protected BeanPropertyWriter(BeanPropertyWriter base) { this(base, base._name); } /** * @since 2.5 */ protected BeanPropertyWriter(BeanPropertyWriter base, PropertyName name) { super(base); /* * 02-Dec-2014, tatu: This is a big mess, alas, what with dependency to * MapperConfig to encode, and Afterburner having heartburn for * SerializableString (vs SerializedString). Hope it can be * resolved/reworked in 2.6 timeframe, if not for 2.5 */ _name = new SerializedString(name.getSimpleName()); _wrapperName = base._wrapperName; _contextAnnotations = base._contextAnnotations; _declaredType = base._declaredType; _member = base._member; _accessorMethod = base._accessorMethod; _field = base._field; _serializer = base._serializer; _nullSerializer = base._nullSerializer; // one more thing: copy internal settings, if any if (base._internalSettings != null) { _internalSettings = new HashMap( base._internalSettings); } _cfgSerializationType = base._cfgSerializationType; _dynamicSerializers = base._dynamicSerializers; _suppressNulls = base._suppressNulls; _suppressableValue = base._suppressableValue; _includeInViews = base._includeInViews; _typeSerializer = base._typeSerializer; _nonTrivialBaseType = base._nonTrivialBaseType; } protected BeanPropertyWriter(BeanPropertyWriter base, SerializedString name) { super(base); _name = name; _wrapperName = base._wrapperName; _member = base._member; _contextAnnotations = base._contextAnnotations; _declaredType = base._declaredType; _accessorMethod = base._accessorMethod; _field = base._field; _serializer = base._serializer; _nullSerializer = base._nullSerializer; if (base._internalSettings != null) { _internalSettings = new HashMap( base._internalSettings); } _cfgSerializationType = base._cfgSerializationType; _dynamicSerializers = base._dynamicSerializers; _suppressNulls = base._suppressNulls; _suppressableValue = base._suppressableValue; _includeInViews = base._includeInViews; _typeSerializer = base._typeSerializer; _nonTrivialBaseType = base._nonTrivialBaseType; } public BeanPropertyWriter rename(NameTransformer transformer) { String newName = transformer.transform(_name.getValue()); if (newName.equals(_name.toString())) { return this; } return _new(PropertyName.construct(newName)); } /** * Overridable factory method used by sub-classes * * @since 2.6 */ protected BeanPropertyWriter _new(PropertyName newName) { return new BeanPropertyWriter(this, newName); } /** * Method called to set, reset or clear the configured type serializer for * property. * * @since 2.6 */ public void assignTypeSerializer(TypeSerializer typeSer) { _typeSerializer = typeSer; } /** * Method called to assign value serializer for property */ public void assignSerializer(JsonSerializer ser) { // may need to disable check in future? if ((_serializer != null) && (_serializer != ser)) { throw new IllegalStateException(String.format( "Cannot override _serializer: had a %s, trying to set to %s", ClassUtil.classNameOf(_serializer), ClassUtil.classNameOf(ser))); } _serializer = ser; } /** * Method called to assign null value serializer for property */ public void assignNullSerializer(JsonSerializer nullSer) { // may need to disable check in future? if ((_nullSerializer != null) && (_nullSerializer != nullSer)) { throw new IllegalStateException(String.format( "Cannot override _nullSerializer: had a %s, trying to set to %s", ClassUtil.classNameOf(_nullSerializer), ClassUtil.classNameOf(nullSer))); } _nullSerializer = nullSer; } /** * Method called create an instance that handles details of unwrapping * contained value. */ public BeanPropertyWriter unwrappingWriter(NameTransformer unwrapper) { return new UnwrappingBeanPropertyWriter(this, unwrapper); } /** * Method called to define type to consider as "non-trivial" basetype, * needed for dynamic serialization resolution for complex (usually * container) types */ public void setNonTrivialBaseType(JavaType t) { _nonTrivialBaseType = t; } /** * Method called to ensure that the mutator has proper access rights to * be called, as per configuration. Overridden by implementations that * have mutators that require access, fields and setters. * * @since 2.8.3 */ public void fixAccess(SerializationConfig config) { _member.fixAccess(config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } /* /*********************************************************** /* JDK Serializability /*********************************************************** */ /* * Ideally would not require mutable state, and instead would re-create with * final settings. However, as things are, with sub-types and all, simplest * to just change Field/Method value directly. */ Object readResolve() { if (_member instanceof AnnotatedField) { _accessorMethod = null; _field = (Field) _member.getMember(); } else if (_member instanceof AnnotatedMethod) { _accessorMethod = (Method) _member.getMember(); _field = null; } if (_serializer == null) { _dynamicSerializers = PropertySerializerMap.emptyForProperties(); } return this; } /* /************************************************************ /* BeanProperty impl /*********************************************************** */ // Note: also part of 'PropertyWriter' @Override public String getName() { return _name.getValue(); } // Note: also part of 'PropertyWriter' @Override public PropertyName getFullName() { // !!! TODO: impl properly return new PropertyName(_name.getValue()); } @Override public JavaType getType() { return _declaredType; } @Override public PropertyName getWrapperName() { return _wrapperName; } // Note: also part of 'PropertyWriter' @Override public A getAnnotation(Class acls) { return (_member == null) ? null : _member.getAnnotation(acls); } // Note: also part of 'PropertyWriter' @Override public A getContextAnnotation(Class acls) { return (_contextAnnotations == null) ? null : _contextAnnotations .get(acls); } @Override public AnnotatedMember getMember() { return _member; } // @since 2.3 -- needed so it can be overridden by unwrapping writer protected void _depositSchemaProperty(ObjectNode propertiesNode, JsonNode schemaNode) { propertiesNode.set(getName(), schemaNode); } /* /*********************************************************** /* Managing and accessing of opaque internal settings /* (used by extensions) /*********************************************************** */ /** * Method for accessing value of specified internal setting. * * @return Value of the setting, if any; null if none. */ public Object getInternalSetting(Object key) { return (_internalSettings == null) ? null : _internalSettings.get(key); } /** * Method for setting specific internal setting to given value * * @return Old value of the setting, if any (null if none) */ public Object setInternalSetting(Object key, Object value) { if (_internalSettings == null) { _internalSettings = new HashMap(); } return _internalSettings.put(key, value); } /** * Method for removing entry for specified internal setting. * * @return Existing value of the setting, if any (null if none) */ public Object removeInternalSetting(Object key) { Object removed = null; if (_internalSettings != null) { removed = _internalSettings.remove(key); // to reduce memory usage, let's also drop the Map itself, if empty if (_internalSettings.size() == 0) { _internalSettings = null; } } return removed; } /* /*********************************************************** /* Accessors /*********************************************************** */ public SerializableString getSerializedName() { return _name; } public boolean hasSerializer() { return _serializer != null; } public boolean hasNullSerializer() { return _nullSerializer != null; } /** * @since 2.6 */ public TypeSerializer getTypeSerializer() { return _typeSerializer; } /** * Accessor that will return true if this bean property has to support * "unwrapping"; ability to replace POJO structural wrapping with optional * name prefix and/or suffix (or in some cases, just removal of wrapper * name). *

* Default implementation simply returns false. * * @since 2.3 */ public boolean isUnwrapping() { return false; } public boolean willSuppressNulls() { return _suppressNulls; } /** * Method called to check to see if this property has a name that would * conflict with a given name. * * @since 2.6 */ public boolean wouldConflictWithName(PropertyName name) { if (_wrapperName != null) { return _wrapperName.equals(name); } // Bit convoluted since our support for namespaces is spotty but: return name.hasSimpleName(_name.getValue()) && !name.hasNamespace(); } // Needed by BeanSerializer#getSchema public JsonSerializer getSerializer() { return _serializer; } public JavaType getSerializationType() { return _cfgSerializationType; } @Deprecated // since 2.9 public Class getRawSerializationType() { return (_cfgSerializationType == null) ? null : _cfgSerializationType .getRawClass(); } /** * @deprecated Since 2.7, to be removed from 2.9, use {@link #getType()} instead. */ @Deprecated public Class getPropertyType() { if (_accessorMethod != null) { return _accessorMethod.getReturnType(); } if (_field != null) { return _field.getType(); } return null; } /** * Get the generic property type of this property writer. * * @return The property type, or null if not found. * * @deprecated Since 2.7, to be removed from 2.9, use {@link #getType()} instead. */ @Deprecated public Type getGenericPropertyType() { if (_accessorMethod != null) { return _accessorMethod.getGenericReturnType(); } if (_field != null) { return _field.getGenericType(); } return null; } public Class[] getViews() { return _includeInViews; } /* /*********************************************************** /* PropertyWriter methods (serialization) /*********************************************************** */ /** * Method called to access property that this bean stands for, from within * given bean, and to serialize it as a JSON Object field using appropriate * serializer. */ @Override public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { // inlined 'get()' final Object value = (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean, (Object[]) null); // Null handling is bit different, check that first if (value == null) { if (_nullSerializer != null) { gen.writeFieldName(_name); _nullSerializer.serialize(null, gen, prov); } return; } // then find serializer to use JsonSerializer ser = _serializer; if (ser == null) { Class cls = value.getClass(); PropertySerializerMap m = _dynamicSerializers; ser = m.serializerFor(cls); if (ser == null) { ser = _findAndAddDynamic(m, cls, prov); } } // and then see if we must suppress certain values (default, empty) if (_suppressableValue != null) { if (MARKER_FOR_EMPTY == _suppressableValue) { if (ser.isEmpty(prov, value)) { return; } } else if (_suppressableValue.equals(value)) { return; } } // For non-nulls: simple check for direct cycles if (value == bean) { // three choices: exception; handled by call; or pass-through if (_handleSelfReference(bean, gen, prov, ser)) { return; } } gen.writeFieldName(_name); if (_typeSerializer == null) { ser.serialize(value, gen, prov); } else { ser.serializeWithType(value, gen, prov, _typeSerializer); } } /** * Method called to indicate that serialization of a field was omitted due * to filtering, in cases where backend data format does not allow basic * omission. * * @since 2.3 */ @Override public void serializeAsOmittedField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { if (!gen.canOmitFields()) { gen.writeOmittedField(_name.getValue()); } } /** * Alternative to {@link #serializeAsField} that is used when a POJO is * serialized as JSON Array; the difference is that no field names are * written. * * @since 2.3 */ @Override public void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { // inlined 'get()' final Object value = (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean, (Object[]) null); if (value == null) { // nulls need specialized handling if (_nullSerializer != null) { _nullSerializer.serialize(null, gen, prov); } else { // can NOT suppress entries in tabular output gen.writeNull(); } return; } // otherwise find serializer to use JsonSerializer ser = _serializer; if (ser == null) { Class cls = value.getClass(); PropertySerializerMap map = _dynamicSerializers; ser = map.serializerFor(cls); if (ser == null) { ser = _findAndAddDynamic(map, cls, prov); } } // and then see if we must suppress certain values (default, empty) if (_suppressableValue != null) { if (MARKER_FOR_EMPTY == _suppressableValue) { if (ser.isEmpty(prov, value)) { // can NOT suppress entries in // tabular output serializeAsPlaceholder(bean, gen, prov); return; } } else if (_suppressableValue.equals(value)) { // can NOT suppress // entries in tabular // output serializeAsPlaceholder(bean, gen, prov); return; } } // For non-nulls: simple check for direct cycles if (value == bean) { if (_handleSelfReference(bean, gen, prov, ser)) { return; } } if (_typeSerializer == null) { ser.serialize(value, gen, prov); } else { ser.serializeWithType(value, gen, prov, _typeSerializer); } } /** * Method called to serialize a placeholder used in tabular output when real * value is not to be included (is filtered out), but when we need an entry * so that field indexes will not be off. Typically this should output null * or empty String, depending on datatype. * * @since 2.1 */ @Override public void serializeAsPlaceholder(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { if (_nullSerializer != null) { _nullSerializer.serialize(null, gen, prov); } else { gen.writeNull(); } } /* /*********************************************************** /* PropertyWriter methods (schema generation) /*********************************************************** */ // Also part of BeanProperty implementation @Override public void depositSchemaProperty(JsonObjectFormatVisitor v, SerializerProvider provider) throws JsonMappingException { if (v != null) { if (isRequired()) { v.property(this); } else { v.optionalProperty(this); } } } // // // Legacy support for JsonFormatVisitable /** * Attempt to add the output of the given {@link BeanPropertyWriter} in the * given {@link ObjectNode}. Otherwise, add the default schema * {@link JsonNode} in place of the writer's output * * @param propertiesNode * Node which the given property would exist within * @param provider * Provider that can be used for accessing dynamic aspects of * serialization processing */ @Override @Deprecated public void depositSchemaProperty(ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException { JavaType propType = getSerializationType(); // 03-Dec-2010, tatu: SchemaAware REALLY should use JavaType, but alas // it doesn't... Type hint = (propType == null) ? getType() : propType.getRawClass(); JsonNode schemaNode; // Maybe it already has annotated/statically configured serializer? JsonSerializer ser = getSerializer(); if (ser == null) { // nope ser = provider.findValueSerializer(getType(), this); } boolean isOptional = !isRequired(); if (ser instanceof SchemaAware) { schemaNode = ((SchemaAware) ser).getSchema(provider, hint, isOptional); } else { schemaNode = com.fasterxml.jackson.databind.jsonschema.JsonSchema .getDefaultSchemaNode(); } _depositSchemaProperty(propertiesNode, schemaNode); } /* /********************************************************** /* Helper methods /********************************************************** */ protected JsonSerializer _findAndAddDynamic( PropertySerializerMap map, Class type, SerializerProvider provider) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result; if (_nonTrivialBaseType != null) { JavaType t = provider.constructSpecializedType(_nonTrivialBaseType, type); result = map.findAndAddPrimarySerializer(t, provider, this); } else { result = map.findAndAddPrimarySerializer(type, provider, this); } // did we get a new map of serializers? If so, start using it if (map != result.map) { _dynamicSerializers = result.map; } return result.serializer; } /** * Method that can be used to access value of the property this Object * describes, from given bean instance. *

* Note: method is final as it should not need to be overridden -- rather, * calling method(s) ({@link #serializeAsField}) should be overridden to * change the behavior */ public final Object get(Object bean) throws Exception { return (_accessorMethod == null) ? _field.get(bean) : _accessorMethod .invoke(bean, (Object[]) null); } /** * Method called to handle a direct self-reference through this property. * Method can choose to indicate an error by throwing * {@link JsonMappingException}; fully handle serialization (and return * true); or indicate that it should be serialized normally (return false). *

* Default implementation will throw {@link JsonMappingException} if * {@link SerializationFeature#FAIL_ON_SELF_REFERENCES} is enabled; or * return false if it is disabled. * * @return True if method fully handled self-referential value; false if not * (caller is to handle it) or {@link JsonMappingException} if there * is no way handle it */ protected boolean _handleSelfReference(Object bean, JsonGenerator gen, SerializerProvider prov, JsonSerializer ser) throws JsonMappingException { if (prov.isEnabled(SerializationFeature.FAIL_ON_SELF_REFERENCES) && !ser.usesObjectId()) { // 05-Feb-2013, tatu: Usually a problem, but NOT if we are handling // object id; this may be the case for BeanSerializers at least. // 13-Feb-2014, tatu: another possible ok case: custom serializer // (something // OTHER than {@link BeanSerializerBase} if (ser instanceof BeanSerializerBase) { prov.reportBadDefinition(getType(), "Direct self-reference leading to cycle"); } } return false; } @Override public String toString() { StringBuilder sb = new StringBuilder(40); sb.append("property '").append(getName()).append("' ("); if (_accessorMethod != null) { sb.append("via method ") .append(_accessorMethod.getDeclaringClass().getName()) .append("#").append(_accessorMethod.getName()); } else if (_field != null) { sb.append("field \"").append(_field.getDeclaringClass().getName()) .append("#").append(_field.getName()); } else { sb.append("virtual"); } if (_serializer == null) { sb.append(", no static serializer"); } else { sb.append(", static serializer of type " + _serializer.getClass().getName()); } sb.append(')'); return sb.toString(); } } BeanSerializer.java000066400000000000000000000127041325620701100350070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.Set; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.impl.BeanAsArraySerializer; import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter; import com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer; import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Serializer class that can serialize Java objects that map * to JSON Object output. Internally handling is mostly dealt with * by a sequence of {@link BeanPropertyWriter}s that will handle * access value to serialize and call appropriate serializers to * write out JSON. *

* Implementation note: we will post-process resulting serializer, * to figure out actual serializers for final types. This must be * done from {@link #resolve} method, and NOT from constructor; * otherwise we could end up with an infinite loop. */ public class BeanSerializer extends BeanSerializerBase { private static final long serialVersionUID = 29; // as per jackson 2.9 /* /********************************************************** /* Life-cycle: constructors /********************************************************** */ /** * @param builder Builder object that contains collected information * that may be needed for serializer * @param properties Property writers used for actual serialization */ public BeanSerializer(JavaType type, BeanSerializerBuilder builder, BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties) { super(type, builder, properties, filteredProperties); } /** * Alternate copy constructor that can be used to construct * standard {@link BeanSerializer} passing an instance of * "compatible enough" source serializer. */ protected BeanSerializer(BeanSerializerBase src) { super(src); } protected BeanSerializer(BeanSerializerBase src, ObjectIdWriter objectIdWriter) { super(src, objectIdWriter); } protected BeanSerializer(BeanSerializerBase src, ObjectIdWriter objectIdWriter, Object filterId) { super(src, objectIdWriter, filterId); } protected BeanSerializer(BeanSerializerBase src, Set toIgnore) { super(src, toIgnore); } /* /********************************************************** /* Life-cycle: factory methods, fluent factories /********************************************************** */ /** * Method for constructing dummy bean serializer; one that * never outputs any properties */ public static BeanSerializer createDummy(JavaType forType) { return new BeanSerializer(forType, null, NO_PROPS, null); } @Override public JsonSerializer unwrappingSerializer(NameTransformer unwrapper) { return new UnwrappingBeanSerializer(this, unwrapper); } @Override public BeanSerializerBase withObjectIdWriter(ObjectIdWriter objectIdWriter) { return new BeanSerializer(this, objectIdWriter, _propertyFilterId); } @Override public BeanSerializerBase withFilterId(Object filterId) { return new BeanSerializer(this, _objectIdWriter, filterId); } @Override protected BeanSerializerBase withIgnorals(Set toIgnore) { return new BeanSerializer(this, toIgnore); } /** * Implementation has to check whether as-array serialization * is possible reliably; if (and only if) so, will construct * a {@link BeanAsArraySerializer}, otherwise will return this * serializer as is. */ @Override protected BeanSerializerBase asArraySerializer() { /* Cannot: * * - have Object Id (may be allowed in future) * - have "any getter" * - have per-property filters */ if ((_objectIdWriter == null) && (_anyGetterWriter == null) && (_propertyFilterId == null) ) { return new BeanAsArraySerializer(this); } // already is one, so: return this; } /* /********************************************************** /* JsonSerializer implementation that differs between impls /********************************************************** */ /** * Main serialization method that will delegate actual output to * configured * {@link BeanPropertyWriter} instances. */ @Override public final void serialize(Object bean, JsonGenerator gen, SerializerProvider provider) throws IOException { if (_objectIdWriter != null) { gen.setCurrentValue(bean); // [databind#631] _serializeWithObjectId(bean, gen, provider, true); return; } gen.writeStartObject(bean); if (_propertyFilterId != null) { serializeFieldsFiltered(bean, gen, provider); } else { serializeFields(bean, gen, provider); } gen.writeEndObject(); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return "BeanSerializer for "+handledType().getName(); } } BeanSerializerBuilder.java000066400000000000000000000172331325620701100363200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter; /** * Builder class used for aggregating deserialization information about * a POJO, in order to build a {@link JsonSerializer} for serializing * intances. * Main reason for using separate builder class is that this makes it easier * to make actual serializer class fully immutable. */ public class BeanSerializerBuilder { private final static BeanPropertyWriter[] NO_PROPERTIES = new BeanPropertyWriter[0]; /* /********************************************************** /* Basic configuration we start with /********************************************************** */ final protected BeanDescription _beanDesc; protected SerializationConfig _config; /* /********************************************************** /* Accumulated information about properties /********************************************************** */ /** * Bean properties, in order of serialization */ protected List _properties = Collections.emptyList(); /** * Optional array of filtered property writers; if null, no * view-based filtering is performed. */ protected BeanPropertyWriter[] _filteredProperties; /** * Writer used for "any getter" properties, if any. */ protected AnyGetterWriter _anyGetter; /** * Id of the property filter to use for POJO, if any. */ protected Object _filterId; /** * Property that is used for type id (and not serialized as regular * property) */ protected AnnotatedMember _typeId; /** * Object responsible for serializing Object Ids for the handled * type, if any. */ protected ObjectIdWriter _objectIdWriter; /* /********************************************************** /* Construction and setter methods /********************************************************** */ public BeanSerializerBuilder(BeanDescription beanDesc) { _beanDesc = beanDesc; } /** * Copy-constructor that may be used for sub-classing */ protected BeanSerializerBuilder(BeanSerializerBuilder src) { _beanDesc = src._beanDesc; _properties = src._properties; _filteredProperties = src._filteredProperties; _anyGetter = src._anyGetter; _filterId = src._filterId; } /** * Initialization method called right after construction, to specify * configuration to use. *

* Note: ideally should be passed in constructor, but for backwards * compatibility, needed to add a setter instead * * @since 2.1 */ protected void setConfig(SerializationConfig config) { _config = config; } public void setProperties(List properties) { _properties = properties; } /** * @param properties Number and order of properties here MUST match that * of "regular" properties set earlier using {@link #setProperties(List)}; if not, * an {@link IllegalArgumentException} will be thrown */ public void setFilteredProperties(BeanPropertyWriter[] properties) { if (properties != null) { if (properties.length != _properties.size()) { // as per [databind#1612] throw new IllegalArgumentException(String.format( "Trying to set %d filtered properties; must match length of non-filtered `properties` (%d)", properties.length, _properties.size())); } } _filteredProperties = properties; } public void setAnyGetter(AnyGetterWriter anyGetter) { _anyGetter = anyGetter; } public void setFilterId(Object filterId) { _filterId = filterId; } public void setTypeId(AnnotatedMember idProp) { // Not legal to use multiple ones... if (_typeId != null) { throw new IllegalArgumentException("Multiple type ids specified with "+_typeId+" and "+idProp); } _typeId = idProp; } public void setObjectIdWriter(ObjectIdWriter w) { _objectIdWriter = w; } /* /********************************************************** /* Accessors for things BeanSerializer cares about: /* note -- likely to change between minor revisions /* by new methods getting added. /********************************************************** */ public AnnotatedClass getClassInfo() { return _beanDesc.getClassInfo(); } public BeanDescription getBeanDescription() { return _beanDesc; } public List getProperties() { return _properties; } public boolean hasProperties() { return (_properties != null) && (_properties.size() > 0); } public BeanPropertyWriter[] getFilteredProperties() { return _filteredProperties; } public AnyGetterWriter getAnyGetter() { return _anyGetter; } public Object getFilterId() { return _filterId; } public AnnotatedMember getTypeId() { return _typeId; } public ObjectIdWriter getObjectIdWriter() { return _objectIdWriter; } /* /********************************************************** /* Build methods for actually creating serializer instance /********************************************************** */ /** * Method called to create {@link BeanSerializer} instance with * all accumulated information. Will construct a serializer if we * have enough information, or return null if not. */ public JsonSerializer build() { BeanPropertyWriter[] properties; // No properties, any getter or object id writer? // No real serializer; caller gets to handle if (_properties == null || _properties.isEmpty()) { if (_anyGetter == null && _objectIdWriter == null) { return null; } properties = NO_PROPERTIES; } else { properties = _properties.toArray(new BeanPropertyWriter[_properties.size()]); if (_config.isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { for (int i = 0, end = properties.length; i < end; ++i) { properties[i].fixAccess(_config); } } } // 27-Apr-2017, tatu: Verify that filtered-properties settings are compatible if (_filteredProperties != null) { if (_filteredProperties.length != _properties.size()) { throw new IllegalStateException(String.format( "Mismatch between `properties` size (%d), `filteredProperties` (%s): should have as many (or `null` for latter)", _properties.size(), _filteredProperties.length)); } } if (_anyGetter != null) { _anyGetter.fixAccess(_config); } if (_typeId != null) { if (_config.isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { _typeId.fixAccess(_config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } } return new BeanSerializer(_beanDesc.getType(), this, properties, _filteredProperties); } /** * Factory method for constructing an "empty" serializer; one that * outputs no properties (but handles JSON objects properly, including * type information) */ public BeanSerializer createDummy() { return BeanSerializer.createDummy(_beanDesc.getType()); } } BeanSerializerFactory.java000066400000000000000000001061421325620701100363370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.impl.FilteredBeanPropertyWriter; import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter; import com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator; import com.fasterxml.jackson.databind.ser.std.MapSerializer; import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer; import com.fasterxml.jackson.databind.type.ReferenceType; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.Converter; /** * Factory class that can provide serializers for any regular Java beans * (as defined by "having at least one get method recognizable as bean * accessor" -- where {@link Object#getClass} does not count); * as well as for "standard" JDK types. Latter is achieved * by delegating calls to {@link BasicSerializerFactory} * to find serializers both for "standard" JDK types (and in some cases, * sub-classes as is the case for collection classes like * {@link java.util.List}s and {@link java.util.Map}s) and bean (value) * classes. *

* Note about delegating calls to {@link BasicSerializerFactory}: * although it would be nicer to use linear delegation * for construction (to essentially dispatch all calls first to the * underlying {@link BasicSerializerFactory}; or alternatively after * failing to provide bean-based serializer}, there is a problem: * priority levels for detecting standard types are mixed. That is, * we want to check if a type is a bean after some of "standard" JDK * types, but before the rest. * As a result, "mixed" delegation used, and calls are NOT done using * regular {@link SerializerFactory} interface but rather via * direct calls to {@link BasicSerializerFactory}. *

* Finally, since all caching is handled by the serializer provider * (not factory) and there is no configurability, this * factory is stateless. * This means that a global singleton instance can be used. */ public class BeanSerializerFactory extends BasicSerializerFactory implements java.io.Serializable // since 2.1 { private static final long serialVersionUID = 1; /** * Like {@link BasicSerializerFactory}, this factory is stateless, and * thus a single shared global (== singleton) instance can be used * without thread-safety issues. */ public final static BeanSerializerFactory instance = new BeanSerializerFactory(null); /* /********************************************************** /* Life-cycle: creation, configuration /********************************************************** */ /** * Constructor for creating instances with specified configuration. */ protected BeanSerializerFactory(SerializerFactoryConfig config) { super(config); } /** * Method used by module registration functionality, to attach additional * serializer providers into this serializer factory. This is typically * handled by constructing a new instance with additional serializers, * to ensure thread-safe access. */ @Override public SerializerFactory withConfig(SerializerFactoryConfig config) { if (_factoryConfig == config) { return this; } /* 22-Nov-2010, tatu: Handling of subtypes is tricky if we do immutable-with-copy-ctor; * and we pretty much have to here either choose between losing subtype instance * when registering additional serializers, or losing serializers. * Instead, let's actually just throw an error if this method is called when subtype * has not properly overridden this method; this to indicate problem as soon as possible. */ if (getClass() != BeanSerializerFactory.class) { throw new IllegalStateException("Subtype of BeanSerializerFactory ("+getClass().getName() +") has not properly overridden method 'withAdditionalSerializers': cannot instantiate subtype with " +"additional serializer definitions"); } return new BeanSerializerFactory(config); } @Override protected Iterable customSerializers() { return _factoryConfig.serializers(); } /* /********************************************************** /* SerializerFactory impl /********************************************************** */ /** * Main serializer constructor method. We will have to be careful * with respect to ordering of various method calls: essentially * we want to reliably figure out which classes are standard types, * and which are beans. The problem is that some bean Classes may * implement standard interfaces (say, {@link java.lang.Iterable}. *

* Note: sub-classes may choose to complete replace implementation, * if they want to alter priority of serializer lookups. */ @Override @SuppressWarnings("unchecked") public JsonSerializer createSerializer(SerializerProvider prov, JavaType origType) throws JsonMappingException { // Very first thing, let's check if there is explicit serializer annotation: final SerializationConfig config = prov.getConfig(); BeanDescription beanDesc = config.introspect(origType); JsonSerializer ser = findSerializerFromAnnotation(prov, beanDesc.getClassInfo()); if (ser != null) { return (JsonSerializer) ser; } boolean staticTyping; // Next: we may have annotations that further indicate actual type to use (a super type) final AnnotationIntrospector intr = config.getAnnotationIntrospector(); JavaType type; if (intr == null) { type = origType; } else { try { type = intr.refineSerializationType(config, beanDesc.getClassInfo(), origType); } catch (JsonMappingException e) { return prov.reportBadTypeDefinition(beanDesc, e.getMessage()); } } if (type == origType) { // no changes, won't force static typing staticTyping = false; } else { // changes; assume static typing; plus, need to re-introspect if class differs staticTyping = true; if (!type.hasRawClass(origType.getRawClass())) { beanDesc = config.introspect(type); } } // Slight detour: do we have a Converter to consider? Converter conv = beanDesc.findSerializationConverter(); if (conv == null) { // no, simple return (JsonSerializer) _createSerializer2(prov, type, beanDesc, staticTyping); } JavaType delegateType = conv.getOutputType(prov.getTypeFactory()); // One more twist, as per [databind#288]; probably need to get new BeanDesc if (!delegateType.hasRawClass(type.getRawClass())) { beanDesc = config.introspect(delegateType); // [#359]: explicitly check (again) for @JsonSerializer... ser = findSerializerFromAnnotation(prov, beanDesc.getClassInfo()); } // [databind#731]: Should skip if nominally java.lang.Object if (ser == null && !delegateType.isJavaLangObject()) { ser = _createSerializer2(prov, delegateType, beanDesc, true); } return new StdDelegatingSerializer(conv, delegateType, ser); } protected JsonSerializer _createSerializer2(SerializerProvider prov, JavaType type, BeanDescription beanDesc, boolean staticTyping) throws JsonMappingException { JsonSerializer ser = null; final SerializationConfig config = prov.getConfig(); // Container types differ from non-container types // (note: called method checks for module-provided serializers) if (type.isContainerType()) { if (!staticTyping) { staticTyping = usesStaticTyping(config, beanDesc, null); } // 03-Aug-2012, tatu: As per [databind#40], may require POJO serializer... ser = buildContainerSerializer(prov, type, beanDesc, staticTyping); // Will return right away, since called method does post-processing: if (ser != null) { return ser; } } else { if (type.isReferenceType()) { ser = findReferenceSerializer(prov, (ReferenceType) type, beanDesc, staticTyping); } else { // Modules may provide serializers of POJO types: for (Serializers serializers : customSerializers()) { ser = serializers.findSerializer(config, type, beanDesc); if (ser != null) { break; } } } // 25-Jun-2015, tatu: Then JsonSerializable, @JsonValue etc. NOTE! Prior to 2.6, // this call was BEFORE custom serializer lookup, which was wrong. if (ser == null) { ser = findSerializerByAnnotations(prov, type, beanDesc); } } if (ser == null) { // Otherwise, we will check "primary types"; both marker types that // indicate specific handling (JsonSerializable), or main types that have // precedence over container types ser = findSerializerByLookup(type, config, beanDesc, staticTyping); if (ser == null) { ser = findSerializerByPrimaryType(prov, type, beanDesc, staticTyping); if (ser == null) { // And this is where this class comes in: if type is not a // known "primary JDK type", perhaps it's a bean? We can still // get a null, if we can't find a single suitable bean property. ser = findBeanSerializer(prov, type, beanDesc); // Finally: maybe we can still deal with it as an implementation of some basic JDK interface? if (ser == null) { ser = findSerializerByAddonType(config, type, beanDesc, staticTyping); // 18-Sep-2014, tatu: Actually, as per [jackson-databind#539], need to get // 'unknown' serializer assigned earlier, here, so that it gets properly // post-processed if (ser == null) { ser = prov.getUnknownTypeSerializer(beanDesc.getBeanClass()); } } } } } if (ser != null) { // [databind#120]: Allow post-processing if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { ser = mod.modifySerializer(config, beanDesc, ser); } } } return ser; } /* /********************************************************** /* Other public methods that are not part of /* JsonSerializerFactory API /********************************************************** */ /** * Method that will try to construct a {@link BeanSerializer} for * given class. Returns null if no properties are found. */ public JsonSerializer findBeanSerializer(SerializerProvider prov, JavaType type, BeanDescription beanDesc) throws JsonMappingException { // First things first: we know some types are not beans... if (!isPotentialBeanType(type.getRawClass())) { // 03-Aug-2012, tatu: Except we do need to allow serializers for Enums, // as per [databind#24] if (!type.isEnumType()) { return null; } } return constructBeanSerializer(prov, beanDesc); } /** * Method called to create a type information serializer for values of given * non-container property * if one is needed. If not needed (no polymorphic handling configured), should * return null. * * @param baseType Declared type to use as the base type for type information serializer * * @return Type serializer to use for property values, if one is needed; null if not. */ public TypeSerializer findPropertyTypeSerializer(JavaType baseType, SerializationConfig config, AnnotatedMember accessor) throws JsonMappingException { AnnotationIntrospector ai = config.getAnnotationIntrospector(); TypeResolverBuilder b = ai.findPropertyTypeResolver(config, accessor, baseType); TypeSerializer typeSer; // Defaulting: if no annotations on member, check value class if (b == null) { typeSer = createTypeSerializer(config, baseType); } else { Collection subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByClass( config, accessor, baseType); typeSer = b.buildTypeSerializer(config, baseType, subtypes); } return typeSer; } /** * Method called to create a type information serializer for values of given * container property * if one is needed. If not needed (no polymorphic handling configured), should * return null. * * @param containerType Declared type of the container to use as the base type for type information serializer * * @return Type serializer to use for property value contents, if one is needed; null if not. */ public TypeSerializer findPropertyContentTypeSerializer(JavaType containerType, SerializationConfig config, AnnotatedMember accessor) throws JsonMappingException { JavaType contentType = containerType.getContentType(); AnnotationIntrospector ai = config.getAnnotationIntrospector(); TypeResolverBuilder b = ai.findPropertyContentTypeResolver(config, accessor, containerType); TypeSerializer typeSer; // Defaulting: if no annotations on member, check value class if (b == null) { typeSer = createTypeSerializer(config, contentType); } else { Collection subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByClass(config, accessor, contentType); typeSer = b.buildTypeSerializer(config, contentType, subtypes); } return typeSer; } /* /********************************************************** /* Overridable non-public factory methods /********************************************************** */ /** * Method called to construct serializer for serializing specified bean type. * * @since 2.1 */ @SuppressWarnings("unchecked") protected JsonSerializer constructBeanSerializer(SerializerProvider prov, BeanDescription beanDesc) throws JsonMappingException { // 13-Oct-2010, tatu: quick sanity check: never try to create bean serializer for plain Object // 05-Jul-2012, tatu: ... but we should be able to just return "unknown type" serializer, right? if (beanDesc.getBeanClass() == Object.class) { return prov.getUnknownTypeSerializer(Object.class); // throw new IllegalArgumentException("Cannot create bean serializer for Object.class"); } final SerializationConfig config = prov.getConfig(); BeanSerializerBuilder builder = constructBeanSerializerBuilder(beanDesc); builder.setConfig(config); // First: any detectable (auto-detect, annotations) properties to serialize? List props = findBeanProperties(prov, beanDesc, builder); if (props == null) { props = new ArrayList(); } else { props = removeOverlappingTypeIds(prov, beanDesc, builder, props); } // [databind#638]: Allow injection of "virtual" properties: prov.getAnnotationIntrospector().findAndAddVirtualProperties(config, beanDesc.getClassInfo(), props); // [JACKSON-440] Need to allow modification bean properties to serialize: if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { props = mod.changeProperties(config, beanDesc, props); } } // Any properties to suppress? props = filterBeanProperties(config, beanDesc, props); // Need to allow reordering of properties to serialize if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { props = mod.orderProperties(config, beanDesc, props); } } // And if Object Id is needed, some preparation for that as well: better // do before view handling, mostly for the custom id case which needs // access to a property builder.setObjectIdWriter(constructObjectIdHandler(prov, beanDesc, props)); builder.setProperties(props); builder.setFilterId(findFilterId(config, beanDesc)); AnnotatedMember anyGetter = beanDesc.findAnyGetter(); if (anyGetter != null) { JavaType type = anyGetter.getType(); // copied from BasicSerializerFactory.buildMapSerializer(): boolean staticTyping = config.isEnabled(MapperFeature.USE_STATIC_TYPING); JavaType valueType = type.getContentType(); TypeSerializer typeSer = createTypeSerializer(config, valueType); // last 2 nulls; don't know key, value serializers (yet) // 23-Feb-2015, tatu: As per [databind#705], need to support custom serializers JsonSerializer anySer = findSerializerFromAnnotation(prov, anyGetter); if (anySer == null) { // TODO: support '@JsonIgnoreProperties' with any setter? anySer = MapSerializer.construct(/* ignored props*/ (Set) null, type, staticTyping, typeSer, null, null, /*filterId*/ null); } // TODO: can we find full PropertyName? PropertyName name = PropertyName.construct(anyGetter.getName()); BeanProperty.Std anyProp = new BeanProperty.Std(name, valueType, null, anyGetter, PropertyMetadata.STD_OPTIONAL); builder.setAnyGetter(new AnyGetterWriter(anyProp, anyGetter, anySer)); } // Next: need to gather view information, if any: processViews(config, builder); // Finally: let interested parties mess with the result bit more... if (_factoryConfig.hasSerializerModifiers()) { for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { builder = mod.updateBuilder(config, beanDesc, builder); } } JsonSerializer ser = null; try { ser = (JsonSerializer) builder.build(); } catch (RuntimeException e) { prov.reportBadTypeDefinition(beanDesc, "Failed to construct BeanSerializer for %s: (%s) %s", beanDesc.getType(), e.getClass().getName(), e.getMessage()); } if (ser == null) { // If we get this far, there were no properties found, so no regular BeanSerializer // would be constructed. But, couple of exceptions. // First: if there are known annotations, just create 'empty bean' serializer if (beanDesc.hasKnownClassAnnotations()) { return builder.createDummy(); } } return ser; } protected ObjectIdWriter constructObjectIdHandler(SerializerProvider prov, BeanDescription beanDesc, List props) throws JsonMappingException { ObjectIdInfo objectIdInfo = beanDesc.getObjectIdInfo(); if (objectIdInfo == null) { return null; } ObjectIdGenerator gen; Class implClass = objectIdInfo.getGeneratorType(); // Just one special case: Property-based generator is trickier if (implClass == ObjectIdGenerators.PropertyGenerator.class) { // most special one, needs extra work String propName = objectIdInfo.getPropertyName().getSimpleName(); BeanPropertyWriter idProp = null; for (int i = 0, len = props.size() ;; ++i) { if (i == len) { throw new IllegalArgumentException("Invalid Object Id definition for "+beanDesc.getBeanClass().getName() +": cannot find property with name '"+propName+"'"); } BeanPropertyWriter prop = props.get(i); if (propName.equals(prop.getName())) { idProp = prop; // Let's force it to be the first property to output // (although it may still get rearranged etc) if (i > 0) { props.remove(i); props.add(0, idProp); } break; } } JavaType idType = idProp.getType(); gen = new PropertyBasedObjectIdGenerator(objectIdInfo, idProp); // one more thing: must ensure that ObjectIdWriter does not actually write the value: return ObjectIdWriter.construct(idType, (PropertyName) null, gen, objectIdInfo.getAlwaysAsId()); } // other types are simpler JavaType type = prov.constructType(implClass); // Could require type to be passed explicitly, but we should be able to find it too: JavaType idType = prov.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0]; gen = prov.objectIdGeneratorInstance(beanDesc.getClassInfo(), objectIdInfo); return ObjectIdWriter.construct(idType, objectIdInfo.getPropertyName(), gen, objectIdInfo.getAlwaysAsId()); } /** * Method called to construct a filtered writer, for given view * definitions. Default implementation constructs filter that checks * active view type to views property is to be included in. */ protected BeanPropertyWriter constructFilteredBeanWriter(BeanPropertyWriter writer, Class[] inViews) { return FilteredBeanPropertyWriter.constructViewBased(writer, inViews); } protected PropertyBuilder constructPropertyBuilder(SerializationConfig config, BeanDescription beanDesc) { return new PropertyBuilder(config, beanDesc); } protected BeanSerializerBuilder constructBeanSerializerBuilder(BeanDescription beanDesc) { return new BeanSerializerBuilder(beanDesc); } /* /********************************************************** /* Overridable non-public introspection methods /********************************************************** */ /** * Helper method used to skip processing for types that we know * cannot be (i.e. are never consider to be) beans: * things like primitives, Arrays, Enums, and proxy types. *

* Note that usually we shouldn't really be getting these sort of * types anyway; but better safe than sorry. */ protected boolean isPotentialBeanType(Class type) { return (ClassUtil.canBeABeanType(type) == null) && !ClassUtil.isProxyType(type); } /** * Method used to collect all actual serializable properties. * Can be overridden to implement custom detection schemes. */ protected List findBeanProperties(SerializerProvider prov, BeanDescription beanDesc, BeanSerializerBuilder builder) throws JsonMappingException { List properties = beanDesc.findProperties(); final SerializationConfig config = prov.getConfig(); // ignore specified types removeIgnorableTypes(config, beanDesc, properties); // and possibly remove ones without matching mutator... if (config.isEnabled(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS)) { removeSetterlessGetters(config, beanDesc, properties); } // nothing? can't proceed (caller may or may not throw an exception) if (properties.isEmpty()) { return null; } // null is for value type serializer, which we don't have access to from here (ditto for bean prop) boolean staticTyping = usesStaticTyping(config, beanDesc, null); PropertyBuilder pb = constructPropertyBuilder(config, beanDesc); ArrayList result = new ArrayList(properties.size()); for (BeanPropertyDefinition property : properties) { final AnnotatedMember accessor = property.getAccessor(); // Type id? Requires special handling: if (property.isTypeId()) { if (accessor != null) { builder.setTypeId(accessor); } continue; } // suppress writing of back references AnnotationIntrospector.ReferenceProperty refType = property.findReferenceType(); if (refType != null && refType.isBackReference()) { continue; } if (accessor instanceof AnnotatedMethod) { result.add(_constructWriter(prov, property, pb, staticTyping, (AnnotatedMethod) accessor)); } else { result.add(_constructWriter(prov, property, pb, staticTyping, (AnnotatedField) accessor)); } } return result; } /* /********************************************************** /* Overridable non-public methods for manipulating bean properties /********************************************************** */ /** * Overridable method that can filter out properties. Default implementation * checks annotations class may have. */ protected List filterBeanProperties(SerializationConfig config, BeanDescription beanDesc, List props) { // 01-May-2016, tatu: Which base type to use here gets tricky, since // it may often make most sense to use general type for overrides, // but what we have here may be more specific impl type. But for now // just use it as is. JsonIgnoreProperties.Value ignorals = config.getDefaultPropertyIgnorals(beanDesc.getBeanClass(), beanDesc.getClassInfo()); if (ignorals != null) { Set ignored = ignorals.findIgnoredForSerialization(); if (!ignored.isEmpty()) { Iterator it = props.iterator(); while (it.hasNext()) { if (ignored.contains(it.next().getName())) { it.remove(); } } } } return props; } /** * Method called to handle view information for constructed serializer, * based on bean property writers. *

* Note that this method is designed to be overridden by sub-classes * if they want to provide custom view handling. As such it is not * considered an internal implementation detail, and will be supported * as part of API going forward. */ protected void processViews(SerializationConfig config, BeanSerializerBuilder builder) { // whether non-annotated fields are included by default or not is configurable List props = builder.getProperties(); boolean includeByDefault = config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION); final int propCount = props.size(); int viewsFound = 0; BeanPropertyWriter[] filtered = new BeanPropertyWriter[propCount]; // Simple: view information is stored within individual writers, need to combine: for (int i = 0; i < propCount; ++i) { BeanPropertyWriter bpw = props.get(i); Class[] views = bpw.getViews(); if (views == null) { // no view info? include or exclude by default? if (includeByDefault) { filtered[i] = bpw; } } else { ++viewsFound; filtered[i] = constructFilteredBeanWriter(bpw, views); } } // minor optimization: if no view info, include-by-default, can leave out filtering info altogether: if (includeByDefault && viewsFound == 0) { return; } builder.setFilteredProperties(filtered); } /** * Method that will apply by-type limitations (as per [JACKSON-429]); * by default this is based on {@link com.fasterxml.jackson.annotation.JsonIgnoreType} * annotation but can be supplied by module-provided introspectors too. * Starting with 2.8 there are also "Config overrides" to consider. */ protected void removeIgnorableTypes(SerializationConfig config, BeanDescription beanDesc, List properties) { AnnotationIntrospector intr = config.getAnnotationIntrospector(); HashMap,Boolean> ignores = new HashMap,Boolean>(); Iterator it = properties.iterator(); while (it.hasNext()) { BeanPropertyDefinition property = it.next(); AnnotatedMember accessor = property.getAccessor(); /* 22-Oct-2016, tatu: Looks like this removal is an important part of * processing, as taking it out will result in a few test failures... * But should probably be done somewhere else, not here? */ if (accessor == null) { it.remove(); continue; } Class type = property.getRawPrimaryType(); Boolean result = ignores.get(type); if (result == null) { // 21-Apr-2016, tatu: For 2.8, can specify config overrides result = config.getConfigOverride(type).getIsIgnoredType(); if (result == null) { BeanDescription desc = config.introspectClassAnnotations(type); AnnotatedClass ac = desc.getClassInfo(); result = intr.isIgnorableType(ac); // default to false, non-ignorable if (result == null) { result = Boolean.FALSE; } } ignores.put(type, result); } // lotsa work, and yes, it is ignorable type, so: if (result.booleanValue()) { it.remove(); } } } /** * Helper method that will remove all properties that do not have a mutator. */ protected void removeSetterlessGetters(SerializationConfig config, BeanDescription beanDesc, List properties) { Iterator it = properties.iterator(); while (it.hasNext()) { BeanPropertyDefinition property = it.next(); // one caveat: only remove implicit properties; // explicitly annotated ones should remain if (!property.couldDeserialize() && !property.isExplicitlyIncluded()) { it.remove(); } } } /** * Helper method called to ensure that we do not have "duplicate" type ids. * Added to resolve [databind#222] * * @since 2.6 */ protected List removeOverlappingTypeIds(SerializerProvider prov, BeanDescription beanDesc, BeanSerializerBuilder builder, List props) { for (int i = 0, end = props.size(); i < end; ++i) { BeanPropertyWriter bpw = props.get(i); TypeSerializer td = bpw.getTypeSerializer(); if ((td == null) || (td.getTypeInclusion() != As.EXTERNAL_PROPERTY)) { continue; } String n = td.getPropertyName(); PropertyName typePropName = PropertyName.construct(n); for (BeanPropertyWriter w2 : props) { if ((w2 != bpw) && w2.wouldConflictWithName(typePropName)) { bpw.assignTypeSerializer(null); break; } } } return props; } /* /********************************************************** /* Internal helper methods /********************************************************** */ /** * Secondary helper method for constructing {@link BeanPropertyWriter} for * given member (field or method). */ protected BeanPropertyWriter _constructWriter(SerializerProvider prov, BeanPropertyDefinition propDef, PropertyBuilder pb, boolean staticTyping, AnnotatedMember accessor) throws JsonMappingException { final PropertyName name = propDef.getFullName(); JavaType type = accessor.getType(); BeanProperty.Std property = new BeanProperty.Std(name, type, propDef.getWrapperName(), accessor, propDef.getMetadata()); // Does member specify a serializer? If so, let's use it. JsonSerializer annotatedSerializer = findSerializerFromAnnotation(prov, accessor); // Unlike most other code paths, serializer produced // here will NOT be resolved or contextualized, unless done here, so: if (annotatedSerializer instanceof ResolvableSerializer) { ((ResolvableSerializer) annotatedSerializer).resolve(prov); } // 05-Sep-2013, tatu: should be primary property serializer so: annotatedSerializer = prov.handlePrimaryContextualization(annotatedSerializer, property); // And how about polymorphic typing? First special to cover JAXB per-field settings: TypeSerializer contentTypeSer = null; // 16-Feb-2014, cgc: contentType serializers for collection-like and map-like types if (type.isContainerType() || type.isReferenceType()) { contentTypeSer = findPropertyContentTypeSerializer(type, prov.getConfig(), accessor); } // and if not JAXB collection/array with annotations, maybe regular type info? TypeSerializer typeSer = findPropertyTypeSerializer(type, prov.getConfig(), accessor); return pb.buildWriter(prov, propDef, type, annotatedSerializer, typeSer, contentTypeSer, accessor, staticTyping); } } BeanSerializerModifier.java000066400000000000000000000173561325620701100364760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.List; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.DeserializerFactory; import com.fasterxml.jackson.databind.type.*; /** * Abstract class that defines API for objects that can be registered (for {@link BeanSerializerFactory} * to participate in constructing {@link BeanSerializer} instances. * This is typically done by modules that want alter some aspects of serialization * process; and is preferable to sub-classing of {@link BeanSerializerFactory}. *

* Sequence in which callback methods are called is as follows: *

    *
  1. After factory has collected tentative set of properties (instances of * BeanPropertyWriter) is sent for modification via * {@link #changeProperties}. Changes can include removal, addition and * replacement of suggested properties. *
  2. Resulting set of properties are ordered (sorted) by factory, as per * configuration, and then {@link #orderProperties} is called to allow * modifiers to alter ordering. *
  3. After all bean properties and related information is accumulated, * {@link #updateBuilder} is called with builder, to allow builder state * to be modified (including possibly replacing builder itself if necessary) *
  4. Once all bean information has been determined, * factory creates default {@link BeanSerializer} instance and passes * it to modifiers using {@link #modifySerializer}, for possible * modification or replacement (by any {@link com.fasterxml.jackson.databind.JsonSerializer} instance) *
*

* Default method implementations are "no-op"s, meaning that methods are implemented * but have no effect. */ public abstract class BeanSerializerModifier { /** * Method called by {@link BeanSerializerFactory} with tentative set * of discovered properties. * Implementations can add, remove or replace any of passed properties. * * Properties List passed as argument is modifiable, and returned List must * likewise be modifiable as it may be passed to multiple registered * modifiers. */ public List changeProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) { return beanProperties; } /** * Method called by {@link BeanSerializerFactory} with set of properties * to serialize, in default ordering (based on defaults as well as * possible type annotations). * Implementations can change ordering any way they like. * * Properties List passed as argument is modifiable, and returned List must * likewise be modifiable as it may be passed to multiple registered * modifiers. */ public List orderProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) { return beanProperties; } /** * Method called by {@link BeanSerializerFactory} after collecting all information * regarding POJO to serialize and updating builder with it, but before constructing * serializer. * Implementations may choose to modify state of builder (to affect serializer being * built), or even completely replace it (if they want to build different kind of * serializer). Typically, however, passed-in builder is returned, possibly with * some modifications. */ public BeanSerializerBuilder updateBuilder(SerializationConfig config, BeanDescription beanDesc, BeanSerializerBuilder builder) { return builder; } /** * Method called by {@link BeanSerializerFactory} after constructing default * bean serializer instance with properties collected and ordered earlier. * Implementations can modify or replace given serializer and return serializer * to use. Note that although initial serializer being passed is of type * {@link BeanSerializer}, modifiers may return serializers of other types; * and this is why implementations must check for type before casting. *

* NOTE: since 2.2, gets called for serializer of those non-POJO types that * do not go through any of more specific modifyXxxSerializer * methods; mostly for JDK types like {@link java.util.Iterator} and such. */ public JsonSerializer modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer serializer) { return serializer; } /* /********************************************************** /* Callback methods for other types (since 2.2) /********************************************************** */ /** * Method called by {@link DeserializerFactory} after it has constructed the * standard serializer for given * {@link ArrayType} * to make it possible to either replace or augment this serializer with * additional functionality. * * @param config Configuration in use * @param valueType Type of the value serializer is used for. * @param beanDesc Details of the type in question, to allow checking class annotations * @param serializer Default serializer that would be used. * * @return Serializer to use; either serializer that was passed * in, or an instance method constructed. * * @since 2.2 */ public JsonSerializer modifyArraySerializer(SerializationConfig config, ArrayType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return serializer; } /** * @since 2.2 */ public JsonSerializer modifyCollectionSerializer(SerializationConfig config, CollectionType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return serializer; } /** * @since 2.2 */ public JsonSerializer modifyCollectionLikeSerializer(SerializationConfig config, CollectionLikeType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return serializer; } /** * @since 2.2 */ public JsonSerializer modifyMapSerializer(SerializationConfig config, MapType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return serializer; } /** * @since 2.2 */ public JsonSerializer modifyMapLikeSerializer(SerializationConfig config, MapLikeType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return serializer; } /** * @since 2.2 */ public JsonSerializer modifyEnumSerializer(SerializationConfig config, JavaType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return serializer; } /** * Method called by {@link DeserializerFactory} after it has constructed the * default key serializer to use for serializing {@link java.util.Map} keys of * given type. * This makes it possible to either replace or augment default serializer with * additional functionality. * * @param config Configuration in use * @param valueType Type of keys the serializer is used for. * @param beanDesc Details of the type in question, to allow checking class annotations * @param serializer Default serializer that would be used. * * @return Serializer to use; either serializer that was passed * in, or an instance method constructed. * * @since 2.2 */ public JsonSerializer modifyKeySerializer(SerializationConfig config, JavaType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return serializer; } } ContainerSerializer.java000066400000000000000000000122511325620701100360610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; /** * Intermediate base class for serializers used for serializing * types that contain element(s) of other types, such as arrays, * {@link java.util.Collection}s (Lists, Sets * etc) and {@link java.util.Map}s and iterable things * ({@link java.util.Iterator}s). */ @SuppressWarnings("serial") public abstract class ContainerSerializer extends StdSerializer { /* /********************************************************** /* Construction, initialization /********************************************************** */ protected ContainerSerializer(Class t) { super(t); } /** * @since 2.5 */ protected ContainerSerializer(JavaType fullType) { super(fullType); } /** * Alternate constructor that is (alas!) needed to work * around kinks of generic type handling * * @param t */ protected ContainerSerializer(Class t, boolean dummy) { super(t, dummy); } protected ContainerSerializer(ContainerSerializer src) { super(src._handledType, false); } /** * Factory(-like) method that can be used to construct a new container * serializer that uses specified {@link TypeSerializer} for decorating * contained values with additional type information. * * @param vts Type serializer to use for contained values; can be null, * in which case 'this' serializer is returned as is * @return Serializer instance that uses given type serializer for values if * that is possible (or if not, just 'this' serializer) */ public ContainerSerializer withValueTypeSerializer(TypeSerializer vts) { if (vts == null) return this; return _withValueTypeSerializer(vts); } /* /********************************************************** /* Extended API /********************************************************** */ /** * Accessor for finding declared (static) element type for * type this serializer is used for. */ public abstract JavaType getContentType(); /** * Accessor for serializer used for serializing contents * (List and array elements, Map values etc) of the * container for which this serializer is used, if it is * known statically. * Note that for dynamic types this may return null; if so, * caller has to instead use {@link #getContentType()} and * {@link com.fasterxml.jackson.databind.SerializerProvider#findValueSerializer}. */ public abstract JsonSerializer getContentSerializer(); /* /********************************************************** /* Abstract methods for sub-classes to implement /********************************************************** */ // since 2.5: should be declared abstract in future (2.9?) // @Override // public abstract boolean isEmpty(SerializerProvider prov, T value); /** * Method called to determine if the given value (of type handled by * this serializer) contains exactly one element. *

* Note: although it might seem sensible to instead define something * like "getElementCount()" method, this would not work well for * containers that do not keep track of size (like linked lists may * not). *

* Note, too, that as of now (2.9) this method is only called by serializer * itself; and specifically is not used for non-array/collection types * like Map or Map.Entry instances. */ public abstract boolean hasSingleElement(T value); /** * Method that needs to be implemented to allow construction of a new * serializer object with given {@link TypeSerializer}, used when * addition type information is to be embedded. */ protected abstract ContainerSerializer _withValueTypeSerializer(TypeSerializer vts); /* /********************************************************** /* Helper methods for sub-types /********************************************************** */ /** * Helper method used to encapsulate logic for determining whether there is * a property annotation that overrides element type; if so, we can * and need to statically find the serializer. * * @since 2.1 * * @deprecated Since 2.7: should not be needed; should be enough to see if * type has 'isStatic' modifier */ @Deprecated protected boolean hasContentTypeAnnotation(SerializerProvider provider, BeanProperty property) { /* if (property != null) { AnnotationIntrospector intr = provider.getAnnotationIntrospector(); AnnotatedMember m = property.getMember(); if ((m != null) && (intr != null)) { if (intr.findSerializationContentType(m, property.getType()) != null) { return true; } } } */ return false; } } ContextualSerializer.java000066400000000000000000000036571325620701100362770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.databind.*; /** * Add-on interface that {@link JsonSerializer}s can implement to get a callback * that can be used to create contextual instances of serializer to use for * handling properties of supported type. This can be useful * for serializers that can be configured by annotations, or should otherwise * have differing behavior depending on what kind of property is being serialized. *

* Note that in cases where serializer needs both contextualization and * resolution -- that is, implements both this interface and {@link ResolvableSerializer} * -- resolution via {@link ResolvableSerializer} occurs first, and contextual * resolution (via this interface) later on. */ public interface ContextualSerializer { /** * Method called to see if a different (or differently configured) serializer * is needed to serialize values of specified property. * Note that instance that this method is called on is typically shared one and * as a result method should NOT modify this instance but rather construct * and return a new instance. This instance should only be returned as-is, in case * it is already suitable for use. * * @param prov Serializer provider to use for accessing config, other serializers * @param property Method or field that represents the property * (and is used to access value to serialize). * Should be available; but there may be cases where caller cannot provide it and * null is passed instead (in which case impls usually pass 'this' serializer as is) * * @return Serializer to use for serializing values of specified property; * may be this instance or a new instance. * * @throws JsonMappingException */ public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException; } DefaultSerializerProvider.java000066400000000000000000000552551325620701100372510ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonschema.SchemaAware; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.impl.WritableObjectId; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Standard implementation used by {@link ObjectMapper}: * adds methods only exposed to {@link ObjectMapper}, * as well as constructors. *

* Note that class is abstract just because it does not * define {@link #createInstance} method. *

* Also note that all custom {@link SerializerProvider} * implementations must sub-class this class: {@link ObjectMapper} * requires this type, not basic provider type. */ public abstract class DefaultSerializerProvider extends SerializerProvider implements java.io.Serializable // since 2.1; only because ObjectWriter needs it { private static final long serialVersionUID = 1L; /* /********************************************************** /* State, for non-blueprint instances /********************************************************** */ /** * Per-serialization map Object Ids that have seen so far, iff * Object Id handling is enabled. */ protected transient Map _seenObjectIds; protected transient ArrayList> _objectIdGenerators; /** * Generator used for serialization. Needed mostly for error reporting * purposes. * * @since 2.8 */ protected transient JsonGenerator _generator; /* /********************************************************** /* Life-cycle /********************************************************** */ protected DefaultSerializerProvider() { super(); } protected DefaultSerializerProvider(SerializerProvider src, SerializationConfig config,SerializerFactory f) { super(src, config, f); } protected DefaultSerializerProvider(DefaultSerializerProvider src) { super(src); } /** * Method that sub-classes need to implement: used to create a non-blueprint instances * from the blueprint. * This is needed to retain state during serialization. */ public abstract DefaultSerializerProvider createInstance(SerializationConfig config, SerializerFactory jsf); /** * Method needed to ensure that {@link ObjectMapper#copy} will work * properly; specifically, that caches are cleared, but settings * will otherwise remain identical; and that no sharing of state * occurs. * * @since 2.5 */ public DefaultSerializerProvider copy() { throw new IllegalStateException("DefaultSerializerProvider sub-class not overriding copy()"); } /* /********************************************************** /* Abstract method impls, factory methods /********************************************************** */ @Override public JsonSerializer serializerInstance(Annotated annotated, Object serDef) throws JsonMappingException { if (serDef == null) { return null; } JsonSerializer ser; if (serDef instanceof JsonSerializer) { ser = (JsonSerializer) serDef; } else { // Alas, there's no way to force return type of "either class // X or Y" -- need to throw an exception after the fact if (!(serDef instanceof Class)) { reportBadDefinition(annotated.getType(), "AnnotationIntrospector returned serializer definition of type " +serDef.getClass().getName()+"; expected type JsonSerializer or Class instead"); } Class serClass = (Class)serDef; // there are some known "no class" markers to consider too: if (serClass == JsonSerializer.None.class || ClassUtil.isBogusClass(serClass)) { return null; } if (!JsonSerializer.class.isAssignableFrom(serClass)) { reportBadDefinition(annotated.getType(), "AnnotationIntrospector returned Class " +serClass.getName()+"; expected Class"); } HandlerInstantiator hi = _config.getHandlerInstantiator(); ser = (hi == null) ? null : hi.serializerInstance(_config, annotated, serClass); if (ser == null) { ser = (JsonSerializer) ClassUtil.createInstance(serClass, _config.canOverrideAccessModifiers()); } } return (JsonSerializer) _handleResolvable(ser); } @Override public Object includeFilterInstance(BeanPropertyDefinition forProperty, Class filterClass) { if (filterClass == null) { return null; } HandlerInstantiator hi = _config.getHandlerInstantiator(); Object filter = (hi == null) ? null : hi.includeFilterInstance(_config, forProperty, filterClass); if (filter == null) { filter = ClassUtil.createInstance(filterClass, _config.canOverrideAccessModifiers()); } return filter; } @Override public boolean includeFilterSuppressNulls(Object filter) throws JsonMappingException { if (filter == null) { return true; } // should let filter decide what to do with nulls: // But just case, let's handle unexpected (from our perspective) problems explicitly try { return filter.equals(null); } catch (Throwable t) { String msg = String.format( "Problem determining whether filter of type '%s' should filter out `null` values: (%s) %s", filter.getClass().getName(), t.getClass().getName(), t.getMessage()); reportBadDefinition(filter.getClass(), msg, t); return false; // never gets here } } /* /********************************************************** /* Object Id handling /********************************************************** */ @Override public WritableObjectId findObjectId(Object forPojo, ObjectIdGenerator generatorType) { if (_seenObjectIds == null) { _seenObjectIds = _createObjectIdMap(); } else { WritableObjectId oid = _seenObjectIds.get(forPojo); if (oid != null) { return oid; } } // Not seen yet; must add an entry, return it. For that, we need generator ObjectIdGenerator generator = null; if (_objectIdGenerators == null) { _objectIdGenerators = new ArrayList>(8); } else { for (int i = 0, len = _objectIdGenerators.size(); i < len; ++i) { ObjectIdGenerator gen = _objectIdGenerators.get(i); if (gen.canUseFor(generatorType)) { generator = gen; break; } } } if (generator == null) { generator = generatorType.newForSerialization(this); _objectIdGenerators.add(generator); } WritableObjectId oid = new WritableObjectId(generator); _seenObjectIds.put(forPojo, oid); return oid; } /** * Overridable helper method used for creating {@link java.util.Map} * used for storing mappings from serializable objects to their * Object Ids. * * @since 2.3 */ protected Map _createObjectIdMap() { /* 06-Aug-2013, tatu: We may actually want to use equality, * instead of identity... so: */ if (isEnabled(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID)) { return new HashMap(); } return new IdentityHashMap(); } /* /********************************************************** /* Extended API: simple accesors /********************************************************** */ /** * Method that can be called to see if this serializer provider * can find a serializer for an instance of given class. *

* Note that no Exceptions are thrown, including unchecked ones: * implementations are to swallow exceptions if necessary. */ public boolean hasSerializerFor(Class cls, AtomicReference cause) { // 07-Nov-2015, tatu: One special case, Object.class; will work only if // empty beans are allowed or custom serializer registered. Easiest to // check here. if (cls == Object.class) { if (!_config.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) { return true; } } try { JsonSerializer ser = _findExplicitUntypedSerializer(cls); return (ser != null); } catch (JsonMappingException e) { if (cause != null) { cause.set(e); } } catch (RuntimeException e) { if (cause == null) { // earlier behavior throw e; } cause.set(e); } return false; } /** * Accessor for the {@link JsonGenerator} currently in use for serializing * content. Null for blueprint instances; non-null for actual active * provider instances. * * @since 2.8 */ @Override public JsonGenerator getGenerator() { return _generator; } /* /********************************************************** /* Extended API called by ObjectMapper: value serialization /********************************************************** */ /** * The method to be called by {@link ObjectMapper} and {@link ObjectWriter} * for serializing given value, using serializers that * this provider has access to (via caching and/or creating new serializers * as need be). */ public void serializeValue(JsonGenerator gen, Object value) throws IOException { _generator = gen; if (value == null) { _serializeNull(gen); return; } final Class cls = value.getClass(); // true, since we do want to cache root-level typed serializers (ditto for null property) final JsonSerializer ser = findTypedValueSerializer(cls, true, null); PropertyName rootName = _config.getFullRootName(); if (rootName == null) { // not explicitly specified if (_config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE)) { _serialize(gen, value, ser, _config.findRootName(cls)); return; } } else if (!rootName.isEmpty()) { _serialize(gen, value, ser, rootName); return; } _serialize(gen, value, ser); } /** * The method to be called by {@link ObjectMapper} and {@link ObjectWriter} * for serializing given value (assumed to be of specified root type, * instead of runtime type of value), * using serializers that * this provider has access to (via caching and/or creating new serializers * as need be), * * @param rootType Type to use for locating serializer to use, instead of actual * runtime type. Must be actual type, or one of its super types */ public void serializeValue(JsonGenerator gen, Object value, JavaType rootType) throws IOException { _generator = gen; if (value == null) { _serializeNull(gen); return; } // Let's ensure types are compatible at this point if (!rootType.getRawClass().isAssignableFrom(value.getClass())) { _reportIncompatibleRootType(value, rootType); } // root value, not reached via property: JsonSerializer ser = findTypedValueSerializer(rootType, true, null); PropertyName rootName = _config.getFullRootName(); if (rootName == null) { // not explicitly specified if (_config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE)) { _serialize(gen, value, ser, _config.findRootName(rootType)); return; } } else if (!rootName.isEmpty()) { _serialize(gen, value, ser, rootName); return; } _serialize(gen, value, ser); } /** * The method to be called by {@link ObjectWriter} * for serializing given value (assumed to be of specified root type, * instead of runtime type of value), when it may know specific * {@link JsonSerializer} to use. * * @param rootType Type to use for locating serializer to use, instead of actual * runtime type, if no serializer is passed * @param ser Root Serializer to use, if not null * * @since 2.1 */ public void serializeValue(JsonGenerator gen, Object value, JavaType rootType, JsonSerializer ser) throws IOException { _generator = gen; if (value == null) { _serializeNull(gen); return; } // Let's ensure types are compatible at this point if ((rootType != null) && !rootType.getRawClass().isAssignableFrom(value.getClass())) { _reportIncompatibleRootType(value, rootType); } // root value, not reached via property: if (ser == null) { ser = findTypedValueSerializer(rootType, true, null); } PropertyName rootName = _config.getFullRootName(); if (rootName == null) { // not explicitly specified if (_config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE)) { rootName = (rootType == null) ? _config.findRootName(value.getClass()) : _config.findRootName(rootType); _serialize(gen, value, ser, rootName); return; } } else if (!rootName.isEmpty()) { _serialize(gen, value, ser, rootName); return; } _serialize(gen, value, ser); } /** * Alternate serialization call used for polymorphic types, when {@link TypeSerializer} * is already known, but the actual serializer may or may not be. * * @since 2.6 */ public void serializePolymorphic(JsonGenerator gen, Object value, JavaType rootType, JsonSerializer valueSer, TypeSerializer typeSer) throws IOException { _generator = gen; if (value == null) { _serializeNull(gen); return; } // Let's ensure types are compatible at this point if ((rootType != null) && !rootType.getRawClass().isAssignableFrom(value.getClass())) { _reportIncompatibleRootType(value, rootType); } /* 12-Jun-2015, tatu: nominal root type is necessary for Maps at least; * possibly collections, but can cause problems for other polymorphic * types. We really need to distinguish between serialization type, * base type; but right we don't. Hence this check */ if (valueSer == null) { if ((rootType != null) && rootType.isContainerType()) { valueSer = findValueSerializer(rootType, null); } else { valueSer = findValueSerializer(value.getClass(), null); } } final boolean wrap; PropertyName rootName = _config.getFullRootName(); if (rootName == null) { wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE); if (wrap) { gen.writeStartObject(); PropertyName pname = _config.findRootName(value.getClass()); gen.writeFieldName(pname.simpleAsEncoded(_config)); } } else if (rootName.isEmpty()) { wrap = false; } else { wrap = true; gen.writeStartObject(); gen.writeFieldName(rootName.getSimpleName()); } try { valueSer.serializeWithType(value, gen, this, typeSer); if (wrap) { gen.writeEndObject(); } } catch (Exception e) { throw _wrapAsIOE(gen, e); } } private final void _serialize(JsonGenerator gen, Object value, JsonSerializer ser, PropertyName rootName) throws IOException { try { gen.writeStartObject(); gen.writeFieldName(rootName.simpleAsEncoded(_config)); ser.serialize(value, gen, this); gen.writeEndObject(); } catch (Exception e) { throw _wrapAsIOE(gen, e); } } private final void _serialize(JsonGenerator gen, Object value, JsonSerializer ser) throws IOException { try { ser.serialize(value, gen, this); } catch (Exception e) { throw _wrapAsIOE(gen, e); } } /** * Helper method called when root value to serialize is null * * @since 2.3 */ protected void _serializeNull(JsonGenerator gen) throws IOException { JsonSerializer ser = getDefaultNullValueSerializer(); try { ser.serialize(null, gen, this); } catch (Exception e) { throw _wrapAsIOE(gen, e); } } private IOException _wrapAsIOE(JsonGenerator g, Exception e) { if (e instanceof IOException) { return (IOException) e; } String msg = e.getMessage(); if (msg == null) { msg = "[no message for "+e.getClass().getName()+"]"; } return new JsonMappingException(g, msg, e); } /* /******************************************************** /* Access to caching details /******************************************************** */ /** * Method that can be used to determine how many serializers this * provider is caching currently * (if it does caching: default implementation does) * Exact count depends on what kind of serializers get cached; * default implementation caches all serializers, including ones that * are eagerly constructed (for optimal access speed) *

* The main use case for this method is to allow conditional flushing of * serializer cache, if certain number of entries is reached. */ public int cachedSerializersCount() { return _serializerCache.size(); } /** * Method that will drop all serializers currently cached by this provider. * This can be used to remove memory usage (in case some serializers are * only used once or so), or to force re-construction of serializers after * configuration changes for mapper than owns the provider. */ public void flushCachedSerializers() { _serializerCache.flush(); } /* /********************************************************** /* Extended API called by ObjectMapper: other /********************************************************** */ /** * The method to be called by {@link ObjectMapper} and {@link ObjectWriter} * to to expose the format of the given to to the given visitor * * @param javaType The type for which to generate format * @param visitor the visitor to accept the format */ public void acceptJsonFormatVisitor(JavaType javaType, JsonFormatVisitorWrapper visitor) throws JsonMappingException { if (javaType == null) { throw new IllegalArgumentException("A class must be provided"); } /* no need for embedded type information for JSON schema generation (all * type information it needs is accessible via "untyped" serializer) */ visitor.setProvider(this); findValueSerializer(javaType, null).acceptJsonFormatVisitor(visitor, javaType); } /** * The method to be called by {@link ObjectMapper} * to generate JSON schema for * given type. * * @param type The type for which to generate schema * * @deprecated Should not be used any more */ @Deprecated // since 2.6 public com.fasterxml.jackson.databind.jsonschema.JsonSchema generateJsonSchema(Class type) throws JsonMappingException { /* no need for embedded type information for JSON schema generation (all * type information it needs is accessible via "untyped" serializer) */ JsonSerializer ser = findValueSerializer(type, null); JsonNode schemaNode = (ser instanceof SchemaAware) ? ((SchemaAware) ser).getSchema(this, null) : com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode(); if (!(schemaNode instanceof ObjectNode)) { throw new IllegalArgumentException("Class " + type.getName() +" would not be serialized as a JSON object and therefore has no schema"); } return new com.fasterxml.jackson.databind.jsonschema.JsonSchema((ObjectNode) schemaNode); } /* /********************************************************** /* Helper classes /********************************************************** */ /** * Concrete implementation that defines factory method(s), * defined as final. */ public final static class Impl extends DefaultSerializerProvider { private static final long serialVersionUID = 1L; public Impl() { super(); } public Impl(Impl src) { super(src); } protected Impl(SerializerProvider src, SerializationConfig config, SerializerFactory f) { super(src, config, f); } @Override public DefaultSerializerProvider copy() { if (getClass() != Impl.class) { return super.copy(); } return new Impl(this); } @Override public Impl createInstance(SerializationConfig config, SerializerFactory jsf) { return new Impl(this, config, jsf); } } } FilterProvider.java000066400000000000000000000045561325620701100350560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; /** * Interface for objects that providers instances of {@link PropertyFilter} * that match given ids. A provider is configured to be used during serialization, * to find filter to used based on id specified by {@link com.fasterxml.jackson.annotation.JsonFilter} * annotation on bean class. */ public abstract class FilterProvider { /** * Lookup method used to find {@link BeanPropertyFilter} that has specified id. * Note that id is typically a {@link java.lang.String}, but is not necessarily * limited to that; that is, while standard components use String, custom * implementation can choose other kinds of keys. * * @return Filter registered with specified id, if one defined; null if * none found. * * @deprecated Since 2.3 deprecated because {@link BeanPropertyFilter} is deprecated; */ @Deprecated public abstract BeanPropertyFilter findFilter(Object filterId); /** * Lookup method used to find {@link PropertyFilter} that has specified id. * Note that id is typically a {@link java.lang.String}, but is not necessarily * limited to that; that is, while standard components use String, custom * implementation can choose other kinds of keys. *

* This method is the replacement for {@link #findFilter} starting with 2.3. *

* Note that the default implementation is designed to support short-term * backwards compatibility, and will call the deprecated findFilter * method, then wrap filter if one found as {@link PropertyFilter}. * It should be overridden by up-to-date implementations * * @param filterId Id of the filter to fetch * @param valueToFilter Object being filtered (usually POJO, but may be a {@link java.util.Map}, * or in future a container), if available; not available when generating * schemas. * * @return Filter to use, if any. * * @since 2.3 */ public PropertyFilter findPropertyFilter(Object filterId, Object valueToFilter) { @SuppressWarnings("deprecation") BeanPropertyFilter old = findFilter(filterId); if (old == null) { return null; } return SimpleBeanPropertyFilter.from(old); } } PropertyBuilder.java000066400000000000000000000414031325620701100352410ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.util.*; /** * Helper class for {@link BeanSerializerFactory} that is used to * construct {@link BeanPropertyWriter} instances. Can be sub-classed * to change behavior. */ public class PropertyBuilder { // @since 2.7 private final static Object NO_DEFAULT_MARKER = Boolean.FALSE; final protected SerializationConfig _config; final protected BeanDescription _beanDesc; final protected AnnotationIntrospector _annotationIntrospector; /** * If a property has serialization inclusion value of * {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_DEFAULT}, * we may need to know the default value of the bean, to know if property value * equals default one. *

* NOTE: only used if enclosing class defines NON_DEFAULT, but NOT if it is the * global default OR per-property override. */ protected Object _defaultBean; /** * Default inclusion mode for properties of the POJO for which * properties are collected; possibly overridden on * per-property basis. Combines global inclusion defaults and * per-type (annotation and type-override) inclusion overrides. */ final protected JsonInclude.Value _defaultInclusion; /** * Marker flag used to indicate that "real" default values are to be used * for properties, as per per-type value inclusion of type NON_DEFAULT * * @since 2.8 */ final protected boolean _useRealPropertyDefaults; public PropertyBuilder(SerializationConfig config, BeanDescription beanDesc) { _config = config; _beanDesc = beanDesc; // 08-Sep-2016, tatu: This gets tricky, with 3 levels of definitions: // (a) global default inclusion // (b) per-type default inclusion (from annotation or config overrides; // config override having precedence) // (c) per-property override (from annotation on specific property or // config overrides per type of property; // annotation having precedence) // // and not only requiring merging, but also considering special handling // for NON_DEFAULT in case of (b) (vs (a) or (c)) JsonInclude.Value inclPerType = JsonInclude.Value.merge( beanDesc.findPropertyInclusion(JsonInclude.Value.empty()), config.getDefaultPropertyInclusion(beanDesc.getBeanClass(), JsonInclude.Value.empty())); _defaultInclusion = JsonInclude.Value.merge(config.getDefaultPropertyInclusion(), inclPerType); _useRealPropertyDefaults = inclPerType.getValueInclusion() == JsonInclude.Include.NON_DEFAULT; _annotationIntrospector = _config.getAnnotationIntrospector(); } /* /********************************************************** /* Public API /********************************************************** */ public Annotations getClassAnnotations() { return _beanDesc.getClassAnnotations(); } /** * @param contentTypeSer Optional explicit type information serializer * to use for contained values (only used for properties that are * of container type) */ protected BeanPropertyWriter buildWriter(SerializerProvider prov, BeanPropertyDefinition propDef, JavaType declaredType, JsonSerializer ser, TypeSerializer typeSer, TypeSerializer contentTypeSer, AnnotatedMember am, boolean defaultUseStaticTyping) throws JsonMappingException { // do we have annotation that forces type to use (to declared type or its super type)? JavaType serializationType; try { serializationType = findSerializationType(am, defaultUseStaticTyping, declaredType); } catch (JsonMappingException e) { if (propDef == null) { return prov.reportBadDefinition(declaredType, e.getMessage()); } return prov.reportBadPropertyDefinition(_beanDesc, propDef, e.getMessage()); } // Container types can have separate type serializers for content (value / element) type if (contentTypeSer != null) { // 04-Feb-2010, tatu: Let's force static typing for collection, if there is // type information for contents. Should work well (for JAXB case); can be // revisited if this causes problems. if (serializationType == null) { // serializationType = TypeFactory.type(am.getGenericType(), _beanDesc.getType()); serializationType = declaredType; } JavaType ct = serializationType.getContentType(); // Not exactly sure why, but this used to occur; better check explicitly: if (ct == null) { prov.reportBadPropertyDefinition(_beanDesc, propDef, "serialization type "+serializationType+" has no content"); } serializationType = serializationType.withContentTypeHandler(contentTypeSer); ct = serializationType.getContentType(); } Object valueToSuppress = null; boolean suppressNulls = false; // 12-Jul-2016, tatu: [databind#1256] Need to make sure we consider type refinement JavaType actualType = (serializationType == null) ? declaredType : serializationType; // 17-Mar-2017: [databind#1522] Allow config override per property type AnnotatedMember accessor = propDef.getAccessor(); if (accessor == null) { // neither Setter nor ConstructorParameter are expected here return prov.reportBadPropertyDefinition(_beanDesc, propDef, "could not determine property type"); } Class rawPropertyType = accessor.getRawType(); // 17-Aug-2016, tatu: Default inclusion covers global default (for all types), as well // as type-default for enclosing POJO. What we need, then, is per-type default (if any) // for declared property type... and finally property annotation overrides JsonInclude.Value inclV = _config.getDefaultInclusion(actualType.getRawClass(), rawPropertyType, _defaultInclusion); // property annotation override inclV = inclV.withOverrides(propDef.findInclusion()); JsonInclude.Include inclusion = inclV.getValueInclusion(); if (inclusion == JsonInclude.Include.USE_DEFAULTS) { // should not occur but... inclusion = JsonInclude.Include.ALWAYS; } switch (inclusion) { case NON_DEFAULT: // 11-Nov-2015, tatu: This is tricky because semantics differ between cases, // so that if enclosing class has this, we may need to access values of property, // whereas for global defaults OR per-property overrides, we have more // static definition. Sigh. // First: case of class/type specifying it; try to find POJO property defaults Object defaultBean; // 16-Oct-2016, tatu: Note: if we cannot for some reason create "default instance", // revert logic to the case of general/per-property handling, so both // type-default AND null are to be excluded. // (as per [databind#1417] if (_useRealPropertyDefaults && (defaultBean = getDefaultBean()) != null) { // 07-Sep-2016, tatu: may also need to front-load access forcing now if (prov.isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { am.fixAccess(_config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } try { valueToSuppress = am.getValue(defaultBean); } catch (Exception e) { _throwWrapped(e, propDef.getName(), defaultBean); } } else { valueToSuppress = BeanUtil.getDefaultValue(actualType); suppressNulls = true; } if (valueToSuppress == null) { suppressNulls = true; } else { if (valueToSuppress.getClass().isArray()) { valueToSuppress = ArrayBuilders.getArrayComparator(valueToSuppress); } } break; case NON_ABSENT: // new with 2.6, to support Guava/JDK8 Optionals // always suppress nulls suppressNulls = true; // and for referential types, also "empty", which in their case means "absent" if (actualType.isReferenceType()) { valueToSuppress = BeanPropertyWriter.MARKER_FOR_EMPTY; } break; case NON_EMPTY: // always suppress nulls suppressNulls = true; // but possibly also 'empty' values: valueToSuppress = BeanPropertyWriter.MARKER_FOR_EMPTY; break; case CUSTOM: // new with 2.9 valueToSuppress = prov.includeFilterInstance(propDef, inclV.getValueFilter()); if (valueToSuppress == null) { // is this legal? suppressNulls = true; } else { suppressNulls = prov.includeFilterSuppressNulls(valueToSuppress); } break; case NON_NULL: suppressNulls = true; // fall through case ALWAYS: // default default: // we may still want to suppress empty collections if (actualType.isContainerType() && !_config.isEnabled(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS)) { valueToSuppress = BeanPropertyWriter.MARKER_FOR_EMPTY; } break; } Class[] views = propDef.findViews(); if (views == null) { views = _beanDesc.findDefaultViews(); } BeanPropertyWriter bpw = new BeanPropertyWriter(propDef, am, _beanDesc.getClassAnnotations(), declaredType, ser, typeSer, serializationType, suppressNulls, valueToSuppress, views); // How about custom null serializer? Object serDef = _annotationIntrospector.findNullSerializer(am); if (serDef != null) { bpw.assignNullSerializer(prov.serializerInstance(am, serDef)); } // And then, handling of unwrapping NameTransformer unwrapper = _annotationIntrospector.findUnwrappingNameTransformer(am); if (unwrapper != null) { bpw = bpw.unwrappingWriter(unwrapper); } return bpw; } /* /********************************************************** /* Helper methods; annotation access /********************************************************** */ /** * Method that will try to determine statically defined type of property * being serialized, based on annotations (for overrides), and alternatively * declared type (if static typing for serialization is enabled). * If neither can be used (no annotations, dynamic typing), returns null. */ protected JavaType findSerializationType(Annotated a, boolean useStaticTyping, JavaType declaredType) throws JsonMappingException { JavaType secondary = _annotationIntrospector.refineSerializationType(_config, a, declaredType); // 11-Oct-2015, tatu: As of 2.7, not 100% sure following checks are needed. But keeping // for now, just in case if (secondary != declaredType) { Class serClass = secondary.getRawClass(); // Must be a super type to be usable Class rawDeclared = declaredType.getRawClass(); if (serClass.isAssignableFrom(rawDeclared)) { ; // fine as is } else { /* 18-Nov-2010, tatu: Related to fixing [JACKSON-416], an issue with such * check is that for deserialization more specific type makes sense; * and for serialization more generic. But alas JAXB uses but a single * annotation to do both... Hence, we must just discard type, as long as * types are related */ if (!rawDeclared.isAssignableFrom(serClass)) { throw new IllegalArgumentException("Illegal concrete-type annotation for method '"+a.getName()+"': class "+serClass.getName()+" not a super-type of (declared) class "+rawDeclared.getName()); } /* 03-Dec-2010, tatu: Actually, ugh, we may need to further relax this * and actually accept subtypes too for serialization. Bit dangerous in theory * but need to trust user here... */ } useStaticTyping = true; declaredType = secondary; } // If using static typing, declared type is known to be the type... JsonSerialize.Typing typing = _annotationIntrospector.findSerializationTyping(a); if ((typing != null) && (typing != JsonSerialize.Typing.DEFAULT_TYPING)) { useStaticTyping = (typing == JsonSerialize.Typing.STATIC); } if (useStaticTyping) { // 11-Oct-2015, tatu: Make sure JavaType also "knows" static-ness... return declaredType.withStaticTyping(); } return null; } /* /********************************************************** /* Helper methods for default value handling /********************************************************** */ protected Object getDefaultBean() { Object def = _defaultBean; if (def == null) { /* If we can fix access rights, we should; otherwise non-public * classes or default constructor will prevent instantiation */ def = _beanDesc.instantiateBean(_config.canOverrideAccessModifiers()); if (def == null) { // 06-Nov-2015, tatu: As per [databind#998], do not fail. /* Class cls = _beanDesc.getClassInfo().getAnnotated(); throw new IllegalArgumentException("Class "+cls.getName()+" has no default constructor; cannot instantiate default bean value to support 'properties=JsonSerialize.Inclusion.NON_DEFAULT' annotation"); */ // And use a marker def = NO_DEFAULT_MARKER; } _defaultBean = def; } return (def == NO_DEFAULT_MARKER) ? null : _defaultBean; } /** * Accessor used to find out "default value" for given property, to use for * comparing values to serialize, to determine whether to exclude value from serialization with * inclusion type of {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_DEFAULT}. * This method is called when we specifically want to know default value within context * of a POJO, when annotation is within containing class, and not for property or * defined as global baseline. *

* Note that returning of pseudo-type * {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_EMPTY} requires special handling. * * @since 2.7 * @deprecated Since 2.9 since this will not allow determining difference between "no default instance" * case and default being `null`. */ @Deprecated // since 2.9 protected Object getPropertyDefaultValue(String name, AnnotatedMember member, JavaType type) { Object defaultBean = getDefaultBean(); if (defaultBean == null) { return getDefaultValue(type); } try { return member.getValue(defaultBean); } catch (Exception e) { return _throwWrapped(e, name, defaultBean); } } /** * @deprecated Since 2.9 */ @Deprecated // since 2.9 protected Object getDefaultValue(JavaType type) { return BeanUtil.getDefaultValue(type); } /* /********************************************************** /* Helper methods for exception handling /********************************************************** */ protected Object _throwWrapped(Exception e, String propName, Object defaultBean) { Throwable t = e; while (t.getCause() != null) { t = t.getCause(); } ClassUtil.throwIfError(t); ClassUtil.throwIfRTE(t); throw new IllegalArgumentException("Failed to get property '"+propName+"' of default "+defaultBean.getClass().getName()+" instance"); } } PropertyFilter.java000066400000000000000000000120061325620701100350750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.node.ObjectNode; /** * Interface that defines API for filter objects use (as configured * using {@link com.fasterxml.jackson.annotation.JsonFilter}) * for filtering bean properties to serialize. *

* Note that this is the replacement for BeanPropertyFilter, * which is replaced because it was too closely bound to Bean properties * and would not work with {@link java.util.Map}s or "any getters". *

* Note that since this is an interface, it is * strongly recommended that custom implementations extend * {@link com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter}, * to avoid backwards compatibility issues in case interface needs to change. * * @since 2.3 */ public interface PropertyFilter { /** * Method called by {@link BeanSerializer} to let the filter decide what to do with * given bean property value: * the usual choices are to either filter out (i.e. * do nothing) or write using given {@link PropertyWriter}, although filters * can choose other to do something different altogether. *

* Typical implementation is something like: *

     * if (include(writer)) {
     *      writer.serializeAsField(pojo, gen, prov);
     * }
     *
* * @param pojo Object that contains property value to serialize * @param gen Generator use for serializing value * @param prov Provider that can be used for accessing dynamic aspects of serialization * processing * @param writer Object called to do actual serialization of the field, if not filtered out */ public void serializeAsField(Object pojo, JsonGenerator gen, SerializerProvider prov, PropertyWriter writer) throws Exception; /** * Method called by container to let the filter decide what to do with given element * value: * the usual choices are to either filter out (i.e. * do nothing) or write using given {@link PropertyWriter}, although filters * can choose other to do something different altogether. *

* Typical implementation is something like: *

     * if (include(writer)) {
     *      writer.serializeAsElement(pojo, gen, prov);
     * }
     *
* * @param elementValue Element value being serializerd * @param gen Generator use for serializing value * @param prov Provider that can be used for accessing dynamic aspects of serialization * processing * @param writer Object called to do actual serialization of the field, if not filtered out */ public void serializeAsElement(Object elementValue, JsonGenerator gen, SerializerProvider prov, PropertyWriter writer) throws Exception; /** * Method called by {@link BeanSerializer} to let the filter determine whether, and in what * form the given property exist within the parent, or root, schema. Filters can omit * adding the property to the node, or choose the form of the schema value for the property. *

* Typical implementation is something like: *

     * if (include(writer)) {
     *      writer.depositSchemaProperty(propertiesNode, provider);
     * }
     *
* * @param writer Bean property writer to use to create schema value * @param propertiesNode Node which the given property would exist within * @param provider Provider that can be used for accessing dynamic aspects of serialization * processing * * @deprecated Since 2.3: new code should use the alternative depositSchemaProperty * method */ @Deprecated public void depositSchemaProperty(PropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException; /** * Method called by {@link BeanSerializer} to let the filter determine whether, and in what * form the given property exist within the parent, or root, schema. Filters can omit * adding the property to the node, or choose the form of the schema value for the property *

* Typical implementation is something like: *

     * if (include(writer)) {
     *      writer.depositSchemaProperty(objectVisitor, provider);
     * }
     *
* * @param writer Bean property serializer to use to create schema value * @param objectVisitor JsonObjectFormatVisitor which should be aware of * the property's existence * @param provider Provider that can be used for accessing dynamic aspects of serialization * processing */ public void depositSchemaProperty(PropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException; } PropertyWriter.java000066400000000000000000000135371325620701100351360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.lang.annotation.Annotation; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.introspect.ConcreteBeanPropertyBase; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.node.ObjectNode; /** * Base class for writers used to output property values (name-value pairs) * as key/value pairs via streaming API. This is the most generic abstraction * implemented by both POJO and {@link java.util.Map} serializers, and invoked * by filtering functionality. * * @since 2.3 */ public abstract class PropertyWriter extends ConcreteBeanPropertyBase // since 2.7 implements java.io.Serializable { private static final long serialVersionUID = 1L; protected PropertyWriter(PropertyMetadata md) { super(md); } protected PropertyWriter(BeanPropertyDefinition propDef) { super(propDef.getMetadata()); } protected PropertyWriter(PropertyWriter base) { super(base); } /* /********************************************************** /* Metadata access /********************************************************** */ @Override public abstract String getName(); @Override public abstract PropertyName getFullName(); /** * Convenience method for accessing annotation that may be associated * either directly on property, or, if not, via enclosing class (context). * This allows adding baseline contextual annotations, for example, by adding * an annotation for a given class and making that apply to all properties * unless overridden by per-property annotations. *

* This method is functionally equivalent to: *

     *  MyAnnotation ann = propWriter.getAnnotation(MyAnnotation.class);
     *  if (ann == null) {
     *    ann = propWriter.getContextAnnotation(MyAnnotation.class);
     *  }
     *
* that is, tries to find a property annotation first, but if one is not * found, tries to find context-annotation (from enclosing class) of * same type. * * @since 2.5 */ public A findAnnotation(Class acls) { A ann = getAnnotation(acls); if (ann == null) { ann = getContextAnnotation(acls); } return ann; } /** * Method for accessing annotations directly declared for property that this * writer is associated with. * * @since 2.5 */ @Override public abstract A getAnnotation(Class acls); /** * Method for accessing annotations declared in context of the property that this * writer is associated with; usually this means annotations on enclosing class * for property. * * @since 2.5 */ @Override public abstract A getContextAnnotation(Class acls); /* /********************************************************** /* Serialization methods, regular output /********************************************************** */ /** * The main serialization method called by filter when property is to be written normally. */ public abstract void serializeAsField(Object value, JsonGenerator jgen, SerializerProvider provider) throws Exception; /** * Serialization method that filter needs to call in cases where property is to be * filtered, but the underlying data format requires a placeholder of some kind. * This is usually the case for tabular (positional) data formats such as CSV. */ public abstract void serializeAsOmittedField(Object value, JsonGenerator jgen, SerializerProvider provider) throws Exception; /* /********************************************************** /* Serialization methods, explicit positional/tabular formats /********************************************************** */ /** * Serialization method called when output is to be done as an array, * that is, not using property names. This is needed when serializing * container ({@link java.util.Collection}, array) types, * or POJOs using tabular ("as array") output format. *

* Note that this mode of operation is independent of underlying * data format; so it is typically NOT called for fully tabular formats such as CSV, * where logical output is still as form of POJOs. */ public abstract void serializeAsElement(Object value, JsonGenerator jgen, SerializerProvider provider) throws Exception; /** * Serialization method called when doing tabular (positional) output from databind, * but then value is to be omitted. This requires output of a placeholder value * of some sort; often similar to {@link #serializeAsOmittedField}. */ public abstract void serializeAsPlaceholder(Object value, JsonGenerator jgen, SerializerProvider provider) throws Exception; /* /********************************************************** /* Schema-related /********************************************************** */ /** * Traversal method used for things like JSON Schema generation, or * POJO introspection. */ @Override public abstract void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException; /** * Legacy method called for JSON Schema generation; should not be called by new code * * @deprecated Since 2.2 */ @Deprecated public abstract void depositSchemaProperty(ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException; } ResolvableSerializer.java000066400000000000000000000025651325620701100362440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.databind.*; /** * Interface used to indicate serializers that want to do post-processing * after construction and being added to {@link SerializerProvider}, * but before being used. This is typically used to resolve references * to other contained types; for example, bean serializers use this * to eagerly find serializers for contained field types. *

* Note that in cases where serializer needs both contextualization and * resolution -- that is, implements both this interface and {@link ContextualSerializer} * -- resolution via this interface occurs first, and contextual * resolution (using {@link ContextualSerializer}) later on. */ public interface ResolvableSerializer { /** * Method called after {@link SerializerProvider} has registered * the serializer, but before it has returned it to the caller. * Called object can then resolve its dependencies to other types, * including self-references (direct or indirect). *

* Note that this method does NOT return serializer, since resolution * is not allowed to change actual serializer to use. * * @param provider Provider that has constructed serializer this method * is called on. */ public abstract void resolve(SerializerProvider provider) throws JsonMappingException; } SerializerCache.java000066400000000000000000000163471325620701100351540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap; import com.fasterxml.jackson.databind.util.TypeKey; /** * Simple cache object that allows for doing 2-level lookups: first level is * by "local" read-only lookup Map (used without locking) * and second backup level is by a shared modifiable HashMap. * The idea is that after a while, most serializers are found from the * local Map (to optimize performance, reduce lock contention), * but that during buildup we can use a shared map to reduce both * number of distinct read-only maps constructed, and number of * serializers constructed. *

* Cache contains three kinds of entries, * based on combination of class pair key. First class in key is for the * type to serialize, and second one is type used for determining how * to resolve value type. One (but not both) of entries can be null. */ public final class SerializerCache { /** * Shared, modifiable map; all access needs to be through synchronized blocks. *

* NOTE: keys are of various types (see below for key types), in addition to * basic {@link JavaType} used for "untyped" serializers. */ private final HashMap> _sharedMap = new HashMap>(64); /** * Most recent read-only instance, created from _sharedMap, if any. */ private final AtomicReference _readOnlyMap = new AtomicReference(); public SerializerCache() { } /** * Method that can be called to get a read-only instance populated from the * most recent version of the shared lookup Map. */ public ReadOnlyClassToSerializerMap getReadOnlyLookupMap() { ReadOnlyClassToSerializerMap m = _readOnlyMap.get(); if (m != null) { return m; } return _makeReadOnlyLookupMap(); } private final synchronized ReadOnlyClassToSerializerMap _makeReadOnlyLookupMap() { // double-locking; safe, but is it really needed? Not doing that is only a perf problem, // not correctness ReadOnlyClassToSerializerMap m = _readOnlyMap.get(); if (m == null) { m = ReadOnlyClassToSerializerMap.from(_sharedMap); _readOnlyMap.set(m); } return m; } /* /********************************************************** /* Lookup methods for accessing shared (slow) cache /********************************************************** */ public synchronized int size() { return _sharedMap.size(); } /** * Method that checks if the shared (and hence, synchronized) lookup Map might have * untyped serializer for given type. */ public JsonSerializer untypedValueSerializer(Class type) { synchronized (this) { return _sharedMap.get(new TypeKey(type, false)); } } public JsonSerializer untypedValueSerializer(JavaType type) { synchronized (this) { return _sharedMap.get(new TypeKey(type, false)); } } public JsonSerializer typedValueSerializer(JavaType type) { synchronized (this) { return _sharedMap.get(new TypeKey(type, true)); } } public JsonSerializer typedValueSerializer(Class cls) { synchronized (this) { return _sharedMap.get(new TypeKey(cls, true)); } } /* /********************************************************** /* Methods for adding shared serializer instances /********************************************************** */ /** * Method called if none of lookups succeeded, and caller had to construct * a serializer. If so, we will update the shared lookup map so that it * can be resolved via it next time. */ public void addTypedSerializer(JavaType type, JsonSerializer ser) { synchronized (this) { if (_sharedMap.put(new TypeKey(type, true), ser) == null) { // let's invalidate the read-only copy, too, to get it updated _readOnlyMap.set(null); } } } public void addTypedSerializer(Class cls, JsonSerializer ser) { synchronized (this) { if (_sharedMap.put(new TypeKey(cls, true), ser) == null) { // let's invalidate the read-only copy, too, to get it updated _readOnlyMap.set(null); } } } public void addAndResolveNonTypedSerializer(Class type, JsonSerializer ser, SerializerProvider provider) throws JsonMappingException { synchronized (this) { if (_sharedMap.put(new TypeKey(type, false), ser) == null) { _readOnlyMap.set(null); } // Need resolution to handle cyclic POJO type dependencies /* 14-May-2011, tatu: Resolving needs to be done in synchronized manner; * this because while we do need to register instance first, we also must * keep lock until resolution is complete. */ if (ser instanceof ResolvableSerializer) { ((ResolvableSerializer) ser).resolve(provider); } } } public void addAndResolveNonTypedSerializer(JavaType type, JsonSerializer ser, SerializerProvider provider) throws JsonMappingException { synchronized (this) { if (_sharedMap.put(new TypeKey(type, false), ser) == null) { _readOnlyMap.set(null); } // Need resolution to handle cyclic POJO type dependencies /* 14-May-2011, tatu: Resolving needs to be done in synchronized manner; * this because while we do need to register instance first, we also must * keep lock until resolution is complete. */ if (ser instanceof ResolvableSerializer) { ((ResolvableSerializer) ser).resolve(provider); } } } /** * Another alternative that will cover both access via raw type and matching * fully resolved type, in one fell swoop. * * @since 2.7 */ public void addAndResolveNonTypedSerializer(Class rawType, JavaType fullType, JsonSerializer ser, SerializerProvider provider) throws JsonMappingException { synchronized (this) { Object ob1 = _sharedMap.put(new TypeKey(rawType, false), ser); Object ob2 = _sharedMap.put(new TypeKey(fullType, false), ser); if ((ob1 == null) || (ob2 == null)) { _readOnlyMap.set(null); } if (ser instanceof ResolvableSerializer) { ((ResolvableSerializer) ser).resolve(provider); } } } /** * Method called by StdSerializerProvider#flushCachedSerializers() to * clear all cached serializers */ public synchronized void flush() { _sharedMap.clear(); } } SerializerFactory.java000066400000000000000000000064111325620701100355470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * Abstract class that defines API used by {@link SerializerProvider} * to obtain actual * {@link JsonSerializer} instances from multiple distinct factories. */ public abstract class SerializerFactory { /* /********************************************************** /* Additional configuration methods /********************************************************** */ /** * Convenience method for creating a new factory instance with additional serializer * provider; equivalent to calling *
     *   withConfig(getConfig().withAdditionalSerializers(additional));
     *
*/ public abstract SerializerFactory withAdditionalSerializers(Serializers additional); public abstract SerializerFactory withAdditionalKeySerializers(Serializers additional); /** * Convenience method for creating a new factory instance with additional bean * serializer modifier; equivalent to calling *
     *   withConfig(getConfig().withSerializerModifier(modifier));
     *
*/ public abstract SerializerFactory withSerializerModifier(BeanSerializerModifier modifier); /* /********************************************************** /* Basic SerializerFactory API: /********************************************************** */ /** * Method called to create (or, for immutable serializers, reuse) a serializer for given type. * * @param prov Provider that needs to be used to resolve annotation-provided * serializers (but NOT for others) * * @since 2.1 (earlier versions had method with different signature) */ public abstract JsonSerializer createSerializer(SerializerProvider prov, JavaType baseType) throws JsonMappingException; /** * Method called to create a type information serializer for given base type, * if one is needed. If not needed (no polymorphic handling configured), should * return null. * * @param baseType Declared type to use as the base type for type information serializer * * @return Type serializer to use for the base type, if one is needed; null if not. */ public abstract TypeSerializer createTypeSerializer(SerializationConfig config, JavaType baseType) throws JsonMappingException; /** * Method called to create serializer to use for serializing JSON property names (which must * be output as JsonToken.FIELD_NAME) for Map that has specified declared * key type, and is for specified property (or, if property is null, as root value) * * @param type Declared type for Map keys * @param defaultImpl Default key serializer implementation to use, if no custom ones * are found (may be null) * * @return Serializer to use, if factory knows it; null if not (in which case default * serializer is to be used) */ public abstract JsonSerializer createKeySerializer(SerializationConfig config, JavaType type, JsonSerializer defaultImpl) throws JsonMappingException; } Serializers.java000066400000000000000000000160441325620701100344050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.type.*; /** * Interface that defines API for simple extensions that can provide additional serializers * for various types. Access is by a single callback method; instance is to either return * a configured {@link JsonSerializer} for specified type, or null to indicate that it * does not support handling of the type. In latter case, further calls can be made * for other providers; in former case returned serializer is used for handling of * instances of specified type. */ public interface Serializers { /** * Method called by serialization framework first time a serializer is needed for * specified type, which is not of a container or reference type (for which * other methods are called). * * @param type Fully resolved type of instances to serialize * @param config Serialization configuration in use * @param beanDesc Additional information about type * * @return Configured serializer to use for the type; or null if implementation * does not recognize or support type */ public JsonSerializer findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc); /** * Method called by serialization framework first time a serializer is needed for * given {@link ReferenceType} * * @since 2.7 */ public JsonSerializer findReferenceSerializer(SerializationConfig config, ReferenceType type, BeanDescription beanDesc, TypeSerializer contentTypeSerializer, JsonSerializer contentValueSerializer); /** * Method called by serialization framework first time a serializer is needed for * specified array type. * Implementation should return a serializer instance if it supports * specified type; or null if it does not. */ public JsonSerializer findArraySerializer(SerializationConfig config, ArrayType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer); /** * Method called by serialization framework first time a serializer is needed for * specified {@link java.util.Collection} type. * Implementation should return a serializer instance if it supports * specified type; or null if it does not. */ public JsonSerializer findCollectionSerializer(SerializationConfig config, CollectionType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer); /** * Method called by serialization framework first time a serializer is needed for * specified "Collection-like" type (type that acts like {@link java.util.Collection}, * but does not implement it). * Implementation should return a serializer instance if it supports * specified type; or null if it does not. */ public JsonSerializer findCollectionLikeSerializer(SerializationConfig config, CollectionLikeType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer); /** * Method called by serialization framework first time a serializer is needed for * specified {@link java.util.Map} type. * Implementation should return a serializer instance if it supports * specified type; or null if it does not. */ public JsonSerializer findMapSerializer(SerializationConfig config, MapType type, BeanDescription beanDesc, JsonSerializer keySerializer, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer); /** * Method called by serialization framework first time a serializer is needed for * specified "Map-like" type (type that acts like {@link java.util.Map}, * but does not implement it). * Implementation should return a serializer instance if it supports * specified type; or null if it does not. */ public JsonSerializer findMapLikeSerializer(SerializationConfig config, MapLikeType type, BeanDescription beanDesc, JsonSerializer keySerializer, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer); /** * Basic {@link Serializers} implementation that implements all methods but provides * no serializers. Its main purpose is to serve as a base class so that * sub-classes only need to override methods they need. */ public static class Base implements Serializers { @Override public JsonSerializer findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc) { return null; } @Override public JsonSerializer findReferenceSerializer(SerializationConfig config, ReferenceType type, BeanDescription beanDesc, TypeSerializer contentTypeSerializer, JsonSerializer contentValueSerializer) { // 21-Oct-2015, tatu: For backwards compatibility, let's delegate to "bean" variant, // for 2.7 -- remove work-around from 2.8 or later return findSerializer(config, type, beanDesc); } @Override public JsonSerializer findArraySerializer(SerializationConfig config, ArrayType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { return null; } @Override public JsonSerializer findCollectionSerializer(SerializationConfig config, CollectionType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { return null; } @Override public JsonSerializer findCollectionLikeSerializer(SerializationConfig config, CollectionLikeType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { return null; } @Override public JsonSerializer findMapSerializer(SerializationConfig config, MapType type, BeanDescription beanDesc, JsonSerializer keySerializer, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { return null; } @Override public JsonSerializer findMapLikeSerializer(SerializationConfig config, MapLikeType type, BeanDescription beanDesc, JsonSerializer keySerializer, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { return null; } } } VirtualBeanPropertyWriter.java000066400000000000000000000217451325620701100372730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; import com.fasterxml.jackson.databind.util.Annotations; /** * {@link BeanPropertyWriter} implementation used with * {@link com.fasterxml.jackson.databind.annotation.JsonAppend} * to add "virtual" properties in addition to regular ones. * * @since 2.5 * * @see com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter */ public abstract class VirtualBeanPropertyWriter extends BeanPropertyWriter implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Constructor used by most sub-types. */ protected VirtualBeanPropertyWriter(BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType) { this(propDef, contextAnnotations, declaredType, null, null, null, propDef.findInclusion()); } /** * Constructor that may be used by sub-classes for constructing a "blue-print" instance; * one that will only become (or create) actual usable instance when its * {@link #withConfig} method is called. */ protected VirtualBeanPropertyWriter() { super(); } /** * Pass-through constructor that may be used by sub-classes that * want full control over implementation. */ protected VirtualBeanPropertyWriter(BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType, JsonSerializer ser, TypeSerializer typeSer, JavaType serType, JsonInclude.Value inclusion, Class[] includeInViews) { super(propDef, propDef.getPrimaryMember(), contextAnnotations, declaredType, ser, typeSer, serType, _suppressNulls(inclusion), _suppressableValue(inclusion), includeInViews); } @Deprecated // since 2.8 protected VirtualBeanPropertyWriter(BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType, JsonSerializer ser, TypeSerializer typeSer, JavaType serType, JsonInclude.Value inclusion) { this(propDef, contextAnnotations, declaredType, ser, typeSer, serType, inclusion, null); } protected VirtualBeanPropertyWriter(VirtualBeanPropertyWriter base) { super(base); } protected VirtualBeanPropertyWriter(VirtualBeanPropertyWriter base, PropertyName name) { super(base, name); } protected static boolean _suppressNulls(JsonInclude.Value inclusion) { if (inclusion == null) { return false; } JsonInclude.Include incl = inclusion.getValueInclusion(); return (incl != JsonInclude.Include.ALWAYS) && (incl != JsonInclude.Include.USE_DEFAULTS); } protected static Object _suppressableValue(JsonInclude.Value inclusion) { if (inclusion == null) { return false; } JsonInclude.Include incl = inclusion.getValueInclusion(); if ((incl == JsonInclude.Include.ALWAYS) || (incl == JsonInclude.Include.NON_NULL) || (incl == JsonInclude.Include.USE_DEFAULTS)) { return null; } return MARKER_FOR_EMPTY; } /* /********************************************************** /* Standard accessor overrides /********************************************************** */ @Override public boolean isVirtual() { return true; } /* /********************************************************** /* Abstract methods for sub-classes to define /********************************************************** */ /** * Method called to figure out the value to serialize. For simple sub-types * (such as {@link com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter}) * this may be one of few methods to define, although more advanced implementations * may choose to not even use this method (by overriding {@link #serializeAsField}) * and define a bogus implementation. */ protected abstract Object value(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception; /** * Contextualization method called on a newly constructed virtual bean property. * Usually a new intance needs to be created due to finality of some of configuration * members; otherwise while recommended, creating a new instance is not strictly-speaking * mandatory because calls are made in thread-safe manner, as part of initialization * before use. * * @param config Currenct configuration; guaranteed to be {@link SerializationConfig} * (just not typed since caller does not have dependency to serialization-specific types) * @param declaringClass Class that contains this property writer * @param propDef Nominal property definition to use * @param type Declared type for the property */ public abstract VirtualBeanPropertyWriter withConfig(MapperConfig config, AnnotatedClass declaringClass, BeanPropertyDefinition propDef, JavaType type); /* /********************************************************** /* PropertyWriter serialization method overrides /********************************************************** */ @Override public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { // NOTE: mostly copied from base class, but off-lined get() access final Object value = value(bean, gen, prov); if (value == null) { if (_nullSerializer != null) { gen.writeFieldName(_name); _nullSerializer.serialize(null, gen, prov); } return; } JsonSerializer ser = _serializer; if (ser == null) { Class cls = value.getClass(); PropertySerializerMap m = _dynamicSerializers; ser = m.serializerFor(cls); if (ser == null) { ser = _findAndAddDynamic(m, cls, prov); } } if (_suppressableValue != null) { if (MARKER_FOR_EMPTY == _suppressableValue) { if (ser.isEmpty(prov, value)) { return; } } else if (_suppressableValue.equals(value)) { return; } } if (value == bean) { // simple check for direct cycles // three choices: exception; handled by call; or pass-through if (_handleSelfReference(bean, gen, prov, ser)) { return; } } gen.writeFieldName(_name); if (_typeSerializer == null) { ser.serialize(value, gen, prov); } else { ser.serializeWithType(value, gen, prov, _typeSerializer); } } // This one's fine as-is from base class //public void serializeAsOmittedField(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception @Override public void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { // NOTE: mostly copied from base class, but off-lined get() access final Object value = value(bean, gen, prov); if (value == null) { if (_nullSerializer != null) { _nullSerializer.serialize(null, gen, prov); } else { gen.writeNull(); } return; } JsonSerializer ser = _serializer; if (ser == null) { Class cls = value.getClass(); PropertySerializerMap map = _dynamicSerializers; ser = map.serializerFor(cls); if (ser == null) { ser = _findAndAddDynamic(map, cls, prov); } } if (_suppressableValue != null) { if (MARKER_FOR_EMPTY == _suppressableValue) { if (ser.isEmpty(prov, value)) { serializeAsPlaceholder(bean, gen, prov); return; } } else if (_suppressableValue.equals(value)) { serializeAsPlaceholder(bean, gen, prov); return; } } if (value == bean) { if (_handleSelfReference(bean, gen, prov, ser)) { return; } } if (_typeSerializer == null) { ser.serialize(value, gen, prov); } else { ser.serializeWithType(value, gen, prov, _typeSerializer); } } // This one's fine as-is from base class //public void serializeAsPlaceholder(Object bean, JsonGenerator jgen, SerializerProvider prov) } jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/impl/000077500000000000000000000000001325620701100322615ustar00rootroot00000000000000AttributePropertyWriter.java000066400000000000000000000060601325620701100377540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter; import com.fasterxml.jackson.databind.util.Annotations; /** * {@link VirtualBeanPropertyWriter} implementation used for * {@link com.fasterxml.jackson.databind.annotation.JsonAppend}, * to serialize properties backed-by dynamically assignable attribute * values. * * @since 2.5 */ public class AttributePropertyWriter extends VirtualBeanPropertyWriter { private static final long serialVersionUID = 1; protected final String _attrName; /* /********************************************************** /* Life-cycle /********************************************************** */ protected AttributePropertyWriter(String attrName, BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType) { this(attrName, propDef, contextAnnotations, declaredType, propDef.findInclusion()); } protected AttributePropertyWriter(String attrName, BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType, JsonInclude.Value inclusion) { super(propDef, contextAnnotations, declaredType, /* value serializer */ null, /* type serializer */ null, /* ser type */ null, inclusion, // 10-Oct-2016, tatu: Could enable per-view settings too in future null); _attrName = attrName; } public static AttributePropertyWriter construct(String attrName, BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType) { return new AttributePropertyWriter(attrName, propDef, contextAnnotations, declaredType); } protected AttributePropertyWriter(AttributePropertyWriter base) { super(base); _attrName = base._attrName; } /** * Since this method should typically not be called on this sub-type, * default implementation simply throws an {@link IllegalStateException}. */ @Override public VirtualBeanPropertyWriter withConfig(MapperConfig config, AnnotatedClass declaringClass, BeanPropertyDefinition propDef, JavaType type) { throw new IllegalStateException("Should not be called on this type"); } /* /********************************************************** /* Overrides for actual serialization, value access /********************************************************** */ @Override protected Object value(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception { return prov.getAttribute(_attrName); } } BeanAsArraySerializer.java000066400000000000000000000201671325620701100372350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import java.util.Set; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Specialized POJO serializer that differs from * {@link com.fasterxml.jackson.databind.ser.BeanSerializer} * in that instead of producing a JSON Object it will output * a JSON Array, omitting field names, and serializing values in * specified serialization order. * This behavior is usually triggered by using annotation * {@link com.fasterxml.jackson.annotation.JsonFormat} or its * equivalents. *

* This serializer can be used for "simple" instances; and will NOT * be used if one of following is true: *

    *
  • Unwrapping is used (no way to expand out array in JSON Object) *
  • *
  • Type information ("type id") is to be used: while this could work * for some embedding methods, it would likely cause conflicts. *
  • *
  • Object Identity ("object id") is used: while references would work, * the problem is inclusion of id itself. *
  • *
* Note that it is theoretically possible that last 2 issues could be addressed * (by reserving room in array, for example); and if so, support improved. *

* In cases where array-based output is not feasible, this serializer * can instead delegate to the original Object-based serializer; this * is why a reference is retained to the original serializer. * * @since 2.1 */ public class BeanAsArraySerializer extends BeanSerializerBase { private static final long serialVersionUID = 1L; // since 2.6 /** * Serializer that would produce JSON Object version; used in * cases where array output cannot be used. */ protected final BeanSerializerBase _defaultSerializer; /* /********************************************************** /* Life-cycle: constructors /********************************************************** */ public BeanAsArraySerializer(BeanSerializerBase src) { super(src, (ObjectIdWriter) null); _defaultSerializer = src; } protected BeanAsArraySerializer(BeanSerializerBase src, Set toIgnore) { super(src, toIgnore); _defaultSerializer = src; } protected BeanAsArraySerializer(BeanSerializerBase src, ObjectIdWriter oiw, Object filterId) { super(src, oiw, filterId); _defaultSerializer = src; } /* /********************************************************** /* Life-cycle: factory methods, fluent factories /********************************************************** */ @Override public JsonSerializer unwrappingSerializer(NameTransformer transformer) { /* If this gets called, we will just need delegate to the default * serializer, to "undo" as-array serialization */ return _defaultSerializer.unwrappingSerializer(transformer); } @Override public boolean isUnwrappingSerializer() { return false; } @Override public BeanSerializerBase withObjectIdWriter(ObjectIdWriter objectIdWriter) { // can't handle Object Ids, for now, so: return _defaultSerializer.withObjectIdWriter(objectIdWriter); } @Override public BeanSerializerBase withFilterId(Object filterId) { return new BeanAsArraySerializer(this, _objectIdWriter, filterId); } @Override protected BeanAsArraySerializer withIgnorals(Set toIgnore) { return new BeanAsArraySerializer(this, toIgnore); } @Override protected BeanSerializerBase asArraySerializer() { // already is one, so: return this; } /* /********************************************************** /* JsonSerializer implementation that differs between impls /********************************************************** */ // Re-defined from base class, due to differing prefixes @Override public void serializeWithType(Object bean, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { /* 10-Dec-2014, tatu: Not sure if this can be made to work reliably; * but for sure delegating to default implementation will not work. So: */ if (_objectIdWriter != null) { _serializeWithObjectId(bean, gen, provider, typeSer); return; } gen.setCurrentValue(bean); WritableTypeId typeIdDef = _typeIdDef(typeSer, bean, JsonToken.START_ARRAY); typeSer.writeTypePrefix(gen, typeIdDef); serializeAsArray(bean, gen, provider); typeSer.writeTypeSuffix(gen, typeIdDef); } /** * Main serialization method that will delegate actual output to * configured * {@link BeanPropertyWriter} instances. */ @Override public final void serialize(Object bean, JsonGenerator gen, SerializerProvider provider) throws IOException { if (provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) && hasSingleElement(provider)) { serializeAsArray(bean, gen, provider); return; } /* note: it is assumed here that limitations (type id, object id, * any getter, filtering) have already been checked; so code here * is trivial. */ gen.writeStartArray(); // [databind#631]: Assign current value, to be accessible by custom serializers gen.setCurrentValue(bean); serializeAsArray(bean, gen, provider); gen.writeEndArray(); } /* /********************************************************** /* Field serialization methods /********************************************************** */ private boolean hasSingleElement(SerializerProvider provider) { final BeanPropertyWriter[] props; if (_filteredProps != null && provider.getActiveView() != null) { props = _filteredProps; } else { props = _props; } return props.length == 1; } protected final void serializeAsArray(Object bean, JsonGenerator gen, SerializerProvider provider) throws IOException { final BeanPropertyWriter[] props; if (_filteredProps != null && provider.getActiveView() != null) { props = _filteredProps; } else { props = _props; } int i = 0; try { for (final int len = props.length; i < len; ++i) { BeanPropertyWriter prop = props[i]; if (prop == null) { // can have nulls in filtered list; but if so, MUST write placeholders gen.writeNull(); } else { prop.serializeAsElement(bean, gen, provider); } } // NOTE: any getters cannot be supported either //if (_anyGetterWriter != null) { // _anyGetterWriter.getAndSerialize(bean, gen, provider); //} } catch (Exception e) { String name = (i == props.length) ? "[anySetter]" : props[i].getName(); wrapAndThrow(provider, e, bean, name); } catch (StackOverflowError e) { JsonMappingException mapE = JsonMappingException.from(gen, "Infinite recursion (StackOverflowError)", e); String name = (i == props.length) ? "[anySetter]" : props[i].getName(); mapE.prependPath(new JsonMappingException.Reference(bean, name)); throw mapE; } } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return "BeanAsArraySerializer for "+handledType().getName(); } } FailingSerializer.java000066400000000000000000000027041325620701100364530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.ser.std.StdSerializer; /** * Special bogus "serializer" that will throw * {@link JsonMappingException} if its {@link #serialize} * gets invoked. Most commonly registered as handler for unknown types, * as well as for catching unintended usage (like trying to use null * as Map/Object key). */ @SuppressWarnings("serial") public class FailingSerializer extends StdSerializer { protected final String _msg; public FailingSerializer(String msg) { super(Object.class); _msg = msg; } @Override public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException { provider.reportMappingProblem(_msg); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { return null; } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) { ; } } FilteredBeanPropertyWriter.java000066400000000000000000000132621325620701100403370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Decorated {@link BeanPropertyWriter} that will filter out properties * that are not to be included in currently active JsonView. */ public abstract class FilteredBeanPropertyWriter { public static BeanPropertyWriter constructViewBased(BeanPropertyWriter base, Class[] viewsToIncludeIn) { if (viewsToIncludeIn.length == 1) { return new SingleView(base, viewsToIncludeIn[0]); } return new MultiView(base, viewsToIncludeIn); } /* /********************************************************** /* Concrete sub-classes /********************************************************** */ private final static class SingleView extends BeanPropertyWriter implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final BeanPropertyWriter _delegate; protected final Class _view; protected SingleView(BeanPropertyWriter delegate, Class view) { super(delegate); _delegate = delegate; _view = view; } @Override public SingleView rename(NameTransformer transformer) { return new SingleView(_delegate.rename(transformer), _view); } @Override public void assignSerializer(JsonSerializer ser) { _delegate.assignSerializer(ser); } @Override public void assignNullSerializer(JsonSerializer nullSer) { _delegate.assignNullSerializer(nullSer); } @Override public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { Class activeView = prov.getActiveView(); if (activeView == null || _view.isAssignableFrom(activeView)) { _delegate.serializeAsField(bean, gen, prov); } else { _delegate.serializeAsOmittedField(bean, gen, prov); } } @Override public void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { Class activeView = prov.getActiveView(); if (activeView == null || _view.isAssignableFrom(activeView)) { _delegate.serializeAsElement(bean, gen, prov); } else { _delegate.serializeAsPlaceholder(bean, gen, prov); } } @Override public void depositSchemaProperty(JsonObjectFormatVisitor v, SerializerProvider provider) throws JsonMappingException { Class activeView = provider.getActiveView(); if (activeView == null || _view.isAssignableFrom(activeView)) { super.depositSchemaProperty(v, provider); } } } private final static class MultiView extends BeanPropertyWriter implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final BeanPropertyWriter _delegate; protected final Class[] _views; protected MultiView(BeanPropertyWriter delegate, Class[] views) { super(delegate); _delegate = delegate; _views = views; } @Override public MultiView rename(NameTransformer transformer) { return new MultiView(_delegate.rename(transformer), _views); } @Override public void assignSerializer(JsonSerializer ser) { _delegate.assignSerializer(ser); } @Override public void assignNullSerializer(JsonSerializer nullSer) { _delegate.assignNullSerializer(nullSer); } @Override public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { if (_inView(prov.getActiveView())) { _delegate.serializeAsField(bean, gen, prov); return; } _delegate.serializeAsOmittedField(bean, gen, prov); } @Override public void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { if (_inView(prov.getActiveView())) { _delegate.serializeAsElement(bean, gen, prov); return; } _delegate.serializeAsPlaceholder(bean, gen, prov); } @Override public void depositSchemaProperty(JsonObjectFormatVisitor v, SerializerProvider provider) throws JsonMappingException { if (_inView(provider.getActiveView())) { super.depositSchemaProperty(v, provider); } } private final boolean _inView(Class activeView) { if (activeView == null) { return true; } final int len = _views.length; for (int i = 0; i < len; ++i) { if (_views[i].isAssignableFrom(activeView)) { return true; } } return false; } } } IndexedListSerializer.java000066400000000000000000000155111325620701100373160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContainerSerializer; import com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase; /** * This is an optimized serializer for Lists that can be efficiently * traversed by index (as opposed to others, such as {@link LinkedList} * that cannot}. */ @JacksonStdImpl public final class IndexedListSerializer extends AsArraySerializerBase> { private static final long serialVersionUID = 1L; public IndexedListSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts, JsonSerializer valueSerializer) { super(List.class, elemType, staticTyping, vts, valueSerializer); } public IndexedListSerializer(IndexedListSerializer src, BeanProperty property, TypeSerializer vts, JsonSerializer valueSerializer, Boolean unwrapSingle) { super(src, property, vts, valueSerializer, unwrapSingle); } @Override public IndexedListSerializer withResolved(BeanProperty property, TypeSerializer vts, JsonSerializer elementSerializer, Boolean unwrapSingle) { return new IndexedListSerializer(this, property, vts, elementSerializer, unwrapSingle); } /* /********************************************************** /* Accessors /********************************************************** */ @Override public boolean isEmpty(SerializerProvider prov, List value) { return value.isEmpty(); } @Override public boolean hasSingleElement(List value) { return (value.size() == 1); } @Override public ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { return new IndexedListSerializer(this, _property, vts, _elementSerializer, _unwrapSingle); } @Override public final void serialize(List value, JsonGenerator gen, SerializerProvider provider) throws IOException { final int len = value.size(); if (len == 1) { if (((_unwrapSingle == null) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) || (_unwrapSingle == Boolean.TRUE)) { serializeContents(value, gen, provider); return; } } gen.writeStartArray(len); serializeContents(value, gen, provider); gen.writeEndArray(); } @Override public void serializeContents(List value, JsonGenerator g, SerializerProvider provider) throws IOException { if (_elementSerializer != null) { serializeContentsUsing(value, g, provider, _elementSerializer); return; } if (_valueTypeSerializer != null) { serializeTypedContents(value, g, provider); return; } final int len = value.size(); if (len == 0) { return; } int i = 0; try { PropertySerializerMap serializers = _dynamicSerializers; for (; i < len; ++i) { Object elem = value.get(i); if (elem == null) { provider.defaultSerializeNull(g); } else { Class cc = elem.getClass(); JsonSerializer serializer = serializers.serializerFor(cc); if (serializer == null) { // To fix [JACKSON-508] if (_elementType.hasGenericTypes()) { serializer = _findAndAddDynamic(serializers, provider.constructSpecializedType(_elementType, cc), provider); } else { serializer = _findAndAddDynamic(serializers, cc, provider); } serializers = _dynamicSerializers; } serializer.serialize(elem, g, provider); } } } catch (Exception e) { wrapAndThrow(provider, e, value, i); } } public void serializeContentsUsing(List value, JsonGenerator jgen, SerializerProvider provider, JsonSerializer ser) throws IOException { final int len = value.size(); if (len == 0) { return; } final TypeSerializer typeSer = _valueTypeSerializer; for (int i = 0; i < len; ++i) { Object elem = value.get(i); try { if (elem == null) { provider.defaultSerializeNull(jgen); } else if (typeSer == null) { ser.serialize(elem, jgen, provider); } else { ser.serializeWithType(elem, jgen, provider, typeSer); } } catch (Exception e) { // [JACKSON-55] Need to add reference information wrapAndThrow(provider, e, value, i); } } } public void serializeTypedContents(List value, JsonGenerator jgen, SerializerProvider provider) throws IOException { final int len = value.size(); if (len == 0) { return; } int i = 0; try { final TypeSerializer typeSer = _valueTypeSerializer; PropertySerializerMap serializers = _dynamicSerializers; for (; i < len; ++i) { Object elem = value.get(i); if (elem == null) { provider.defaultSerializeNull(jgen); } else { Class cc = elem.getClass(); JsonSerializer serializer = serializers.serializerFor(cc); if (serializer == null) { // To fix [JACKSON-508] if (_elementType.hasGenericTypes()) { serializer = _findAndAddDynamic(serializers, provider.constructSpecializedType(_elementType, cc), provider); } else { serializer = _findAndAddDynamic(serializers, cc, provider); } serializers = _dynamicSerializers; } serializer.serializeWithType(elem, jgen, provider, typeSer); } } } catch (Exception e) { // [JACKSON-55] Need to add reference information wrapAndThrow(provider, e, value, i); } } } IndexedStringListSerializer.java000066400000000000000000000074441325620701100405130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.std.StaticListSerializerBase; /** * Efficient implement for serializing {@link List}s that contains Strings and are random-accessible. * The only complexity is due to possibility that serializer for {@link String} * may be overridde; because of this, logic is needed to ensure that the default * serializer is in use to use fastest mode, or if not, to defer to custom * String serializer. */ @JacksonStdImpl public final class IndexedStringListSerializer extends StaticListSerializerBase> { private static final long serialVersionUID = 1L; public final static IndexedStringListSerializer instance = new IndexedStringListSerializer(); /* /********************************************************** /* Life-cycle /********************************************************** */ protected IndexedStringListSerializer() { super(List.class); } public IndexedStringListSerializer(IndexedStringListSerializer src, Boolean unwrapSingle) { super(src, unwrapSingle); } @Override public JsonSerializer _withResolved(BeanProperty prop, Boolean unwrapSingle) { return new IndexedStringListSerializer(this, unwrapSingle); } @Override protected JsonNode contentSchema() { return createSchemaNode("string", true); } @Override protected void acceptContentVisitor(JsonArrayFormatVisitor visitor) throws JsonMappingException { visitor.itemsFormat(JsonFormatTypes.STRING); } /* /********************************************************** /* Actual serialization /********************************************************** */ @Override public void serialize(List value, JsonGenerator g, SerializerProvider provider) throws IOException { final int len = value.size(); if (len == 1) { if (((_unwrapSingle == null) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) || (_unwrapSingle == Boolean.TRUE)) { serializeContents(value, g, provider, 1); return; } } g.writeStartArray(len); serializeContents(value, g, provider, len); g.writeEndArray(); } @Override public void serializeWithType(List value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.START_ARRAY)); serializeContents(value, g, provider, value.size()); typeSer.writeTypeSuffix(g, typeIdDef); } private final void serializeContents(List value, JsonGenerator g, SerializerProvider provider, int len) throws IOException { g.setCurrentValue(value); int i = 0; try { for (; i < len; ++i) { String str = value.get(i); if (str == null) { provider.defaultSerializeNull(g); } else { g.writeString(str); } } } catch (Exception e) { wrapAndThrow(provider, e, value, i); } } } IteratorSerializer.java000066400000000000000000000110001325620701100366600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import java.util.Iterator; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContainerSerializer; import com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase; @SuppressWarnings("serial") @JacksonStdImpl public class IteratorSerializer extends AsArraySerializerBase> { public IteratorSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts) { super(Iterator.class, elemType, staticTyping, vts, null); } public IteratorSerializer(IteratorSerializer src, BeanProperty property, TypeSerializer vts, JsonSerializer valueSerializer, Boolean unwrapSingle) { super(src, property, vts, valueSerializer, unwrapSingle); } @Override public boolean isEmpty(SerializerProvider prov, Iterator value) { return !value.hasNext(); } @Override public boolean hasSingleElement(Iterator value) { // no really good way to determine (without consuming iterator), so: return false; } @Override public ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { return new IteratorSerializer(this, _property, vts, _elementSerializer, _unwrapSingle); } @Override public IteratorSerializer withResolved(BeanProperty property, TypeSerializer vts, JsonSerializer elementSerializer, Boolean unwrapSingle) { return new IteratorSerializer(this, property, vts, elementSerializer, unwrapSingle); } @Override public final void serialize(Iterator value, JsonGenerator gen, SerializerProvider provider) throws IOException { // 02-Dec-2016, tatu: As per comments above, can't determine single element so... /* if (((_unwrapSingle == null) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) || (_unwrapSingle == Boolean.TRUE)) { if (hasSingleElement(value)) { serializeContents(value, gen, provider); return; } } */ gen.writeStartArray(); serializeContents(value, gen, provider); gen.writeEndArray(); } @Override public void serializeContents(Iterator value, JsonGenerator g, SerializerProvider provider) throws IOException { if (!value.hasNext()) { return; } JsonSerializer serializer = _elementSerializer; if (serializer == null) { _serializeDynamicContents(value, g, provider); return; } final TypeSerializer typeSer = _valueTypeSerializer; do { Object elem = value.next(); if (elem == null) { provider.defaultSerializeNull(g); } else if (typeSer == null) { serializer.serialize(elem, g, provider); } else { serializer.serializeWithType(elem, g, provider, typeSer); } } while (value.hasNext()); } protected void _serializeDynamicContents(Iterator value, JsonGenerator g, SerializerProvider provider) throws IOException { final TypeSerializer typeSer = _valueTypeSerializer; PropertySerializerMap serializers = _dynamicSerializers; do { Object elem = value.next(); if (elem == null) { provider.defaultSerializeNull(g); continue; } Class cc = elem.getClass(); JsonSerializer serializer = serializers.serializerFor(cc); if (serializer == null) { if (_elementType.hasGenericTypes()) { serializer = _findAndAddDynamic(serializers, provider.constructSpecializedType(_elementType, cc), provider); } else { serializer = _findAndAddDynamic(serializers, cc, provider); } serializers = _dynamicSerializers; } if (typeSer == null) { serializer.serialize(elem, g, provider); } else { serializer.serializeWithType(elem, g, provider, typeSer); } } while (value.hasNext()); } }MapEntrySerializer.java000066400000000000000000000401701325620701100366400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import java.util.Map; import java.util.Map.Entry; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContainerSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.util.ArrayBuilders; import com.fasterxml.jackson.databind.util.BeanUtil; /** * @since 2.5 */ @SuppressWarnings("serial") @JacksonStdImpl public class MapEntrySerializer extends ContainerSerializer> implements ContextualSerializer { /** * @since 2.9 */ public final static Object MARKER_FOR_EMPTY = JsonInclude.Include.NON_EMPTY; /** * Map-valued property being serialized with this instance */ protected final BeanProperty _property; /** * Whether static types should be used for serialization of values * or not (if not, dynamic runtime type is used) */ protected final boolean _valueTypeIsStatic; protected final JavaType _entryType, _keyType, _valueType; /* /********************************************************** /* Serializers used /********************************************************** */ /** * Key serializer to use, if it can be statically determined */ protected JsonSerializer _keySerializer; /** * Value serializer to use, if it can be statically determined */ protected JsonSerializer _valueSerializer; /** * Type identifier serializer used for values, if any. */ protected final TypeSerializer _valueTypeSerializer; /** * If value type cannot be statically determined, mapping from * runtime value types to serializers are stored in this object. */ protected PropertySerializerMap _dynamicValueSerializers; /* /********************************************************** /* Config settings, filtering /********************************************************** */ /** * Value that indicates suppression mechanism to use for values contained; * either "filter" (of which equals() is called), or marker * value of {@link #MARKER_FOR_EMPTY}, or null to indicate no filtering for * non-null values. * Note that inclusion value for Map instance itself is handled by caller (POJO * property that refers to the Map value). * * @since 2.5 */ protected final Object _suppressableValue; /** * Flag that indicates what to do with `null` values, distinct from * handling of {@link #_suppressableValue} * * @since 2.9 */ protected final boolean _suppressNulls; /* /********************************************************** /* Construction, initialization /********************************************************** */ public MapEntrySerializer(JavaType type, JavaType keyType, JavaType valueType, boolean staticTyping, TypeSerializer vts, BeanProperty property) { super(type); _entryType = type; _keyType = keyType; _valueType = valueType; _valueTypeIsStatic = staticTyping; _valueTypeSerializer = vts; _property = property; _dynamicValueSerializers = PropertySerializerMap.emptyForProperties(); _suppressableValue = null; _suppressNulls = false; } @Deprecated // since 2.9 protected MapEntrySerializer(MapEntrySerializer src, BeanProperty property, TypeSerializer vts, JsonSerializer keySer, JsonSerializer valueSer) { this(src, property, vts, keySer, valueSer, src._suppressableValue, src._suppressNulls); } @SuppressWarnings("unchecked") protected MapEntrySerializer(MapEntrySerializer src, BeanProperty property, TypeSerializer vts, JsonSerializer keySer, JsonSerializer valueSer, Object suppressableValue, boolean suppressNulls) { super(Map.class, false); _entryType = src._entryType; _keyType = src._keyType; _valueType = src._valueType; _valueTypeIsStatic = src._valueTypeIsStatic; _valueTypeSerializer = src._valueTypeSerializer; _keySerializer = (JsonSerializer) keySer; _valueSerializer = (JsonSerializer) valueSer; _dynamicValueSerializers = src._dynamicValueSerializers; _property = src._property; _suppressableValue = suppressableValue; _suppressNulls = suppressNulls; } @Override public ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { return new MapEntrySerializer(this, _property, vts, _keySerializer, _valueSerializer, _suppressableValue, _suppressNulls); } /** * @since 2.9 */ public MapEntrySerializer withResolved(BeanProperty property, JsonSerializer keySerializer, JsonSerializer valueSerializer, Object suppressableValue, boolean suppressNulls) { return new MapEntrySerializer(this, property, _valueTypeSerializer, keySerializer, valueSerializer, suppressableValue, suppressNulls); } /** * @since 2.9 */ public MapEntrySerializer withContentInclusion(Object suppressableValue, boolean suppressNulls) { if ((_suppressableValue == suppressableValue) && (_suppressNulls == suppressNulls)) { return this; } return new MapEntrySerializer(this, _property, _valueTypeSerializer, _keySerializer, _valueSerializer, suppressableValue, suppressNulls); } @Override public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { JsonSerializer ser = null; JsonSerializer keySer = null; final AnnotationIntrospector intr = provider.getAnnotationIntrospector(); final AnnotatedMember propertyAcc = (property == null) ? null : property.getMember(); // First: if we have a property, may have property-annotation overrides if (propertyAcc != null && intr != null) { Object serDef = intr.findKeySerializer(propertyAcc); if (serDef != null) { keySer = provider.serializerInstance(propertyAcc, serDef); } serDef = intr.findContentSerializer(propertyAcc); if (serDef != null) { ser = provider.serializerInstance(propertyAcc, serDef); } } if (ser == null) { ser = _valueSerializer; } // [databind#124]: May have a content converter ser = findContextualConvertingSerializer(provider, property, ser); if (ser == null) { // 30-Sep-2012, tatu: One more thing -- if explicit content type is annotated, // we can consider it a static case as well. // 20-Aug-2013, tatu: Need to avoid trying to access serializer for java.lang.Object tho if (_valueTypeIsStatic && !_valueType.isJavaLangObject()) { ser = provider.findValueSerializer(_valueType, property); } } if (keySer == null) { keySer = _keySerializer; } if (keySer == null) { keySer = provider.findKeySerializer(_keyType, property); } else { keySer = provider.handleSecondaryContextualization(keySer, property); } Object valueToSuppress = _suppressableValue; boolean suppressNulls = _suppressNulls; if (property != null) { JsonInclude.Value inclV = property.findPropertyInclusion(provider.getConfig(), null); if (inclV != null) { JsonInclude.Include incl = inclV.getContentInclusion(); if (incl != JsonInclude.Include.USE_DEFAULTS) { switch (incl) { case NON_DEFAULT: valueToSuppress = BeanUtil.getDefaultValue(_valueType); suppressNulls = true; if (valueToSuppress != null) { if (valueToSuppress.getClass().isArray()) { valueToSuppress = ArrayBuilders.getArrayComparator(valueToSuppress); } } break; case NON_ABSENT: suppressNulls = true; valueToSuppress = _valueType.isReferenceType() ? MARKER_FOR_EMPTY : null; break; case NON_EMPTY: suppressNulls = true; valueToSuppress = MARKER_FOR_EMPTY; break; case CUSTOM: valueToSuppress = provider.includeFilterInstance(null, inclV.getContentFilter()); if (valueToSuppress == null) { // is this legal? suppressNulls = true; } else { suppressNulls = provider.includeFilterSuppressNulls(valueToSuppress); } break; case NON_NULL: valueToSuppress = null; suppressNulls = true; break; case ALWAYS: // default default: valueToSuppress = null; // 30-Sep-2016, tatu: Should not need to check global flags here, // if inclusion forced to be ALWAYS suppressNulls = false; break; } } } } MapEntrySerializer mser = withResolved(property, keySer, ser, valueToSuppress, suppressNulls); // but note: no (full) filtering or sorting (unlike Maps) return mser; } /* /********************************************************** /* Accessors /********************************************************** */ @Override public JavaType getContentType() { return _valueType; } @Override public JsonSerializer getContentSerializer() { return _valueSerializer; } @Override public boolean hasSingleElement(Map.Entry value) { return true; } @Override public boolean isEmpty(SerializerProvider prov, Entry entry) { Object value = entry.getValue(); if (value == null) { return _suppressNulls; } if (_suppressableValue == null) { return false; } JsonSerializer valueSer = _valueSerializer; if (valueSer == null) { // Let's not worry about generic types here, actually; // unlikely to make any difference, but does add significant overhead Class cc = value.getClass(); valueSer = _dynamicValueSerializers.serializerFor(cc); if (valueSer == null) { try { valueSer = _findAndAddDynamic(_dynamicValueSerializers, cc, prov); } catch (JsonMappingException e) { // Ugh... cannot just throw as-is, so... return false; } } } if (_suppressableValue == MARKER_FOR_EMPTY) { return valueSer.isEmpty(prov, value); } return _suppressableValue.equals(value); } /* /********************************************************** /* Serialization methods /********************************************************** */ @Override public void serialize(Map.Entry value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(value); serializeDynamic(value, gen, provider); gen.writeEndObject(); } @Override public void serializeWithType(Map.Entry value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // [databind#631]: Assign current value, to be accessible by custom serializers g.setCurrentValue(value); WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.START_OBJECT)); serializeDynamic(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } protected void serializeDynamic(Map.Entry value, JsonGenerator gen, SerializerProvider provider) throws IOException { final TypeSerializer vts = _valueTypeSerializer; final Object keyElem = value.getKey(); JsonSerializer keySerializer; if (keyElem == null) { keySerializer = provider.findNullKeySerializer(_keyType, _property); } else { keySerializer = _keySerializer; } // or by value; nulls often suppressed final Object valueElem = value.getValue(); JsonSerializer valueSer; // And then value if (valueElem == null) { if (_suppressNulls) { return; } valueSer = provider.getDefaultNullValueSerializer(); } else { valueSer = _valueSerializer; if (valueSer == null) { Class cc = valueElem.getClass(); valueSer = _dynamicValueSerializers.serializerFor(cc); if (valueSer == null) { if (_valueType.hasGenericTypes()) { valueSer = _findAndAddDynamic(_dynamicValueSerializers, provider.constructSpecializedType(_valueType, cc), provider); } else { valueSer = _findAndAddDynamic(_dynamicValueSerializers, cc, provider); } } } // also may need to skip non-empty values: if (_suppressableValue != null) { if (_suppressableValue == MARKER_FOR_EMPTY) { if (valueSer.isEmpty(provider, valueElem)) { return; } } if (_suppressableValue.equals(valueElem)) { return; } } } keySerializer.serialize(keyElem, gen, provider); try { if (vts == null) { valueSer.serialize(valueElem, gen, provider); } else { valueSer.serializeWithType(valueElem, gen, provider, vts); } } catch (Exception e) { String keyDesc = ""+keyElem; wrapAndThrow(provider, e, value, keyDesc); } } /* /********************************************************** /* Internal helper methods /********************************************************** */ protected final JsonSerializer _findAndAddDynamic(PropertySerializerMap map, Class type, SerializerProvider provider) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property); if (map != result.map) { _dynamicValueSerializers = result.map; } return result.serializer; } protected final JsonSerializer _findAndAddDynamic(PropertySerializerMap map, JavaType type, SerializerProvider provider) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property); if (map != result.map) { _dynamicValueSerializers = result.map; } return result.serializer; } }ObjectIdWriter.java000066400000000000000000000054171325620701100357340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.databind.*; /** * Object that knows how to serialize Object Ids. */ public final class ObjectIdWriter { public final JavaType idType; /** * Name of id property to write, if not null: if null, should * only write references, but id property is handled by some * other entity. */ public final SerializableString propertyName; /** * Blueprint generator instance: actual instance will be * fetched from {@link SerializerProvider} using this as * the key. */ public final ObjectIdGenerator generator; /** * Serializer used for serializing id values. */ public final JsonSerializer serializer; /** * Marker that indicates what the first reference is to be * serialized as full POJO, or as Object Id (other references * will always be serialized as Object Id) * * @since 2.1 */ public final boolean alwaysAsId; /* /********************************************************** /* Life-cycle /********************************************************** */ @SuppressWarnings("unchecked") protected ObjectIdWriter(JavaType t, SerializableString propName, ObjectIdGenerator gen, JsonSerializer ser, boolean alwaysAsId) { idType = t; propertyName = propName; generator = gen; serializer = (JsonSerializer) ser; this.alwaysAsId = alwaysAsId; } /** * Factory method called by {@link com.fasterxml.jackson.databind.ser.std.BeanSerializerBase} * with the initial information based on standard settings for the type * for which serializer is being built. * * @since 2.3 */ public static ObjectIdWriter construct(JavaType idType, PropertyName propName, ObjectIdGenerator generator, boolean alwaysAsId) { String simpleName = (propName == null) ? null : propName.getSimpleName(); SerializableString serName = (simpleName == null) ? null : new SerializedString(simpleName); return new ObjectIdWriter(idType, serName, generator, null, alwaysAsId); } public ObjectIdWriter withSerializer(JsonSerializer ser) { return new ObjectIdWriter(idType, propertyName, generator, ser, alwaysAsId); } /** * @since 2.1 */ public ObjectIdWriter withAlwaysAsId(boolean newState) { if (newState == alwaysAsId) { return this; } return new ObjectIdWriter(idType, propertyName, generator, serializer, newState); } } PropertyBasedObjectIdGenerator.java000066400000000000000000000052341325620701100411070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.introspect.ObjectIdInfo; import com.fasterxml.jackson.databind.ser.*; public class PropertyBasedObjectIdGenerator extends ObjectIdGenerators.PropertyGenerator { private static final long serialVersionUID = 1L; protected final BeanPropertyWriter _property; public PropertyBasedObjectIdGenerator(ObjectIdInfo oid, BeanPropertyWriter prop) { this(oid.getScope(), prop); } protected PropertyBasedObjectIdGenerator(Class scope, BeanPropertyWriter prop) { super(scope); _property = prop; } /** * We must override this method, to prevent errors when scopes are the same, * but underlying class (on which to access property) is different. */ @Override public boolean canUseFor(ObjectIdGenerator gen) { if (gen.getClass() == getClass()) { PropertyBasedObjectIdGenerator other = (PropertyBasedObjectIdGenerator) gen; if (other.getScope() == _scope) { /* 26-Jul-2012, tatu: This is actually not enough, because the property * accessor within BeanPropertyWriter won't work for other property fields * (see [https://github.com/FasterXML/jackson-module-jaxb-annotations/issues/9] * for details). * So we need to verify that underlying property is actually the same. */ return (other._property == _property); } } return false; } @Override public Object generateId(Object forPojo) { try { return _property.get(forPojo); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new IllegalStateException("Problem accessing property '" +_property.getName()+"': "+e.getMessage(), e); } } @Override public ObjectIdGenerator forScope(Class scope) { return (scope == _scope) ? this : new PropertyBasedObjectIdGenerator(scope, _property); } @Override public ObjectIdGenerator newForSerialization(Object context) { // No state, can return this return this; } @Override public com.fasterxml.jackson.annotation.ObjectIdGenerator.IdKey key(Object key) { if (key == null) { return null; } // should we use general type for all; or type of property itself? return new IdKey(getClass(), _scope, key); } } PropertySerializerMap.java000066400000000000000000000321341325620701100373640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.util.Arrays; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; /** * Helper container used for resolving serializers for dynamic (possibly but not * necessarily polymorphic) properties: properties whose type is not forced * to use dynamic (declared) type and that are not final. * If so, serializer to use can only be established once actual value type is known. * Since this happens a lot unless static typing is forced (or types are final) * this implementation is optimized for efficiency. * Instances are immutable; new instances are created with factory methods: this * is important to ensure correct multi-threaded access. */ public abstract class PropertySerializerMap { /** * Configuration setting that determines what happens when maximum * size (currently 8) is reached: if true, will "start from beginning"; * if false, will simply stop adding new entries. * * @since 2.5 */ protected final boolean _resetWhenFull; /** * @since 2.5 */ protected PropertySerializerMap(boolean resetWhenFull) { _resetWhenFull = resetWhenFull; } protected PropertySerializerMap(PropertySerializerMap base) { _resetWhenFull = base._resetWhenFull; } /** * Main lookup method. Takes a "raw" type since usage is always from * place where parameterization is fixed such that there cannot be * type-parametric variations. */ public abstract JsonSerializer serializerFor(Class type); /** * Method called if initial lookup fails, when looking for a primary * serializer (one that is directly attached to a property). * Will both find serializer * and construct new map instance if warranted, and return both. * * @since 2.3 * * @throws JsonMappingException */ public final SerializerAndMapResult findAndAddPrimarySerializer(Class type, SerializerProvider provider, BeanProperty property) throws JsonMappingException { JsonSerializer serializer = provider.findPrimaryPropertySerializer(type, property); return new SerializerAndMapResult(serializer, newWith(type, serializer)); } public final SerializerAndMapResult findAndAddPrimarySerializer(JavaType type, SerializerProvider provider, BeanProperty property) throws JsonMappingException { JsonSerializer serializer = provider.findPrimaryPropertySerializer(type, property); return new SerializerAndMapResult(serializer, newWith(type.getRawClass(), serializer)); } /** * Method called if initial lookup fails, when looking for a non-primary * serializer (one that is not directly attached to a property). * Will both find serializer * and construct new map instance if warranted, and return both. * * @since 2.3 * * @throws JsonMappingException */ public final SerializerAndMapResult findAndAddSecondarySerializer(Class type, SerializerProvider provider, BeanProperty property) throws JsonMappingException { JsonSerializer serializer = provider.findValueSerializer(type, property); return new SerializerAndMapResult(serializer, newWith(type, serializer)); } public final SerializerAndMapResult findAndAddSecondarySerializer(JavaType type, SerializerProvider provider, BeanProperty property) throws JsonMappingException { JsonSerializer serializer = provider.findValueSerializer(type, property); return new SerializerAndMapResult(serializer, newWith(type.getRawClass(), serializer)); } /** * Method called if initial lookup fails, when looking for a root value * serializer: one that is not directly attached to a property, but needs to * have {@link com.fasterxml.jackson.databind.jsontype.TypeSerializer} wrapped * around it. Will both find the serializer * and construct new map instance if warranted, and return both. * * @since 2.5 * * @throws JsonMappingException */ public final SerializerAndMapResult findAndAddRootValueSerializer(Class type, SerializerProvider provider) throws JsonMappingException { JsonSerializer serializer = provider.findTypedValueSerializer(type, false, null); return new SerializerAndMapResult(serializer, newWith(type, serializer)); } /** * @since 2.5 */ public final SerializerAndMapResult findAndAddRootValueSerializer(JavaType type, SerializerProvider provider) throws JsonMappingException { JsonSerializer serializer = provider.findTypedValueSerializer(type, false, null); return new SerializerAndMapResult(serializer, newWith(type.getRawClass(), serializer)); } /** * Method called if initial lookup fails, when looking for a key * serializer (possible attached indirectly to a property) * Will both find serializer * and construct new map instance if warranted, and return both. * * @since 2.7 */ public final SerializerAndMapResult findAndAddKeySerializer(Class type, SerializerProvider provider, BeanProperty property) throws JsonMappingException { JsonSerializer serializer = provider.findKeySerializer(type, property); return new SerializerAndMapResult(serializer, newWith(type, serializer)); } /** * Method that can be used to 'register' a serializer that caller has resolved * without help of this map. * * @since 2.5 */ public final SerializerAndMapResult addSerializer(Class type, JsonSerializer serializer) { return new SerializerAndMapResult(serializer, newWith(type, serializer)); } /** * @since 2.5 */ public final SerializerAndMapResult addSerializer(JavaType type, JsonSerializer serializer) { return new SerializerAndMapResult(serializer, newWith(type.getRawClass(), serializer)); } public abstract PropertySerializerMap newWith(Class type, JsonSerializer serializer); /** * @deprecated Since 2.5 Use {@link #emptyForProperties} instead */ @Deprecated public static PropertySerializerMap emptyMap() { return emptyForProperties(); } /** * @since 2.5 */ public static PropertySerializerMap emptyForProperties() { return Empty.FOR_PROPERTIES; } /** * @since 2.5 */ public static PropertySerializerMap emptyForRootValues() { return Empty.FOR_ROOT_VALUES; } /* /********************************************************** /* Helper classes /********************************************************** */ /** * Value class used for returning tuple that has both serializer * that was retrieved and new map instance */ public final static class SerializerAndMapResult { public final JsonSerializer serializer; public final PropertySerializerMap map; public SerializerAndMapResult(JsonSerializer serializer, PropertySerializerMap map) { this.serializer = serializer; this.map = map; } } /** * Trivial container for bundling type + serializer entries. */ private final static class TypeAndSerializer { public final Class type; public final JsonSerializer serializer; public TypeAndSerializer(Class type, JsonSerializer serializer) { this.type = type; this.serializer = serializer; } } /* /********************************************************** /* Implementations /********************************************************** */ /** * Bogus instance that contains no serializers; used as the default * map with new serializers. */ private final static class Empty extends PropertySerializerMap { // No root serializers; do not reset when full public final static Empty FOR_PROPERTIES = new Empty(false); // Yes, root serializers; do reset when full public final static Empty FOR_ROOT_VALUES = new Empty(true); protected Empty(boolean resetWhenFull) { super(resetWhenFull); } @Override public JsonSerializer serializerFor(Class type) { return null; // empty, nothing to find } @Override public PropertySerializerMap newWith(Class type, JsonSerializer serializer) { return new Single(this, type, serializer); } } /** * Map that contains a single serializer; although seemingly silly * this is probably the most commonly used variant because many * theoretically dynamic or polymorphic types just have single * actual type. */ private final static class Single extends PropertySerializerMap { private final Class _type; private final JsonSerializer _serializer; public Single(PropertySerializerMap base, Class type, JsonSerializer serializer) { super(base); _type = type; _serializer = serializer; } @Override public JsonSerializer serializerFor(Class type) { if (type == _type) { return _serializer; } return null; } @Override public PropertySerializerMap newWith(Class type, JsonSerializer serializer) { return new Double(this, _type, _serializer, type, serializer); } } private final static class Double extends PropertySerializerMap { private final Class _type1, _type2; private final JsonSerializer _serializer1, _serializer2; public Double(PropertySerializerMap base, Class type1, JsonSerializer serializer1, Class type2, JsonSerializer serializer2) { super(base); _type1 = type1; _serializer1 = serializer1; _type2 = type2; _serializer2 = serializer2; } @Override public JsonSerializer serializerFor(Class type) { if (type == _type1) { return _serializer1; } if (type == _type2) { return _serializer2; } return null; } @Override public PropertySerializerMap newWith(Class type, JsonSerializer serializer) { // Ok: let's just create generic one TypeAndSerializer[] ts = new TypeAndSerializer[3]; ts[0] = new TypeAndSerializer(_type1, _serializer1); ts[1] = new TypeAndSerializer(_type2, _serializer2); ts[2] = new TypeAndSerializer(type, serializer); return new Multi(this, ts); } } private final static class Multi extends PropertySerializerMap { /** * Let's limit number of serializers we actually cache; linear * lookup won't scale too well beyond smallish number, and if * we really want to support larger collections should use * a hash map. But it seems unlikely this is a common use * case so for now let's just stop building after hard-coded * limit. 8 sounds like a reasonable stab for now. */ private final static int MAX_ENTRIES = 8; private final TypeAndSerializer[] _entries; public Multi(PropertySerializerMap base, TypeAndSerializer[] entries) { super(base); _entries = entries; } @Override public JsonSerializer serializerFor(Class type) { for (int i = 0, len = _entries.length; i < len; ++i) { TypeAndSerializer entry = _entries[i]; if (entry.type == type) { return entry.serializer; } } return null; } @Override public PropertySerializerMap newWith(Class type, JsonSerializer serializer) { int len = _entries.length; // Will only grow up to N entries. We could consider couple of alternatives after // this if we wanted to... but for now, two main choices make most sense if (len == MAX_ENTRIES) { if (_resetWhenFull) { return new Single(this, type, serializer); } return this; } TypeAndSerializer[] entries = Arrays.copyOf(_entries, len+1); entries[len] = new TypeAndSerializer(type, serializer); return new Multi(this, entries); } } } ReadOnlyClassToSerializerMap.java000066400000000000000000000120311325620701100405400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.util.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.util.TypeKey; /** * Optimized lookup table for accessing two types of serializers; typed * and non-typed. Only accessed from a single thread, so no synchronization * needed for accessors. *

* Note that before 2.6 this class was much smaller, and referred most * operations to separate JsonSerializerMap, but in 2.6 * functions were combined. */ public final class ReadOnlyClassToSerializerMap { private final Bucket[] _buckets; private final int _size; private final int _mask; public ReadOnlyClassToSerializerMap(Map> serializers) { int size = findSize(serializers.size()); _size = size; _mask = (size-1); Bucket[] buckets = new Bucket[size]; for (Map.Entry> entry : serializers.entrySet()) { TypeKey key = entry.getKey(); int index = key.hashCode() & _mask; buckets[index] = new Bucket(buckets[index], key, entry.getValue()); } _buckets = buckets; } private final static int findSize(int size) { // For small enough results (64 or less), we'll require <= 50% fill rate; otherwise 80% int needed = (size <= 64) ? (size + size) : (size + (size >> 2)); int result = 8; while (result < needed) { result += result; } return result; } /** * Factory method for constructing an instance. */ public static ReadOnlyClassToSerializerMap from(HashMap> src) { return new ReadOnlyClassToSerializerMap(src); } /* /********************************************************** /* Public API /********************************************************** */ public int size() { return _size; } public JsonSerializer typedValueSerializer(JavaType type) { Bucket bucket = _buckets[TypeKey.typedHash(type) & _mask]; if (bucket == null) { return null; } if (bucket.matchesTyped(type)) { return bucket.value; } while ((bucket = bucket.next) != null) { if (bucket.matchesTyped(type)) { return bucket.value; } } return null; } public JsonSerializer typedValueSerializer(Class type) { Bucket bucket = _buckets[TypeKey.typedHash(type) & _mask]; if (bucket == null) { return null; } if (bucket.matchesTyped(type)) { return bucket.value; } while ((bucket = bucket.next) != null) { if (bucket.matchesTyped(type)) { return bucket.value; } } return null; } public JsonSerializer untypedValueSerializer(JavaType type) { Bucket bucket = _buckets[TypeKey.untypedHash(type) & _mask]; if (bucket == null) { return null; } if (bucket.matchesUntyped(type)) { return bucket.value; } while ((bucket = bucket.next) != null) { if (bucket.matchesUntyped(type)) { return bucket.value; } } return null; } public JsonSerializer untypedValueSerializer(Class type) { Bucket bucket = _buckets[TypeKey.untypedHash(type) & _mask]; if (bucket == null) { return null; } if (bucket.matchesUntyped(type)) { return bucket.value; } while ((bucket = bucket.next) != null) { if (bucket.matchesUntyped(type)) { return bucket.value; } } return null; } /* /********************************************************** /* Helper classes /********************************************************** */ private final static class Bucket { public final JsonSerializer value; public final Bucket next; protected final Class _class; protected final JavaType _type; protected final boolean _isTyped; public Bucket(Bucket next, TypeKey key, JsonSerializer value) { this.next = next; this.value = value; _isTyped = key.isTyped(); _class = key.getRawType(); _type = key.getType(); } public boolean matchesTyped(Class key) { return (_class == key) && _isTyped; } public boolean matchesUntyped(Class key) { return (_class == key) && !_isTyped; } public boolean matchesTyped(JavaType key) { return _isTyped && key.equals(_type); } public boolean matchesUntyped(JavaType key) { return !_isTyped && key.equals(_type); } } } SimpleBeanPropertyFilter.java000066400000000000000000000245551325620701100400120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.ser.*; /** * Simple {@link PropertyFilter} implementation that only uses property name * to determine whether to serialize property as is, or to filter it out. *

* Use of this class as the base implementation for any custom * {@link PropertyFilter} implementations is strongly encouraged, * because it can provide default implementation for any methods that may * be added in {@link PropertyFilter} (as unfortunate as additions may be). */ @SuppressWarnings("deprecation") public class SimpleBeanPropertyFilter implements BeanPropertyFilter, PropertyFilter // sub-classes must also implement java.io.Serializable { /* /********************************************************** /* Life-cycle /********************************************************** */ protected SimpleBeanPropertyFilter() { } /** * Convenience factory method that will return a "no-op" filter that will * simply just serialize all properties that are given, and filter out * nothing. * * @since 2.6 */ public static SimpleBeanPropertyFilter serializeAll() { return SerializeExceptFilter.INCLUDE_ALL; } /** * Factory method that was accidentally added in 2.5 with arguments; basically * works just as an alias of {@link #filterOutAllExcept(Set)} which is not * very useful. Instead, see {@link #serializeAll()} for intended signature. * * @deprecated Since 2.6; to be removed from 2.7 */ @Deprecated public static SimpleBeanPropertyFilter serializeAll(Set properties) { return new FilterExceptFilter(properties); } /** * Factory method to construct filter that filters out all properties except * ones includes in set */ public static SimpleBeanPropertyFilter filterOutAllExcept(Set properties) { return new FilterExceptFilter(properties); } public static SimpleBeanPropertyFilter filterOutAllExcept(String... propertyArray) { HashSet properties = new HashSet(propertyArray.length); Collections.addAll(properties, propertyArray); return new FilterExceptFilter(properties); } public static SimpleBeanPropertyFilter serializeAllExcept(Set properties) { return new SerializeExceptFilter(properties); } public static SimpleBeanPropertyFilter serializeAllExcept(String... propertyArray) { HashSet properties = new HashSet(propertyArray.length); Collections.addAll(properties, propertyArray); return new SerializeExceptFilter(properties); } /** * Helper method to ease transition from {@link BeanPropertyWriter} into * {@link PropertyWriter} * * @since 2.3 */ public static PropertyFilter from(final BeanPropertyFilter src) { return new PropertyFilter() { @Override public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception { src.serializeAsField(pojo, jgen, prov, (BeanPropertyWriter) writer); } @Override public void depositSchemaProperty(PropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException { src.depositSchemaProperty((BeanPropertyWriter) writer, propertiesNode, provider); } @Override public void depositSchemaProperty(PropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException { src.depositSchemaProperty((BeanPropertyWriter) writer, objectVisitor, provider); } @Override public void serializeAsElement(Object elementValue, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception { // not needed; element filtering only available through new interfaces throw new UnsupportedOperationException(); } }; } /* /********************************************************** /* Methods for sub-classes /********************************************************** */ /** * Method called to determine whether property will be included * (if 'true' returned) or filtered out (if 'false' returned) */ protected boolean include(BeanPropertyWriter writer) { return true; } /** * Method called to determine whether property will be included * (if 'true' returned) or filtered out (if 'false' returned) * * @since 2.3 */ protected boolean include(PropertyWriter writer) { return true; } /** * Method that defines what to do with container elements * (values contained in an array or {@link java.util.Collection}: * default implementation simply writes them out. * * @since 2.3 */ protected boolean includeElement(Object elementValue) { return true; } /* /********************************************************** /* BeanPropertyFilter (deprecated) implementation /********************************************************** */ @Deprecated @Override public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider provider, BeanPropertyWriter writer) throws Exception { if (include(writer)) { writer.serializeAsField(bean, jgen, provider); } else if (!jgen.canOmitFields()) { // since 2.3 writer.serializeAsOmittedField(bean, jgen, provider); } } @Deprecated @Override public void depositSchemaProperty(BeanPropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException { if (include(writer)) { writer.depositSchemaProperty(propertiesNode, provider); } } @Deprecated @Override public void depositSchemaProperty(BeanPropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException { if (include(writer)) { writer.depositSchemaProperty(objectVisitor, provider); } } /* /********************************************************** /* PropertyFilter implementation /********************************************************** */ @Override public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception { if (include(writer)) { writer.serializeAsField(pojo, jgen, provider); } else if (!jgen.canOmitFields()) { // since 2.3 writer.serializeAsOmittedField(pojo, jgen, provider); } } @Override public void serializeAsElement(Object elementValue, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception { if (includeElement(elementValue)) { writer.serializeAsElement(elementValue, jgen, provider); } } @Deprecated @Override public void depositSchemaProperty(PropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException { if (include(writer)) { writer.depositSchemaProperty(propertiesNode, provider); } } @Override public void depositSchemaProperty(PropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException { if (include(writer)) { writer.depositSchemaProperty(objectVisitor, provider); } } /* /********************************************************** /* Sub-classes /********************************************************** */ /** * Filter implementation which defaults to filtering out unknown * properties and only serializes ones explicitly listed. */ public static class FilterExceptFilter extends SimpleBeanPropertyFilter implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Set of property names to serialize. */ protected final Set _propertiesToInclude; public FilterExceptFilter(Set properties) { _propertiesToInclude = properties; } @Override protected boolean include(BeanPropertyWriter writer) { return _propertiesToInclude.contains(writer.getName()); } @Override protected boolean include(PropertyWriter writer) { return _propertiesToInclude.contains(writer.getName()); } } /** * Filter implementation which defaults to serializing all * properties, except for ones explicitly listed to be filtered out. */ public static class SerializeExceptFilter extends SimpleBeanPropertyFilter implements java.io.Serializable { private static final long serialVersionUID = 1L; final static SerializeExceptFilter INCLUDE_ALL = new SerializeExceptFilter(); /** * Set of property names to filter out. */ protected final Set _propertiesToExclude; SerializeExceptFilter() { _propertiesToExclude = Collections.emptySet(); } public SerializeExceptFilter(Set properties) { _propertiesToExclude = properties; } @Override protected boolean include(BeanPropertyWriter writer) { return !_propertiesToExclude.contains(writer.getName()); } @Override protected boolean include(PropertyWriter writer) { return !_propertiesToExclude.contains(writer.getName()); } } }SimpleFilterProvider.java000066400000000000000000000133671325620701100371710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.util.*; import com.fasterxml.jackson.databind.ser.*; /** * Simple {@link FilterProvider} implementation that just stores * direct id-to-filter mapping. *

* Note that version 2.3 was a partial rewrite, now that * {@link PropertyFilter} is set to replace BeanPropertyFilter. */ public class SimpleFilterProvider extends FilterProvider implements java.io.Serializable // since 2.1 { // for 2.5+ private static final long serialVersionUID = 1L; /** * Mappings from ids to filters. */ protected final Map _filtersById; /** * This is the filter we return in case no mapping was found for * given id; default is 'null' (in which case caller typically * reports an error), but can be set to an explicit filter. */ protected PropertyFilter _defaultFilter; /** * Flag that indicates whether request for an unknown filter id should * result an exception (default) or not. * Note that this is only relevant if no default filter has been * configured. */ protected boolean _cfgFailOnUnknownId = true; /* /********************************************************** /* Life-cycle: constructing, configuring /********************************************************** */ public SimpleFilterProvider() { this(new HashMap()); } /** * @param mapping Mapping from id to filter; used as is if if possible */ @SuppressWarnings("unchecked") public SimpleFilterProvider(Map mapping) { /* 16-Oct-2013, tatu: Since we can now be getting both new and old * obsolete filters (PropertyFilter vs BeanPropertyFilter), need * to verify contents. */ for (Object ob : mapping.values()) { if (!(ob instanceof PropertyFilter)) { _filtersById = _convert(mapping); return; } } _filtersById = (Map) mapping; } @SuppressWarnings("deprecation") private final static Map _convert(Map filters) { HashMap result = new HashMap(); for (Map.Entry entry : filters.entrySet()) { Object f = entry.getValue(); if (f instanceof PropertyFilter) { result.put(entry.getKey(), (PropertyFilter) f); } else if (f instanceof BeanPropertyFilter) { result.put(entry.getKey(), _convert((BeanPropertyFilter) f)); } else { throw new IllegalArgumentException("Unrecognized filter type ("+f.getClass().getName()+")"); } } return result; } @SuppressWarnings("deprecation") private final static PropertyFilter _convert(BeanPropertyFilter f) { return SimpleBeanPropertyFilter.from((BeanPropertyFilter) f); } /** * Method for defining filter to return for "unknown" filters; cases * where there is no mapping from given id to an explicit filter. * * @param f Filter to return when no filter is found for given id * * @deprecated Since 2.3 should use {@link PropertyFilter} instead of {@link BeanPropertyFilter} */ @Deprecated public SimpleFilterProvider setDefaultFilter(BeanPropertyFilter f) { _defaultFilter = SimpleBeanPropertyFilter.from(f); return this; } public SimpleFilterProvider setDefaultFilter(PropertyFilter f) { _defaultFilter = f; return this; } /** * Overloaded variant just to resolve "ties" when using {@link SimpleBeanPropertyFilter}. */ public SimpleFilterProvider setDefaultFilter(SimpleBeanPropertyFilter f) { _defaultFilter = f; return this; } public PropertyFilter getDefaultFilter() { return _defaultFilter; } public SimpleFilterProvider setFailOnUnknownId(boolean state) { _cfgFailOnUnknownId = state; return this; } public boolean willFailOnUnknownId() { return _cfgFailOnUnknownId; } /** * @deprecated since 2.3 */ @Deprecated public SimpleFilterProvider addFilter(String id, BeanPropertyFilter filter) { _filtersById.put(id, _convert(filter)); return this; } public SimpleFilterProvider addFilter(String id, PropertyFilter filter) { _filtersById.put(id, filter); return this; } /** * Overloaded variant just to resolve "ties" when using {@link SimpleBeanPropertyFilter}. */ public SimpleFilterProvider addFilter(String id, SimpleBeanPropertyFilter filter) { _filtersById.put(id, filter); return this; } public PropertyFilter removeFilter(String id) { return _filtersById.remove(id); } /* /********************************************************** /* Public lookup API /********************************************************** */ @Deprecated // since 2.3 @Override public BeanPropertyFilter findFilter(Object filterId) { throw new UnsupportedOperationException("Access to deprecated filters not supported"); } @Override public PropertyFilter findPropertyFilter(Object filterId, Object valueToFilter) { PropertyFilter f = _filtersById.get(filterId); if (f == null) { f = _defaultFilter; if (f == null && _cfgFailOnUnknownId) { throw new IllegalArgumentException("No filter configured with id '"+filterId+"' (type " +filterId.getClass().getName()+")"); } } return f; } } StringArraySerializer.java000066400000000000000000000167151325620701100373560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContainerSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.std.ArraySerializerBase; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Standard serializer used for String[] values. */ @JacksonStdImpl @SuppressWarnings("serial") public class StringArraySerializer extends ArraySerializerBase implements ContextualSerializer { /* Note: not clean in general, but we are betting against * anyone re-defining properties of String.class here... */ @SuppressWarnings("deprecation") private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(String.class); public final static StringArraySerializer instance = new StringArraySerializer(); /** * Value serializer to use, if it's not the standard one * (if it is we can optimize serialization a lot) */ protected final JsonSerializer _elementSerializer; /* /********************************************************** /* Life-cycle /********************************************************** */ protected StringArraySerializer() { super(String[].class); _elementSerializer = null; } @SuppressWarnings("unchecked") public StringArraySerializer(StringArraySerializer src, BeanProperty prop, JsonSerializer ser, Boolean unwrapSingle) { super(src, prop, unwrapSingle); _elementSerializer = (JsonSerializer) ser; } @Override public JsonSerializer _withResolved(BeanProperty prop, Boolean unwrapSingle) { return new StringArraySerializer(this, prop, _elementSerializer, unwrapSingle); } /** * Strings never add type info; hence, even if type serializer is suggested, * we'll ignore it... */ @Override public ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { return this; } /* /********************************************************** /* Post-processing /********************************************************** */ @Override public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { /* 29-Sep-2012, tatu: Actually, we need to do much more contextual * checking here since we finally know for sure the property, * and it may have overrides */ JsonSerializer ser = null; // First: if we have a property, may have property-annotation overrides if (property != null) { final AnnotationIntrospector ai = provider.getAnnotationIntrospector(); AnnotatedMember m = property.getMember(); if (m != null) { Object serDef = ai.findContentSerializer(m); if (serDef != null) { ser = provider.serializerInstance(m, serDef); } } } // but since formats have both property overrides and global per-type defaults, // need to do that separately Boolean unwrapSingle = findFormatFeature(provider, property, String[].class, JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); if (ser == null) { ser = _elementSerializer; } // May have a content converter ser = findContextualConvertingSerializer(provider, property, ser); if (ser == null) { ser = provider.findValueSerializer(String.class, property); } // Optimization: default serializer just writes String, so we can avoid a call: if (isDefaultSerializer(ser)) { ser = null; } // note: will never have TypeSerializer, because Strings are "natural" type if ((ser == _elementSerializer) && (unwrapSingle == _unwrapSingle)) { return this; } return new StringArraySerializer(this, property, ser, unwrapSingle); } /* /********************************************************** /* Simple accessors /********************************************************** */ @Override public JavaType getContentType() { return VALUE_TYPE; } @Override public JsonSerializer getContentSerializer() { return _elementSerializer; } @Override public boolean isEmpty(SerializerProvider prov, String[] value) { return (value.length == 0); } @Override public boolean hasSingleElement(String[] value) { return (value.length == 1); } /* /********************************************************** /* Actual serialization /********************************************************** */ @Override public final void serialize(String[] value, JsonGenerator gen, SerializerProvider provider) throws IOException { final int len = value.length; if (len == 1) { if (((_unwrapSingle == null) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) || (_unwrapSingle == Boolean.TRUE)) { serializeContents(value, gen, provider); return; } } gen.writeStartArray(len); serializeContents(value, gen, provider); gen.writeEndArray(); } @Override public void serializeContents(String[] value, JsonGenerator gen, SerializerProvider provider) throws IOException { final int len = value.length; if (len == 0) { return; } if (_elementSerializer != null) { serializeContentsSlow(value, gen, provider, _elementSerializer); return; } for (int i = 0; i < len; ++i) { String str = value[i]; if (str == null) { gen.writeNull(); } else { gen.writeString(value[i]); } } } private void serializeContentsSlow(String[] value, JsonGenerator gen, SerializerProvider provider, JsonSerializer ser) throws IOException { for (int i = 0, len = value.length; i < len; ++i) { String str = value[i]; if (str == null) { provider.defaultSerializeNull(gen); } else { ser.serialize(value[i], gen, provider); } } } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("array", true).set("items", createSchemaNode("string")); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitArrayFormat(visitor, typeHint, JsonFormatTypes.STRING); } } StringCollectionSerializer.java000066400000000000000000000074431325620701100403710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.std.StaticListSerializerBase; /** * Efficient implement for serializing {@link Collection}s that contain Strings. * The only complexity is due to possibility that serializer for {@link String} * may be overridde; because of this, logic is needed to ensure that the default * serializer is in use to use fastest mode, or if not, to defer to custom * String serializer. */ @JacksonStdImpl @SuppressWarnings("serial") public class StringCollectionSerializer extends StaticListSerializerBase> { public final static StringCollectionSerializer instance = new StringCollectionSerializer(); /* /********************************************************** /* Life-cycle /********************************************************** */ protected StringCollectionSerializer() { super(Collection.class); } protected StringCollectionSerializer(StringCollectionSerializer src, Boolean unwrapSingle) { super(src, unwrapSingle); } @Override public JsonSerializer _withResolved(BeanProperty prop, Boolean unwrapSingle) { return new StringCollectionSerializer(this, unwrapSingle); } @Override protected JsonNode contentSchema() { return createSchemaNode("string", true); } @Override protected void acceptContentVisitor(JsonArrayFormatVisitor visitor) throws JsonMappingException { visitor.itemsFormat(JsonFormatTypes.STRING); } /* /********************************************************** /* Actual serialization /********************************************************** */ @Override public void serialize(Collection value, JsonGenerator g, SerializerProvider provider) throws IOException { g.setCurrentValue(value); final int len = value.size(); if (len == 1) { if (((_unwrapSingle == null) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) || (_unwrapSingle == Boolean.TRUE)) { serializeContents(value, g, provider); return; } } g.writeStartArray(len); serializeContents(value, g, provider); g.writeEndArray(); } @Override public void serializeWithType(Collection value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { g.setCurrentValue(value); WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.START_ARRAY)); serializeContents(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } private final void serializeContents(Collection value, JsonGenerator g, SerializerProvider provider) throws IOException { int i = 0; try { for (String str : value) { if (str == null) { provider.defaultSerializeNull(g); } else { g.writeString(str); } ++i; } } catch (Exception e) { wrapAndThrow(provider, e, value, i); } } } TypeWrappedSerializer.java000066400000000000000000000051761325620701100373540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; /** * Simple serializer that will call configured type serializer, passing * in configured data serializer, and exposing it all as a simple * serializer. */ public final class TypeWrappedSerializer extends JsonSerializer implements ContextualSerializer // since 2.9 { final protected TypeSerializer _typeSerializer; final protected JsonSerializer _serializer; @SuppressWarnings("unchecked") public TypeWrappedSerializer(TypeSerializer typeSer, JsonSerializer ser) { super(); _typeSerializer = typeSer; _serializer = (JsonSerializer) ser; } @Override public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException { _serializer.serializeWithType(value, g, provider, _typeSerializer); } @Override public void serializeWithType(Object value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // Is this an erroneous call? For now, let's assume it is not, and // that type serializer is just overridden if so _serializer.serializeWithType(value, g, provider, typeSer); } @Override public Class handledType() { return Object.class; } /* /********************************************************** /* ContextualDeserializer /********************************************************** */ @Override // since 2.9 public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { // 13-Mar-2017, tatu: Should we call `TypeSerializer.forProperty()`? JsonSerializer ser = _serializer; if (ser instanceof ContextualSerializer) { ser = provider.handleSecondaryContextualization(ser, property); } if (ser == _serializer) { return this; } return new TypeWrappedSerializer(_typeSerializer, ser); } /* /********************************************************** /* Extended API for other core classes /********************************************************** */ public JsonSerializer valueSerializer() { return _serializer; } public TypeSerializer typeSerializer() { return _typeSerializer; } } UnknownSerializer.java000066400000000000000000000047761325620701100365540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; @SuppressWarnings("serial") public class UnknownSerializer extends StdSerializer { public UnknownSerializer() { super(Object.class); } /** * @since 2.6 */ public UnknownSerializer(Class cls) { super(cls, false); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { // 27-Nov-2009, tatu: As per [JACKSON-201] may or may not fail... if (provider.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) { failForEmpty(provider, value); } // But if it's fine, we'll just output empty JSON Object: gen.writeStartObject(); gen.writeEndObject(); } @Override public final void serializeWithType(Object value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { if (provider.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) { failForEmpty(provider, value); } WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.START_OBJECT)); typeSer.writeTypeSuffix(gen, typeIdDef); } @Override public boolean isEmpty(SerializerProvider provider, Object value) { return true; } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { return null; } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitor.expectAnyFormat(typeHint); } protected void failForEmpty(SerializerProvider prov, Object value) throws JsonMappingException { prov.reportBadDefinition(handledType(), String.format( "No serializer found for class %s and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)", value.getClass().getName())); } } UnwrappingBeanPropertyWriter.java000066400000000000000000000173141325620701100407350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.util.Iterator; import java.util.Map.Entry; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Variant of {@link BeanPropertyWriter} which will handle unwrapping * of JSON Object (including of properties of Object within surrounding * JSON object, and not as sub-object). */ public class UnwrappingBeanPropertyWriter extends BeanPropertyWriter implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Transformer used to add prefix and/or suffix for properties * of unwrapped POJO. */ protected final NameTransformer _nameTransformer; /* /********************************************************** /* Life-cycle /********************************************************** */ public UnwrappingBeanPropertyWriter(BeanPropertyWriter base, NameTransformer unwrapper) { super(base); _nameTransformer = unwrapper; } protected UnwrappingBeanPropertyWriter(UnwrappingBeanPropertyWriter base, NameTransformer transformer, SerializedString name) { super(base, name); _nameTransformer = transformer; } @Override public UnwrappingBeanPropertyWriter rename(NameTransformer transformer) { String oldName = _name.getValue(); String newName = transformer.transform(oldName); // important: combine transformers: transformer = NameTransformer.chainedTransformer(transformer, _nameTransformer); return _new(transformer, new SerializedString(newName)); } /** * Overridable factory method used by sub-classes * * @since 2.6.0 */ protected UnwrappingBeanPropertyWriter _new(NameTransformer transformer, SerializedString newName) { return new UnwrappingBeanPropertyWriter(this, transformer, newName); } /* /********************************************************** /* Overrides, public methods /********************************************************** */ @Override public boolean isUnwrapping() { return true; } @Override public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { final Object value = get(bean); if (value == null) { // Hmmh. I assume we MUST pretty much suppress nulls, since we // can't really unwrap them... return; } JsonSerializer ser = _serializer; if (ser == null) { Class cls = value.getClass(); PropertySerializerMap map = _dynamicSerializers; ser = map.serializerFor(cls); if (ser == null) { ser = _findAndAddDynamic(map, cls, prov); } } if (_suppressableValue != null) { if (MARKER_FOR_EMPTY == _suppressableValue) { if (ser.isEmpty(prov, value)) { return; } } else if (_suppressableValue.equals(value)) { return; } } // For non-nulls, first: simple check for direct cycles if (value == bean) { if (_handleSelfReference(bean, gen, prov, ser)) { return; } } // note: must verify we are using unwrapping serializer; if not, will write field name if (!ser.isUnwrappingSerializer()) { gen.writeFieldName(_name); } if (_typeSerializer == null) { ser.serialize(value, gen, prov); } else { ser.serializeWithType(value, gen, prov, _typeSerializer); } } // need to override as we must get unwrapping instance... @Override public void assignSerializer(JsonSerializer ser) { if (ser != null) { NameTransformer t = _nameTransformer; if (ser.isUnwrappingSerializer()) { t = NameTransformer.chainedTransformer(t, ((UnwrappingBeanSerializer) ser)._nameTransformer); } ser = ser.unwrappingSerializer(t); } super.assignSerializer(ser); } /* /********************************************************** /* Overrides: schema generation /********************************************************** */ @Override public void depositSchemaProperty(final JsonObjectFormatVisitor visitor, SerializerProvider provider) throws JsonMappingException { JsonSerializer ser = provider .findValueSerializer(this.getType(), this) .unwrappingSerializer(_nameTransformer); if (ser.isUnwrappingSerializer()) { ser.acceptJsonFormatVisitor(new JsonFormatVisitorWrapper.Base(provider) { // an unwrapping serializer will always expect ObjectFormat, // hence, the other cases do not have to be implemented @Override public JsonObjectFormatVisitor expectObjectFormat(JavaType type) throws JsonMappingException { return visitor; } }, this.getType()); } else { super.depositSchemaProperty(visitor, provider); } } // Override needed to support legacy JSON Schema generator @Override protected void _depositSchemaProperty(ObjectNode propertiesNode, JsonNode schemaNode) { JsonNode props = schemaNode.get("properties"); if (props != null) { Iterator> it = props.fields(); while (it.hasNext()) { Entry entry = it.next(); String name = entry.getKey(); if (_nameTransformer != null) { name = _nameTransformer.transform(name); } propertiesNode.set(name, entry.getValue()); } } } /* /********************************************************** /* Overrides: internal, other /********************************************************** */ // need to override as we must get unwrapping instance... @Override protected JsonSerializer _findAndAddDynamic(PropertySerializerMap map, Class type, SerializerProvider provider) throws JsonMappingException { JsonSerializer serializer; if (_nonTrivialBaseType != null) { JavaType subtype = provider.constructSpecializedType(_nonTrivialBaseType, type); serializer = provider.findValueSerializer(subtype, this); } else { serializer = provider.findValueSerializer(type, this); } NameTransformer t = _nameTransformer; if (serializer.isUnwrappingSerializer()) { t = NameTransformer.chainedTransformer(t, ((UnwrappingBeanSerializer) serializer)._nameTransformer); } serializer = serializer.unwrappingSerializer(t); _dynamicSerializers = _dynamicSerializers.newWith(type, serializer); return serializer; } } UnwrappingBeanSerializer.java000066400000000000000000000120061325620701100400160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; import com.fasterxml.jackson.databind.util.NameTransformer; import java.io.IOException; import java.util.Set; public class UnwrappingBeanSerializer extends BeanSerializerBase implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Transformer used to add prefix and/or suffix for properties * of unwrapped POJO. */ protected final NameTransformer _nameTransformer; /* /********************************************************** /* Life-cycle: constructors /********************************************************** */ /** * Constructor used for creating unwrapping instance of a * standard BeanSerializer */ public UnwrappingBeanSerializer(BeanSerializerBase src, NameTransformer transformer) { super(src, transformer); _nameTransformer = transformer; } public UnwrappingBeanSerializer(UnwrappingBeanSerializer src, ObjectIdWriter objectIdWriter) { super(src, objectIdWriter); _nameTransformer = src._nameTransformer; } public UnwrappingBeanSerializer(UnwrappingBeanSerializer src, ObjectIdWriter objectIdWriter, Object filterId) { super(src, objectIdWriter, filterId); _nameTransformer = src._nameTransformer; } protected UnwrappingBeanSerializer(UnwrappingBeanSerializer src, Set toIgnore) { super(src, toIgnore); _nameTransformer = src._nameTransformer; } /* /********************************************************** /* Life-cycle: factory methods, fluent factories /********************************************************** */ @Override public JsonSerializer unwrappingSerializer(NameTransformer transformer) { // !!! 23-Jan-2012, tatu: Should we chain transformers? return new UnwrappingBeanSerializer(this, transformer); } @Override public boolean isUnwrappingSerializer() { return true; // sure is } @Override public BeanSerializerBase withObjectIdWriter(ObjectIdWriter objectIdWriter) { return new UnwrappingBeanSerializer(this, objectIdWriter); } @Override public BeanSerializerBase withFilterId(Object filterId) { return new UnwrappingBeanSerializer(this, _objectIdWriter, filterId); } @Override protected BeanSerializerBase withIgnorals(Set toIgnore) { return new UnwrappingBeanSerializer(this, toIgnore); } /** * JSON Array output cannot be done if unwrapping operation is * requested; so implementation will simply return 'this'. */ @Override protected BeanSerializerBase asArraySerializer() { return this; } /* /********************************************************** /* JsonSerializer implementation that differs between impls /********************************************************** */ /** * Main serialization method that will delegate actual output to * configured * {@link BeanPropertyWriter} instances. */ @Override public final void serialize(Object bean, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.setCurrentValue(bean); // [databind#631] if (_objectIdWriter != null) { _serializeWithObjectId(bean, gen, provider, false); return; } if (_propertyFilterId != null) { serializeFieldsFiltered(bean, gen, provider); } else { serializeFields(bean, gen, provider); } } @Override public void serializeWithType(Object bean, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { if (provider.isEnabled(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS)) { provider.reportBadDefinition(handledType(), "Unwrapped property requires use of type information: cannot serialize without disabling `SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS`"); } gen.setCurrentValue(bean); // [databind#631] if (_objectIdWriter != null) { _serializeWithObjectId(bean, gen, provider, typeSer); return; } if (_propertyFilterId != null) { serializeFieldsFiltered(bean, gen, provider); } else { serializeFields(bean, gen, provider); } } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return "UnwrappingBeanSerializer for "+handledType().getName(); } } WritableObjectId.java000066400000000000000000000046031325620701100362250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/implpackage com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.databind.SerializerProvider; /** * Simple value container used to keep track of Object Ids during * serialization. */ public final class WritableObjectId { public final ObjectIdGenerator generator; public Object id; /** * Marker to denote whether Object Id value has been written as part of an Object, * to be referencible. Remains false when forward-reference is written. */ protected boolean idWritten = false; public WritableObjectId(ObjectIdGenerator generator) { this.generator = generator; } public boolean writeAsId(JsonGenerator gen, SerializerProvider provider, ObjectIdWriter w) throws IOException { if ((id != null) && (idWritten || w.alwaysAsId)) { // 03-Aug-2013, tatu: Prefer Native Object Ids if available if (gen.canWriteObjectId()) { gen.writeObjectRef(String.valueOf(id)); } else { w.serializer.serialize(id, gen, provider); } return true; } return false; } public Object generateId(Object forPojo) { // 04-Jun-2016, tatu: As per [databind#1255], need to consider possibility of // id being generated for "alwaysAsId", but not being written as POJO; regardless, // need to use existing id if there is one: if (id == null) { id = generator.generateId(forPojo); } return id; } /** * Method called to output Object Id as specified. */ public void writeAsField(JsonGenerator gen, SerializerProvider provider, ObjectIdWriter w) throws IOException { idWritten = true; // 03-Aug-2013, tatu: Prefer Native Object Ids if available if (gen.canWriteObjectId()) { // Need to assume String(ified) ids, for now... could add 'long' variant? gen.writeObjectId(String.valueOf(id)); return; } SerializableString name = w.propertyName; if (name != null) { gen.writeFieldName(name); w.serializer.serialize(id, gen, provider); } } } package-info.java000066400000000000000000000002071325620701100353700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/impl/** * Contains implementation classes of serialization part of * data binding. */ package com.fasterxml.jackson.databind.ser.impl; package-info.java000066400000000000000000000002021325620701100344220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/** * Contains implementation classes of serialization part of * data binding. */ package com.fasterxml.jackson.databind.ser; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/std/000077500000000000000000000000001325620701100321125ustar00rootroot00000000000000ArraySerializerBase.java000066400000000000000000000114551325620701100366070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.*; /** * Intermediate base class for serializers used for various * Java arrays. * * @param Type of arrays serializer handles */ @SuppressWarnings("serial") public abstract class ArraySerializerBase extends ContainerSerializer implements ContextualSerializer // for 'unwrapSingleElemArray' { protected final BeanProperty _property; /** * Setting for specific local override for "unwrap single element arrays": * true for enable unwrapping, false for preventing it, `null` for using * global configuration. * * @since 2.6 */ protected final Boolean _unwrapSingle; protected ArraySerializerBase(Class cls) { super(cls); _property = null; _unwrapSingle = null; } /** * Use either variant that just takes type (non-contextual), or, * copy constructor that allows passing of property. * * @deprecated Since 2.6 */ @Deprecated protected ArraySerializerBase(Class cls, BeanProperty property) { super(cls); _property = property; _unwrapSingle = null; } protected ArraySerializerBase(ArraySerializerBase src) { super(src._handledType, false); _property = src._property; _unwrapSingle = src._unwrapSingle; } /** * @since 2.6 */ protected ArraySerializerBase(ArraySerializerBase src, BeanProperty property, Boolean unwrapSingle) { super(src._handledType, false); _property = property; _unwrapSingle = unwrapSingle; } /** * @deprecated Since 2.6 */ @Deprecated protected ArraySerializerBase(ArraySerializerBase src, BeanProperty property) { super(src._handledType, false); _property = property; _unwrapSingle = src._unwrapSingle; } /** * @since 2.6 */ public abstract JsonSerializer _withResolved(BeanProperty prop, Boolean unwrapSingle); @Override public JsonSerializer createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException { Boolean unwrapSingle = null; // First: if we have a property, may have property-annotation overrides if (property != null) { JsonFormat.Value format = findFormatOverrides(serializers, property, handledType()); if (format != null) { unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); if (unwrapSingle != _unwrapSingle) { return _withResolved(property, unwrapSingle); } } } return this; } // NOTE: as of 2.5, sub-classes SHOULD override (in 2.4 and before, was final), // at least if they can provide access to actual size of value and use `writeStartArray()` // variant that passes size of array to output, which is helpful with some data formats @Override public void serialize(T value, JsonGenerator gen, SerializerProvider provider) throws IOException { if (_shouldUnwrapSingle(provider)) { if (hasSingleElement(value)) { serializeContents(value, gen, provider); return; } } gen.setCurrentValue(value); gen.writeStartArray(); // [databind#631]: Assign current value, to be accessible by custom serializers serializeContents(value, gen, provider); gen.writeEndArray(); } @Override public final void serializeWithType(T value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // [databind#631]: Assign current value, to be accessible by custom serializers g.setCurrentValue(value); WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.START_ARRAY)); serializeContents(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } protected abstract void serializeContents(T value, JsonGenerator jgen, SerializerProvider provider) throws IOException; /** * @since 2.9 */ protected final boolean _shouldUnwrapSingle(SerializerProvider provider) { if (_unwrapSingle == null) { return provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); } return _unwrapSingle.booleanValue(); } } AsArraySerializerBase.java000066400000000000000000000275341325620701100371000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonschema.SchemaAware; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.ContainerSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; /** * Base class for serializers that will output contents as JSON * arrays; typically serializers used for {@link java.util.Collection} * and array types. */ @SuppressWarnings("serial") public abstract class AsArraySerializerBase extends ContainerSerializer implements ContextualSerializer { protected final JavaType _elementType; /** * Collection-valued property being serialized with this instance */ protected final BeanProperty _property; protected final boolean _staticTyping; /** * Setting for specific local override for "unwrap single element arrays": * true for enable unwrapping, false for preventing it, `null` for using * global configuration. * * @since 2.6 */ protected final Boolean _unwrapSingle; /** * Type serializer used for values, if any. */ protected final TypeSerializer _valueTypeSerializer; /** * Value serializer to use, if it can be statically determined */ protected final JsonSerializer _elementSerializer; /** * If element type cannot be statically determined, mapping from * runtime type to serializer is handled using this object */ protected PropertySerializerMap _dynamicSerializers; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * Non-contextual, "blueprint" constructor typically called when the first * instance is created, without knowledge of property it was used via. * * @since 2.6 */ protected AsArraySerializerBase(Class cls, JavaType et, boolean staticTyping, TypeSerializer vts, JsonSerializer elementSerializer) { super(cls, false); _elementType = et; // static if explicitly requested, or if element type is final _staticTyping = staticTyping || (et != null && et.isFinal()); _valueTypeSerializer = vts; _property = null; _elementSerializer = elementSerializer; _dynamicSerializers = PropertySerializerMap.emptyForProperties(); _unwrapSingle = null; } /** * @deprecated Since 2.6 Use variants that either take 'src', or do NOT pass * BeanProperty */ @Deprecated protected AsArraySerializerBase(Class cls, JavaType et, boolean staticTyping, TypeSerializer vts, BeanProperty property, JsonSerializer elementSerializer) { // typing with generics is messy... have to resort to this: super(cls, false); _elementType = et; // static if explicitly requested, or if element type is final _staticTyping = staticTyping || (et != null && et.isFinal()); _valueTypeSerializer = vts; _property = property; _elementSerializer = elementSerializer; _dynamicSerializers = PropertySerializerMap.emptyForProperties(); _unwrapSingle = null; } @SuppressWarnings("unchecked") protected AsArraySerializerBase(AsArraySerializerBase src, BeanProperty property, TypeSerializer vts, JsonSerializer elementSerializer, Boolean unwrapSingle) { super(src); _elementType = src._elementType; _staticTyping = src._staticTyping; _valueTypeSerializer = vts; _property = property; _elementSerializer = (JsonSerializer) elementSerializer; _dynamicSerializers = src._dynamicSerializers; _unwrapSingle = unwrapSingle; } /** * @deprecated since 2.6: use the overloaded method that takes 'unwrapSingle' */ @Deprecated protected AsArraySerializerBase(AsArraySerializerBase src, BeanProperty property, TypeSerializer vts, JsonSerializer elementSerializer) { this(src, property, vts, elementSerializer, src._unwrapSingle); } /** * @deprecated since 2.6: use the overloaded method that takes 'unwrapSingle' */ @Deprecated public final AsArraySerializerBase withResolved(BeanProperty property, TypeSerializer vts, JsonSerializer elementSerializer) { return withResolved(property, vts, elementSerializer, _unwrapSingle); } /** * @since 2.6 */ public abstract AsArraySerializerBase withResolved(BeanProperty property, TypeSerializer vts, JsonSerializer elementSerializer, Boolean unwrapSingle); /* /********************************************************** /* Post-processing /********************************************************** */ /** * This method is needed to resolve contextual annotations like * per-property overrides, as well as do recursive call * to createContextual of content serializer, if * known statically. */ @Override public JsonSerializer createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException { TypeSerializer typeSer = _valueTypeSerializer; if (typeSer != null) { typeSer = typeSer.forProperty(property); } JsonSerializer ser = null; Boolean unwrapSingle = null; // First: if we have a property, may have property-annotation overrides if (property != null) { final AnnotationIntrospector intr = serializers.getAnnotationIntrospector(); AnnotatedMember m = property.getMember(); if (m != null) { Object serDef = intr.findContentSerializer(m); if (serDef != null) { ser = serializers.serializerInstance(m, serDef); } } } JsonFormat.Value format = findFormatOverrides(serializers, property, handledType()); if (format != null) { unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); } if (ser == null) { ser = _elementSerializer; } // 18-Feb-2013, tatu: May have a content converter: ser = findContextualConvertingSerializer(serializers, property, ser); if (ser == null) { // 30-Sep-2012, tatu: One more thing -- if explicit content type is annotated, // we can consider it a static case as well. if (_elementType != null) { if (_staticTyping && !_elementType.isJavaLangObject()) { ser = serializers.findValueSerializer(_elementType, property); } } } if ((ser != _elementSerializer) || (property != _property) || (_valueTypeSerializer != typeSer) || (_unwrapSingle != unwrapSingle)) { return withResolved(property, typeSer, ser, unwrapSingle); } return this; } /* /********************************************************** /* Accessors /********************************************************** */ @Override public JavaType getContentType() { return _elementType; } @Override public JsonSerializer getContentSerializer() { return _elementSerializer; } /* /********************************************************** /* Serialization /********************************************************** */ // NOTE: as of 2.5, sub-classes SHOULD override (in 2.4 and before, was final), // at least if they can provide access to actual size of value and use `writeStartArray()` // variant that passes size of array to output, which is helpful with some data formats @Override public void serialize(T value, JsonGenerator gen, SerializerProvider provider) throws IOException { if (provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) && hasSingleElement(value)) { serializeContents(value, gen, provider); return; } gen.writeStartArray(); // [databind#631]: Assign current value, to be accessible by custom serializers gen.setCurrentValue(value); serializeContents(value, gen, provider); gen.writeEndArray(); } @Override public void serializeWithType(T value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // [databind#631]: Assign current value, to be accessible by custom serializers g.setCurrentValue(value); WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.START_ARRAY)); serializeContents(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } protected abstract void serializeContents(T value, JsonGenerator gen, SerializerProvider provider) throws IOException; @SuppressWarnings("deprecation") @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { ObjectNode o = createSchemaNode("array", true); if (_elementSerializer != null) { JsonNode schemaNode = null; if (_elementSerializer instanceof SchemaAware) { schemaNode = ((SchemaAware) _elementSerializer).getSchema(provider, null); } if (schemaNode == null) { schemaNode = com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode(); } o.set("items", schemaNode); } return o; } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { JsonSerializer valueSer = _elementSerializer; if (valueSer == null) { // 19-Oct-2016, tatu: Apparently we get null for untyped/raw `EnumSet`s... not 100% // sure what'd be the clean way but let's try this for now: if (_elementType != null) { valueSer = visitor.getProvider().findValueSerializer(_elementType, _property); } } visitArrayFormat(visitor, typeHint, valueSer, _elementType); } protected final JsonSerializer _findAndAddDynamic(PropertySerializerMap map, Class type, SerializerProvider provider) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property); // did we get a new map of serializers? If so, start using it if (map != result.map) { _dynamicSerializers = result.map; } return result.serializer; } protected final JsonSerializer _findAndAddDynamic(PropertySerializerMap map, JavaType type, SerializerProvider provider) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property); if (map != result.map) { _dynamicSerializers = result.map; } return result.serializer; } } AtomicReferenceSerializer.java000066400000000000000000000046421325620701100377710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.type.ReferenceType; import com.fasterxml.jackson.databind.util.NameTransformer; public class AtomicReferenceSerializer extends ReferenceTypeSerializer> { private static final long serialVersionUID = 1L; /* /********************************************************** /* Constructors, factory methods /********************************************************** */ public AtomicReferenceSerializer(ReferenceType fullType, boolean staticTyping, TypeSerializer vts, JsonSerializer ser) { super(fullType, staticTyping, vts, ser); } protected AtomicReferenceSerializer(AtomicReferenceSerializer base, BeanProperty property, TypeSerializer vts, JsonSerializer valueSer, NameTransformer unwrapper, Object suppressableValue, boolean suppressNulls) { super(base, property, vts, valueSer, unwrapper, suppressableValue, suppressNulls); } @Override protected ReferenceTypeSerializer> withResolved(BeanProperty prop, TypeSerializer vts, JsonSerializer valueSer, NameTransformer unwrapper) { return new AtomicReferenceSerializer(this, prop, vts, valueSer, unwrapper, _suppressableValue, _suppressNulls); } @Override public ReferenceTypeSerializer> withContentInclusion(Object suppressableValue, boolean suppressNulls) { return new AtomicReferenceSerializer(this, _property, _valueTypeSerializer, _valueSerializer, _unwrapper, suppressableValue, suppressNulls); } /* /********************************************************** /* Abstract method impls /********************************************************** */ @Override protected boolean _isValuePresent(AtomicReference value) { return value.get() != null; } @Override protected Object _getReferenced(AtomicReference value) { return value.get(); } @Override protected Object _getReferencedIfPresent(AtomicReference value) { return value.get(); } } BeanSerializerBase.java000066400000000000000000001052251325620701100363750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.ObjectIdInfo; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.jsonschema.JsonSerializableSchema; import com.fasterxml.jackson.databind.jsonschema.SchemaAware; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.*; import com.fasterxml.jackson.databind.ser.impl.MapEntrySerializer; import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter; import com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator; import com.fasterxml.jackson.databind.ser.impl.WritableObjectId; import com.fasterxml.jackson.databind.util.ArrayBuilders; import com.fasterxml.jackson.databind.util.Converter; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Base class both for the standard bean serializer, and couple * of variants that only differ in small details. * Can be used for custom bean serializers as well, although that * is not the primary design goal. */ @SuppressWarnings("serial") public abstract class BeanSerializerBase extends StdSerializer implements ContextualSerializer, ResolvableSerializer, JsonFormatVisitable, SchemaAware { protected final static PropertyName NAME_FOR_OBJECT_REF = new PropertyName("#object-ref"); final protected static BeanPropertyWriter[] NO_PROPS = new BeanPropertyWriter[0]; /* /********************************************************** /* Configuration /********************************************************** */ /** * @since 2.9 */ final protected JavaType _beanType; /** * Writers used for outputting actual property values */ final protected BeanPropertyWriter[] _props; /** * Optional filters used to suppress output of properties that * are only to be included in certain views */ final protected BeanPropertyWriter[] _filteredProps; /** * Handler for {@link com.fasterxml.jackson.annotation.JsonAnyGetter} * annotated properties */ final protected AnyGetterWriter _anyGetterWriter; /** * Id of the bean property filter to use, if any; null if none. */ final protected Object _propertyFilterId; /** * If using custom type ids (usually via getter, or field), this is the * reference to that member. */ final protected AnnotatedMember _typeId; /** * If this POJO can be alternatively serialized using just an object id * to denote a reference to previously serialized object, * this Object will handle details. */ final protected ObjectIdWriter _objectIdWriter; /** * Requested shape from bean class annotations. */ final protected JsonFormat.Shape _serializationShape; /* /********************************************************** /* Life-cycle: constructors /********************************************************** */ /** * Constructor used by {@link BeanSerializerBuilder} to create an * instance * * @param type Nominal type of values handled by this serializer * @param builder Builder for accessing other collected information */ protected BeanSerializerBase(JavaType type, BeanSerializerBuilder builder, BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties) { super(type); _beanType = type; _props = properties; _filteredProps = filteredProperties; if (builder == null) { // mostly for testing _typeId = null; _anyGetterWriter = null; _propertyFilterId = null; _objectIdWriter = null; _serializationShape = null; } else { _typeId = builder.getTypeId(); _anyGetterWriter = builder.getAnyGetter(); _propertyFilterId = builder.getFilterId(); _objectIdWriter = builder.getObjectIdWriter(); JsonFormat.Value format = builder.getBeanDescription().findExpectedFormat(null); _serializationShape = (format == null) ? null : format.getShape(); } } public BeanSerializerBase(BeanSerializerBase src, BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties) { super(src._handledType); _beanType = src._beanType; _props = properties; _filteredProps = filteredProperties; _typeId = src._typeId; _anyGetterWriter = src._anyGetterWriter; _objectIdWriter = src._objectIdWriter; _propertyFilterId = src._propertyFilterId; _serializationShape = src._serializationShape; } protected BeanSerializerBase(BeanSerializerBase src, ObjectIdWriter objectIdWriter) { this(src, objectIdWriter, src._propertyFilterId); } /** * @since 2.3 */ protected BeanSerializerBase(BeanSerializerBase src, ObjectIdWriter objectIdWriter, Object filterId) { super(src._handledType); _beanType = src._beanType; _props = src._props; _filteredProps = src._filteredProps; _typeId = src._typeId; _anyGetterWriter = src._anyGetterWriter; _objectIdWriter = objectIdWriter; _propertyFilterId = filterId; _serializationShape = src._serializationShape; } @Deprecated // since 2.8, remove soon protected BeanSerializerBase(BeanSerializerBase src, String[] toIgnore) { this(src, ArrayBuilders.arrayToSet(toIgnore)); } protected BeanSerializerBase(BeanSerializerBase src, Set toIgnore) { super(src._handledType); _beanType = src._beanType; final BeanPropertyWriter[] propsIn = src._props; final BeanPropertyWriter[] fpropsIn = src._filteredProps; final int len = propsIn.length; ArrayList propsOut = new ArrayList(len); ArrayList fpropsOut = (fpropsIn == null) ? null : new ArrayList(len); for (int i = 0; i < len; ++i) { BeanPropertyWriter bpw = propsIn[i]; // should be ignored? if ((toIgnore != null) && toIgnore.contains(bpw.getName())) { continue; } propsOut.add(bpw); if (fpropsIn != null) { fpropsOut.add(fpropsIn[i]); } } _props = propsOut.toArray(new BeanPropertyWriter[propsOut.size()]); _filteredProps = (fpropsOut == null) ? null : fpropsOut.toArray(new BeanPropertyWriter[fpropsOut.size()]); _typeId = src._typeId; _anyGetterWriter = src._anyGetterWriter; _objectIdWriter = src._objectIdWriter; _propertyFilterId = src._propertyFilterId; _serializationShape = src._serializationShape; } /** * Mutant factory used for creating a new instance with different * {@link ObjectIdWriter}. * * @since 2.0 */ public abstract BeanSerializerBase withObjectIdWriter(ObjectIdWriter objectIdWriter); /** * Mutant factory used for creating a new instance with additional * set of properties to ignore (from properties this instance otherwise has) * * @since 2.8 */ protected abstract BeanSerializerBase withIgnorals(Set toIgnore); /** * Mutant factory used for creating a new instance with additional * set of properties to ignore (from properties this instance otherwise has) * * @deprecated since 2.8 */ @Deprecated protected BeanSerializerBase withIgnorals(String[] toIgnore) { return withIgnorals(ArrayBuilders.arrayToSet(toIgnore)); } /** * Mutant factory for creating a variant that output POJO as a * JSON Array. Implementations may ignore this request if output * as array is not possible (either at all, or reliably). * * @since 2.1 */ protected abstract BeanSerializerBase asArraySerializer(); /** * Mutant factory used for creating a new instance with different * filter id (used with JsonFilter annotation) * * @since 2.3 */ @Override public abstract BeanSerializerBase withFilterId(Object filterId); /** * Copy-constructor that is useful for sub-classes that just want to * copy all super-class properties without modifications. */ protected BeanSerializerBase(BeanSerializerBase src) { this(src, src._props, src._filteredProps); } /** * Copy-constructor that will also rename properties with given prefix * (if it's non-empty) */ protected BeanSerializerBase(BeanSerializerBase src, NameTransformer unwrapper) { this(src, rename(src._props, unwrapper), rename(src._filteredProps, unwrapper)); } private final static BeanPropertyWriter[] rename(BeanPropertyWriter[] props, NameTransformer transformer) { if (props == null || props.length == 0 || transformer == null || transformer == NameTransformer.NOP) { return props; } final int len = props.length; BeanPropertyWriter[] result = new BeanPropertyWriter[len]; for (int i = 0; i < len; ++i) { BeanPropertyWriter bpw = props[i]; if (bpw != null) { result[i] = bpw.rename(transformer); } } return result; } /* /********************************************************** /* Post-constriction processing: resolvable, contextual /********************************************************** */ /** * We need to implement {@link ResolvableSerializer} to be able to * properly handle cyclic type references. */ @Override public void resolve(SerializerProvider provider) throws JsonMappingException { int filteredCount = (_filteredProps == null) ? 0 : _filteredProps.length; for (int i = 0, len = _props.length; i < len; ++i) { BeanPropertyWriter prop = _props[i]; // let's start with null serializer resolution actually if (!prop.willSuppressNulls() && !prop.hasNullSerializer()) { JsonSerializer nullSer = provider.findNullValueSerializer(prop); if (nullSer != null) { prop.assignNullSerializer(nullSer); // also: remember to replace filtered property too? (see [JACKSON-364]) if (i < filteredCount) { BeanPropertyWriter w2 = _filteredProps[i]; if (w2 != null) { w2.assignNullSerializer(nullSer); } } } } if (prop.hasSerializer()) { continue; } // [databind#124]: allow use of converters JsonSerializer ser = findConvertingSerializer(provider, prop); if (ser == null) { // Was the serialization type hard-coded? If so, use it JavaType type = prop.getSerializationType(); // It not, we can use declared return type if and only if declared type is final: // if not, we don't really know the actual type until we get the instance. if (type == null) { type = prop.getType(); if (!type.isFinal()) { if (type.isContainerType() || type.containedTypeCount() > 0) { prop.setNonTrivialBaseType(type); } continue; } } ser = provider.findValueSerializer(type, prop); /* 04-Feb-2010, tatu: We may have stashed type serializer for content types * too, earlier; if so, it's time to connect the dots here: */ if (type.isContainerType()) { TypeSerializer typeSer = type.getContentType().getTypeHandler(); if (typeSer != null) { // for now, can do this only for standard containers... if (ser instanceof ContainerSerializer) { // ugly casts... but necessary @SuppressWarnings("unchecked") JsonSerializer ser2 = (JsonSerializer)((ContainerSerializer) ser).withValueTypeSerializer(typeSer); ser = ser2; } } } } // and maybe replace filtered property too? if (i < filteredCount) { BeanPropertyWriter w2 = _filteredProps[i]; if (w2 != null) { w2.assignSerializer(ser); // 17-Mar-2017, tatu: Typically will lead to chained call to original property, // which would lead to double set. Not a problem itself, except... unwrapping // may require work to be done, which does lead to an actual issue. continue; } } prop.assignSerializer(ser); } // also, any-getter may need to be resolved if (_anyGetterWriter != null) { // 23-Feb-2015, tatu: Misleading, as this actually triggers call to contextualization... _anyGetterWriter.resolve(provider); } } /** * Helper method that can be used to see if specified property is annotated * to indicate use of a converter for property value (in case of container types, * it is container type itself, not key or content type). * * @since 2.2 */ protected JsonSerializer findConvertingSerializer(SerializerProvider provider, BeanPropertyWriter prop) throws JsonMappingException { final AnnotationIntrospector intr = provider.getAnnotationIntrospector(); if (intr != null) { AnnotatedMember m = prop.getMember(); if (m != null) { Object convDef = intr.findSerializationConverter(m); if (convDef != null) { Converter conv = provider.converterInstance(prop.getMember(), convDef); JavaType delegateType = conv.getOutputType(provider.getTypeFactory()); // [databind#731]: Should skip if nominally java.lang.Object JsonSerializer ser = delegateType.isJavaLangObject() ? null : provider.findValueSerializer(delegateType, prop); return new StdDelegatingSerializer(conv, delegateType, ser); } } } return null; } @SuppressWarnings("incomplete-switch") @Override public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { final AnnotationIntrospector intr = provider.getAnnotationIntrospector(); final AnnotatedMember accessor = (property == null || intr == null) ? null : property.getMember(); final SerializationConfig config = provider.getConfig(); // Let's start with one big transmutation: Enums that are annotated // to serialize as Objects may want to revert JsonFormat.Value format = findFormatOverrides(provider, property, handledType()); JsonFormat.Shape shape = null; if ((format != null) && format.hasShape()) { shape = format.getShape(); // or, alternatively, asked to revert "back to" other representations... if ((shape != JsonFormat.Shape.ANY) && (shape != _serializationShape)) { if (_handledType.isEnum()) { switch (shape) { case STRING: case NUMBER: case NUMBER_INT: // 12-Oct-2014, tatu: May need to introspect full annotations... but // for now, just do class ones BeanDescription desc = config.introspectClassAnnotations(_beanType); JsonSerializer ser = EnumSerializer.construct(_beanType.getRawClass(), provider.getConfig(), desc, format); return provider.handlePrimaryContextualization(ser, property); } // 16-Oct-2016, tatu: Ditto for `Map`, `Map.Entry` subtypes } else if (shape == JsonFormat.Shape.NATURAL) { if (_beanType.isMapLikeType() && Map.class.isAssignableFrom(_handledType)) { ; } else if (Map.Entry.class.isAssignableFrom(_handledType)) { JavaType mapEntryType = _beanType.findSuperType(Map.Entry.class); JavaType kt = mapEntryType.containedTypeOrUnknown(0); JavaType vt = mapEntryType.containedTypeOrUnknown(1); // 16-Oct-2016, tatu: could have problems with type handling, as we do not // see if "static" typing is needed, nor look for `TypeSerializer` yet... JsonSerializer ser = new MapEntrySerializer(_beanType, kt, vt, false, null, property); return provider.handlePrimaryContextualization(ser, property); } } } } ObjectIdWriter oiw = _objectIdWriter; Set ignoredProps = null; Object newFilterId = null; // Then we may have an override for Object Id if (accessor != null) { JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnorals(accessor); if (ignorals != null) { ignoredProps = ignorals.findIgnoredForSerialization(); } ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor); if (objectIdInfo == null) { // no ObjectId override, but maybe ObjectIdRef? if (oiw != null) { objectIdInfo = intr.findObjectReferenceInfo(accessor, null); if (objectIdInfo != null) { oiw = _objectIdWriter.withAlwaysAsId(objectIdInfo.getAlwaysAsId()); } } } else { // Ugh: mostly copied from BeanDeserializerBase: but can't easily change it // to be able to move to SerializerProvider (where it really belongs) // 2.1: allow modifications by "id ref" annotations as well: objectIdInfo = intr.findObjectReferenceInfo(accessor, objectIdInfo); ObjectIdGenerator gen; Class implClass = objectIdInfo.getGeneratorType(); JavaType type = provider.constructType(implClass); JavaType idType = provider.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0]; // Property-based generator is trickier if (implClass == ObjectIdGenerators.PropertyGenerator.class) { // most special one, needs extra work String propName = objectIdInfo.getPropertyName().getSimpleName(); BeanPropertyWriter idProp = null; for (int i = 0, len = _props.length; ; ++i) { if (i == len) { provider.reportBadDefinition(_beanType, String.format( "Invalid Object Id definition for %s: cannot find property with name '%s'", handledType().getName(), propName)); } BeanPropertyWriter prop = _props[i]; if (propName.equals(prop.getName())) { idProp = prop; // Let's force it to be the first property to output // (although it may still get rearranged etc) if (i > 0) { // note: must shuffle both regular properties and filtered System.arraycopy(_props, 0, _props, 1, i); _props[0] = idProp; if (_filteredProps != null) { BeanPropertyWriter fp = _filteredProps[i]; System.arraycopy(_filteredProps, 0, _filteredProps, 1, i); _filteredProps[0] = fp; } } break; } } idType = idProp.getType(); gen = new PropertyBasedObjectIdGenerator(objectIdInfo, idProp); oiw = ObjectIdWriter.construct(idType, (PropertyName) null, gen, objectIdInfo.getAlwaysAsId()); } else { // other types need to be simpler gen = provider.objectIdGeneratorInstance(accessor, objectIdInfo); oiw = ObjectIdWriter.construct(idType, objectIdInfo.getPropertyName(), gen, objectIdInfo.getAlwaysAsId()); } } // Or change Filter Id in use? Object filterId = intr.findFilterId(accessor); if (filterId != null) { // but only consider case of adding a new filter id (no removal via annotation) if (_propertyFilterId == null || !filterId.equals(_propertyFilterId)) { newFilterId = filterId; } } } // either way, need to resolve serializer: BeanSerializerBase contextual = this; if (oiw != null) { JsonSerializer ser = provider.findValueSerializer(oiw.idType, property); oiw = oiw.withSerializer(ser); if (oiw != _objectIdWriter) { contextual = contextual.withObjectIdWriter(oiw); } } // And possibly add more properties to ignore if ((ignoredProps != null) && !ignoredProps.isEmpty()) { contextual = contextual.withIgnorals(ignoredProps); } if (newFilterId != null) { contextual = contextual.withFilterId(newFilterId); } if (shape == null) { shape = _serializationShape; } // last but not least; may need to transmute into as-array serialization if (shape == JsonFormat.Shape.ARRAY) { return contextual.asArraySerializer(); } return contextual; } /* /********************************************************** /* Accessors /********************************************************** */ @Override public Iterator properties() { return Arrays.asList(_props).iterator(); } /* /********************************************************** /* Partial JsonSerializer implementation /********************************************************** */ @Override public boolean usesObjectId() { return (_objectIdWriter != null); } // Main serialization method left unimplemented @Override public abstract void serialize(Object bean, JsonGenerator gen, SerializerProvider provider) throws IOException; // Type-info-augmented case implemented as it does not usually differ between impls @Override public void serializeWithType(Object bean, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { if (_objectIdWriter != null) { gen.setCurrentValue(bean); // [databind#631] _serializeWithObjectId(bean, gen, provider, typeSer); return; } gen.setCurrentValue(bean); // [databind#631] WritableTypeId typeIdDef = _typeIdDef(typeSer, bean, JsonToken.START_OBJECT); typeSer.writeTypePrefix(gen, typeIdDef); if (_propertyFilterId != null) { serializeFieldsFiltered(bean, gen, provider); } else { serializeFields(bean, gen, provider); } typeSer.writeTypeSuffix(gen, typeIdDef); } protected final void _serializeWithObjectId(Object bean, JsonGenerator gen, SerializerProvider provider, boolean startEndObject) throws IOException { final ObjectIdWriter w = _objectIdWriter; WritableObjectId objectId = provider.findObjectId(bean, w.generator); // If possible, write as id already if (objectId.writeAsId(gen, provider, w)) { return; } // If not, need to inject the id: Object id = objectId.generateId(bean); if (w.alwaysAsId) { w.serializer.serialize(id, gen, provider); return; } if (startEndObject) { gen.writeStartObject(bean); } objectId.writeAsField(gen, provider, w); if (_propertyFilterId != null) { serializeFieldsFiltered(bean, gen, provider); } else { serializeFields(bean, gen, provider); } if (startEndObject) { gen.writeEndObject(); } } protected final void _serializeWithObjectId(Object bean, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { final ObjectIdWriter w = _objectIdWriter; WritableObjectId objectId = provider.findObjectId(bean, w.generator); // If possible, write as id already if (objectId.writeAsId(gen, provider, w)) { return; } // If not, need to inject the id: Object id = objectId.generateId(bean); if (w.alwaysAsId) { w.serializer.serialize(id, gen, provider); return; } _serializeObjectId(bean, gen, provider, typeSer, objectId); } protected void _serializeObjectId(Object bean, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer, WritableObjectId objectId) throws IOException { final ObjectIdWriter w = _objectIdWriter; WritableTypeId typeIdDef = _typeIdDef(typeSer, bean, JsonToken.START_OBJECT); typeSer.writeTypePrefix(g, typeIdDef); objectId.writeAsField(g, provider, w); if (_propertyFilterId != null) { serializeFieldsFiltered(bean, g, provider); } else { serializeFields(bean, g, provider); } typeSer.writeTypeSuffix(g, typeIdDef); } /** * @since 2.9 */ protected final WritableTypeId _typeIdDef(TypeSerializer typeSer, Object bean, JsonToken valueShape) { if (_typeId == null) { return typeSer.typeId(bean, valueShape); } Object typeId = _typeId.getValue(bean); if (typeId == null) { // 28-Jun-2017, tatu: Is this really needed? Unchanged from 2.8 but... typeId = ""; } return typeSer.typeId(bean, valueShape, typeId); } @Deprecated // since 2.9 protected final String _customTypeId(Object bean) { final Object typeId = _typeId.getValue(bean); if (typeId == null) { return ""; } return (typeId instanceof String) ? (String) typeId : typeId.toString(); } /* /********************************************************** /* Field serialization methods /********************************************************** */ protected void serializeFields(Object bean, JsonGenerator gen, SerializerProvider provider) throws IOException { final BeanPropertyWriter[] props; if (_filteredProps != null && provider.getActiveView() != null) { props = _filteredProps; } else { props = _props; } int i = 0; try { for (final int len = props.length; i < len; ++i) { BeanPropertyWriter prop = props[i]; if (prop != null) { // can have nulls in filtered list prop.serializeAsField(bean, gen, provider); } } if (_anyGetterWriter != null) { _anyGetterWriter.getAndSerialize(bean, gen, provider); } } catch (Exception e) { String name = (i == props.length) ? "[anySetter]" : props[i].getName(); wrapAndThrow(provider, e, bean, name); } catch (StackOverflowError e) { // 04-Sep-2009, tatu: Dealing with this is tricky, since we don't have many // stack frames to spare... just one or two; can't make many calls. // 10-Dec-2015, tatu: and due to above, avoid "from" method, call ctor directly: //JsonMappingException mapE = JsonMappingException.from(gen, "Infinite recursion (StackOverflowError)", e); JsonMappingException mapE = new JsonMappingException(gen, "Infinite recursion (StackOverflowError)", e); String name = (i == props.length) ? "[anySetter]" : props[i].getName(); mapE.prependPath(new JsonMappingException.Reference(bean, name)); throw mapE; } } /** * Alternative serialization method that gets called when there is a * {@link PropertyFilter} that needs to be called to determine * which properties are to be serialized (and possibly how) */ protected void serializeFieldsFiltered(Object bean, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonGenerationException { /* note: almost verbatim copy of "serializeFields"; copied (instead of merged) * so that old method need not add check for existence of filter. */ final BeanPropertyWriter[] props; if (_filteredProps != null && provider.getActiveView() != null) { props = _filteredProps; } else { props = _props; } final PropertyFilter filter = findPropertyFilter(provider, _propertyFilterId, bean); // better also allow missing filter actually.. if (filter == null) { serializeFields(bean, gen, provider); return; } int i = 0; try { for (final int len = props.length; i < len; ++i) { BeanPropertyWriter prop = props[i]; if (prop != null) { // can have nulls in filtered list filter.serializeAsField(bean, gen, provider, prop); } } if (_anyGetterWriter != null) { _anyGetterWriter.getAndFilter(bean, gen, provider, filter); } } catch (Exception e) { String name = (i == props.length) ? "[anySetter]" : props[i].getName(); wrapAndThrow(provider, e, bean, name); } catch (StackOverflowError e) { // Minimize call depth since we are close to fail: //JsonMappingException mapE = JsonMappingException.from(gen, "Infinite recursion (StackOverflowError)", e); JsonMappingException mapE = new JsonMappingException(gen, "Infinite recursion (StackOverflowError)", e); String name = (i == props.length) ? "[anySetter]" : props[i].getName(); mapE.prependPath(new JsonMappingException.Reference(bean, name)); throw mapE; } } @Deprecated @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { ObjectNode o = createSchemaNode("object", true); // [JACKSON-813]: Add optional JSON Schema id attribute, if found // NOTE: not optimal, does NOT go through AnnotationIntrospector etc: JsonSerializableSchema ann = _handledType.getAnnotation(JsonSerializableSchema.class); if (ann != null) { String id = ann.id(); if (id != null && id.length() > 0) { o.put("id", id); } } //todo: should the classname go in the title? //o.put("title", _className); ObjectNode propertiesNode = o.objectNode(); final PropertyFilter filter; if (_propertyFilterId != null) { filter = findPropertyFilter(provider, _propertyFilterId, null); } else { filter = null; } for (int i = 0; i < _props.length; i++) { BeanPropertyWriter prop = _props[i]; if (filter == null) { prop.depositSchemaProperty(propertiesNode, provider); } else { filter.depositSchemaProperty(prop, propertiesNode, provider); } } o.set("properties", propertiesNode); return o; } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { //deposit your output format if (visitor == null) { return; } JsonObjectFormatVisitor objectVisitor = visitor.expectObjectFormat(typeHint); if (objectVisitor == null) { return; } final SerializerProvider provider = visitor.getProvider(); if (_propertyFilterId != null) { PropertyFilter filter = findPropertyFilter(visitor.getProvider(), _propertyFilterId, null); for (int i = 0, end = _props.length; i < end; ++i) { filter.depositSchemaProperty(_props[i], objectVisitor, provider); } } else { Class view = ((_filteredProps == null) || (provider == null)) ? null : provider.getActiveView(); final BeanPropertyWriter[] props; if (view != null) { props = _filteredProps; } else { props = _props; } for (int i = 0, end = props.length; i < end; ++i) { BeanPropertyWriter prop = props[i]; if (prop != null) { // may be filtered out unconditionally prop.depositSchemaProperty(objectVisitor, provider); } } } } } BooleanSerializer.java000066400000000000000000000124751325620701100363200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser.NumberType; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; /** * Serializer used for primitive boolean, as well as java.util.Boolean * wrapper type. *

* Since this is one of "natural" (aka "native") types, no type information is ever * included on serialization (unlike for most other scalar types) */ @JacksonStdImpl public final class BooleanSerializer //In 2.9, removed use of intermediate type `NonTypedScalarSerializerBase` extends StdScalarSerializer implements ContextualSerializer { private static final long serialVersionUID = 1L; /** * Whether type serialized is primitive (boolean) or wrapper * (java.lang.Boolean); if true, former, if false, latter. */ protected final boolean _forPrimitive; public BooleanSerializer(boolean forPrimitive) { super(forPrimitive ? Boolean.TYPE : Boolean.class, false); _forPrimitive = forPrimitive; } @Override public JsonSerializer createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException { JsonFormat.Value format = findFormatOverrides(serializers, property, Boolean.class); if (format != null) { JsonFormat.Shape shape = format.getShape(); if (shape.isNumeric()) { return new AsNumber(_forPrimitive); } } return this; } @Override public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException { g.writeBoolean(Boolean.TRUE.equals(value)); } @Override public final void serializeWithType(Object value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { g.writeBoolean(Boolean.TRUE.equals(value)); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("boolean", !_forPrimitive); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitor.expectBooleanFormat(typeHint); } /** * Alternate implementation that is used when values are to be serialized * as numbers 0 (false) or 1 (true). * * @since 2.9 */ final static class AsNumber extends StdScalarSerializer implements ContextualSerializer { private static final long serialVersionUID = 1L; /** * Whether type serialized is primitive (boolean) or wrapper * (java.lang.Boolean); if true, former, if false, latter. */ protected final boolean _forPrimitive; public AsNumber(boolean forPrimitive) { super(forPrimitive ? Boolean.TYPE : Boolean.class, false); _forPrimitive = forPrimitive; } @Override public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException { g.writeNumber((Boolean.FALSE.equals(value)) ? 0 : 1); } @Override public final void serializeWithType(Object value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // 27-Mar-2017, tatu: Actually here we CAN NOT serialize as number without type, // since with natural types that would map to number, not boolean. So choice // comes to between either add type id, or serialize as boolean. Choose // latter at this point g.writeBoolean(Boolean.TRUE.equals(value)); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { // 27-Mar-2017, tatu: As usual, bit tricky but... seems like we should call // visitor for actual representation visitIntFormat(visitor, typeHint, NumberType.INT); } @Override public JsonSerializer createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException { JsonFormat.Value format = findFormatOverrides(serializers, property, Boolean.class); if (format != null) { JsonFormat.Shape shape = format.getShape(); if (!shape.isNumeric()) { return new BooleanSerializer(_forPrimitive); } } return this; } } } ByteArraySerializer.java000066400000000000000000000071231325620701100366350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.node.ObjectNode; /** * Unlike other integral number array serializers, we do not just print out byte values * as numbers. Instead, we assume that it would make more sense to output content * as base64 encoded bytes (using default base64 encoding). *

* NOTE: since it is NOT serialized as an array, cannot use AsArraySerializer as base *

* NOTE: since 2.6, has been a main-level class; earlier was embedded in * {@link StdArraySerializers}. */ @JacksonStdImpl public class ByteArraySerializer extends StdSerializer { private static final long serialVersionUID = 1L; public ByteArraySerializer() { super(byte[].class); } @Override public boolean isEmpty(SerializerProvider prov, byte[] value) { return value.length == 0; } @Override public void serialize(byte[] value, JsonGenerator g, SerializerProvider provider) throws IOException { g.writeBinary(provider.getConfig().getBase64Variant(), value, 0, value.length); } @Override public void serializeWithType(byte[] value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // most likely scalar WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.VALUE_EMBEDDED_OBJECT)); g.writeBinary(provider.getConfig().getBase64Variant(), value, 0, value.length); typeSer.writeTypeSuffix(g, typeIdDef); /* OLD impl typeSer.writeTypePrefixForScalar(value, g); g.writeBinary(provider.getConfig().getBase64Variant(), value, 0, value.length); typeSer.writeTypeSuffixForScalar(value, g); */ } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { ObjectNode o = createSchemaNode("array", true); ObjectNode itemSchema = createSchemaNode("byte"); //binary values written as strings? return o.set("items", itemSchema); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { // 14-Mar-2016, tatu: while logically (and within JVM) binary, gets encoded as Base64 String, // let's try to indicate it is array of Bytes... difficult, thanks to JSON Schema's // lackluster listing of types // // TODO: for 2.8, make work either as String/base64, or array of numbers, // with a qualifier that can be used to determine it's byte[] JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint); if (v2 != null) { v2.itemsFormat(JsonFormatTypes.INTEGER); } } } ByteBufferSerializer.java000066400000000000000000000034111325620701100367640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.*; import java.nio.ByteBuffer; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.util.ByteBufferBackedInputStream; @SuppressWarnings("serial") public class ByteBufferSerializer extends StdScalarSerializer { public ByteBufferSerializer() { super(ByteBuffer.class); } @Override public void serialize(ByteBuffer bbuf, JsonGenerator gen, SerializerProvider provider) throws IOException { // first, simple case when wrapping an array... if (bbuf.hasArray()) { gen.writeBinary(bbuf.array(), 0, bbuf.limit()); return; } // the other case is more complicated however. Best to handle with InputStream wrapper. // But should we rewind it; and/or make a copy? ByteBuffer copy = bbuf.asReadOnlyBuffer(); if (copy.position() > 0) { copy.rewind(); } InputStream in = new ByteBufferBackedInputStream(copy); gen.writeBinary(in, copy.remaining()); in.close(); } @Override // since 2.9 public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { // 31-Mar-2017, tatu: Use same type as `ByteArraySerializer`: not optimal but has to do JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint); if (v2 != null) { v2.itemsFormat(JsonFormatTypes.INTEGER); } } } CalendarSerializer.java000066400000000000000000000027601325620701100364460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.text.DateFormat; import java.util.Calendar; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; /** * Standard serializer for {@link java.util.Calendar}. * As with other time/date types, is configurable to produce timestamps * (standard Java 64-bit timestamp) or textual formats (usually ISO-8601). */ @JacksonStdImpl @SuppressWarnings("serial") public class CalendarSerializer extends DateTimeSerializerBase { public static final CalendarSerializer instance = new CalendarSerializer(); public CalendarSerializer() { this(null, null); } public CalendarSerializer(Boolean useTimestamp, DateFormat customFormat) { super(Calendar.class, useTimestamp, customFormat); } @Override public CalendarSerializer withFormat(Boolean timestamp, DateFormat customFormat) { return new CalendarSerializer(timestamp, customFormat); } @Override protected long _timestamp(Calendar value) { return (value == null) ? 0L : value.getTimeInMillis(); } @Override public void serialize(Calendar value, JsonGenerator g, SerializerProvider provider) throws IOException { if (_asTimestamp(provider)) { g.writeNumber(_timestamp(value)); return; } _serializeAsString(value.getTime(), g, provider); } } ClassSerializer.java000066400000000000000000000024211325620701100357740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; /** * Also: default bean access will not do much good with Class.class. But * we can just serialize the class name and that should be enough. */ @SuppressWarnings("serial") public class ClassSerializer extends StdScalarSerializer> { public ClassSerializer() { super(Class.class, false); } @Override public void serialize(Class value, JsonGenerator g, SerializerProvider provider) throws IOException { g.writeString(value.getName()); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("string", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitStringFormat(visitor, typeHint); } }CollectionSerializer.java000066400000000000000000000147201325620701100370270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContainerSerializer; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; /** * Fallback serializer for cases where Collection is not known to be * of type for which more specializer serializer exists (such as * index-accessible List). * If so, we will just construct an {@link java.util.Iterator} * to iterate over elements. */ public class CollectionSerializer extends AsArraySerializerBase> { private static final long serialVersionUID = 1L; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @since 2.6 */ public CollectionSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts, JsonSerializer valueSerializer) { super(Collection.class, elemType, staticTyping, vts, valueSerializer); } /** * @deprecated since 2.6 */ @Deprecated // since 2.6 public CollectionSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts, BeanProperty property, JsonSerializer valueSerializer) { // note: assumption is 'property' is always passed as null this(elemType, staticTyping, vts, valueSerializer); } public CollectionSerializer(CollectionSerializer src, BeanProperty property, TypeSerializer vts, JsonSerializer valueSerializer, Boolean unwrapSingle) { super(src, property, vts, valueSerializer, unwrapSingle); } @Override public ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { return new CollectionSerializer(this, _property, vts, _elementSerializer, _unwrapSingle); } @Override public CollectionSerializer withResolved(BeanProperty property, TypeSerializer vts, JsonSerializer elementSerializer, Boolean unwrapSingle) { return new CollectionSerializer(this, property, vts, elementSerializer, unwrapSingle); } /* /********************************************************** /* Accessors /********************************************************** */ @Override public boolean isEmpty(SerializerProvider prov, Collection value) { return value.isEmpty(); } @Override public boolean hasSingleElement(Collection value) { return value.size() == 1; } /* /********************************************************** /* Actual serialization /********************************************************** */ @Override public final void serialize(Collection value, JsonGenerator g, SerializerProvider provider) throws IOException { final int len = value.size(); if (len == 1) { if (((_unwrapSingle == null) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) || (_unwrapSingle == Boolean.TRUE)) { serializeContents(value, g, provider); return; } } g.writeStartArray(len); serializeContents(value, g, provider); g.writeEndArray(); } @Override public void serializeContents(Collection value, JsonGenerator g, SerializerProvider provider) throws IOException { g.setCurrentValue(value); if (_elementSerializer != null) { serializeContentsUsing(value, g, provider, _elementSerializer); return; } Iterator it = value.iterator(); if (!it.hasNext()) { return; } PropertySerializerMap serializers = _dynamicSerializers; final TypeSerializer typeSer = _valueTypeSerializer; int i = 0; try { do { Object elem = it.next(); if (elem == null) { provider.defaultSerializeNull(g); } else { Class cc = elem.getClass(); JsonSerializer serializer = serializers.serializerFor(cc); if (serializer == null) { if (_elementType.hasGenericTypes()) { serializer = _findAndAddDynamic(serializers, provider.constructSpecializedType(_elementType, cc), provider); } else { serializer = _findAndAddDynamic(serializers, cc, provider); } serializers = _dynamicSerializers; } if (typeSer == null) { serializer.serialize(elem, g, provider); } else { serializer.serializeWithType(elem, g, provider, typeSer); } } ++i; } while (it.hasNext()); } catch (Exception e) { wrapAndThrow(provider, e, value, i); } } public void serializeContentsUsing(Collection value, JsonGenerator g, SerializerProvider provider, JsonSerializer ser) throws IOException { Iterator it = value.iterator(); if (it.hasNext()) { TypeSerializer typeSer = _valueTypeSerializer; int i = 0; do { Object elem = it.next(); try { if (elem == null) { provider.defaultSerializeNull(g); } else { if (typeSer == null) { ser.serialize(elem, g, provider); } else { ser.serializeWithType(elem, g, provider, typeSer); } } ++i; } catch (Exception e) { wrapAndThrow(provider, e, value, i); } } while (it.hasNext()); } } } DateSerializer.java000066400000000000000000000026661325620701100356170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.text.DateFormat; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; /** * For efficiency, we will serialize Dates as longs, instead of * potentially more readable Strings. */ @JacksonStdImpl @SuppressWarnings("serial") public class DateSerializer extends DateTimeSerializerBase { /** * Default instance that is used when no contextual configuration * is needed. */ public static final DateSerializer instance = new DateSerializer(); public DateSerializer() { this(null, null); } public DateSerializer(Boolean useTimestamp, DateFormat customFormat) { super(Date.class, useTimestamp, customFormat); } @Override public DateSerializer withFormat(Boolean timestamp, DateFormat customFormat) { return new DateSerializer(timestamp, customFormat); } @Override protected long _timestamp(Date value) { return (value == null) ? 0L : value.getTime(); } @Override public void serialize(Date value, JsonGenerator g, SerializerProvider provider) throws IOException { if (_asTimestamp(provider)) { g.writeNumber(_timestamp(value)); return; } _serializeAsString(value, g, provider); } } DateTimeSerializerBase.java000066400000000000000000000211631325620701100372220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.*; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.util.StdDateFormat; @SuppressWarnings("serial") public abstract class DateTimeSerializerBase extends StdScalarSerializer implements ContextualSerializer { /** * Flag that indicates that serialization must be done as the * Java timestamp, regardless of other settings. */ protected final Boolean _useTimestamp; /** * Specific format to use, if not default format: non null value * also indicates that serialization is to be done as JSON String, * not numeric timestamp, unless {@link #_useTimestamp} is true. */ protected final DateFormat _customFormat; /** * If {@link #_customFormat} is used, we will try to reuse instances in simplest * possible form; thread-safe, but without overhead of ThreadLocal * (not from code, but wrt retaining of possibly large number of format instances * over all threads, properties with custom formats). * * @since 2.9 */ protected final AtomicReference _reusedCustomFormat; protected DateTimeSerializerBase(Class type, Boolean useTimestamp, DateFormat customFormat) { super(type); _useTimestamp = useTimestamp; _customFormat = customFormat; _reusedCustomFormat = (customFormat == null) ? null : new AtomicReference(); } public abstract DateTimeSerializerBase withFormat(Boolean timestamp, DateFormat customFormat); @Override public JsonSerializer createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException { if (property == null) { return this; } JsonFormat.Value format = findFormatOverrides(serializers, property, handledType()); if (format == null) { return this; } // Simple case first: serialize as numeric timestamp? JsonFormat.Shape shape = format.getShape(); if (shape.isNumeric()) { return withFormat(Boolean.TRUE, null); } // 08-Jun-2017, tatu: With [databind#1648], this gets bit tricky.. // First: custom pattern will override things if (format.hasPattern()) { final Locale loc = format.hasLocale() ? format.getLocale() : serializers.getLocale(); SimpleDateFormat df = new SimpleDateFormat(format.getPattern(), loc); TimeZone tz = format.hasTimeZone() ? format.getTimeZone() : serializers.getTimeZone(); df.setTimeZone(tz); return withFormat(Boolean.FALSE, df); } // Otherwise, need one of these changes: final boolean hasLocale = format.hasLocale(); final boolean hasTZ = format.hasTimeZone(); final boolean asString = (shape == JsonFormat.Shape.STRING); if (!hasLocale && !hasTZ && !asString) { return this; } DateFormat df0 = serializers.getConfig().getDateFormat(); // Jackson's own `StdDateFormat` is quite easy to deal with... if (df0 instanceof StdDateFormat) { StdDateFormat std = (StdDateFormat) df0; if (format.hasLocale()) { std = std.withLocale(format.getLocale()); } if (format.hasTimeZone()) { std = std.withTimeZone(format.getTimeZone()); } return withFormat(Boolean.FALSE, std); } // 08-Jun-2017, tatu: Unfortunately there's no generally usable // mechanism for changing `DateFormat` instances (or even clone()ing) // So: require it be `SimpleDateFormat`; can't config other types if (!(df0 instanceof SimpleDateFormat)) { serializers.reportBadDefinition(handledType(), String.format( "Configured `DateFormat` (%s) not a `SimpleDateFormat`; cannot configure `Locale` or `TimeZone`", df0.getClass().getName())); } SimpleDateFormat df = (SimpleDateFormat) df0; if (hasLocale) { // Ugh. No way to change `Locale`, create copy; must re-crete completely: df = new SimpleDateFormat(df.toPattern(), format.getLocale()); } else { df = (SimpleDateFormat) df.clone(); } TimeZone newTz = format.getTimeZone(); boolean changeTZ = (newTz != null) && !newTz.equals(df.getTimeZone()); if (changeTZ) { df.setTimeZone(newTz); } return withFormat(Boolean.FALSE, df); } /* /********************************************************** /* Accessors /********************************************************** */ @Override public boolean isEmpty(SerializerProvider serializers, T value) { // 09-Mar-2017, tatu: as per [databind#1550] timestamp 0 is NOT "empty"; but // with versions up to 2.8.x this was the case. Fixed for 2.9. // return _timestamp(value) == 0L; return false; } protected abstract long _timestamp(T value); @Override public JsonNode getSchema(SerializerProvider serializers, Type typeHint) { //todo: (ryan) add a format for the date in the schema? return createSchemaNode(_asTimestamp(serializers) ? "number" : "string", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { _acceptJsonFormatVisitor(visitor, typeHint, _asTimestamp(visitor.getProvider())); } /* /********************************************************** /* Actual serialization /********************************************************** */ @Override public abstract void serialize(T value, JsonGenerator gen, SerializerProvider serializers) throws IOException; /* /********************************************************** /* Helper methods /********************************************************** */ protected boolean _asTimestamp(SerializerProvider serializers) { if (_useTimestamp != null) { return _useTimestamp.booleanValue(); } if (_customFormat == null) { if (serializers != null) { return serializers.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); } // 12-Jun-2014, tatu: Is it legal not to have provider? Was NPE:ing earlier so leave a check throw new IllegalArgumentException("Null SerializerProvider passed for "+handledType().getName()); } return false; } protected void _acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint, boolean asNumber) throws JsonMappingException { if (asNumber) { visitIntFormat(visitor, typeHint, JsonParser.NumberType.LONG, JsonValueFormat.UTC_MILLISEC); } else { visitStringFormat(visitor, typeHint, JsonValueFormat.DATE_TIME); } } /** * @since 2.9 */ protected void _serializeAsString(Date value, JsonGenerator g, SerializerProvider provider) throws IOException { if (_customFormat == null) { provider.defaultSerializeDateValue(value, g); return; } // 19-Jul-2017, tatu: Here we will try a simple but (hopefully) effective mechanism for // reusing formatter instance. This is our second attempt, after initially trying simple // synchronization (which turned out to be bottleneck for some users in production...). // While `ThreadLocal` could alternatively be used, it is likely that it would lead to // higher memory footprint, but without much upside -- if we can not reuse, we'll just // clone(), which has some overhead but not drastic one. DateFormat f = _reusedCustomFormat.getAndSet(null); if (f == null) { f = (DateFormat) _customFormat.clone(); } g.writeString(f.format(value)); _reusedCustomFormat.compareAndSet(null, f); } } EnumSerializer.java000066400000000000000000000203051325620701100356340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat.Shape; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.util.EnumValues; /** * Standard serializer used for {@link java.lang.Enum} types. *

* Based on {@link StdScalarSerializer} since the JSON value is * scalar (String). */ @JacksonStdImpl public class EnumSerializer extends StdScalarSerializer> implements ContextualSerializer { private static final long serialVersionUID = 1L; /** * This map contains pre-resolved values (since there are ways * to customize actual String constants to use) to use as * serializations. */ protected final EnumValues _values; /** * Flag that is set if we statically know serialization choice * between index and textual format (null if it needs to be dynamically * checked). * * @since 2.1 */ protected final Boolean _serializeAsIndex; /* /********************************************************** /* Construction, initialization /********************************************************** */ public EnumSerializer(EnumValues v, Boolean serializeAsIndex) { super(v.getEnumClass(), false); _values = v; _serializeAsIndex = serializeAsIndex; } /** * Factory method used by {@link com.fasterxml.jackson.databind.ser.BasicSerializerFactory} * for constructing serializer instance of Enum types. * * @since 2.1 */ @SuppressWarnings("unchecked") public static EnumSerializer construct(Class enumClass, SerializationConfig config, BeanDescription beanDesc, JsonFormat.Value format) { /* 08-Apr-2015, tatu: As per [databind#749], we cannot statically determine * between name() and toString(), need to construct `EnumValues` with names, * handle toString() case dynamically (for example) */ EnumValues v = EnumValues.constructFromName(config, (Class>) enumClass); Boolean serializeAsIndex = _isShapeWrittenUsingIndex(enumClass, format, true, null); return new EnumSerializer(v, serializeAsIndex); } /** * To support some level of per-property configuration, we will need * to make things contextual. We are limited to "textual vs index" * choice here, however. */ @Override public JsonSerializer createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException { JsonFormat.Value format = findFormatOverrides(serializers, property, handledType()); if (format != null) { Class type = handledType(); Boolean serializeAsIndex = _isShapeWrittenUsingIndex(type, format, false, _serializeAsIndex); if (serializeAsIndex != _serializeAsIndex) { return new EnumSerializer(_values, serializeAsIndex); } } return this; } /* /********************************************************** /* Extended API for Jackson databind core /********************************************************** */ public EnumValues getEnumValues() { return _values; } /* /********************************************************** /* Actual serialization /********************************************************** */ @Override public final void serialize(Enum en, JsonGenerator gen, SerializerProvider serializers) throws IOException { // [JACKSON-684]: serialize as index? if (_serializeAsIndex(serializers)) { gen.writeNumber(en.ordinal()); return; } // [databind#749]: or via toString()? if (serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) { gen.writeString(en.toString()); return; } gen.writeString(_values.serializedValueFor(en)); } /* /********************************************************** /* Schema support /********************************************************** */ @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { if (_serializeAsIndex(provider)) { return createSchemaNode("integer", true); } ObjectNode objectNode = createSchemaNode("string", true); if (typeHint != null) { JavaType type = provider.constructType(typeHint); if (type.isEnumType()) { ArrayNode enumNode = objectNode.putArray("enum"); for (SerializableString value : _values.values()) { enumNode.add(value.getValue()); } } } return objectNode; } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { SerializerProvider serializers = visitor.getProvider(); if (_serializeAsIndex(serializers)) { visitIntFormat(visitor, typeHint, JsonParser.NumberType.INT); return; } JsonStringFormatVisitor stringVisitor = visitor.expectStringFormat(typeHint); if (stringVisitor != null) { Set enums = new LinkedHashSet(); // Use toString()? if ((serializers != null) && serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) { for (Enum e : _values.enums()) { enums.add(e.toString()); } } else { // No, serialize using name() or explicit overrides for (SerializableString value : _values.values()) { enums.add(value.getValue()); } } stringVisitor.enumTypes(enums); } } /* /********************************************************** /* Helper methods /********************************************************** */ protected final boolean _serializeAsIndex(SerializerProvider serializers) { if (_serializeAsIndex != null) { return _serializeAsIndex.booleanValue(); } return serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX); } /** * Helper method called to check whether serialization should be done using * index (number) or not. */ protected static Boolean _isShapeWrittenUsingIndex(Class enumClass, JsonFormat.Value format, boolean fromClass, Boolean defaultValue) { JsonFormat.Shape shape = (format == null) ? null : format.getShape(); if (shape == null) { return defaultValue; } // i.e. "default", check dynamically if (shape == Shape.ANY || shape == Shape.SCALAR) { return defaultValue; } // 19-May-2016, tatu: also consider "natural" shape if (shape == Shape.STRING || shape == Shape.NATURAL) { return Boolean.FALSE; } // 01-Oct-2014, tatu: For convenience, consider "as-array" to also mean 'yes, use index') if (shape.isNumeric() || (shape == Shape.ARRAY)) { return Boolean.TRUE; } // 07-Mar-2017, tatu: Also means `OBJECT` not available as property annotation... throw new IllegalArgumentException(String.format( "Unsupported serialization shape (%s) for Enum %s, not supported as %s annotation", shape, enumClass.getName(), (fromClass? "class" : "property"))); } } EnumSetSerializer.java000066400000000000000000000056611325620701100363200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; @SuppressWarnings("serial") public class EnumSetSerializer extends AsArraySerializerBase>> { /** * @since 2.6 */ public EnumSetSerializer(JavaType elemType) { super(EnumSet.class, elemType, true, null, null); } public EnumSetSerializer(EnumSetSerializer src, BeanProperty property, TypeSerializer vts, JsonSerializer valueSerializer, Boolean unwrapSingle) { super(src, property, vts, valueSerializer, unwrapSingle); } @Override public EnumSetSerializer _withValueTypeSerializer(TypeSerializer vts) { // no typing for enums (always "hard" type) return this; } @Override public EnumSetSerializer withResolved(BeanProperty property, TypeSerializer vts, JsonSerializer elementSerializer, Boolean unwrapSingle) { return new EnumSetSerializer(this, property, vts, elementSerializer, unwrapSingle); } @Override public boolean isEmpty(SerializerProvider prov, EnumSet> value) { return value.isEmpty(); } @Override public boolean hasSingleElement(EnumSet> value) { return value.size() == 1; } @Override public final void serialize(EnumSet> value, JsonGenerator gen, SerializerProvider provider) throws IOException { final int len = value.size(); if (len == 1) { if (((_unwrapSingle == null) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) || (_unwrapSingle == Boolean.TRUE)) { serializeContents(value, gen, provider); return; } } gen.writeStartArray(len); serializeContents(value, gen, provider); gen.writeEndArray(); } @Override public void serializeContents(EnumSet> value, JsonGenerator gen, SerializerProvider provider) throws IOException { JsonSerializer enumSer = _elementSerializer; /* Need to dynamically find instance serializer; unfortunately * that seems to be the only way to figure out type (no accessors * to the enum class that set knows) */ for (Enum en : value) { if (enumSer == null) { /* 12-Jan-2010, tatu: Since enums cannot be polymorphic, let's * not bother with typed serializer variant here */ enumSer = provider.findValueSerializer(en.getDeclaringClass(), _property); } enumSer.serialize(en, gen, provider); } } } FileSerializer.java000066400000000000000000000023671325620701100356170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.File; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; /** * For now, File objects get serialized by just outputting * absolute (but not canonical) name as String value */ @SuppressWarnings("serial") public class FileSerializer extends StdScalarSerializer { public FileSerializer() { super(File.class); } @Override public void serialize(File value, JsonGenerator g, SerializerProvider provider) throws IOException { g.writeString(value.getAbsolutePath()); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("string", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitStringFormat(visitor, typeHint); } }InetAddressSerializer.java000066400000000000000000000063721325620701100371450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.net.InetAddress; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; /** * Simple serializer for {@link java.net.InetAddress}. Main complexity is * with registration, since same serializer is to be used for sub-classes. *

* Since 2.9 allows use of {@link JsonFormat} configuration (annotation, * per-type defaulting) so that if JsonFormat.Shape.NUMBER * (or ARRAY) is used, will serialize as "host address" * (dotted numbers) instead of simple conversion. */ @SuppressWarnings("serial") public class InetAddressSerializer extends StdScalarSerializer implements ContextualSerializer { /** * @since 2.9 */ protected final boolean _asNumeric; public InetAddressSerializer() { this(false); } /** * @since 2.9 */ public InetAddressSerializer(boolean asNumeric) { super(InetAddress.class); _asNumeric = asNumeric; } @Override public JsonSerializer createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException { JsonFormat.Value format = findFormatOverrides(serializers, property, handledType()); boolean asNumeric = false; if (format != null) { JsonFormat.Shape shape = format.getShape(); if (shape.isNumeric() || shape == JsonFormat.Shape.ARRAY) { asNumeric = true; } } if (asNumeric != _asNumeric) { return new InetAddressSerializer(asNumeric); } return this; } @Override public void serialize(InetAddress value, JsonGenerator g, SerializerProvider provider) throws IOException { String str; if (_asNumeric) { // since 2.9 str = value.getHostAddress(); } else { // Ok: get textual description; choose "more specific" part str = value.toString().trim(); int ix = str.indexOf('/'); if (ix >= 0) { if (ix == 0) { // missing host name; use address str = str.substring(1); } else { // otherwise use name str = str.substring(0, ix); } } } g.writeString(str); } @Override public void serializeWithType(InetAddress value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // Better ensure we don't use specific sub-classes... WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, InetAddress.class, JsonToken.VALUE_STRING)); serialize(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } } InetSocketAddressSerializer.java000066400000000000000000000035021325620701100403060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.net.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * Simple serializer for {@link InetSocketAddress}. */ @SuppressWarnings("serial") public class InetSocketAddressSerializer extends StdScalarSerializer { public InetSocketAddressSerializer() { super(InetSocketAddress.class); } @Override public void serialize(InetSocketAddress value, JsonGenerator jgen, SerializerProvider provider) throws IOException { InetAddress addr = value.getAddress(); String str = addr == null ? value.getHostName() : addr.toString().trim(); int ix = str.indexOf('/'); if (ix >= 0) { if (ix == 0) { // missing host name; use address str = addr instanceof Inet6Address ? "[" + str.substring(1) + "]" // bracket IPv6 addresses with : str.substring(1); } else { // otherwise use name str = str.substring(0, ix); } } jgen.writeString(str + ":" + value.getPort()); } @Override public void serializeWithType(InetSocketAddress value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // Better ensure we don't use specific sub-classes... WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, InetSocketAddress.class, JsonToken.VALUE_STRING)); serialize(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } } IterableSerializer.java000066400000000000000000000077741325620701100364760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContainerSerializer; @JacksonStdImpl @SuppressWarnings("serial") public class IterableSerializer extends AsArraySerializerBase> { public IterableSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts) { super(Iterable.class, elemType, staticTyping, vts, null); } public IterableSerializer(IterableSerializer src, BeanProperty property, TypeSerializer vts, JsonSerializer valueSerializer, Boolean unwrapSingle) { super(src, property, vts, valueSerializer, unwrapSingle); } @Override public ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { return new IterableSerializer(this, _property, vts, _elementSerializer, _unwrapSingle); } @Override public IterableSerializer withResolved(BeanProperty property, TypeSerializer vts, JsonSerializer elementSerializer, Boolean unwrapSingle) { return new IterableSerializer(this, property, vts, elementSerializer, unwrapSingle); } @Override public boolean isEmpty(SerializerProvider prov, Iterable value) { // Not really good way to implement this, but has to do for now: return !value.iterator().hasNext(); } @Override public boolean hasSingleElement(Iterable value) { // we can do it actually (fixed in 2.3.1) if (value != null) { Iterator it = value.iterator(); if (it.hasNext()) { it.next(); if (!it.hasNext()) { return true; } } } return false; } @Override public final void serialize(Iterable value, JsonGenerator gen, SerializerProvider provider)throws IOException { if (((_unwrapSingle == null) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) || (_unwrapSingle == Boolean.TRUE)) { if (hasSingleElement(value)) { serializeContents(value, gen, provider); return; } } gen.writeStartArray(); serializeContents(value, gen, provider); gen.writeEndArray(); } @Override public void serializeContents(Iterable value, JsonGenerator jgen, SerializerProvider provider) throws IOException { Iterator it = value.iterator(); if (it.hasNext()) { final TypeSerializer typeSer = _valueTypeSerializer; JsonSerializer prevSerializer = null; Class prevClass = null; do { Object elem = it.next(); if (elem == null) { provider.defaultSerializeNull(jgen); continue; } JsonSerializer currSerializer = _elementSerializer; if (currSerializer == null) { // Minor optimization to avoid most lookups: Class cc = elem.getClass(); if (cc == prevClass) { currSerializer = prevSerializer; } else { currSerializer = provider.findValueSerializer(cc, _property); prevSerializer = currSerializer; prevClass = cc; } } if (typeSer == null) { currSerializer.serialize(elem, jgen, provider); } else { currSerializer.serializeWithType(elem, jgen, provider, typeSer); } } while (it.hasNext()); } } } JsonValueSerializer.java000066400000000000000000000461121325620701100366420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; import java.util.LinkedHashSet; import java.util.Set; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor; import com.fasterxml.jackson.databind.jsonschema.SchemaAware; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.BeanSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Serializer class that can serialize Object that have a * {@link com.fasterxml.jackson.annotation.JsonValue} annotation to * indicate that serialization should be done by calling the method * annotated, and serializing result it returns. *

* Implementation note: we will post-process resulting serializer * (much like what is done with {@link BeanSerializer}) * to figure out actual serializers for final types. * This must be done from {@link #createContextual} method, and NOT from constructor; * otherwise we could end up with an infinite loop. */ @SuppressWarnings("serial") @JacksonStdImpl public class JsonValueSerializer extends StdSerializer implements ContextualSerializer, JsonFormatVisitable, SchemaAware { /** * @since 2.9 */ protected final AnnotatedMember _accessor; protected final JsonSerializer _valueSerializer; protected final BeanProperty _property; /** * This is a flag that is set in rare (?) cases where this serializer * is used for "natural" types (boolean, int, String, double); and where * we actually must force type information wrapping, even though * one would not normally be added. */ protected final boolean _forceTypeInformation; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @param ser Explicit serializer to use, if caller knows it (which * occurs if and only if the "value method" was annotated with * {@link com.fasterxml.jackson.databind.annotation.JsonSerialize#using}), otherwise * null * * @since 2.8 Earlier method took "raw" Method, but that does not work with access * to information we need */ @SuppressWarnings("unchecked") public JsonValueSerializer(AnnotatedMember accessor, JsonSerializer ser) { super(accessor.getType()); _accessor = accessor; _valueSerializer = (JsonSerializer) ser; _property = null; _forceTypeInformation = true; // gets reconsidered when we are contextualized } @SuppressWarnings("unchecked") public JsonValueSerializer(JsonValueSerializer src, BeanProperty property, JsonSerializer ser, boolean forceTypeInfo) { super(_notNullClass(src.handledType())); _accessor = src._accessor; _valueSerializer = (JsonSerializer) ser; _property = property; _forceTypeInformation = forceTypeInfo; } @SuppressWarnings("unchecked") private final static Class _notNullClass(Class cls) { return (cls == null) ? Object.class : (Class) cls; } public JsonValueSerializer withResolved(BeanProperty property, JsonSerializer ser, boolean forceTypeInfo) { if (_property == property && _valueSerializer == ser && forceTypeInfo == _forceTypeInformation) { return this; } return new JsonValueSerializer(this, property, ser, forceTypeInfo); } /* /********************************************************** /* Post-processing /********************************************************** */ /** * We can try to find the actual serializer for value, if we can * statically figure out what the result type must be. */ @Override public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { JsonSerializer ser = _valueSerializer; if (ser == null) { /* Can only assign serializer statically if the declared type is final: * if not, we don't really know the actual type until we get the instance. */ // 10-Mar-2010, tatu: Except if static typing is to be used JavaType t = _accessor.getType(); if (provider.isEnabled(MapperFeature.USE_STATIC_TYPING) || t.isFinal()) { // false -> no need to cache /* 10-Mar-2010, tatu: Ideally we would actually separate out type * serializer from value serializer; but, alas, there's no access * to serializer factory at this point... */ // 05-Sep-2013, tatu: I _think_ this can be considered a primary property... ser = provider.findPrimaryPropertySerializer(t, property); /* 09-Dec-2010, tatu: Turns out we must add special handling for * cases where "native" (aka "natural") type is being serialized, * using standard serializer */ boolean forceTypeInformation = isNaturalTypeWithStdHandling(t.getRawClass(), ser); return withResolved(property, ser, forceTypeInformation); } } else { // 05-Sep-2013, tatu: I _think_ this can be considered a primary property... ser = provider.handlePrimaryContextualization(ser, property); return withResolved(property, ser, _forceTypeInformation); } return this; } /* /********************************************************** /* Actual serialization /********************************************************** */ @Override public void serialize(Object bean, JsonGenerator gen, SerializerProvider prov) throws IOException { try { Object value = _accessor.getValue(bean); if (value == null) { prov.defaultSerializeNull(gen); return; } JsonSerializer ser = _valueSerializer; if (ser == null) { Class c = value.getClass(); /* 10-Mar-2010, tatu: Ideally we would actually separate out type * serializer from value serializer; but, alas, there's no access * to serializer factory at this point... */ // let's cache it, may be needed soon again ser = prov.findTypedValueSerializer(c, true, _property); } ser.serialize(value, gen, prov); } catch (Exception e) { wrapAndThrow(prov, e, bean, _accessor.getName() + "()"); } } @Override public void serializeWithType(Object bean, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer0) throws IOException { // Regardless of other parts, first need to find value to serialize: Object value = null; try { value = _accessor.getValue(bean); // and if we got null, can also just write it directly if (value == null) { provider.defaultSerializeNull(gen); return; } JsonSerializer ser = _valueSerializer; if (ser == null) { // no serializer yet? Need to fetch ser = provider.findValueSerializer(value.getClass(), _property); } else { // 09-Dec-2010, tatu: To work around natural type's refusal to add type info, we do // this (note: type is for the wrapper type, not enclosed value!) if (_forceTypeInformation) { // Confusing? Type id is for POJO and NOT for value returned by JsonValue accessor... WritableTypeId typeIdDef = typeSer0.writeTypePrefix(gen, typeSer0.typeId(bean, JsonToken.VALUE_STRING)); ser.serialize(value, gen, provider); typeSer0.writeTypeSuffix(gen, typeIdDef); return; } } // 28-Sep-2016, tatu: As per [databind#1385], we do need to do some juggling // to use different Object for type id (logical type) and actual serialization // (delegat type). TypeSerializerRerouter rr = new TypeSerializerRerouter(typeSer0, bean); ser.serializeWithType(value, gen, provider, rr); } catch (Exception e) { wrapAndThrow(provider, e, bean, _accessor.getName() + "()"); } } @SuppressWarnings("deprecation") @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { if (_valueSerializer instanceof SchemaAware) { return ((SchemaAware)_valueSerializer).getSchema(provider, null); } return com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode(); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { /* 27-Apr-2015, tatu: First things first; for JSON Schema introspection, * Enum types that use `@JsonValue` are special (but NOT necessarily * anything else that RETURNS an enum!) * So we will need to add special * handling here (see https://github.com/FasterXML/jackson-module-jsonSchema/issues/57 * for details). * * Note that meaning of JsonValue, then, is very different for Enums. Sigh. */ final JavaType type = _accessor.getType(); Class declaring = _accessor.getDeclaringClass(); if ((declaring != null) && declaring.isEnum()) { if (_acceptJsonFormatVisitorForEnum(visitor, typeHint, declaring)) { return; } } JsonSerializer ser = _valueSerializer; if (ser == null) { ser = visitor.getProvider().findTypedValueSerializer(type, false, _property); if (ser == null) { // can this ever occur? visitor.expectAnyFormat(typeHint); return; } } ser.acceptJsonFormatVisitor(visitor, type); } /** * Overridable helper method used for special case handling of schema information for * Enums. * * @return True if method handled callbacks; false if not; in latter case caller will * send default callbacks * * @since 2.6 */ protected boolean _acceptJsonFormatVisitorForEnum(JsonFormatVisitorWrapper visitor, JavaType typeHint, Class enumType) throws JsonMappingException { // Copied from EnumSerializer#acceptJsonFormatVisitor JsonStringFormatVisitor stringVisitor = visitor.expectStringFormat(typeHint); if (stringVisitor != null) { Set enums = new LinkedHashSet(); for (Object en : enumType.getEnumConstants()) { try { // 21-Apr-2016, tatu: This is convoluted to the max, but essentially we // call `@JsonValue`-annotated accessor method on all Enum members, // so it all "works out". To some degree. enums.add(String.valueOf(_accessor.getValue(en))); } catch (Exception e) { Throwable t = e; while (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } ClassUtil.throwIfError(t); throw JsonMappingException.wrapWithPath(t, en, _accessor.getName() + "()"); } } stringVisitor.enumTypes(enums); } return true; } protected boolean isNaturalTypeWithStdHandling(Class rawType, JsonSerializer ser) { // First: do we have a natural type being handled? if (rawType.isPrimitive()) { if (rawType != Integer.TYPE && rawType != Boolean.TYPE && rawType != Double.TYPE) { return false; } } else { if (rawType != String.class && rawType != Integer.class && rawType != Boolean.class && rawType != Double.class) { return false; } } return isDefaultSerializer(ser); } /* /********************************************************** /* Other methods /********************************************************** */ @Override public String toString() { return "(@JsonValue serializer for method " + _accessor.getDeclaringClass() + "#" + _accessor.getName() + ")"; } /* /********************************************************** /* Helper class /********************************************************** */ /** * Silly little wrapper class we need to re-route type serialization so that we can * override Object to use for type id (logical type) even when asking serialization * of something else (delegate type) */ static class TypeSerializerRerouter extends TypeSerializer { protected final TypeSerializer _typeSerializer; protected final Object _forObject; public TypeSerializerRerouter(TypeSerializer ts, Object ob) { _typeSerializer = ts; _forObject = ob; } @Override public TypeSerializer forProperty(BeanProperty prop) { // should never get called throw new UnsupportedOperationException(); } @Override public As getTypeInclusion() { return _typeSerializer.getTypeInclusion(); } @Override public String getPropertyName() { return _typeSerializer.getPropertyName(); } @Override public TypeIdResolver getTypeIdResolver() { return _typeSerializer.getTypeIdResolver(); } // // // New Write API, 2.9+ @Override // since 2.9 public WritableTypeId writeTypePrefix(JsonGenerator g, WritableTypeId typeId) throws IOException { // 28-Jun-2017, tatu: Important! Need to "override" value typeId.forValue = _forObject; return _typeSerializer.writeTypePrefix(g, typeId); } @Override // since 2.9 public WritableTypeId writeTypeSuffix(JsonGenerator g, WritableTypeId typeId) throws IOException { // NOTE: already overwrote value object so: return _typeSerializer.writeTypeSuffix(g, typeId); } // // // Old Write API, pre-2.9 @Override @Deprecated public void writeTypePrefixForScalar(Object value, JsonGenerator gen) throws IOException { _typeSerializer.writeTypePrefixForScalar(_forObject, gen); } @Override @Deprecated public void writeTypePrefixForObject(Object value, JsonGenerator gen) throws IOException { _typeSerializer.writeTypePrefixForObject(_forObject, gen); } @Override @Deprecated public void writeTypePrefixForArray(Object value, JsonGenerator gen) throws IOException { _typeSerializer.writeTypePrefixForArray(_forObject, gen); } @Override @Deprecated public void writeTypeSuffixForScalar(Object value, JsonGenerator gen) throws IOException { _typeSerializer.writeTypeSuffixForScalar(_forObject, gen); } @Override @Deprecated public void writeTypeSuffixForObject(Object value, JsonGenerator gen) throws IOException { _typeSerializer.writeTypeSuffixForObject(_forObject, gen); } @Override @Deprecated public void writeTypeSuffixForArray(Object value, JsonGenerator gen) throws IOException { _typeSerializer.writeTypeSuffixForArray(_forObject, gen); } @Override @Deprecated public void writeTypePrefixForScalar(Object value, JsonGenerator gen, Class type) throws IOException { _typeSerializer.writeTypePrefixForScalar(_forObject, gen, type); } @Override @Deprecated public void writeTypePrefixForObject(Object value, JsonGenerator gen, Class type) throws IOException { _typeSerializer.writeTypePrefixForObject(_forObject, gen, type); } @Override @Deprecated public void writeTypePrefixForArray(Object value, JsonGenerator gen, Class type) throws IOException { _typeSerializer.writeTypePrefixForArray(_forObject, gen, type); } /* /********************************************************** /* Deprecated methods (since 2.9) /********************************************************** */ @Override @Deprecated public void writeCustomTypePrefixForScalar(Object value, JsonGenerator gen, String typeId) throws IOException { _typeSerializer.writeCustomTypePrefixForScalar(_forObject, gen, typeId); } @Override @Deprecated public void writeCustomTypePrefixForObject(Object value, JsonGenerator gen, String typeId) throws IOException { _typeSerializer.writeCustomTypePrefixForObject(_forObject, gen, typeId); } @Override @Deprecated public void writeCustomTypePrefixForArray(Object value, JsonGenerator gen, String typeId) throws IOException { _typeSerializer.writeCustomTypePrefixForArray(_forObject, gen, typeId); } @Override @Deprecated public void writeCustomTypeSuffixForScalar(Object value, JsonGenerator gen, String typeId) throws IOException { _typeSerializer.writeCustomTypeSuffixForScalar(_forObject, gen, typeId); } @Override @Deprecated public void writeCustomTypeSuffixForObject(Object value, JsonGenerator gen, String typeId) throws IOException { _typeSerializer.writeCustomTypeSuffixForObject(_forObject, gen, typeId); } @Override @Deprecated public void writeCustomTypeSuffixForArray(Object value, JsonGenerator gen, String typeId) throws IOException { _typeSerializer.writeCustomTypeSuffixForArray(_forObject, gen, typeId); } } } MapProperty.java000066400000000000000000000115211325620701100351600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.annotation.Annotation; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.PropertyWriter; /** * Helper class needed to support flexible filtering of Map properties * with generic JSON Filter functionality. Since {@link java.util.Map}s * are not handled as a collection of properties by Jackson (unlike POJOs), * bit more wrapping is required. */ public class MapProperty extends PropertyWriter { private static final long serialVersionUID = 1L; private final static BeanProperty BOGUS_PROP = new BeanProperty.Bogus(); protected final TypeSerializer _typeSerializer; protected final BeanProperty _property; protected Object _key, _value; protected JsonSerializer _keySerializer, _valueSerializer; public MapProperty(TypeSerializer typeSer, BeanProperty prop) { super((prop == null) ? PropertyMetadata.STD_REQUIRED_OR_OPTIONAL : prop.getMetadata()); _typeSerializer = typeSer; _property = (prop == null) ? BOGUS_PROP : prop; } /** * Initialization method that needs to be called before passing * property to filter. * * @since 2.9 */ public void reset(Object key, Object value, JsonSerializer keySer, JsonSerializer valueSer) { _key = key; _value = value; _keySerializer = keySer; _valueSerializer = valueSer; } @Deprecated // since 2.9 public void reset(Object key, JsonSerializer keySer, JsonSerializer valueSer) { reset(key, _value, keySer, valueSer); } @Override public String getName() { if (_key instanceof String) { return (String) _key; } return String.valueOf(_key); } /** * @since 2.9 */ public Object getValue() { return _value; } /** * @since 2.9 */ public void setValue(Object v) { _value = v; } @Override public PropertyName getFullName() { return new PropertyName(getName()); } @Override public A getAnnotation(Class acls) { return _property.getAnnotation(acls); } @Override public A getContextAnnotation(Class acls) { return _property.getContextAnnotation(acls); } @Override public void serializeAsField(Object map, JsonGenerator gen, SerializerProvider provider) throws IOException { _keySerializer.serialize(_key, gen, provider); if (_typeSerializer == null) { _valueSerializer.serialize(_value, gen, provider); } else { _valueSerializer.serializeWithType(_value, gen, provider, _typeSerializer); } } @Override public void serializeAsOmittedField(Object map, JsonGenerator gen, SerializerProvider provider) throws Exception { if (!gen.canOmitFields()) { gen.writeOmittedField(getName()); } } @Override public void serializeAsElement(Object map, JsonGenerator gen, SerializerProvider provider) throws Exception { if (_typeSerializer == null) { _valueSerializer.serialize(_value, gen, provider); } else { _valueSerializer.serializeWithType(_value, gen, provider, _typeSerializer); } } @Override public void serializeAsPlaceholder(Object value, JsonGenerator gen, SerializerProvider provider) throws Exception { gen.writeNull(); } /* /********************************************************** /* Rest of BeanProperty, nop /********************************************************** */ @Override public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException { _property.depositSchemaProperty(objectVisitor, provider); } @Override @Deprecated public void depositSchemaProperty(ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException { // nothing to do here } @Override public JavaType getType() { return _property.getType(); } @Override public PropertyName getWrapperName() { return _property.getWrapperName(); } @Override public AnnotatedMember getMember() { return _property.getMember(); } } MapSerializer.java000066400000000000000000001253131325620701100354520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonMapFormatVisitor; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContainerSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.PropertyFilter; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ArrayBuilders; import com.fasterxml.jackson.databind.util.BeanUtil; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Standard serializer implementation for serializing {link java.util.Map} types. *

* Note: about the only configurable setting currently is ability to filter out * entries with specified names. */ @JacksonStdImpl public class MapSerializer extends ContainerSerializer> implements ContextualSerializer { private static final long serialVersionUID = 1L; protected final static JavaType UNSPECIFIED_TYPE = TypeFactory.unknownType(); /** * @since 2.9 */ public final static Object MARKER_FOR_EMPTY = JsonInclude.Include.NON_EMPTY; /* /********************************************************** /* Basic information about referring property, type /********************************************************** */ /** * Map-valued property being serialized with this instance */ protected final BeanProperty _property; /** * Whether static types should be used for serialization of values * or not (if not, dynamic runtime type is used) */ protected final boolean _valueTypeIsStatic; /** * Declared type of keys */ protected final JavaType _keyType; /** * Declared type of contained values */ protected final JavaType _valueType; /* /********************************************************** /* Serializers used /********************************************************** */ /** * Key serializer to use, if it can be statically determined */ protected JsonSerializer _keySerializer; /** * Value serializer to use, if it can be statically determined */ protected JsonSerializer _valueSerializer; /** * Type identifier serializer used for values, if any. */ protected final TypeSerializer _valueTypeSerializer; /** * If value type cannot be statically determined, mapping from * runtime value types to serializers are stored in this object. */ protected PropertySerializerMap _dynamicValueSerializers; /* /********************************************************** /* Config settings, filtering /********************************************************** */ /** * Set of entries to omit during serialization, if any */ protected final Set _ignoredEntries; /** * Id of the property filter to use, if any; null if none. * * @since 2.3 */ protected final Object _filterId; /** * Value that indicates suppression mechanism to use for values contained; * either "filter" (of which equals() is called), or marker * value of {@link #MARKER_FOR_EMPTY}, or null to indicate no filtering for * non-null values. * Note that inclusion value for Map instance itself is handled by caller (POJO * property that refers to the Map value). * * @since 2.5 */ protected final Object _suppressableValue; /** * Flag that indicates what to do with `null` values, distinct from * handling of {@link #_suppressableValue} * * @since 2.9 */ protected final boolean _suppressNulls; /* /********************************************************** /* Config settings, other /********************************************************** */ /** * Flag set if output is forced to be sorted by keys (usually due * to annotation). * * @since 2.4 */ protected final boolean _sortKeys; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @since 2.5 */ @SuppressWarnings("unchecked") protected MapSerializer(Set ignoredEntries, JavaType keyType, JavaType valueType, boolean valueTypeIsStatic, TypeSerializer vts, JsonSerializer keySerializer, JsonSerializer valueSerializer) { super(Map.class, false); _ignoredEntries = ((ignoredEntries == null) || ignoredEntries.isEmpty()) ? null : ignoredEntries; _keyType = keyType; _valueType = valueType; _valueTypeIsStatic = valueTypeIsStatic; _valueTypeSerializer = vts; _keySerializer = (JsonSerializer) keySerializer; _valueSerializer = (JsonSerializer) valueSerializer; _dynamicValueSerializers = PropertySerializerMap.emptyForProperties(); _property = null; _filterId = null; _sortKeys = false; _suppressableValue = null; _suppressNulls = false; } @SuppressWarnings("unchecked") protected MapSerializer(MapSerializer src, BeanProperty property, JsonSerializer keySerializer, JsonSerializer valueSerializer, Set ignoredEntries) { super(Map.class, false); _ignoredEntries = ((ignoredEntries == null) || ignoredEntries.isEmpty()) ? null : ignoredEntries; _keyType = src._keyType; _valueType = src._valueType; _valueTypeIsStatic = src._valueTypeIsStatic; _valueTypeSerializer = src._valueTypeSerializer; _keySerializer = (JsonSerializer) keySerializer; _valueSerializer = (JsonSerializer) valueSerializer; _dynamicValueSerializers = src._dynamicValueSerializers; _property = property; _filterId = src._filterId; _sortKeys = src._sortKeys; _suppressableValue = src._suppressableValue; _suppressNulls = src._suppressNulls; } /** * @since 2.9 */ protected MapSerializer(MapSerializer src, TypeSerializer vts, Object suppressableValue, boolean suppressNulls) { super(Map.class, false); _ignoredEntries = src._ignoredEntries; _keyType = src._keyType; _valueType = src._valueType; _valueTypeIsStatic = src._valueTypeIsStatic; _valueTypeSerializer = vts; _keySerializer = src._keySerializer; _valueSerializer = src._valueSerializer; _dynamicValueSerializers = src._dynamicValueSerializers; _property = src._property; _filterId = src._filterId; _sortKeys = src._sortKeys; _suppressableValue = suppressableValue; _suppressNulls = suppressNulls; } protected MapSerializer(MapSerializer src, Object filterId, boolean sortKeys) { super(Map.class, false); _ignoredEntries = src._ignoredEntries; _keyType = src._keyType; _valueType = src._valueType; _valueTypeIsStatic = src._valueTypeIsStatic; _valueTypeSerializer = src._valueTypeSerializer; _keySerializer = src._keySerializer; _valueSerializer = src._valueSerializer; _dynamicValueSerializers = src._dynamicValueSerializers; _property = src._property; _filterId = filterId; _sortKeys = sortKeys; _suppressableValue = src._suppressableValue; _suppressNulls = src._suppressNulls; } @Override public MapSerializer _withValueTypeSerializer(TypeSerializer vts) { if (_valueTypeSerializer == vts) { return this; } _ensureOverride("_withValueTypeSerializer"); return new MapSerializer(this, vts, _suppressableValue, _suppressNulls); } /** * @since 2.4 */ public MapSerializer withResolved(BeanProperty property, JsonSerializer keySerializer, JsonSerializer valueSerializer, Set ignored, boolean sortKeys) { _ensureOverride("withResolved"); MapSerializer ser = new MapSerializer(this, property, keySerializer, valueSerializer, ignored); if (sortKeys != ser._sortKeys) { ser = new MapSerializer(ser, _filterId, sortKeys); } return ser; } @Override public MapSerializer withFilterId(Object filterId) { if (_filterId == filterId) { return this; } _ensureOverride("withFilterId"); return new MapSerializer(this, filterId, _sortKeys); } /** * Mutant factory for constructing an instance with different inclusion strategy * for content (Map values). * * @since 2.9 */ public MapSerializer withContentInclusion(Object suppressableValue, boolean suppressNulls) { if ((suppressableValue == _suppressableValue) && (suppressNulls == _suppressNulls)) { return this; } _ensureOverride("withContentInclusion"); return new MapSerializer(this, _valueTypeSerializer, suppressableValue, suppressNulls); } /** * @since 2.8 */ public static MapSerializer construct(Set ignoredEntries, JavaType mapType, boolean staticValueType, TypeSerializer vts, JsonSerializer keySerializer, JsonSerializer valueSerializer, Object filterId) { JavaType keyType, valueType; if (mapType == null) { keyType = valueType = UNSPECIFIED_TYPE; } else { keyType = mapType.getKeyType(); valueType = mapType.getContentType(); } // If value type is final, it's same as forcing static value typing: if (!staticValueType) { staticValueType = (valueType != null && valueType.isFinal()); } else { // also: Object.class cannot be handled as static, ever if (valueType.getRawClass() == Object.class) { staticValueType = false; } } MapSerializer ser = new MapSerializer(ignoredEntries, keyType, valueType, staticValueType, vts, keySerializer, valueSerializer); if (filterId != null) { ser = ser.withFilterId(filterId); } return ser; } /** * @since 2.9 */ protected void _ensureOverride(String method) { ClassUtil.verifyMustOverride(MapSerializer.class, this, method); } /** * @since 2.5 */ @Deprecated // since 2.9 protected void _ensureOverride() { _ensureOverride("N/A"); } /* /********************************************************** /* Deprecated creators /********************************************************** */ /** * @since 2.5 * @deprecated // since 2.9 */ @Deprecated // since 2.9 protected MapSerializer(MapSerializer src, TypeSerializer vts, Object suppressableValue) { this(src, vts, suppressableValue, false); } /** * @deprecated since 2.9 */ @Deprecated // since 2.9 public MapSerializer withContentInclusion(Object suppressableValue) { return new MapSerializer(this, _valueTypeSerializer, suppressableValue, _suppressNulls); } /** * @since 2.3 * * @deprecated Since 2.8 use the other overload */ @Deprecated // since 2.8 public static MapSerializer construct(String[] ignoredList, JavaType mapType, boolean staticValueType, TypeSerializer vts, JsonSerializer keySerializer, JsonSerializer valueSerializer, Object filterId) { Set ignoredEntries = ArrayBuilders.arrayToSet(ignoredList); return construct(ignoredEntries, mapType, staticValueType, vts, keySerializer, valueSerializer, filterId); } /* /********************************************************** /* Post-processing (contextualization) /********************************************************** */ @Override public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { JsonSerializer ser = null; JsonSerializer keySer = null; final AnnotationIntrospector intr = provider.getAnnotationIntrospector(); final AnnotatedMember propertyAcc = (property == null) ? null : property.getMember(); // First: if we have a property, may have property-annotation overrides if (_neitherNull(propertyAcc, intr)) { Object serDef = intr.findKeySerializer(propertyAcc); if (serDef != null) { keySer = provider.serializerInstance(propertyAcc, serDef); } serDef = intr.findContentSerializer(propertyAcc); if (serDef != null) { ser = provider.serializerInstance(propertyAcc, serDef); } } if (ser == null) { ser = _valueSerializer; } // [databind#124]: May have a content converter ser = findContextualConvertingSerializer(provider, property, ser); if (ser == null) { // 30-Sep-2012, tatu: One more thing -- if explicit content type is annotated, // we can consider it a static case as well. // 20-Aug-2013, tatu: Need to avoid trying to access serializer for java.lang.Object tho if (_valueTypeIsStatic && !_valueType.isJavaLangObject()) { ser = provider.findValueSerializer(_valueType, property); } } if (keySer == null) { keySer = _keySerializer; } if (keySer == null) { keySer = provider.findKeySerializer(_keyType, property); } else { keySer = provider.handleSecondaryContextualization(keySer, property); } Set ignored = _ignoredEntries; boolean sortKeys = false; if (_neitherNull(propertyAcc, intr)) { JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnorals(propertyAcc); if (ignorals != null){ Set newIgnored = ignorals.findIgnoredForSerialization(); if (_nonEmpty(newIgnored)) { ignored = (ignored == null) ? new HashSet() : new HashSet(ignored); for (String str : newIgnored) { ignored.add(str); } } } Boolean b = intr.findSerializationSortAlphabetically(propertyAcc); sortKeys = Boolean.TRUE.equals(b); } JsonFormat.Value format = findFormatOverrides(provider, property, Map.class); if (format != null) { Boolean B = format.getFeature(JsonFormat.Feature.WRITE_SORTED_MAP_ENTRIES); if (B != null) { sortKeys = B.booleanValue(); } } MapSerializer mser = withResolved(property, keySer, ser, ignored, sortKeys); // [databind#307]: allow filtering if (property != null) { AnnotatedMember m = property.getMember(); if (m != null) { Object filterId = intr.findFilterId(m); if (filterId != null) { mser = mser.withFilterId(filterId); } } JsonInclude.Value inclV = property.findPropertyInclusion(provider.getConfig(), null); if (inclV != null) { JsonInclude.Include incl = inclV.getContentInclusion(); if (incl != JsonInclude.Include.USE_DEFAULTS) { Object valueToSuppress; boolean suppressNulls; switch (incl) { case NON_DEFAULT: valueToSuppress = BeanUtil.getDefaultValue(_valueType); suppressNulls = true; if (valueToSuppress != null) { if (valueToSuppress.getClass().isArray()) { valueToSuppress = ArrayBuilders.getArrayComparator(valueToSuppress); } } break; case NON_ABSENT: suppressNulls = true; valueToSuppress = _valueType.isReferenceType() ? MARKER_FOR_EMPTY : null; break; case NON_EMPTY: suppressNulls = true; valueToSuppress = MARKER_FOR_EMPTY; break; case CUSTOM: valueToSuppress = provider.includeFilterInstance(null, inclV.getContentFilter()); if (valueToSuppress == null) { // is this legal? suppressNulls = true; } else { suppressNulls = provider.includeFilterSuppressNulls(valueToSuppress); } break; case NON_NULL: valueToSuppress = null; suppressNulls = true; break; case ALWAYS: // default default: valueToSuppress = null; // 30-Sep-2016, tatu: Should not need to check global flags here, // if inclusion forced to be ALWAYS suppressNulls = false; break; } mser = mser.withContentInclusion(valueToSuppress, suppressNulls); } } } return mser; } /* /********************************************************** /* Accessors /********************************************************** */ @Override public JavaType getContentType() { return _valueType; } @Override public JsonSerializer getContentSerializer() { return _valueSerializer; } @Override public boolean isEmpty(SerializerProvider prov, Map value) { if (value.isEmpty()) { return true; } // 05-Nove-2015, tatu: Simple cases are cheap, but for recursive // emptiness checking we actually need to see if values are empty as well. Object supp = _suppressableValue; if ((supp == null) && !_suppressNulls) { return false; } JsonSerializer valueSer = _valueSerializer; final boolean checkEmpty = (MARKER_FOR_EMPTY == supp); if (valueSer != null) { for (Object elemValue : value.values()) { if (elemValue == null) { if (_suppressNulls) { continue; } return false; } if (checkEmpty) { if (!valueSer.isEmpty(prov, elemValue)) { return false; } } else if ((supp == null) || !supp.equals(value)) { return false; } } return true; } // But if not statically known, try this: for (Object elemValue : value.values()) { if (elemValue == null) { if (_suppressNulls) { continue; } return false; } try { valueSer = _findSerializer(prov, elemValue); } catch (JsonMappingException e) { // Ugh... cannot just throw as-is, so... // 05-Nov-2015, tatu: For now, probably best not to assume empty then return false; } if (checkEmpty) { if (!valueSer.isEmpty(prov, elemValue)) { return false; } } else if ((supp == null) || !supp.equals(value)) { return false; } } return true; } @Override public boolean hasSingleElement(Map value) { return (value.size() == 1); } /* /********************************************************** /* Extended API /********************************************************** */ /** * Accessor for currently assigned key serializer. Note that * this may return null during construction of MapSerializer: * depedencies are resolved during {@link #createContextual} method * (which can be overridden by custom implementations), but for some * dynamic types, it is possible that serializer is only resolved * during actual serialization. * * @since 2.0 */ public JsonSerializer getKeySerializer() { return _keySerializer; } /* /********************************************************** /* JsonSerializer implementation /********************************************************** */ @Override public void serialize(Map value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(value); if (!value.isEmpty()) { if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) { value = _orderEntries(value, gen, provider); } PropertyFilter pf; if ((_filterId != null) && (pf = findPropertyFilter(provider, _filterId, value)) != null) { serializeFilteredFields(value, gen, provider, pf, _suppressableValue); } else if ((_suppressableValue != null) || _suppressNulls) { serializeOptionalFields(value, gen, provider, _suppressableValue); } else if (_valueSerializer != null) { serializeFieldsUsing(value, gen, provider, _valueSerializer); } else { serializeFields(value, gen, provider); } } gen.writeEndObject(); } @Override public void serializeWithType(Map value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // [databind#631]: Assign current value, to be accessible by custom serializers gen.setCurrentValue(value); WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.START_OBJECT)); if (!value.isEmpty()) { if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) { value = _orderEntries(value, gen, provider); } PropertyFilter pf; if ((_filterId != null) && (pf = findPropertyFilter(provider, _filterId, value)) != null) { serializeFilteredFields(value, gen, provider, pf, _suppressableValue); } else if ((_suppressableValue != null) || _suppressNulls) { serializeOptionalFields(value, gen, provider, _suppressableValue); } else if (_valueSerializer != null) { serializeFieldsUsing(value, gen, provider, _valueSerializer); } else { serializeFields(value, gen, provider); } } typeSer.writeTypeSuffix(gen, typeIdDef); } /* /********************************************************** /* Secondary serialization methods /********************************************************** */ /** * General-purpose serialization for contents, where we do not necessarily know * the value serialization, but * we do know that no value suppression is needed (which simplifies processing a bit) */ public void serializeFields(Map value, JsonGenerator gen, SerializerProvider provider) throws IOException { // If value type needs polymorphic type handling, some more work needed: if (_valueTypeSerializer != null) { serializeTypedFields(value, gen, provider, null); return; } final JsonSerializer keySerializer = _keySerializer; final Set ignored = _ignoredEntries; Object keyElem = null; try { for (Map.Entry entry : value.entrySet()) { Object valueElem = entry.getValue(); // First, serialize key keyElem = entry.getKey(); if (keyElem == null) { provider.findNullKeySerializer(_keyType, _property).serialize(null, gen, provider); } else { // One twist: is entry ignorable? If so, skip if ((ignored != null) && ignored.contains(keyElem)) { continue; } keySerializer.serialize(keyElem, gen, provider); } // And then value if (valueElem == null) { provider.defaultSerializeNull(gen); continue; } JsonSerializer serializer = _valueSerializer; if (serializer == null) { serializer = _findSerializer(provider, valueElem); } serializer.serialize(valueElem, gen, provider); } } catch (Exception e) { // Add reference information wrapAndThrow(provider, e, value, String.valueOf(keyElem)); } } /** * Serialization method called when exclusion filtering needs to be applied. */ public void serializeOptionalFields(Map value, JsonGenerator gen, SerializerProvider provider, Object suppressableValue) throws IOException { // If value type needs polymorphic type handling, some more work needed: if (_valueTypeSerializer != null) { serializeTypedFields(value, gen, provider, suppressableValue); return; } final Set ignored = _ignoredEntries; final boolean checkEmpty = (MARKER_FOR_EMPTY == suppressableValue); for (Map.Entry entry : value.entrySet()) { // First find key serializer final Object keyElem = entry.getKey(); JsonSerializer keySerializer; if (keyElem == null) { keySerializer = provider.findNullKeySerializer(_keyType, _property); } else { if (ignored != null && ignored.contains(keyElem)) continue; keySerializer = _keySerializer; } // Then value serializer final Object valueElem = entry.getValue(); JsonSerializer valueSer; if (valueElem == null) { if (_suppressNulls) { // all suppressions include null-suppression continue; } valueSer = provider.getDefaultNullValueSerializer(); } else { valueSer = _valueSerializer; if (valueSer == null) { valueSer = _findSerializer(provider, valueElem); } // also may need to skip non-empty values: if (checkEmpty) { if (valueSer.isEmpty(provider, valueElem)) { continue; } } else if (suppressableValue != null) { if (suppressableValue.equals(valueElem)) { continue; } } } // and then serialize, if all went well try { keySerializer.serialize(keyElem, gen, provider); valueSer.serialize(valueElem, gen, provider); } catch (Exception e) { wrapAndThrow(provider, e, value, String.valueOf(keyElem)); } } } /** * Method called to serialize fields, when the value type is statically known, * so that value serializer is passed and does not need to be fetched from * provider. */ public void serializeFieldsUsing(Map value, JsonGenerator gen, SerializerProvider provider, JsonSerializer ser) throws IOException { final JsonSerializer keySerializer = _keySerializer; final Set ignored = _ignoredEntries; final TypeSerializer typeSer = _valueTypeSerializer; for (Map.Entry entry : value.entrySet()) { Object keyElem = entry.getKey(); if (ignored != null && ignored.contains(keyElem)) continue; if (keyElem == null) { provider.findNullKeySerializer(_keyType, _property).serialize(null, gen, provider); } else { keySerializer.serialize(keyElem, gen, provider); } final Object valueElem = entry.getValue(); if (valueElem == null) { provider.defaultSerializeNull(gen); } else { try { if (typeSer == null) { ser.serialize(valueElem, gen, provider); } else { ser.serializeWithType(valueElem, gen, provider, typeSer); } } catch (Exception e) { wrapAndThrow(provider, e, value, String.valueOf(keyElem)); } } } } /** * Helper method used when we have a JSON Filter to use for potentially * filtering out Map entries. * * @since 2.5 */ public void serializeFilteredFields(Map value, JsonGenerator gen, SerializerProvider provider, PropertyFilter filter, Object suppressableValue) // since 2.5 throws IOException { final Set ignored = _ignoredEntries; final MapProperty prop = new MapProperty(_valueTypeSerializer, _property); final boolean checkEmpty = (MARKER_FOR_EMPTY == suppressableValue); for (Map.Entry entry : value.entrySet()) { // First, serialize key; unless ignorable by key final Object keyElem = entry.getKey(); if (ignored != null && ignored.contains(keyElem)) continue; JsonSerializer keySerializer; if (keyElem == null) { keySerializer = provider.findNullKeySerializer(_keyType, _property); } else { keySerializer = _keySerializer; } // or by value; nulls often suppressed final Object valueElem = entry.getValue(); JsonSerializer valueSer; // And then value if (valueElem == null) { if (_suppressNulls) { continue; } valueSer = provider.getDefaultNullValueSerializer(); } else { valueSer = _valueSerializer; if (valueSer == null) { valueSer = _findSerializer(provider, valueElem); } // also may need to skip non-empty values: if (checkEmpty) { if (valueSer.isEmpty(provider, valueElem)) { continue; } } else if (suppressableValue != null) { if (suppressableValue.equals(valueElem)) { continue; } } } // and with that, ask filter to handle it prop.reset(keyElem, valueElem, keySerializer, valueSer); try { filter.serializeAsField(value, gen, provider, prop); } catch (Exception e) { wrapAndThrow(provider, e, value, String.valueOf(keyElem)); } } } /** * @since 2.5 */ public void serializeTypedFields(Map value, JsonGenerator gen, SerializerProvider provider, Object suppressableValue) // since 2.5 throws IOException { final Set ignored = _ignoredEntries; final boolean checkEmpty = (MARKER_FOR_EMPTY == suppressableValue); for (Map.Entry entry : value.entrySet()) { Object keyElem = entry.getKey(); JsonSerializer keySerializer; if (keyElem == null) { keySerializer = provider.findNullKeySerializer(_keyType, _property); } else { // One twist: is entry ignorable? If so, skip if (ignored != null && ignored.contains(keyElem)) continue; keySerializer = _keySerializer; } final Object valueElem = entry.getValue(); // And then value JsonSerializer valueSer; if (valueElem == null) { if (_suppressNulls) { // all suppression include null suppression continue; } valueSer = provider.getDefaultNullValueSerializer(); } else { valueSer = _valueSerializer; if (valueSer == null) { valueSer = _findSerializer(provider, valueElem); } // also may need to skip non-empty values: if (checkEmpty) { if (valueSer.isEmpty(provider, valueElem)) { continue; } } else if (suppressableValue != null) { if (suppressableValue.equals(valueElem)) { continue; } } } keySerializer.serialize(keyElem, gen, provider); try { valueSer.serializeWithType(valueElem, gen, provider, _valueTypeSerializer); } catch (Exception e) { wrapAndThrow(provider, e, value, String.valueOf(keyElem)); } } } /** * Helper method used when we have a JSON Filter to use AND contents are * "any properties" of a POJO. * * @param bean Enclosing POJO that has any-getter used to obtain "any properties" * * @since 2.9 */ public void serializeFilteredAnyProperties(SerializerProvider provider, JsonGenerator gen, Object bean, Map value, PropertyFilter filter, Object suppressableValue) throws IOException { final Set ignored = _ignoredEntries; final MapProperty prop = new MapProperty(_valueTypeSerializer, _property); final boolean checkEmpty = (MARKER_FOR_EMPTY == suppressableValue); for (Map.Entry entry : value.entrySet()) { // First, serialize key; unless ignorable by key final Object keyElem = entry.getKey(); if (ignored != null && ignored.contains(keyElem)) continue; JsonSerializer keySerializer; if (keyElem == null) { keySerializer = provider.findNullKeySerializer(_keyType, _property); } else { keySerializer = _keySerializer; } // or by value; nulls often suppressed final Object valueElem = entry.getValue(); JsonSerializer valueSer; // And then value if (valueElem == null) { if (_suppressNulls) { continue; } valueSer = provider.getDefaultNullValueSerializer(); } else { valueSer = _valueSerializer; if (valueSer == null) { valueSer = _findSerializer(provider, valueElem); } // also may need to skip non-empty values: if (checkEmpty) { if (valueSer.isEmpty(provider, valueElem)) { continue; } } else if (suppressableValue != null) { if (suppressableValue.equals(valueElem)) { continue; } } } // and with that, ask filter to handle it prop.reset(keyElem, valueElem, keySerializer, valueSer); try { filter.serializeAsField(bean, gen, provider, prop); } catch (Exception e) { wrapAndThrow(provider, e, value, String.valueOf(keyElem)); } } } /* /********************************************************** /* Schema related functionality /********************************************************** */ @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { // even though it's possible to statically determine the "value" type of the map, // there's no way to statically determine the keys, so the "Entries" can't be determined. return createSchemaNode("object", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { JsonMapFormatVisitor v2 = visitor.expectMapFormat(typeHint); if (v2 != null) { v2.keyFormat(_keySerializer, _keyType); JsonSerializer valueSer = _valueSerializer; if (valueSer == null) { valueSer = _findAndAddDynamic(_dynamicValueSerializers, _valueType, visitor.getProvider()); } v2.valueFormat(valueSer, _valueType); } } /* /********************************************************** /* Internal helper methods /********************************************************** */ protected final JsonSerializer _findAndAddDynamic(PropertySerializerMap map, Class type, SerializerProvider provider) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property); // did we get a new map of serializers? If so, start using it if (map != result.map) { _dynamicValueSerializers = result.map; } return result.serializer; } protected final JsonSerializer _findAndAddDynamic(PropertySerializerMap map, JavaType type, SerializerProvider provider) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property); if (map != result.map) { _dynamicValueSerializers = result.map; } return result.serializer; } protected Map _orderEntries(Map input, JsonGenerator gen, SerializerProvider provider) throws IOException { // minor optimization: may already be sorted? if (input instanceof SortedMap) { return input; } // [databind#1411]: TreeMap does not like null key... (although note that // check above should prevent this code from being called in that case) // [databind#153]: but, apparently, some custom Maps do manage hit this // problem. if (_hasNullKey(input)) { TreeMap result = new TreeMap(); for (Map.Entry entry : input.entrySet()) { Object key = entry.getKey(); if (key == null) { _writeNullKeyedEntry(gen, provider, entry.getValue()); continue; } result.put(key, entry.getValue()); } return result; } return new TreeMap(input); } /** * @since 2.8.7 */ protected boolean _hasNullKey(Map input) { // 19-Feb-2017, tatu: As per [databind#1513] there are many cases where `null` // keys are not allowed, and even attempt to check for presence can cause // problems. Without resorting to external sorting (and internal API change), // or custom sortable Map implementation (more code) we can try black- or // white-listing (that is; either skip known problem cases; or only apply for // known good cases). // While my first instinct was to do black-listing (remove Hashtable and ConcurrentHashMap), // all in all it is probably better to just white list `HashMap` (and its sub-classes). return (input instanceof HashMap) && input.containsKey(null); } protected void _writeNullKeyedEntry(JsonGenerator gen, SerializerProvider provider, Object value) throws IOException { JsonSerializer keySerializer = provider.findNullKeySerializer(_keyType, _property); JsonSerializer valueSer; if (value == null) { if (_suppressNulls) { return; } valueSer = provider.getDefaultNullValueSerializer(); } else { valueSer = _valueSerializer; if (valueSer == null) { valueSer = _findSerializer(provider, value); } if (_suppressableValue == MARKER_FOR_EMPTY) { if (valueSer.isEmpty(provider, value)) { return; } } else if ((_suppressableValue != null) && (_suppressableValue.equals(value))) { return; } } try { keySerializer.serialize(null, gen, provider); valueSer.serialize(value, gen, provider); } catch (Exception e) { wrapAndThrow(provider, e, value, ""); } } private final JsonSerializer _findSerializer(SerializerProvider provider, Object value) throws JsonMappingException { final Class cc = value.getClass(); JsonSerializer valueSer = _dynamicValueSerializers.serializerFor(cc); if (valueSer != null) { return valueSer; } if (_valueType.hasGenericTypes()) { return _findAndAddDynamic(_dynamicValueSerializers, provider.constructSpecializedType(_valueType, cc), provider); } return _findAndAddDynamic(_dynamicValueSerializers, cc, provider); } } NonTypedScalarSerializerBase.java000066400000000000000000000022271325620701100404140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * Intermediate base class for limited number of scalar types * that should never include type information. These are "native" * types that are default mappings for corresponding JSON scalar * types: {@link java.lang.String}, {@link java.lang.Integer}, * {@link java.lang.Double} and {@link java.lang.Boolean}. */ @SuppressWarnings("serial") @Deprecated // since 2.9 public abstract class NonTypedScalarSerializerBase extends StdScalarSerializer { protected NonTypedScalarSerializerBase(Class t) { super(t); } protected NonTypedScalarSerializerBase(Class t, boolean bogus) { super(t, bogus); } @Override public final void serializeWithType(T value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // no type info, just regular serialization serialize(value, gen, provider); } } NullSerializer.java000066400000000000000000000037731325620701100356540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.lang.reflect.Type; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * This is a simple dummy serializer that will just output literal * JSON null value whenever serialization is requested. * Used as the default "null serializer" (which is used for serializing * null object references unless overridden), as well as for some * more exotic types (java.lang.Void). */ @JacksonStdImpl @SuppressWarnings("serial") public class NullSerializer extends StdSerializer { public final static NullSerializer instance = new NullSerializer(); private NullSerializer() { super(Object.class); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeNull(); } /** * Although this method should rarely get called, for convenience we should override * it, and handle it same way as "natural" types: by serializing exactly as is, * without type decorations. The most common possible use case is that of delegation * by JSON filter; caller cannot know what kind of serializer it gets handed. */ @Override public void serializeWithType(Object value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException { gen.writeNull(); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { return createSchemaNode("null"); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitor.expectNullFormat(typeHint); } } NumberSerializer.java000066400000000000000000000073171325620701100361700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.ser.ContextualSerializer; /** * As a fallback, we may need to use this serializer for other * types of {@link Number}s: both custom types and "big" numbers * like {@link BigInteger} and {@link BigDecimal}. */ @JacksonStdImpl @SuppressWarnings("serial") public class NumberSerializer extends StdScalarSerializer implements ContextualSerializer { /** * Static instance that is only to be used for {@link java.lang.Number}. */ public final static NumberSerializer instance = new NumberSerializer(Number.class); protected final boolean _isInt; /** * @since 2.5 */ public NumberSerializer(Class rawType) { super(rawType, false); // since this will NOT be constructed for Integer or Long, only case is: _isInt = (rawType == BigInteger.class); } @Override public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { JsonFormat.Value format = findFormatOverrides(prov, property, handledType()); if (format != null) { switch (format.getShape()) { case STRING: return ToStringSerializer.instance; default: } } return this; } @Override public void serialize(Number value, JsonGenerator g, SerializerProvider provider) throws IOException { // should mostly come in as one of these two: if (value instanceof BigDecimal) { g.writeNumber((BigDecimal) value); } else if (value instanceof BigInteger) { g.writeNumber((BigInteger) value); // These should not occur, as more specific methods should have been called; but // just in case let's cover all bases: } else if (value instanceof Long) { g.writeNumber(value.longValue()); } else if (value instanceof Double) { g.writeNumber(value.doubleValue()); } else if (value instanceof Float) { g.writeNumber(value.floatValue()); } else if (value instanceof Integer || value instanceof Byte || value instanceof Short) { g.writeNumber(value.intValue()); // doesn't need to be cast to smaller numbers } else { // We'll have to use fallback "untyped" number write method g.writeNumber(value.toString()); } } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode(_isInt ? "integer" : "number", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { if (_isInt) { visitIntFormat(visitor, typeHint, JsonParser.NumberType.BIG_INTEGER); } else { Class h = handledType(); if (h == BigDecimal.class) { visitFloatFormat(visitor, typeHint, JsonParser.NumberType.BIG_DECIMAL); } else { // otherwise bit unclear what to call... but let's try: /*JsonNumberFormatVisitor v2 =*/ visitor.expectNumberFormat(typeHint); } } } }NumberSerializers.java000066400000000000000000000203451325620701100363470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import java.util.Map; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; /** * Container class for serializers used for handling standard JDK-provided * types. */ @SuppressWarnings("serial") public class NumberSerializers { protected NumberSerializers() { } public static void addAll(Map> allDeserializers) { allDeserializers.put(Integer.class.getName(), new IntegerSerializer(Integer.class)); allDeserializers.put(Integer.TYPE.getName(), new IntegerSerializer(Integer.TYPE)); allDeserializers.put(Long.class.getName(), new LongSerializer(Long.class)); allDeserializers.put(Long.TYPE.getName(), new LongSerializer(Long.TYPE)); allDeserializers.put(Byte.class.getName(), IntLikeSerializer.instance); allDeserializers.put(Byte.TYPE.getName(), IntLikeSerializer.instance); allDeserializers.put(Short.class.getName(), ShortSerializer.instance); allDeserializers.put(Short.TYPE.getName(), ShortSerializer.instance); // Numbers, limited length floating point allDeserializers.put(Double.class.getName(), new DoubleSerializer(Double.class)); allDeserializers.put(Double.TYPE.getName(), new DoubleSerializer(Double.TYPE)); allDeserializers.put(Float.class.getName(), FloatSerializer.instance); allDeserializers.put(Float.TYPE.getName(), FloatSerializer.instance); } /* /********************************************************** /* Shared base class /********************************************************** */ protected abstract static class Base extends StdScalarSerializer implements ContextualSerializer { protected final JsonParser.NumberType _numberType; protected final String _schemaType; protected final boolean _isInt; protected Base(Class cls, JsonParser.NumberType numberType, String schemaType) { super(cls, false); _numberType = numberType; _schemaType = schemaType; _isInt = (numberType == JsonParser.NumberType.INT) || (numberType == JsonParser.NumberType.LONG) || (numberType == JsonParser.NumberType.BIG_INTEGER); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode(_schemaType, true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { if (_isInt) { visitIntFormat(visitor, typeHint, _numberType); } else { visitFloatFormat(visitor, typeHint, _numberType); } } @Override public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { JsonFormat.Value format = findFormatOverrides(prov, property, handledType()); if (format != null) { switch (format.getShape()) { case STRING: return ToStringSerializer.instance; default: } } return this; } } /* ************************************************************* * Concrete serializers, numerics ************************************************************* */ @JacksonStdImpl public final static class ShortSerializer extends Base { final static ShortSerializer instance = new ShortSerializer(); public ShortSerializer() { super(Short.class, JsonParser.NumberType.INT, "number"); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeNumber(((Short) value).shortValue()); } } /** * This is the special serializer for regular {@link java.lang.Integer}s * (and primitive ints) *

* Since this is one of "native" types, no type information is ever included * on serialization (unlike for most scalar types) *

* NOTE: as of 2.6, generic signature changed to Object, to avoid generation * of bridge methods. */ @JacksonStdImpl public final static class IntegerSerializer extends Base { public IntegerSerializer(Class type) { super(type, JsonParser.NumberType.INT, "integer"); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeNumber(((Integer) value).intValue()); } // IMPORTANT: copied from `NonTypedScalarSerializerBase` @Override public void serializeWithType(Object value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // no type info, just regular serialization serialize(value, gen, provider); } } /** * Similar to {@link IntegerSerializer}, but will not cast to Integer: * instead, cast is to {@link java.lang.Number}, and conversion is by * calling {@link java.lang.Number#intValue}. */ @JacksonStdImpl public final static class IntLikeSerializer extends Base { final static IntLikeSerializer instance = new IntLikeSerializer(); public IntLikeSerializer() { super(Number.class, JsonParser.NumberType.INT, "integer"); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeNumber(((Number) value).intValue()); } } @JacksonStdImpl public final static class LongSerializer extends Base { public LongSerializer(Class cls) { super(cls, JsonParser.NumberType.LONG, "number"); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeNumber(((Long) value).longValue()); } } @JacksonStdImpl public final static class FloatSerializer extends Base { final static FloatSerializer instance = new FloatSerializer(); public FloatSerializer() { super(Float.class, JsonParser.NumberType.FLOAT, "number"); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeNumber(((Float) value).floatValue()); } } /** * This is the special serializer for regular {@link java.lang.Double}s (and * primitive doubles) *

* Since this is one of "native" types, no type information is ever included * on serialization (unlike for most scalar types as of 1.5) */ @JacksonStdImpl public final static class DoubleSerializer extends Base { public DoubleSerializer(Class cls) { super(cls, JsonParser.NumberType.DOUBLE, "number"); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeNumber(((Double) value).doubleValue()); } // IMPORTANT: copied from `NonTypedScalarSerializerBase` @Override public void serializeWithType(Object value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // no type info, just regular serialization serialize(value, gen, provider); } } } ObjectArraySerializer.java000066400000000000000000000312031325620701100371340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContainerSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; /** * Generic serializer for Object arrays (Object[]). */ @JacksonStdImpl @SuppressWarnings("serial") public class ObjectArraySerializer extends ArraySerializerBase implements ContextualSerializer { /** * Whether we are using static typing (using declared types, ignoring * runtime type) or not for elements. */ protected final boolean _staticTyping; /** * Declared type of element entries */ protected final JavaType _elementType; /** * Type serializer to use for values, if any. */ protected final TypeSerializer _valueTypeSerializer; /** * Value serializer to use, if it can be statically determined. */ protected JsonSerializer _elementSerializer; /** * If element type cannot be statically determined, mapping from * runtime type to serializer is handled using this object */ protected PropertySerializerMap _dynamicSerializers; /* /********************************************************** /* Life-cycle /********************************************************** */ public ObjectArraySerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts, JsonSerializer elementSerializer) { super(Object[].class); _elementType = elemType; _staticTyping = staticTyping; _valueTypeSerializer = vts; _dynamicSerializers = PropertySerializerMap.emptyForProperties(); _elementSerializer = elementSerializer; } public ObjectArraySerializer(ObjectArraySerializer src, TypeSerializer vts) { super(src); _elementType = src._elementType; _valueTypeSerializer = vts; _staticTyping = src._staticTyping; _dynamicSerializers = src._dynamicSerializers; _elementSerializer = src._elementSerializer; } @SuppressWarnings("unchecked") public ObjectArraySerializer(ObjectArraySerializer src, BeanProperty property, TypeSerializer vts, JsonSerializer elementSerializer, Boolean unwrapSingle) { super(src, property, unwrapSingle); _elementType = src._elementType; _valueTypeSerializer = vts; _staticTyping = src._staticTyping; _dynamicSerializers = src._dynamicSerializers; _elementSerializer = (JsonSerializer) elementSerializer; } @Override public JsonSerializer _withResolved(BeanProperty prop, Boolean unwrapSingle) { return new ObjectArraySerializer(this, prop, _valueTypeSerializer, _elementSerializer, unwrapSingle); } @Override public ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { return new ObjectArraySerializer(_elementType, _staticTyping, vts, _elementSerializer); } public ObjectArraySerializer withResolved(BeanProperty prop, TypeSerializer vts, JsonSerializer ser, Boolean unwrapSingle) { if ((_property == prop) && (ser == _elementSerializer) && (_valueTypeSerializer == vts) && (_unwrapSingle == unwrapSingle)) { return this; } return new ObjectArraySerializer(this, prop, vts, ser, unwrapSingle); } /* /********************************************************** /* Post-processing /********************************************************** */ @Override public JsonSerializer createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException { TypeSerializer vts = _valueTypeSerializer; if (vts != null) { vts = vts.forProperty(property); } JsonSerializer ser = null; Boolean unwrapSingle = null; // First: if we have a property, may have property-annotation overrides if (property != null) { AnnotatedMember m = property.getMember(); final AnnotationIntrospector intr = serializers.getAnnotationIntrospector(); if (m != null) { Object serDef = intr.findContentSerializer(m); if (serDef != null) { ser = serializers.serializerInstance(m, serDef); } } } JsonFormat.Value format = findFormatOverrides(serializers, property, handledType()); if (format != null) { unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); } if (ser == null) { ser = _elementSerializer; } // [databind#124]: May have a content converter ser = findContextualConvertingSerializer(serializers, property, ser); if (ser == null) { // 30-Sep-2012, tatu: One more thing -- if explicit content type is annotated, // we can consider it a static case as well. if (_elementType != null) { if (_staticTyping && !_elementType.isJavaLangObject()) { ser = serializers.findValueSerializer(_elementType, property); } } } return withResolved(property, vts, ser, unwrapSingle); } /* /********************************************************** /* Accessors /********************************************************** */ @Override public JavaType getContentType() { return _elementType; } @Override public JsonSerializer getContentSerializer() { return _elementSerializer; } @Override public boolean isEmpty(SerializerProvider prov, Object[] value) { return value.length == 0; } @Override public boolean hasSingleElement(Object[] value) { return (value.length == 1); } /* /********************************************************** /* Actual serialization /********************************************************** */ @Override public final void serialize(Object[] value, JsonGenerator gen, SerializerProvider provider) throws IOException { final int len = value.length; if (len == 1) { if (((_unwrapSingle == null) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) || (_unwrapSingle == Boolean.TRUE)) { serializeContents(value, gen, provider); return; } } gen.writeStartArray(len); serializeContents(value, gen, provider); gen.writeEndArray(); } @Override public void serializeContents(Object[] value, JsonGenerator gen, SerializerProvider provider) throws IOException { final int len = value.length; if (len == 0) { return; } if (_elementSerializer != null) { serializeContentsUsing(value, gen, provider, _elementSerializer); return; } if (_valueTypeSerializer != null) { serializeTypedContents(value, gen, provider); return; } int i = 0; Object elem = null; try { PropertySerializerMap serializers = _dynamicSerializers; for (; i < len; ++i) { elem = value[i]; if (elem == null) { provider.defaultSerializeNull(gen); continue; } Class cc = elem.getClass(); JsonSerializer serializer = serializers.serializerFor(cc); if (serializer == null) { if (_elementType.hasGenericTypes()) { serializer = _findAndAddDynamic(serializers, provider.constructSpecializedType(_elementType, cc), provider); } else { serializer = _findAndAddDynamic(serializers, cc, provider); } } serializer.serialize(elem, gen, provider); } } catch (Exception e) { wrapAndThrow(provider, e, elem, i); } } public void serializeContentsUsing(Object[] value, JsonGenerator jgen, SerializerProvider provider, JsonSerializer ser) throws IOException { final int len = value.length; final TypeSerializer typeSer = _valueTypeSerializer; int i = 0; Object elem = null; try { for (; i < len; ++i) { elem = value[i]; if (elem == null) { provider.defaultSerializeNull(jgen); continue; } if (typeSer == null) { ser.serialize(elem, jgen, provider); } else { ser.serializeWithType(elem, jgen, provider, typeSer); } } } catch (Exception e) { wrapAndThrow(provider, e, elem, i); } } public void serializeTypedContents(Object[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException { final int len = value.length; final TypeSerializer typeSer = _valueTypeSerializer; int i = 0; Object elem = null; try { PropertySerializerMap serializers = _dynamicSerializers; for (; i < len; ++i) { elem = value[i]; if (elem == null) { provider.defaultSerializeNull(jgen); continue; } Class cc = elem.getClass(); JsonSerializer serializer = serializers.serializerFor(cc); if (serializer == null) { serializer = _findAndAddDynamic(serializers, cc, provider); } serializer.serializeWithType(elem, jgen, provider, typeSer); } } catch (Exception e) { wrapAndThrow(provider, e, elem, i); } } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { JsonArrayFormatVisitor arrayVisitor = visitor.expectArrayFormat(typeHint); if (arrayVisitor != null) { JavaType contentType = _elementType; // [databind#1793]: Was getting `null` for `typeHint`. But why would we even use it... /* TypeFactory tf = visitor.getProvider().getTypeFactory(); contentType = tf.moreSpecificType(_elementType, typeHint.getContentType()); if (contentType == null) { visitor.getProvider().reportBadDefinition(_elementType, "Could not resolve type: "+_elementType); } */ JsonSerializer valueSer = _elementSerializer; if (valueSer == null) { valueSer = visitor.getProvider().findValueSerializer(contentType, _property); } arrayVisitor.itemsFormat(valueSer, contentType); } } protected final JsonSerializer _findAndAddDynamic(PropertySerializerMap map, Class type, SerializerProvider provider) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property); // did we get a new map of serializers? If so, start using it if (map != result.map) { _dynamicSerializers = result.map; } return result.serializer; } protected final JsonSerializer _findAndAddDynamic(PropertySerializerMap map, JavaType type, SerializerProvider provider) throws JsonMappingException { PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property); // did we get a new map of serializers? If so, start using it if (map != result.map) { _dynamicSerializers = result.map; } return result.serializer; } } RawSerializer.java000066400000000000000000000036161325620701100354670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.lang.reflect.Type; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * This is a simple dummy serializer that will just output raw values by calling * toString() on value to serialize. */ @SuppressWarnings("serial") public class RawSerializer extends StdSerializer { /** * Constructor takes in expected type of values; but since caller * typically cannot really provide actual type parameter, we will * just take wild card and coerce type. */ public RawSerializer(Class cls) { super(cls, false); } @Override public void serialize(T value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeRawValue(value.toString()); } @Override public void serializeWithType(T value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.VALUE_EMBEDDED_OBJECT)); serialize(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { // type not really known, but since it is a JSON string: return createSchemaNode("string", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { // type not really known, but since it is a JSON string: visitStringFormat(visitor, typeHint); } } ReferenceTypeSerializer.java000066400000000000000000000432241325620701100374750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; import com.fasterxml.jackson.databind.type.ReferenceType; import com.fasterxml.jackson.databind.util.ArrayBuilders; import com.fasterxml.jackson.databind.util.BeanUtil; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Base implementation for values of {@link ReferenceType}. * Implements most of functionality, only leaving couple of abstract * methods for sub-classes to implement * * @since 2.8 */ public abstract class ReferenceTypeSerializer extends StdSerializer implements ContextualSerializer { private static final long serialVersionUID = 1L; /** * @since 2.9 */ public final static Object MARKER_FOR_EMPTY = JsonInclude.Include.NON_EMPTY; /** * Value type */ protected final JavaType _referredType; protected final BeanProperty _property; /** * Type serializer used for values, if any. */ protected final TypeSerializer _valueTypeSerializer; /** * Serializer for content values, if statically known. */ protected final JsonSerializer _valueSerializer; /** * In case of unwrapping, need name transformer. */ protected final NameTransformer _unwrapper; /** * If element type cannot be statically determined, mapping from * runtime type to serializer is handled using this object */ protected transient PropertySerializerMap _dynamicSerializers; /* /********************************************************** /* Config settings, filtering /********************************************************** */ /** * Value that indicates suppression mechanism to use for values contained; * either "filter" (of which equals() is called), or marker * value of {@link #MARKER_FOR_EMPTY}, or null to indicate no filtering for * non-null values. * Note that inclusion value for Map instance itself is handled by caller (POJO * property that refers to the Map value). * * @since 2.9 */ protected final Object _suppressableValue; /** * Flag that indicates what to do with `null` values, distinct from * handling of {@link #_suppressableValue} * * @since 2.9 */ protected final boolean _suppressNulls; /* /********************************************************** /* Constructors, factory methods /********************************************************** */ public ReferenceTypeSerializer(ReferenceType fullType, boolean staticTyping, TypeSerializer vts, JsonSerializer ser) { super(fullType); _referredType = fullType.getReferencedType(); _property = null; _valueTypeSerializer = vts; _valueSerializer = ser; _unwrapper = null; _suppressableValue = null; _suppressNulls = false; _dynamicSerializers = PropertySerializerMap.emptyForProperties(); } @SuppressWarnings("unchecked") protected ReferenceTypeSerializer(ReferenceTypeSerializer base, BeanProperty property, TypeSerializer vts, JsonSerializer valueSer, NameTransformer unwrapper, Object suppressableValue, boolean suppressNulls) { super(base); _referredType = base._referredType; _dynamicSerializers = base._dynamicSerializers; _property = property; _valueTypeSerializer = vts; _valueSerializer = (JsonSerializer) valueSer; _unwrapper = unwrapper; _suppressableValue = suppressableValue; _suppressNulls = suppressNulls; } @Override public JsonSerializer unwrappingSerializer(NameTransformer transformer) { JsonSerializer valueSer = _valueSerializer; if (valueSer != null) { valueSer = valueSer.unwrappingSerializer(transformer); } NameTransformer unwrapper = (_unwrapper == null) ? transformer : NameTransformer.chainedTransformer(transformer, _unwrapper); if ((_valueSerializer == valueSer) && (_unwrapper == unwrapper)) { return this; } return withResolved(_property, _valueTypeSerializer, valueSer, unwrapper); } /* /********************************************************** /* Abstract methods to implement /********************************************************** */ /** * Mutant factory method called when changes are needed; should construct * newly configured instance with new values as indicated. *

* NOTE: caller has verified that there are changes, so implementations * need NOT check if a new instance is needed. * * @since 2.9 */ protected abstract ReferenceTypeSerializer withResolved(BeanProperty prop, TypeSerializer vts, JsonSerializer valueSer, NameTransformer unwrapper); /** * Mutant factory method called to create a differently constructed instance, * specifically with different exclusion rules for contained value. *

* NOTE: caller has verified that there are changes, so implementations * need NOT check if a new instance is needed. * * @since 2.9 */ public abstract ReferenceTypeSerializer withContentInclusion(Object suppressableValue, boolean suppressNulls); /** * Method called to see if there is a value present or not. * Note that value itself may still be `null`, even if present, * if referential type allows three states (absent, present-null, * present-non-null); some only allow two (absent, present-non-null). */ protected abstract boolean _isValuePresent(T value); protected abstract Object _getReferenced(T value); protected abstract Object _getReferencedIfPresent(T value); /* /********************************************************** /* Contextualization (support for property annotations) /********************************************************** */ @Override public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { TypeSerializer typeSer = _valueTypeSerializer; if (typeSer != null) { typeSer = typeSer.forProperty(property); } // First: do we have an annotation override from property? JsonSerializer ser = findAnnotatedContentSerializer(provider, property); if (ser == null) { // If not, use whatever was configured by type ser = _valueSerializer; if (ser == null) { // A few conditions needed to be able to fetch serializer here: if (_useStatic(provider, property, _referredType)) { ser = _findSerializer(provider, _referredType, property); } } else { ser = provider.handlePrimaryContextualization(ser, property); } } // First, resolve wrt property, resolved serializers ReferenceTypeSerializer refSer; if ((_property == property) && (_valueTypeSerializer == typeSer) && (_valueSerializer == ser)) { refSer = this; } else { refSer = withResolved(property, typeSer, ser, _unwrapper); } // and then see if we have property-inclusion overrides if (property != null) { JsonInclude.Value inclV = property.findPropertyInclusion(provider.getConfig(), handledType()); if (inclV != null) { JsonInclude.Include incl = inclV.getContentInclusion(); if (incl != JsonInclude.Include.USE_DEFAULTS) { Object valueToSuppress; boolean suppressNulls; switch (incl) { case NON_DEFAULT: valueToSuppress = BeanUtil.getDefaultValue(_referredType); suppressNulls = true; if (valueToSuppress != null) { if (valueToSuppress.getClass().isArray()) { valueToSuppress = ArrayBuilders.getArrayComparator(valueToSuppress); } } break; case NON_ABSENT: suppressNulls = true; valueToSuppress = _referredType.isReferenceType() ? MARKER_FOR_EMPTY : null; break; case NON_EMPTY: suppressNulls = true; valueToSuppress = MARKER_FOR_EMPTY; break; case CUSTOM: valueToSuppress = provider.includeFilterInstance(null, inclV.getContentFilter()); if (valueToSuppress == null) { // is this legal? suppressNulls = true; } else { suppressNulls = provider.includeFilterSuppressNulls(valueToSuppress); } break; case NON_NULL: valueToSuppress = null; suppressNulls = true; break; case ALWAYS: // default default: valueToSuppress = null; suppressNulls = false; break; } if ((_suppressableValue != valueToSuppress) || (_suppressNulls != suppressNulls)) { refSer = refSer.withContentInclusion(valueToSuppress, suppressNulls); } } } } return refSer; } protected boolean _useStatic(SerializerProvider provider, BeanProperty property, JavaType referredType) { // First: no serializer for `Object.class`, must be dynamic if (referredType.isJavaLangObject()) { return false; } // but if type is final, might as well fetch if (referredType.isFinal()) { // or should we allow annotation override? (only if requested...) return true; } // also: if indicated by typing, should be considered static if (referredType.useStaticType()) { return true; } // if neither, maybe explicit annotation? AnnotationIntrospector intr = provider.getAnnotationIntrospector(); if ((intr != null) && (property != null)) { Annotated ann = property.getMember(); if (ann != null) { JsonSerialize.Typing t = intr.findSerializationTyping(property.getMember()); if (t == JsonSerialize.Typing.STATIC) { return true; } if (t == JsonSerialize.Typing.DYNAMIC) { return false; } } } // and finally, may be forced by global static typing (unlikely...) return provider.isEnabled(MapperFeature.USE_STATIC_TYPING); } /* /********************************************************** /* Accessors /********************************************************** */ @Override public boolean isEmpty(SerializerProvider provider, T value) { // First, absent value (note: null check is just sanity check here) if (!_isValuePresent(value)) { return true; } Object contents = _getReferenced(value); if (contents == null) { // possible for explicitly contained `null` return _suppressNulls; } if (_suppressableValue == null) { return false; } JsonSerializer ser = _valueSerializer; if (ser == null) { try { ser = _findCachedSerializer(provider, contents.getClass()); } catch (JsonMappingException e) { // nasty but necessary throw new RuntimeJsonMappingException(e); } } if (_suppressableValue == MARKER_FOR_EMPTY) { return ser.isEmpty(provider, contents); } return _suppressableValue.equals(contents); } @Override public boolean isUnwrappingSerializer() { return (_unwrapper != null); } /** * @since 2.9 */ public JavaType getReferredType() { return _referredType; } /* /********************************************************** /* Serialization methods /********************************************************** */ @Override public void serialize(T ref, JsonGenerator g, SerializerProvider provider) throws IOException { Object value = _getReferencedIfPresent(ref); if (value == null) { if (_unwrapper == null) { provider.defaultSerializeNull(g); } return; } JsonSerializer ser = _valueSerializer; if (ser == null) { ser = _findCachedSerializer(provider, value.getClass()); } if (_valueTypeSerializer != null) { ser.serializeWithType(value, g, provider, _valueTypeSerializer); } else { ser.serialize(value, g, provider); } } @Override public void serializeWithType(T ref, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { Object value = _getReferencedIfPresent(ref); if (value == null) { if (_unwrapper == null) { provider.defaultSerializeNull(g); } return; } // 19-Apr-2016, tatu: In order to basically "skip" the whole wrapper level // (which is what non-polymorphic serialization does too), we will need // to simply delegate call, I think, and NOT try to use it here. // Otherwise apply type-prefix/suffix, then std serialize: /* typeSer.writeTypePrefixForScalar(ref, g); serialize(ref, g, provider); typeSer.writeTypeSuffixForScalar(ref, g); */ JsonSerializer ser = _valueSerializer; if (ser == null) { ser = _findCachedSerializer(provider, value.getClass()); } ser.serializeWithType(value, g, provider, typeSer); } /* /********************************************************** /* Introspection support /********************************************************** */ @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { JsonSerializer ser = _valueSerializer; if (ser == null) { ser = _findSerializer(visitor.getProvider(), _referredType, _property); if (_unwrapper != null) { ser = ser.unwrappingSerializer(_unwrapper); } } ser.acceptJsonFormatVisitor(visitor, _referredType); } /* /********************************************************** /* Helper methods /********************************************************** */ /** * Helper method that encapsulates logic of retrieving and caching required * serializer. */ private final JsonSerializer _findCachedSerializer(SerializerProvider provider, Class rawType) throws JsonMappingException { JsonSerializer ser = _dynamicSerializers.serializerFor(rawType); if (ser == null) { // NOTE: call this instead of `map._findAndAddDynamic(...)` (which in turn calls // `findAndAddSecondarySerializer`) since we may need to apply unwrapper // too, before caching. But calls made are the same if (_referredType.hasGenericTypes()) { // [databind#1673] Must ensure we will resolve all available type information // so as not to miss generic declaration of, say, `List`... JavaType fullType = provider.constructSpecializedType(_referredType, rawType); ser = provider.findValueSerializer(fullType, _property); } else { ser = provider.findValueSerializer(rawType, _property); } if (_unwrapper != null) { ser = ser.unwrappingSerializer(_unwrapper); } _dynamicSerializers = _dynamicSerializers.newWith(rawType, ser); } return ser; } private final JsonSerializer _findSerializer(SerializerProvider provider, JavaType type, BeanProperty prop) throws JsonMappingException { // 13-Mar-2017, tatu: Used to call `findTypeValueSerializer()`, but contextualization // not working for that case for some reason // 15-Jan-2017, tatu: ... possibly because we need to access "secondary" serializer, // not primary (primary being one for Reference type itself, not value) // return provider.findTypedValueSerializer(type, true, prop); return provider.findValueSerializer(type, prop); } } SerializableSerializer.java000066400000000000000000000036371325620701100373470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializable; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * Generic handler for types that implement {@link JsonSerializable}. *

* Note: given that this is used for anything that implements * interface, cannot be checked for direct class equivalence. */ @JacksonStdImpl @SuppressWarnings("serial") public class SerializableSerializer extends StdSerializer { public final static SerializableSerializer instance = new SerializableSerializer(); protected SerializableSerializer() { super(JsonSerializable.class); } @Override public boolean isEmpty(SerializerProvider serializers, JsonSerializable value) { if (value instanceof JsonSerializable.Base) { return ((JsonSerializable.Base) value).isEmpty(serializers); } return false; } @Override public void serialize(JsonSerializable value, JsonGenerator gen, SerializerProvider serializers) throws IOException { value.serialize(gen, serializers); } @Override public final void serializeWithType(JsonSerializable value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException { value.serializeWithType(gen, serializers, typeSer); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitor.expectAnyFormat(typeHint); } } SqlDateSerializer.java000066400000000000000000000036431325620701100362730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.text.DateFormat; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; /** * Compared to regular {@link java.util.Date} serialization, we do use String * representation here. Why? Basically to truncate of time part, since * that should not be used by plain SQL date. */ @JacksonStdImpl @SuppressWarnings("serial") public class SqlDateSerializer extends DateTimeSerializerBase { public SqlDateSerializer() { // 11-Oct-2016, tatu: As per [databind#219] fixed for 2.9; was passing `false` prior this(null, null); } protected SqlDateSerializer(Boolean useTimestamp, DateFormat customFormat) { super(java.sql.Date.class, useTimestamp, customFormat); } @Override public SqlDateSerializer withFormat(Boolean timestamp, DateFormat customFormat) { return new SqlDateSerializer(timestamp, customFormat); } @Override protected long _timestamp(java.sql.Date value) { return (value == null) ? 0L : value.getTime(); } @Override public void serialize(java.sql.Date value, JsonGenerator g, SerializerProvider provider) throws IOException { if (_asTimestamp(provider)) { g.writeNumber(_timestamp(value)); return; } // Alas, can't just call `_serializeAsString()`.... if (_customFormat == null) { // 11-Oct-2016, tatu: For backwards-compatibility purposes, we shall just use // the awful standard JDK serialization via `sqlDate.toString()`... this // is problematic in multiple ways (including using arbitrary timezone...) g.writeString(value.toString()); return; } _serializeAsString(value, g, provider); } } SqlTimeSerializer.java000066400000000000000000000022211325620701100363030ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat; @JacksonStdImpl @SuppressWarnings("serial") public class SqlTimeSerializer extends StdScalarSerializer { public SqlTimeSerializer() { super(java.sql.Time.class); } @Override public void serialize(java.sql.Time value, JsonGenerator g, SerializerProvider provider) throws IOException { g.writeString(value.toString()); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("string", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitStringFormat(visitor, typeHint, JsonValueFormat.DATE_TIME); } }StaticListSerializerBase.java000066400000000000000000000111041325620701100376030ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; /** * Intermediate base class for Lists, Collections and Arrays * that contain static (non-dynamic) value types. */ @SuppressWarnings("serial") public abstract class StaticListSerializerBase> extends StdSerializer implements ContextualSerializer { /** * Setting for specific local override for "unwrap single element arrays": * true for enable unwrapping, false for preventing it, `null` for using * global configuration. * * @since 2.6 */ protected final Boolean _unwrapSingle; protected StaticListSerializerBase(Class cls) { super(cls, false); _unwrapSingle = null; } /** * @since 2.9 */ protected StaticListSerializerBase(StaticListSerializerBase src, Boolean unwrapSingle) { super(src); _unwrapSingle = unwrapSingle; } /** * @since 2.9 */ public abstract JsonSerializer _withResolved(BeanProperty prop, Boolean unwrapSingle); /* /********************************************************** /* Post-processing /********************************************************** */ @SuppressWarnings("unchecked") @Override public JsonSerializer createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException { JsonSerializer ser = null; Boolean unwrapSingle = null; if (property != null) { final AnnotationIntrospector intr = serializers.getAnnotationIntrospector(); AnnotatedMember m = property.getMember(); if (m != null) { Object serDef = intr.findContentSerializer(m); if (serDef != null) { ser = serializers.serializerInstance(m, serDef); } } } JsonFormat.Value format = findFormatOverrides(serializers, property, handledType()); if (format != null) { unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); } // [databind#124]: May have a content converter ser = findContextualConvertingSerializer(serializers, property, ser); if (ser == null) { ser = serializers.findValueSerializer(String.class, property); } // Optimization: default serializer just writes String, so we can avoid a call: if (isDefaultSerializer(ser)) { if (unwrapSingle == _unwrapSingle) { return this; } return _withResolved(property, unwrapSingle); } // otherwise... // note: will never have TypeSerializer, because Strings are "natural" type return new CollectionSerializer(serializers.constructType(String.class), true, /*TypeSerializer*/ null, (JsonSerializer) ser); } @Override public boolean isEmpty(SerializerProvider provider, T value) { return (value == null) || (value.size() == 0); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("array", true).set("items", contentSchema()); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { acceptContentVisitor(visitor.expectArrayFormat(typeHint)); } /* /********************************************************** /* Abstract methods for sub-classes to implement /********************************************************** */ protected abstract JsonNode contentSchema(); protected abstract void acceptContentVisitor(JsonArrayFormatVisitor visitor) throws JsonMappingException; // just to make sure it gets implemented: @Override public abstract void serializeWithType(T value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException; } StdArraySerializers.java000066400000000000000000000560021325620701100366470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import java.util.HashMap; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.ContainerSerializer; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Dummy container class to group standard homogenous array serializer implementations * (primitive arrays and String array). */ @SuppressWarnings("serial") public class StdArraySerializers { protected final static HashMap> _arraySerializers = new HashMap>(); static { // Arrays of various types (including common object types) _arraySerializers.put(boolean[].class.getName(), new StdArraySerializers.BooleanArraySerializer()); _arraySerializers.put(byte[].class.getName(), new ByteArraySerializer()); _arraySerializers.put(char[].class.getName(), new StdArraySerializers.CharArraySerializer()); _arraySerializers.put(short[].class.getName(), new StdArraySerializers.ShortArraySerializer()); _arraySerializers.put(int[].class.getName(), new StdArraySerializers.IntArraySerializer()); _arraySerializers.put(long[].class.getName(), new StdArraySerializers.LongArraySerializer()); _arraySerializers.put(float[].class.getName(), new StdArraySerializers.FloatArraySerializer()); _arraySerializers.put(double[].class.getName(), new StdArraySerializers.DoubleArraySerializer()); } protected StdArraySerializers() { } /** * Accessor for checking to see if there is a standard serializer for * given primitive value type. */ public static JsonSerializer findStandardImpl(Class cls) { return _arraySerializers.get(cls.getName()); } /* **************************************************************** /* Intermediate base classes **************************************************************** */ /** * Intermediate base class used for cases where we may add * type information (excludes boolean/int/double arrays). */ protected abstract static class TypedPrimitiveArraySerializer extends ArraySerializerBase { protected TypedPrimitiveArraySerializer(Class cls) { super(cls); } protected TypedPrimitiveArraySerializer(TypedPrimitiveArraySerializer src, BeanProperty prop, Boolean unwrapSingle) { super(src, prop, unwrapSingle); } // 01-Dec-2016, tatu: Only now realized that due strong typing of Java arrays, // we cannot really ever have value type serializers @Override public final ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { // throw exception or just do nothing? return this; } } /* /**************************************************************** /* Concrete serializers, arrays /**************************************************************** */ @JacksonStdImpl public static class BooleanArraySerializer extends ArraySerializerBase { // as above, assuming no one re-defines primitive/wrapper types @SuppressWarnings("deprecation") private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Boolean.class); public BooleanArraySerializer() { super(boolean[].class); } protected BooleanArraySerializer(BooleanArraySerializer src, BeanProperty prop, Boolean unwrapSingle) { super(src, prop, unwrapSingle); } @Override public JsonSerializer _withResolved(BeanProperty prop, Boolean unwrapSingle) { return new BooleanArraySerializer(this, prop, unwrapSingle); } /** * Booleans never add type info; hence, even if type serializer is suggested, * we'll ignore it... */ @Override public ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { return this; } @Override public JavaType getContentType() { return VALUE_TYPE; } @Override public JsonSerializer getContentSerializer() { // 14-Jan-2012, tatu: We could refer to an actual serializer if absolutely necessary return null; } @Override public boolean isEmpty(SerializerProvider prov, boolean[] value) { return value.length == 0; } @Override public boolean hasSingleElement(boolean[] value) { return (value.length == 1); } @Override public final void serialize(boolean[] value, JsonGenerator g, SerializerProvider provider) throws IOException { final int len = value.length; if ((len == 1) && _shouldUnwrapSingle(provider)) { serializeContents(value, g, provider); return; } g.writeStartArray(len); g.setCurrentValue(value); serializeContents(value, g, provider); g.writeEndArray(); } @Override public void serializeContents(boolean[] value, JsonGenerator g, SerializerProvider provider) throws IOException { for (int i = 0, len = value.length; i < len; ++i) { g.writeBoolean(value[i]); } } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { ObjectNode o = createSchemaNode("array", true); o.set("items", createSchemaNode("boolean")); return o; } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitArrayFormat(visitor, typeHint, JsonFormatTypes.BOOLEAN); } } @JacksonStdImpl public static class ShortArraySerializer extends TypedPrimitiveArraySerializer { // as above, assuming no one re-defines primitive/wrapper types @SuppressWarnings("deprecation") private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Short.TYPE); public ShortArraySerializer() { super(short[].class); } public ShortArraySerializer(ShortArraySerializer src, BeanProperty prop, Boolean unwrapSingle) { super(src, prop, unwrapSingle); } @Override public JsonSerializer _withResolved(BeanProperty prop,Boolean unwrapSingle) { return new ShortArraySerializer(this, prop, unwrapSingle); } @Override public JavaType getContentType() { return VALUE_TYPE; } @Override public JsonSerializer getContentSerializer() { // 14-Jan-2012, tatu: We could refer to an actual serializer if absolutely necessary return null; } @Override public boolean isEmpty(SerializerProvider prov, short[] value) { return value.length == 0; } @Override public boolean hasSingleElement(short[] value) { return (value.length == 1); } @Override public final void serialize(short[] value, JsonGenerator g, SerializerProvider provider) throws IOException { final int len = value.length; if ((len == 1) && _shouldUnwrapSingle(provider)) { serializeContents(value, g, provider); return; } g.writeStartArray(len); g.setCurrentValue(value); serializeContents(value, g, provider); g.writeEndArray(); } @SuppressWarnings("cast") @Override public void serializeContents(short[] value, JsonGenerator g, SerializerProvider provider) throws IOException { for (int i = 0, len = value.length; i < len; ++i) { g.writeNumber((int)value[i]); } } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { //no "short" type defined by json ObjectNode o = createSchemaNode("array", true); return o.set("items", createSchemaNode("integer")); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitArrayFormat(visitor, typeHint, JsonFormatTypes.INTEGER); } } /** * Character arrays are different from other integral number arrays in that * they are most likely to be textual data, and should be written as * Strings, not arrays of entries. *

* NOTE: since it is NOT serialized as an array, cannot use AsArraySerializer as base */ @JacksonStdImpl public static class CharArraySerializer extends StdSerializer { public CharArraySerializer() { super(char[].class); } @Override public boolean isEmpty(SerializerProvider prov, char[] value) { return value.length == 0; } @Override public void serialize(char[] value, JsonGenerator g, SerializerProvider provider) throws IOException { // [JACKSON-289] allows serializing as 'sparse' char array too: if (provider.isEnabled(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS)) { g.writeStartArray(value.length); g.setCurrentValue(value); _writeArrayContents(g, value); g.writeEndArray(); } else { g.writeString(value, 0, value.length); } } @Override public void serializeWithType(char[] value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // [JACKSON-289] allows serializing as 'sparse' char array too: final boolean asArray = provider.isEnabled(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS); WritableTypeId typeIdDef; if (asArray) { typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.START_ARRAY)); _writeArrayContents(g, value); } else { // default is to write as simple String typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.VALUE_STRING)); g.writeString(value, 0, value.length); } typeSer.writeTypeSuffix(g, typeIdDef); } private final void _writeArrayContents(JsonGenerator g, char[] value) throws IOException { for (int i = 0, len = value.length; i < len; ++i) { g.writeString(value, i, 1); } } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { ObjectNode o = createSchemaNode("array", true); ObjectNode itemSchema = createSchemaNode("string"); itemSchema.put("type", "string"); return o.set("items", itemSchema); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitArrayFormat(visitor, typeHint, JsonFormatTypes.STRING); } } @JacksonStdImpl public static class IntArraySerializer extends ArraySerializerBase { // as above, assuming no one re-defines primitive/wrapper types @SuppressWarnings("deprecation") private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Integer.TYPE); public IntArraySerializer() { super(int[].class); } /** * @since 2.6 */ protected IntArraySerializer(IntArraySerializer src, BeanProperty prop, Boolean unwrapSingle) { super(src, prop, unwrapSingle); } @Override public JsonSerializer _withResolved(BeanProperty prop, Boolean unwrapSingle) { return new IntArraySerializer(this, prop, unwrapSingle); } /** * Ints never add type info; hence, even if type serializer is suggested, * we'll ignore it... */ @Override public ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { return this; } @Override public JavaType getContentType() { return VALUE_TYPE; } @Override public JsonSerializer getContentSerializer() { // 14-Jan-2012, tatu: We could refer to an actual serializer if absolutely necessary return null; } @Override public boolean isEmpty(SerializerProvider prov, int[] value) { return value.length == 0; } @Override public boolean hasSingleElement(int[] value) { return (value.length == 1); } @Override public final void serialize(int[] value, JsonGenerator g, SerializerProvider provider) throws IOException { final int len = value.length; if ((len == 1) && _shouldUnwrapSingle(provider)) { serializeContents(value, g, provider); return; } // 11-May-2016, tatu: As per [core#277] we have efficient `writeArray(...)` available g.setCurrentValue(value); g.writeArray(value, 0, value.length); } @Override public void serializeContents(int[] value, JsonGenerator g, SerializerProvider provider) throws IOException { for (int i = 0, len = value.length; i < len; ++i) { g.writeNumber(value[i]); } } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("array", true).set("items", createSchemaNode("integer")); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitArrayFormat(visitor, typeHint, JsonFormatTypes.INTEGER); } } @JacksonStdImpl public static class LongArraySerializer extends TypedPrimitiveArraySerializer { // as above, assuming no one re-defines primitive/wrapper types @SuppressWarnings("deprecation") private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Long.TYPE); public LongArraySerializer() { super(long[].class); } public LongArraySerializer(LongArraySerializer src, BeanProperty prop, Boolean unwrapSingle) { super(src, prop, unwrapSingle); } @Override public JsonSerializer _withResolved(BeanProperty prop,Boolean unwrapSingle) { return new LongArraySerializer(this, prop, unwrapSingle); } @Override public JavaType getContentType() { return VALUE_TYPE; } @Override public JsonSerializer getContentSerializer() { // 14-Jan-2012, tatu: We could refer to an actual serializer if absolutely necessary return null; } @Override public boolean isEmpty(SerializerProvider prov, long[] value) { return value.length == 0; } @Override public boolean hasSingleElement(long[] value) { return (value.length == 1); } @Override public final void serialize(long[] value, JsonGenerator g, SerializerProvider provider) throws IOException { final int len = value.length; if ((len == 1) && _shouldUnwrapSingle(provider)) { serializeContents(value, g, provider); return; } // 11-May-2016, tatu: As per [core#277] we have efficient `writeArray(...)` available g.setCurrentValue(value); g.writeArray(value, 0, value.length); } @Override public void serializeContents(long[] value, JsonGenerator g, SerializerProvider provider) throws IOException { for (int i = 0, len = value.length; i < len; ++i) { g.writeNumber(value[i]); } } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("array", true) .set("items", createSchemaNode("number", true)); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitArrayFormat(visitor, typeHint, JsonFormatTypes.NUMBER); } } @JacksonStdImpl public static class FloatArraySerializer extends TypedPrimitiveArraySerializer { // as above, assuming no one re-defines primitive/wrapper types @SuppressWarnings("deprecation") private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Float.TYPE); public FloatArraySerializer() { super(float[].class); } public FloatArraySerializer(FloatArraySerializer src, BeanProperty prop, Boolean unwrapSingle) { super(src, prop, unwrapSingle); } @Override public JsonSerializer _withResolved(BeanProperty prop,Boolean unwrapSingle) { return new FloatArraySerializer(this, prop, unwrapSingle); } @Override public JavaType getContentType() { return VALUE_TYPE; } @Override public JsonSerializer getContentSerializer() { // 14-Jan-2012, tatu: We could refer to an actual serializer if absolutely necessary return null; } @Override public boolean isEmpty(SerializerProvider prov, float[] value) { return value.length == 0; } @Override public boolean hasSingleElement(float[] value) { return (value.length == 1); } @Override public final void serialize(float[] value, JsonGenerator g, SerializerProvider provider) throws IOException { final int len = value.length; if ((len == 1) && _shouldUnwrapSingle(provider)) { serializeContents(value, g, provider); return; } g.writeStartArray(len); g.setCurrentValue(value); serializeContents(value, g, provider); g.writeEndArray(); } @Override public void serializeContents(float[] value, JsonGenerator g, SerializerProvider provider) throws IOException { for (int i = 0, len = value.length; i < len; ++i) { g.writeNumber(value[i]); } } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("array", true).set("items", createSchemaNode("number")); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitArrayFormat(visitor, typeHint, JsonFormatTypes.NUMBER); } } @JacksonStdImpl public static class DoubleArraySerializer extends ArraySerializerBase { // as above, assuming no one re-defines primitive/wrapper types @SuppressWarnings("deprecation") private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Double.TYPE); public DoubleArraySerializer() { super(double[].class); } /** * @since 2.6 */ protected DoubleArraySerializer(DoubleArraySerializer src, BeanProperty prop, Boolean unwrapSingle) { super(src, prop, unwrapSingle); } @Override public JsonSerializer _withResolved(BeanProperty prop, Boolean unwrapSingle) { return new DoubleArraySerializer(this, prop, unwrapSingle); } /** * Doubles never add type info; hence, even if type serializer is suggested, * we'll ignore it... */ @Override public ContainerSerializer _withValueTypeSerializer(TypeSerializer vts) { return this; } @Override public JavaType getContentType() { return VALUE_TYPE; } @Override public JsonSerializer getContentSerializer() { // 14-Jan-2012, tatu: We could refer to an actual serializer if absolutely necessary return null; } @Override public boolean isEmpty(SerializerProvider prov, double[] value) { return value.length == 0; } @Override public boolean hasSingleElement(double[] value) { return (value.length == 1); } @Override public final void serialize(double[] value, JsonGenerator g, SerializerProvider provider) throws IOException { final int len = value.length; if ((len == 1) && _shouldUnwrapSingle(provider)) { serializeContents(value, g, provider); return; } g.setCurrentValue(value); // 11-May-2016, tatu: As per [core#277] we have efficient `writeArray(...)` available g.writeArray(value, 0, value.length); } @Override public void serializeContents(double[] value, JsonGenerator g, SerializerProvider provider) throws IOException { for (int i = 0, len = value.length; i < len; ++i) { g.writeNumber(value[i]); } } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("array", true).set("items", createSchemaNode("number")); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitArrayFormat(visitor, typeHint, JsonFormatTypes.NUMBER); } } } StdDelegatingSerializer.java000066400000000000000000000225021325620701100374470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsonschema.SchemaAware; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.ResolvableSerializer; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.Converter; import java.io.IOException; import java.lang.reflect.Type; /** * Serializer implementation where given Java type is first converted * to an intermediate "delegate type" (using a configured * {@link Converter}, and then this delegate value is serialized by Jackson. *

* Note that although types may be related, they must not be same; trying * to do this will result in an exception. * * @since 2.1 */ @SuppressWarnings("serial") public class StdDelegatingSerializer extends StdSerializer implements ContextualSerializer, ResolvableSerializer, JsonFormatVisitable, SchemaAware { protected final Converter _converter; /** * Fully resolved delegate type, with generic information if any available. */ protected final JavaType _delegateType; /** * Underlying serializer for type T. */ protected final JsonSerializer _delegateSerializer; /* /********************************************************** /* Life-cycle /********************************************************** */ @SuppressWarnings("unchecked") public StdDelegatingSerializer(Converter converter) { super(Object.class); _converter = (Converter)converter; _delegateType = null; _delegateSerializer = null; } @SuppressWarnings("unchecked") public StdDelegatingSerializer(Class cls, Converter converter) { super(cls, false); _converter = (Converter)converter; _delegateType = null; _delegateSerializer = null; } @SuppressWarnings("unchecked") public StdDelegatingSerializer(Converter converter, JavaType delegateType, JsonSerializer delegateSerializer) { super(delegateType); _converter = converter; _delegateType = delegateType; _delegateSerializer = (JsonSerializer) delegateSerializer; } /** * Method used for creating resolved contextual instances. Must be * overridden when sub-classing. */ protected StdDelegatingSerializer withDelegate(Converter converter, JavaType delegateType, JsonSerializer delegateSerializer) { ClassUtil.verifyMustOverride(StdDelegatingSerializer.class, this, "withDelegate"); return new StdDelegatingSerializer(converter, delegateType, delegateSerializer); } /* /********************************************************** /* Contextualization /********************************************************** */ @Override public void resolve(SerializerProvider provider) throws JsonMappingException { if ((_delegateSerializer != null) && (_delegateSerializer instanceof ResolvableSerializer)) { ((ResolvableSerializer) _delegateSerializer).resolve(provider); } } @Override public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { JsonSerializer delSer = _delegateSerializer; JavaType delegateType = _delegateType; if (delSer == null) { // Otherwise, need to locate serializer to delegate to. For that we need type information... if (delegateType == null) { delegateType = _converter.getOutputType(provider.getTypeFactory()); } // 02-Apr-2015, tatu: For "dynamic case", where type is only specified as // java.lang.Object (or missing generic), [databind#731] if (!delegateType.isJavaLangObject()) { delSer = provider.findValueSerializer(delegateType); } } if (delSer instanceof ContextualSerializer) { delSer = provider.handleSecondaryContextualization(delSer, property); } if (delSer == _delegateSerializer && delegateType == _delegateType) { return this; } return withDelegate(_converter, delegateType, delSer); } /* /********************************************************** /* Accessors /********************************************************** */ protected Converter getConverter() { return _converter; } @Override public JsonSerializer getDelegatee() { return _delegateSerializer; } /* /********************************************************** /* Serialization /********************************************************** */ @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { Object delegateValue = convertValue(value); // should we accept nulls? if (delegateValue == null) { provider.defaultSerializeNull(gen); return; } // 02-Apr-2015, tatu: As per [databind#731] may need to do dynamic lookup JsonSerializer ser = _delegateSerializer; if (ser == null) { ser = _findSerializer(delegateValue, provider); } ser.serialize(delegateValue, gen, provider); } @Override public void serializeWithType(Object value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { /* 03-Oct-2012, tatu: This is actually unlikely to work ok... but for now, * let's give it a chance? */ Object delegateValue = convertValue(value); JsonSerializer ser = _delegateSerializer; if (ser == null) { ser = _findSerializer(value, provider); } ser.serializeWithType(delegateValue, gen, provider, typeSer); } @Override public boolean isEmpty(SerializerProvider prov, Object value) { Object delegateValue = convertValue(value); if (delegateValue == null) { return true; } if (_delegateSerializer == null) { // best we can do for now, too costly to look up return (value == null); } return _delegateSerializer.isEmpty(prov, delegateValue); } /* /********************************************************** /* Schema functionality /********************************************************** */ @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { if (_delegateSerializer instanceof SchemaAware) { return ((SchemaAware) _delegateSerializer).getSchema(provider, typeHint); } return super.getSchema(provider, typeHint); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint, boolean isOptional) throws JsonMappingException { if (_delegateSerializer instanceof SchemaAware) { return ((SchemaAware) _delegateSerializer).getSchema(provider, typeHint, isOptional); } return super.getSchema(provider, typeHint); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { /* 03-Sep-2012, tatu: Not sure if this can be made to really work * properly... but for now, try this: */ // 02-Apr-2015, tatu: For dynamic case, very little we can do if (_delegateSerializer != null) { _delegateSerializer.acceptJsonFormatVisitor(visitor, typeHint); } } /* /********************************************************** /* Overridable methods /********************************************************** */ /** * Method called to convert from source Java value into delegate * value (which will be serialized using standard Jackson serializer for delegate type) *

* The default implementation uses configured {@link Converter} to do * conversion. * * @param value Value to convert * * @return Result of conversion */ protected Object convertValue(Object value) { return _converter.convert(value); } /** * Helper method used for locating serializer to use in dynamic use case, where * actual type value gets converted to is not specified beyond basic * {@link java.lang.Object}, and where serializer needs to be located dynamically * based on actual value type. * * @since 2.6 */ protected JsonSerializer _findSerializer(Object value, SerializerProvider serializers) throws JsonMappingException { // NOTE: will NOT call contextualization return serializers.findValueSerializer(value.getClass()); } } StdJdkSerializers.java000066400000000000000000000125101325620701100362750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.*; import java.lang.reflect.Type; import java.util.*; import java.util.concurrent.atomic.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.ser.BasicSerializerFactory; /** * Class that providers access to serializers user for non-structured JDK types that * are serializer as scalars; some using basic {@link ToStringSerializer}, * others explicit serializers. */ @SuppressWarnings("serial") public class StdJdkSerializers { /** * Method called by {@link BasicSerializerFactory} to access * all serializers this class provides. */ public static Collection, Object>> all() { HashMap,Object> sers = new HashMap,Object>(); // First things that 'toString()' can handle sers.put(java.net.URL.class, new ToStringSerializer(java.net.URL.class)); sers.put(java.net.URI.class, new ToStringSerializer(java.net.URI.class)); sers.put(Currency.class, new ToStringSerializer(Currency.class)); sers.put(UUID.class, new UUIDSerializer()); sers.put(java.util.regex.Pattern.class, new ToStringSerializer(java.util.regex.Pattern.class)); sers.put(Locale.class, new ToStringSerializer(Locale.class)); // then atomic types (note: AtomicReference defined elsewhere) sers.put(AtomicBoolean.class, AtomicBooleanSerializer.class); sers.put(AtomicInteger.class, AtomicIntegerSerializer.class); sers.put(AtomicLong.class, AtomicLongSerializer.class); // then other types that need specialized serializers sers.put(File.class, FileSerializer.class); sers.put(Class.class, ClassSerializer.class); // And then some stranger types... not 100% they are needed but: sers.put(Void.class, NullSerializer.instance); sers.put(Void.TYPE, NullSerializer.instance); // 09-Jan-2015, tatu: As per [databind#1073], let's try to guard against possibility // of some environments missing `java.sql.` types try { // note: timestamps are very similar to java.util.Date, thus serialized as such sers.put(java.sql.Timestamp.class, DateSerializer.instance); // leave some of less commonly used ones as lazy, no point in proactive construction sers.put(java.sql.Date.class, SqlDateSerializer.class); sers.put(java.sql.Time.class, SqlTimeSerializer.class); } catch (NoClassDefFoundError e) { // nothing much we can do here; could log, but probably not useful for now. } return sers.entrySet(); } /* /********************************************************** /* Serializers for atomic types /********************************************************** */ public static class AtomicBooleanSerializer extends StdScalarSerializer { public AtomicBooleanSerializer() { super(AtomicBoolean.class, false); } @Override public void serialize(AtomicBoolean value, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonGenerationException { gen.writeBoolean(value.get()); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("boolean", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitor.expectBooleanFormat(typeHint); } } public static class AtomicIntegerSerializer extends StdScalarSerializer { public AtomicIntegerSerializer() { super(AtomicInteger.class, false); } @Override public void serialize(AtomicInteger value, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonGenerationException { gen.writeNumber(value.get()); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("integer", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitIntFormat(visitor, typeHint, JsonParser.NumberType.INT); } } public static class AtomicLongSerializer extends StdScalarSerializer { public AtomicLongSerializer() { super(AtomicLong.class, false); } @Override public void serialize(AtomicLong value, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonGenerationException { gen.writeNumber(value.get()); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("integer", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitIntFormat(visitor, typeHint, JsonParser.NumberType.LONG); } } } StdKeySerializer.java000066400000000000000000000014451325620701100361370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; /** * Specialized serializer that can be used as the generic key serializer, * when serializing {@link java.util.Map}s to JSON Objects. * * @deprecated Since 2.8, use {@link StdKeySerializers.Default} instead. */ @SuppressWarnings("serial") @Deprecated // since 2.8, public class StdKeySerializer extends StdSerializer { public StdKeySerializer() { super(Object.class); } @Override public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException { // 19-Oct-2016, tatu: Simplified to bare essentials since this is deprecated g.writeFieldName(value.toString()); } } StdKeySerializers.java000066400000000000000000000271761325620701100363330ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.util.Calendar; import java.util.Date; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.EnumValues; @SuppressWarnings("serial") public abstract class StdKeySerializers { @SuppressWarnings("deprecation") protected final static JsonSerializer DEFAULT_KEY_SERIALIZER = new StdKeySerializer(); protected final static JsonSerializer DEFAULT_STRING_SERIALIZER = new StringKeySerializer(); /** * @param config Serialization configuration in use, may be needed in choosing * serializer to use * @param rawKeyType Type of key values to serialize * @param useDefault If no match is found, should we return fallback deserializer * (true), or null (false)? */ public static JsonSerializer getStdKeySerializer(SerializationConfig config, Class rawKeyType, boolean useDefault) { // 24-Sep-2015, tatu: Important -- should ONLY consider types for which `@JsonValue` // cannot be used, since caller has not yet checked for that annotation // This is why Enum types are not handled here quite yet // [databind#943: Use a dynamic key serializer if we are not given actual // type declaration if ((rawKeyType == null) || (rawKeyType == Object.class)) { return new Dynamic(); } if (rawKeyType == String.class) { return DEFAULT_STRING_SERIALIZER; } if (rawKeyType.isPrimitive()) { rawKeyType = ClassUtil.wrapperType(rawKeyType); } if (rawKeyType == Integer.class) { return new Default(Default.TYPE_INTEGER, rawKeyType); } if (rawKeyType == Long.class) { return new Default(Default.TYPE_LONG, rawKeyType); } if (rawKeyType.isPrimitive() || Number.class.isAssignableFrom(rawKeyType)) { // 28-Jun-2016, tatu: Used to just return DEFAULT_KEY_SERIALIZER, but makes // more sense to use simpler one directly return new Default(Default.TYPE_TO_STRING, rawKeyType); } if (rawKeyType == Class.class) { return new Default(Default.TYPE_CLASS, rawKeyType); } if (Date.class.isAssignableFrom(rawKeyType)) { return new Default(Default.TYPE_DATE, rawKeyType); } if (Calendar.class.isAssignableFrom(rawKeyType)) { return new Default(Default.TYPE_CALENDAR, rawKeyType); } // other JDK types we know convert properly with 'toString()'? if (rawKeyType == java.util.UUID.class) { return new Default(Default.TYPE_TO_STRING, rawKeyType); } if (rawKeyType == byte[].class) { return new Default(Default.TYPE_BYTE_ARRAY, rawKeyType); } if (useDefault) { // 19-Oct-2016, tatu: Used to just return DEFAULT_KEY_SERIALIZER but why not: return new Default(Default.TYPE_TO_STRING, rawKeyType); } return null; } /** * Method called if no specified key serializer was located; will return a * "default" key serializer. * * @since 2.7 */ @SuppressWarnings("unchecked") public static JsonSerializer getFallbackKeySerializer(SerializationConfig config, Class rawKeyType) { if (rawKeyType != null) { // 29-Sep-2015, tatu: Odd case here, of `Enum`, which we may get for `EnumMap`; not sure // if that is a bug or feature. Regardless, it seems to require dynamic handling // (compared to getting actual fully typed Enum). // Note that this might even work from the earlier point, but let's play it safe for now // 11-Aug-2016, tatu: Turns out we get this if `EnumMap` is the root value because // then there is no static type if (rawKeyType == Enum.class) { return new Dynamic(); } if (rawKeyType.isEnum()) { return EnumKeySerializer.construct(rawKeyType, EnumValues.constructFromName(config, (Class>) rawKeyType)); } } // 19-Oct-2016, tatu: Used to just return DEFAULT_KEY_SERIALIZER but why not: return new Default(Default.TYPE_TO_STRING, rawKeyType); } /** * @deprecated since 2.7 */ @Deprecated public static JsonSerializer getDefault() { return DEFAULT_KEY_SERIALIZER; } /* /********************************************************** /* Standard implementations used /********************************************************** */ /** * This is a "chameleon" style multi-type key serializer for simple * standard JDK types. *

* TODO: Should (but does not yet) support re-configuring format used for * {@link java.util.Date} and {@link java.util.Calendar} key serializers, * as well as alternative configuration of Enum key serializers. */ public static class Default extends StdSerializer { final static int TYPE_DATE = 1; final static int TYPE_CALENDAR = 2; final static int TYPE_CLASS = 3; final static int TYPE_ENUM = 4; final static int TYPE_INTEGER = 5; // since 2.9 final static int TYPE_LONG = 6; // since 2.9 final static int TYPE_BYTE_ARRAY = 7; // since 2.9 final static int TYPE_TO_STRING = 8; protected final int _typeId; public Default(int typeId, Class type) { super(type, false); _typeId = typeId; } @Override public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException { switch (_typeId) { case TYPE_DATE: provider.defaultSerializeDateKey((Date)value, g); break; case TYPE_CALENDAR: provider.defaultSerializeDateKey(((Calendar) value).getTimeInMillis(), g); break; case TYPE_CLASS: g.writeFieldName(((Class)value).getName()); break; case TYPE_ENUM: { String key; if (provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) { key = value.toString(); } else { Enum e = (Enum) value; if (provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX)) { key = String.valueOf(e.ordinal()); } else { key = e.name(); } } g.writeFieldName(key); } break; case TYPE_INTEGER: case TYPE_LONG: g.writeFieldId(((Number) value).longValue()); break; case TYPE_BYTE_ARRAY: { String encoded = provider.getConfig().getBase64Variant().encode((byte[]) value); g.writeFieldName(encoded); } break; case TYPE_TO_STRING: default: g.writeFieldName(value.toString()); } } } /** * Key serializer used when key type is not known statically, and actual key * serializer needs to be dynamically located. */ public static class Dynamic extends StdSerializer { // Important: MUST be transient, to allow serialization of key serializer itself protected transient PropertySerializerMap _dynamicSerializers; public Dynamic() { super(String.class, false); _dynamicSerializers = PropertySerializerMap.emptyForProperties(); } Object readResolve() { // Since it's transient, and since JDK serialization by-passes ctor, need this: _dynamicSerializers = PropertySerializerMap.emptyForProperties(); return this; } @Override public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException { Class cls = value.getClass(); PropertySerializerMap m = _dynamicSerializers; JsonSerializer ser = m.serializerFor(cls); if (ser == null) { ser = _findAndAddDynamic(m, cls, provider); } ser.serialize(value, g, provider); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitStringFormat(visitor, typeHint); } protected JsonSerializer _findAndAddDynamic(PropertySerializerMap map, Class type, SerializerProvider provider) throws JsonMappingException { // 27-Jun-2017, tatu: [databind#1679] Need to avoid StackOverflowError... if (type == Object.class) { // basically just need to call `toString()`, easiest way: JsonSerializer ser = new Default(Default.TYPE_TO_STRING, type); _dynamicSerializers = map.newWith(type, ser); return ser; } PropertySerializerMap.SerializerAndMapResult result = // null -> for now we won't keep ref or pass BeanProperty; could change map.findAndAddKeySerializer(type, provider, null); // did we get a new map of serializers? If so, start using it if (map != result.map) { _dynamicSerializers = result.map; } return result.serializer; } } /** * Simple and fast key serializer when keys are Strings. */ public static class StringKeySerializer extends StdSerializer { public StringKeySerializer() { super(String.class, false); } @Override public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException { g.writeFieldName((String) value); } } /** * Specialized instance to use for Enum keys, as per [databind#1322] * * @since 2.8 */ public static class EnumKeySerializer extends StdSerializer { protected final EnumValues _values; protected EnumKeySerializer(Class enumType, EnumValues values) { super(enumType, false); _values = values; } public static EnumKeySerializer construct(Class enumType, EnumValues enumValues) { return new EnumKeySerializer(enumType, enumValues); } @Override public void serialize(Object value, JsonGenerator g, SerializerProvider serializers) throws IOException { if (serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) { g.writeFieldName(value.toString()); return; } Enum en = (Enum) value; if (serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX)) { g.writeFieldName(String.valueOf(en.ordinal())); return; } g.writeFieldName(_values.serializedValueFor(en)); } } } StdScalarSerializer.java000066400000000000000000000043321325620701100366120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; @SuppressWarnings("serial") public abstract class StdScalarSerializer extends StdSerializer { protected StdScalarSerializer(Class t) { super(t); } /** * Alternate constructor that is (alas!) needed to work * around kinks of generic type handling */ @SuppressWarnings("unchecked") protected StdScalarSerializer(Class t, boolean dummy) { super((Class) t); } /** * Default implementation will write type prefix, call regular serialization * method (since assumption is that value itself does not need JSON * Array or Object start/end markers), and then write type suffix. * This should work for most cases; some sub-classes may want to * change this behavior. */ @Override public void serializeWithType(T value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // NOTE: need not really be string; just indicates "scalar of some kind" WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.VALUE_STRING)); serialize(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { return createSchemaNode("string", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { // 13-Sep-2013, tatu: Let's assume it's usually a String, right? visitStringFormat(visitor, typeHint); } } StdSerializer.java000066400000000000000000000451211325620701100354650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; import java.util.Collection; import java.util.IdentityHashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.JsonParser.NumberType; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsonFormatVisitors.*; import com.fasterxml.jackson.databind.jsonschema.SchemaAware; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.PropertyFilter; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.Converter; /** * Base class used by all standard serializers, and can also * be used for custom serializers (in fact, this is the recommended * base class to use). * Provides convenience methods for implementing {@link SchemaAware} */ public abstract class StdSerializer extends JsonSerializer implements JsonFormatVisitable, SchemaAware, java.io.Serializable { private static final long serialVersionUID = 1L; /** * Key used for storing a lock object to prevent infinite recursion when * constructing converting serializers. * * @since 2.9 */ private final static Object KEY_CONTENT_CONVERTER_LOCK = new Object(); /** * Nominal type supported, usually declared type of * property for which serializer is used. */ protected final Class _handledType; /* /********************************************************** /* Life-cycle /********************************************************** */ protected StdSerializer(Class t) { _handledType = t; } @SuppressWarnings("unchecked") protected StdSerializer(JavaType type) { _handledType = (Class) type.getRawClass(); } /** * Alternate constructor that is (alas!) needed to work * around kinks of generic type handling */ @SuppressWarnings("unchecked") protected StdSerializer(Class t, boolean dummy) { _handledType = (Class) t; } /** * @since 2.6 */ @SuppressWarnings("unchecked") protected StdSerializer(StdSerializer src) { _handledType = (Class) src._handledType; } /* /********************************************************** /* Accessors /********************************************************** */ @Override public Class handledType() { return _handledType; } /* /********************************************************** /* Serialization /********************************************************** */ @Override public abstract void serialize(T value, JsonGenerator gen, SerializerProvider provider) throws IOException; /* /********************************************************** /* Type introspection API, partial/default implementation /********************************************************** */ /** * Default implementation specifies no format. This behavior is usually * overriden by custom serializers. */ @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitor.expectAnyFormat(typeHint); } /** * Default implementation simply claims type is "string"; usually * overriden by custom serializers. */ @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { return createSchemaNode("string"); } /** * Default implementation simply claims type is "string"; usually * overriden by custom serializers. */ @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint, boolean isOptional) throws JsonMappingException { ObjectNode schema = (ObjectNode) getSchema(provider, typeHint); if (!isOptional) { schema.put("required", !isOptional); } return schema; } /* /********************************************************** /* Helper methods for JSON Schema generation /********************************************************** */ protected ObjectNode createSchemaNode(String type) { ObjectNode schema = JsonNodeFactory.instance.objectNode(); schema.put("type", type); return schema; } protected ObjectNode createSchemaNode(String type, boolean isOptional) { ObjectNode schema = createSchemaNode(type); if (!isOptional) { schema.put("required", !isOptional); } return schema; } /** * Helper method that calls necessary visit method(s) to indicate that the * underlying JSON type is JSON String. * * @since 2.7 */ protected void visitStringFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { /*JsonStringFormatVisitor v2 =*/ visitor.expectStringFormat(typeHint); } /** * Helper method that calls necessary visit method(s) to indicate that the * underlying JSON type is JSON String, but that there is a more refined * logical type * * @since 2.7 */ protected void visitStringFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint, JsonValueFormat format) throws JsonMappingException { JsonStringFormatVisitor v2 = visitor.expectStringFormat(typeHint); if (v2 != null) { v2.format(format); } } /** * Helper method that calls necessary visit method(s) to indicate that the * underlying JSON type is JSON Integer number. * * @since 2.7 */ protected void visitIntFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint, NumberType numberType) throws JsonMappingException { JsonIntegerFormatVisitor v2 = visitor.expectIntegerFormat(typeHint); if (_neitherNull(v2, numberType)) { v2.numberType(numberType); } } /** * Helper method that calls necessary visit method(s) to indicate that the * underlying JSON type is JSON Integer number, but that there is also a further * format restriction involved. * * @since 2.7 */ protected void visitIntFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint, NumberType numberType, JsonValueFormat format) throws JsonMappingException { JsonIntegerFormatVisitor v2 = visitor.expectIntegerFormat(typeHint); if (v2 != null) { if (numberType != null) { v2.numberType(numberType); } if (format != null) { v2.format(format); } } } /** * Helper method that calls necessary visit method(s) to indicate that the * underlying JSON type is a floating-point JSON number. * * @since 2.7 */ protected void visitFloatFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint, NumberType numberType) throws JsonMappingException { JsonNumberFormatVisitor v2 = visitor.expectNumberFormat(typeHint); if (v2 != null) { v2.numberType(numberType); } } /** * @since 2.7 */ protected void visitArrayFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint, JsonSerializer itemSerializer, JavaType itemType) throws JsonMappingException { JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint); if (_neitherNull(v2, itemSerializer)) { v2.itemsFormat(itemSerializer, itemType); } } /** * @since 2.7 */ protected void visitArrayFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint, JsonFormatTypes itemType) throws JsonMappingException { JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint); if (v2 != null) { v2.itemsFormat(itemType); } } /* /********************************************************** /* Helper methods for exception handling /********************************************************** */ /** * Method that will modify caught exception (passed in as argument) * as necessary to include reference information, and to ensure it * is a subtype of {@link IOException}, or an unchecked exception. *

* Rules for wrapping and unwrapping are bit complicated; essentially: *

    *
  • Errors are to be passed as is (if uncovered via unwrapping) *
  • "Plain" IOExceptions (ones that are not of type * {@link JsonMappingException} are to be passed as is *
*/ public void wrapAndThrow(SerializerProvider provider, Throwable t, Object bean, String fieldName) throws IOException { /* 05-Mar-2009, tatu: But one nasty edge is when we get * StackOverflow: usually due to infinite loop. But that * usually gets hidden within an InvocationTargetException... */ while (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } // Errors and "plain" to be passed as is ClassUtil.throwIfError(t); // Ditto for IOExceptions... except for mapping exceptions! boolean wrap = (provider == null) || provider.isEnabled(SerializationFeature.WRAP_EXCEPTIONS); if (t instanceof IOException) { if (!wrap || !(t instanceof JsonMappingException)) { throw (IOException) t; } } else if (!wrap) { ClassUtil.throwIfRTE(t); } // Need to add reference information throw JsonMappingException.wrapWithPath(t, bean, fieldName); } public void wrapAndThrow(SerializerProvider provider, Throwable t, Object bean, int index) throws IOException { while (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } // Errors are to be passed as is ClassUtil.throwIfError(t); // Ditto for IOExceptions... except for mapping exceptions! boolean wrap = (provider == null) || provider.isEnabled(SerializationFeature.WRAP_EXCEPTIONS); if (t instanceof IOException) { if (!wrap || !(t instanceof JsonMappingException)) { throw (IOException) t; } } else if (!wrap) { ClassUtil.throwIfRTE(t); } // Need to add reference information throw JsonMappingException.wrapWithPath(t, bean, index); } /* /********************************************************** /* Helper methods, accessing annotation-based configuration /********************************************************** */ /** * Helper method that can be used to see if specified property has annotation * indicating that a converter is to be used for contained values (contents * of structured types; array/List/Map values) * * @param existingSerializer (optional) configured content * serializer if one already exists. * * @since 2.9 */ protected JsonSerializer findContextualConvertingSerializer(SerializerProvider provider, BeanProperty property, JsonSerializer existingSerializer) throws JsonMappingException { // 08-Dec-2016, tatu: to fix [databind#357], need to prevent recursive calls for // same property @SuppressWarnings("unchecked") Map conversions = (Map) provider.getAttribute(KEY_CONTENT_CONVERTER_LOCK); if (conversions != null) { Object lock = conversions.get(property); if (lock != null) { return existingSerializer; } } else { conversions = new IdentityHashMap<>(); provider.setAttribute(KEY_CONTENT_CONVERTER_LOCK, conversions); } conversions.put(property, Boolean.TRUE); try { JsonSerializer ser = findConvertingContentSerializer(provider, property, existingSerializer); if (ser != null) { return provider.handleSecondaryContextualization(ser, property); } } finally { conversions.remove(property); } return existingSerializer; } /** * @deprecated Since 2.9 use {link {@link #findContextualConvertingSerializer} instead */ @Deprecated protected JsonSerializer findConvertingContentSerializer(SerializerProvider provider, BeanProperty prop, JsonSerializer existingSerializer) throws JsonMappingException { final AnnotationIntrospector intr = provider.getAnnotationIntrospector(); if (_neitherNull(intr, prop)) { AnnotatedMember m = prop.getMember(); if (m != null) { Object convDef = intr.findSerializationContentConverter(m); if (convDef != null) { Converter conv = provider.converterInstance(prop.getMember(), convDef); JavaType delegateType = conv.getOutputType(provider.getTypeFactory()); // [databind#731]: Should skip if nominally java.lang.Object if ((existingSerializer == null) && !delegateType.isJavaLangObject()) { existingSerializer = provider.findValueSerializer(delegateType); } return new StdDelegatingSerializer(conv, delegateType, existingSerializer); } } } return existingSerializer; } /** * Helper method used to locate filter that is needed, based on filter id * this serializer was constructed with. * * @since 2.3 */ protected PropertyFilter findPropertyFilter(SerializerProvider provider, Object filterId, Object valueToFilter) throws JsonMappingException { FilterProvider filters = provider.getFilterProvider(); // Not ok to miss the provider, if a filter is declared to be needed. if (filters == null) { provider.reportBadDefinition(handledType(), "Cannot resolve PropertyFilter with id '"+filterId+"'; no FilterProvider configured"); } // But whether unknown ids are ok just depends on filter provider; if we get null that's fine return filters.findPropertyFilter(filterId, valueToFilter); } /** * Helper method that may be used to find if this deserializer has specific * {@link JsonFormat} settings, either via property, or through type-specific * defaulting. * * @param typeForDefaults Type (erased) used for finding default format settings, if any * * @since 2.7 */ protected JsonFormat.Value findFormatOverrides(SerializerProvider provider, BeanProperty prop, Class typeForDefaults) { if (prop != null) { return prop.findPropertyFormat(provider.getConfig(), typeForDefaults); } // even without property or AnnotationIntrospector, may have type-specific defaults return provider.getDefaultPropertyFormat(typeForDefaults); } /** * Convenience method that uses {@link #findFormatOverrides} to find possible * defaults and/of overrides, and then calls JsonFormat.Value.getFeature(...) * to find whether that feature has been specifically marked as enabled or disabled. * * @param typeForDefaults Type (erased) used for finding default format settings, if any * * @since 2.7 */ protected Boolean findFormatFeature(SerializerProvider provider, BeanProperty prop, Class typeForDefaults, JsonFormat.Feature feat) { JsonFormat.Value format = findFormatOverrides(provider, prop, typeForDefaults); if (format != null) { return format.getFeature(feat); } return null; } /** * @since 2.8 */ protected JsonInclude.Value findIncludeOverrides(SerializerProvider provider, BeanProperty prop, Class typeForDefaults) { if (prop != null) { return prop.findPropertyInclusion(provider.getConfig(), typeForDefaults); } // even without property or AnnotationIntrospector, may have type-specific defaults return provider.getDefaultPropertyInclusion(typeForDefaults); } /** * Convenience method for finding out possibly configured content value serializer. * * @since 2.7.4 */ protected JsonSerializer findAnnotatedContentSerializer(SerializerProvider serializers, BeanProperty property) throws JsonMappingException { if (property != null) { // First: if we have a property, may have property-annotation overrides AnnotatedMember m = property.getMember(); final AnnotationIntrospector intr = serializers.getAnnotationIntrospector(); if (m != null) { Object serDef = intr.findContentSerializer(m); if (serDef != null) { return serializers.serializerInstance(m, serDef); } } } return null; } /* /********************************************************** /* Helper methods, other /********************************************************** */ /** * Method that can be called to determine if given serializer is the default * serializer Jackson uses; as opposed to a custom serializer installed by * a module or calling application. Determination is done using * {@link JacksonStdImpl} annotation on serializer class. */ protected boolean isDefaultSerializer(JsonSerializer serializer) { return ClassUtil.isJacksonStdImpl(serializer); } /** * @since 2.9 */ protected final static boolean _neitherNull(Object a, Object b) { return (a != null) && (b != null); } /** * @since 2.9 */ protected final static boolean _nonEmpty(Collection c) { return (c != null) && !c.isEmpty(); } } StringSerializer.java000066400000000000000000000041221325620701100361750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * This is the special serializer for regular {@link java.lang.String}s. *

* Since this is one of "native" types, no type information is ever * included on serialization (unlike for most scalar types as of 1.5) */ @JacksonStdImpl public final class StringSerializer // NOTE: generic parameter changed from String to Object in 2.6, to avoid // use of bridge methods // In 2.9, removed use of intermediate type `NonTypedScalarSerializerBase` extends StdScalarSerializer { private static final long serialVersionUID = 1L; public StringSerializer() { super(String.class, false); } @Override public boolean isEmpty(SerializerProvider prov, Object value) { String str = (String) value; return str.length() == 0; } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeString((String) value); } @Override public final void serializeWithType(Object value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // no type info, just regular serialization gen.writeString((String) value); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { return createSchemaNode("string", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitStringFormat(visitor, typeHint); } } TimeZoneSerializer.java000066400000000000000000000021321325620701100364600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.util.TimeZone; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; @SuppressWarnings("serial") public class TimeZoneSerializer extends StdScalarSerializer { public TimeZoneSerializer() { super(TimeZone.class); } @Override public void serialize(TimeZone value, JsonGenerator g, SerializerProvider provider) throws IOException { g.writeString(value.getID()); } @Override public void serializeWithType(TimeZone value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // Better ensure we don't use specific sub-classes: WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, TimeZone.class, JsonToken.VALUE_STRING)); serialize(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } } ToStringSerializer.java000066400000000000000000000063051325620701100365050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * Simple general purpose serializer, useful for any * type for which {@link Object#toString} returns the desired JSON * value. */ @JacksonStdImpl @SuppressWarnings("serial") public class ToStringSerializer extends StdSerializer { /** * Singleton instance to use. */ public final static ToStringSerializer instance = new ToStringSerializer(); /** *

* Note: usually you should NOT create new instances, but instead use * {@link #instance} which is stateless and fully thread-safe. However, * there are cases where constructor is needed; for example, * when using explicit serializer annotations like * {@link com.fasterxml.jackson.databind.annotation.JsonSerialize#using}. */ public ToStringSerializer() { super(Object.class); } /** * Sometimes it may actually make sense to retain actual handled type, so... * * @since 2.5 */ public ToStringSerializer(Class handledType) { super(handledType, false); } @Override public boolean isEmpty(SerializerProvider prov, Object value) { return value.toString().isEmpty(); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeString(value.toString()); } /* 01-Mar-2011, tatu: We were serializing as "raw" String; but generally that * is not what we want, since lack of type information would imply real * String type. */ /** * Default implementation will write type prefix, call regular serialization * method (since assumption is that value itself does not need JSON * Array or Object start/end markers), and then write type suffix. * This should work for most cases; some sub-classes may want to * change this behavior. */ @Override public void serializeWithType(Object value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.VALUE_STRING)); serialize(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { return createSchemaNode("string", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { visitStringFormat(visitor, typeHint); } } TokenBufferSerializer.java000066400000000000000000000060011325620701100371370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * We also want to directly support serialization of {@link TokenBuffer}; * and since it is part of core package, it cannot implement * {@link com.fasterxml.jackson.databind.JsonSerializable} * (which is only included in the mapper package) */ @JacksonStdImpl @SuppressWarnings("serial") public class TokenBufferSerializer extends StdSerializer { public TokenBufferSerializer() { super(TokenBuffer.class); } @Override public void serialize(TokenBuffer value, JsonGenerator jgen, SerializerProvider provider) throws IOException { value.serialize(jgen); } /** * Implementing typed output for contents of a TokenBuffer is very tricky, * since we do not know for sure what its contents might look like (or, rather, * we do know when serializing, but not necessarily when deserializing!) * One possibility would be to check the current token, and use that to * determine if we would output JSON Array, Object or scalar value. *

* Note that we just claim it is scalar; this should work ok and is simpler * than doing introspection on both serialization and deserialization. */ @Override public final void serializeWithType(TokenBuffer value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // 28-Jun-2017, tatu: As per javadoc, not sure what to report as likely shape. Could // even look into first actual token inside... but, for now let's keep it simple WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, typeSer.typeId(value, JsonToken.VALUE_EMBEDDED_OBJECT)); serialize(value, g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) { // Not 100% sure what we should say here: type is basically not known. // This seems like closest approximation return createSchemaNode("any", true); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { // Not 100% sure what we should say here: type is basically not known. // This seems like closest approximation visitor.expectAnyFormat(typeHint); } } UUIDSerializer.java000066400000000000000000000071041325620701100355000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/ser/stdpackage com.fasterxml.jackson.databind.ser.std; import java.io.IOException; import java.util.UUID; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Specialized {@link JsonSerializer} to output {@link java.util.UUID}s. * Beyond optimized access and writing of textual representation (which * is the default handling in most cases), it will alternatively * allow serialization using raw binary output (as 16-byte block) * if underlying data format has efficient means to access that. */ @SuppressWarnings("serial") public class UUIDSerializer extends StdScalarSerializer { final static char[] HEX_CHARS = "0123456789abcdef".toCharArray(); public UUIDSerializer() { super(UUID.class); } @Override public boolean isEmpty(SerializerProvider prov, UUID value) { // Null UUID is empty, so... if (value.getLeastSignificantBits() == 0L && value.getMostSignificantBits() == 0L) { return true; } return false; } @Override public void serialize(UUID value, JsonGenerator gen, SerializerProvider provider) throws IOException { // First: perhaps we could serialize it as raw binary data? if (gen.canWriteBinaryNatively()) { /* 07-Dec-2013, tatu: One nasty case; that of TokenBuffer. While it can * technically retain binary data, we do not want to do use binary * with it, as that results in UUIDs getting converted to Base64 for * most conversions. */ if (!(gen instanceof TokenBuffer)) { gen.writeBinary(_asBytes(value)); return; } } // UUID.toString() works ok functionally, but we can make it go much faster // (by 4x with micro-benchmark) final char[] ch = new char[36]; final long msb = value.getMostSignificantBits(); _appendInt((int) (msb >> 32), ch, 0); ch[8] = '-'; int i = (int) msb; _appendShort(i >>> 16, ch, 9); ch[13] = '-'; _appendShort(i, ch, 14); ch[18] = '-'; final long lsb = value.getLeastSignificantBits(); _appendShort((int) (lsb >>> 48), ch, 19); ch[23] = '-'; _appendShort((int) (lsb >>> 32), ch, 24); _appendInt((int) lsb, ch, 28); gen.writeString(ch, 0, 36); } private static void _appendInt(int bits, char[] ch, int offset) { _appendShort(bits >> 16, ch, offset); _appendShort(bits, ch, offset+4); } private static void _appendShort(int bits, char[] ch, int offset) { ch[offset] = HEX_CHARS[(bits >> 12) & 0xF]; ch[++offset] = HEX_CHARS[(bits >> 8) & 0xF]; ch[++offset] = HEX_CHARS[(bits >> 4) & 0xF]; ch[++offset] = HEX_CHARS[bits & 0xF]; } private final static byte[] _asBytes(UUID uuid) { byte[] buffer = new byte[16]; long hi = uuid.getMostSignificantBits(); long lo = uuid.getLeastSignificantBits(); _appendInt((int) (hi >> 32), buffer, 0); _appendInt((int) hi, buffer, 4); _appendInt((int) (lo >> 32), buffer, 8); _appendInt((int) lo, buffer, 12); return buffer; } private final static void _appendInt(int value, byte[] buffer, int offset) { buffer[offset] = (byte) (value >> 24); buffer[++offset] = (byte) (value >> 16); buffer[++offset] = (byte) (value >> 8); buffer[++offset] = (byte) value; } } jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/type/000077500000000000000000000000001325620701100315105ustar00rootroot00000000000000ArrayType.java000066400000000000000000000152021325620701100342140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.lang.reflect.Array; import com.fasterxml.jackson.databind.JavaType; /** * Array types represent Java arrays, both primitive and object valued. * Further, Object-valued arrays can have element type of any other * legal {@link JavaType}. */ public final class ArrayType extends TypeBase { private static final long serialVersionUID = 1L; /** * Type of elements in the array. */ protected final JavaType _componentType; /** * We will also keep track of shareable instance of empty array, * since it usually needs to be constructed any way; and because * it is essentially immutable and thus can be shared. */ protected final Object _emptyArray; protected ArrayType(JavaType componentType, TypeBindings bindings, Object emptyInstance, Object valueHandler, Object typeHandler, boolean asStatic) { // No super-class, interfaces, for now super(emptyInstance.getClass(), bindings, null, null, componentType.hashCode(), valueHandler, typeHandler, asStatic); _componentType = componentType; _emptyArray = emptyInstance; } public static ArrayType construct(JavaType componentType, TypeBindings bindings) { return construct(componentType, bindings, null, null); } public static ArrayType construct(JavaType componentType, TypeBindings bindings, Object valueHandler, Object typeHandler) { // Figuring out raw class for generic array is actually bit tricky... Object emptyInstance = Array.newInstance(componentType.getRawClass(), 0); return new ArrayType(componentType, bindings, emptyInstance, valueHandler, typeHandler, false); } @Override public JavaType withContentType(JavaType contentType) { Object emptyInstance = Array.newInstance(contentType.getRawClass(), 0); return new ArrayType(contentType, _bindings, emptyInstance, _valueHandler, _typeHandler, _asStatic); } @Override public ArrayType withTypeHandler(Object h) { if (h == _typeHandler) { return this; } return new ArrayType(_componentType, _bindings, _emptyArray, _valueHandler, h, _asStatic); } @Override public ArrayType withContentTypeHandler(Object h) { if (h == _componentType.getTypeHandler()) { return this; } return new ArrayType(_componentType.withTypeHandler(h), _bindings, _emptyArray, _valueHandler, _typeHandler, _asStatic); } @Override public ArrayType withValueHandler(Object h) { if (h == _valueHandler) { return this; } return new ArrayType(_componentType, _bindings, _emptyArray, h, _typeHandler,_asStatic); } @Override public ArrayType withContentValueHandler(Object h) { if (h == _componentType.getValueHandler()) { return this; } return new ArrayType(_componentType.withValueHandler(h), _bindings, _emptyArray, _valueHandler, _typeHandler, _asStatic); } @Override public ArrayType withStaticTyping() { if (_asStatic) { return this; } return new ArrayType(_componentType.withStaticTyping(), _bindings, _emptyArray, _valueHandler, _typeHandler, true); } /* /********************************************************** /* Methods for narrowing conversions /********************************************************** */ /** * Handling of narrowing conversions for arrays is trickier: for now, * it is not even allowed. */ @Override @Deprecated // since 2.7 protected JavaType _narrow(Class subclass) { return _reportUnsupported(); } // Should not be called, as array types in Java are not extensible; but // let's not freak out even if it is called? @Override public JavaType refine(Class contentClass, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { return null; } private JavaType _reportUnsupported() { throw new UnsupportedOperationException("Cannot narrow or widen array types"); } /* /********************************************************** /* Overridden methods /********************************************************** */ @Override public boolean isArrayType() { return true; } /** * For some odd reason, modifiers for array classes would * claim they are abstract types. Not so, at least for our * purposes. */ @Override public boolean isAbstract() { return false; } /** * For some odd reason, modifiers for array classes would * claim they are abstract types. Not so, at least for our * purposes. */ @Override public boolean isConcrete() { return true; } @Override public boolean hasGenericTypes() { // arrays are not parameterized, but element type may be: return _componentType.hasGenericTypes(); } /* /********************************************************** /* Public API /********************************************************** */ @Override public boolean isContainerType() { return true; } @Override public JavaType getContentType() { return _componentType; } @Override public Object getContentValueHandler() { return _componentType.getValueHandler(); } @Override public Object getContentTypeHandler() { return _componentType.getTypeHandler(); } @Override public boolean hasHandlers() { return super.hasHandlers() || _componentType.hasHandlers(); } @Override public StringBuilder getGenericSignature(StringBuilder sb) { sb.append('['); return _componentType.getGenericSignature(sb); } @Override public StringBuilder getErasedSignature(StringBuilder sb) { sb.append('['); return _componentType.getErasedSignature(sb); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return "[array type, component type: "+_componentType+"]"; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; ArrayType other = (ArrayType) o; return _componentType.equals(other._componentType); } } ClassKey.java000066400000000000000000000053131325620701100340140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; /** * Key class, used as an efficient and accurate key * for locating per-class values, such as * {@link com.fasterxml.jackson.databind.JsonSerializer}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 implements Comparable, java.io.Serializable // since 2.1 { private static final long serialVersionUID = 1L; private String _className; private Class _class; /** * Let's cache hash code straight away, since we are * almost certain to need it. */ private int _hashCode; public ClassKey() { _class = null; _className = null; _hashCode = 0; } public ClassKey(Class clz) { _class = clz; _className = clz.getName(); _hashCode = _className.hashCode(); } public void reset(Class clz) { _class = clz; _className = clz.getName(); _hashCode = _className.hashCode(); } /* /********************************************************** /* Comparable /********************************************************** */ @Override public int compareTo(ClassKey other) { // Just need to sort by name, ok to collide (unless used in TreeMap/Set!) return _className.compareTo(other._className); } /* /********************************************************** /* 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._className.equals(_className)) && (other._class.getClassLoader() == _class.getClassLoader()); */ return other._class == _class; } @Override public int hashCode() { return _hashCode; } @Override public String toString() { return _className; } } ClassStack.java000066400000000000000000000044441325620701100343350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.ArrayList; import com.fasterxml.jackson.databind.JavaType; /** * Simple helper class used to keep track of 'call stack' for classes being referenced * (as well as unbound variables) * * @since 2.7 */ public final class ClassStack { protected final ClassStack _parent; protected final Class _current; private ArrayList _selfRefs; public ClassStack(Class rootType) { this(null, rootType); } private ClassStack(ClassStack parent, Class curr) { _parent = parent; _current = curr; } /** * @return New stack frame, if addition is ok; null if not */ public ClassStack child(Class cls) { return new ClassStack(this, cls); } /** * Method called to indicate that there is a self-reference from * deeper down in stack pointing into type this stack frame represents. */ public void addSelfReference(ResolvedRecursiveType ref) { if (_selfRefs == null) { _selfRefs = new ArrayList(); } _selfRefs.add(ref); } /** * Method called when type that this stack frame represents is * fully resolved, allowing self-references to be completed * (if there are any) */ public void resolveSelfReferences(JavaType resolved) { if (_selfRefs != null) { for (ResolvedRecursiveType ref : _selfRefs) { ref.setReference(resolved); } } } public ClassStack find(Class cls) { if (_current == cls) return this; for (ClassStack curr = _parent; curr != null; curr = curr._parent) { if (curr._current == cls) { return curr; } } return null; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[ClassStack (self-refs: ") .append((_selfRefs == null) ? "0" : String.valueOf(_selfRefs.size())) .append(')') ; for (ClassStack curr = this; curr != null; curr = curr._parent) { sb.append(' ').append(curr._current.getName()); } sb.append(']'); return sb.toString(); } } CollectionLikeType.java000066400000000000000000000205301325620701100360360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.lang.reflect.TypeVariable; import java.util.Collection; import com.fasterxml.jackson.databind.JavaType; /** * Type that represents things that act similar to {@link java.util.Collection}; * but may or may not be instances of that interface. * This specifically allows framework to check for configuration and annotation * settings used for Map types, and pass these to custom handlers that may be more * familiar with actual type. */ public class CollectionLikeType extends TypeBase { private static final long serialVersionUID = 1L; /** * Type of elements in collection */ protected final JavaType _elementType; /* /********************************************************** /* Life-cycle /********************************************************** */ protected CollectionLikeType(Class collT, TypeBindings bindings, JavaType superClass, JavaType[] superInts, JavaType elemT, Object valueHandler, Object typeHandler, boolean asStatic) { super(collT, bindings, superClass, superInts, elemT.hashCode(), valueHandler, typeHandler, asStatic); _elementType = elemT; } /** * @since 2.7 */ protected CollectionLikeType(TypeBase base, JavaType elemT) { super(base); _elementType = elemT; } /** * @since 2.7 */ public static CollectionLikeType construct(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInts, JavaType elemT) { return new CollectionLikeType(rawType, bindings, superClass, superInts, elemT, null, null, false); } /** * @deprecated Since 2.7, use {@link #upgradeFrom} for constructing instances, given * pre-resolved {@link SimpleType}. */ @Deprecated // since 2.7 public static CollectionLikeType construct(Class rawType, JavaType elemT) { // First: may need to fabricate TypeBindings (needed for refining into // concrete collection types, as per [databind#1102]) TypeVariable[] vars = rawType.getTypeParameters(); TypeBindings bindings; if ((vars == null) || (vars.length != 1)) { bindings = TypeBindings.emptyBindings(); } else { bindings = TypeBindings.create(rawType, elemT); } return new CollectionLikeType(rawType, bindings, _bogusSuperClass(rawType), null, elemT, null, null, false); } /** * Factory method that can be used to "upgrade" a basic type into collection-like * one; usually done via {@link TypeModifier} * * @since 2.7 */ public static CollectionLikeType upgradeFrom(JavaType baseType, JavaType elementType) { // 19-Oct-2015, tatu: Not sure if and how other types could be used as base; // will cross that bridge if and when need be if (baseType instanceof TypeBase) { return new CollectionLikeType((TypeBase) baseType, elementType); } throw new IllegalArgumentException("Cannot upgrade from an instance of "+baseType.getClass()); } @Override @Deprecated // since 2.7 protected JavaType _narrow(Class subclass) { return new CollectionLikeType(subclass, _bindings, _superClass, _superInterfaces, _elementType, _valueHandler, _typeHandler, _asStatic); } @Override public JavaType withContentType(JavaType contentType) { if (_elementType == contentType) { return this; } return new CollectionLikeType(_class, _bindings, _superClass, _superInterfaces, contentType, _valueHandler, _typeHandler, _asStatic); } @Override public CollectionLikeType withTypeHandler(Object h) { return new CollectionLikeType(_class, _bindings, _superClass, _superInterfaces, _elementType, _valueHandler, h, _asStatic); } @Override public CollectionLikeType withContentTypeHandler(Object h) { return new CollectionLikeType(_class, _bindings, _superClass, _superInterfaces, _elementType.withTypeHandler(h), _valueHandler, _typeHandler, _asStatic); } @Override public CollectionLikeType withValueHandler(Object h) { return new CollectionLikeType(_class, _bindings, _superClass, _superInterfaces, _elementType, h, _typeHandler, _asStatic); } @Override public CollectionLikeType withContentValueHandler(Object h) { return new CollectionLikeType(_class, _bindings, _superClass, _superInterfaces, _elementType.withValueHandler(h), _valueHandler, _typeHandler, _asStatic); } @Override public JavaType withHandlersFrom(JavaType src) { JavaType type = super.withHandlersFrom(src); JavaType srcCt = src.getContentType(); if (srcCt != null) { JavaType ct = _elementType.withHandlersFrom(srcCt); if (ct != _elementType) { type = type.withContentType(ct); } } return type; } @Override public CollectionLikeType withStaticTyping() { if (_asStatic) { return this; } return new CollectionLikeType(_class, _bindings, _superClass, _superInterfaces, _elementType.withStaticTyping(), _valueHandler, _typeHandler, true); } @Override public JavaType refine(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { return new CollectionLikeType(rawType, bindings, superClass, superInterfaces, _elementType, _valueHandler, _typeHandler, _asStatic); } /* /********************************************************** /* Public API /********************************************************** */ @Override public boolean isContainerType() { return true; } @Override public boolean isCollectionLikeType() { return true; } @Override public JavaType getContentType() { return _elementType; } @Override public Object getContentValueHandler() { return _elementType.getValueHandler(); } @Override public Object getContentTypeHandler() { return _elementType.getTypeHandler(); } @Override public boolean hasHandlers() { return super.hasHandlers() || _elementType.hasHandlers(); } @Override public StringBuilder getErasedSignature(StringBuilder sb) { return _classSignature(_class, sb, true); } @Override public StringBuilder getGenericSignature(StringBuilder sb) { _classSignature(_class, sb, false); sb.append('<'); _elementType.getGenericSignature(sb); sb.append(">;"); return sb; } @Override protected String buildCanonicalName() { StringBuilder sb = new StringBuilder(); sb.append(_class.getName()); if (_elementType != null) { sb.append('<'); sb.append(_elementType.toCanonical()); sb.append('>'); } return sb.toString(); } /* /********************************************************** /* Extended API /********************************************************** */ /** * Method that can be used for checking whether this type is a * "real" Collection type; meaning whether it represents a parameterized * subtype of {@link java.util.Collection} or just something that acts * like one. */ public boolean isTrueCollectionType() { return Collection.class.isAssignableFrom(_class); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; CollectionLikeType other = (CollectionLikeType) o; return (_class == other._class) && _elementType.equals(other._elementType); } @Override public String toString() { return "[collection-like type; class "+_class.getName()+", contains "+_elementType+"]"; } } CollectionType.java000066400000000000000000000107241325620701100352350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.lang.reflect.TypeVariable; import com.fasterxml.jackson.databind.JavaType; /** * Type that represents Java Collection types (Lists, Sets). */ public final class CollectionType extends CollectionLikeType { private static final long serialVersionUID = 1L; /* /********************************************************** /* Life-cycle /********************************************************** */ private CollectionType(Class collT, TypeBindings bindings, JavaType superClass, JavaType[] superInts, JavaType elemT, Object valueHandler, Object typeHandler, boolean asStatic) { super(collT, bindings, superClass, superInts, elemT, valueHandler, typeHandler, asStatic); } /** * @since 2.7 */ protected CollectionType(TypeBase base, JavaType elemT) { super(base, elemT); } /** * @since 2.7 */ public static CollectionType construct(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInts, JavaType elemT) { return new CollectionType(rawType, bindings, superClass, superInts, elemT, null, null, false); } /** * @deprecated Since 2.7, remove from 2.9 */ @Deprecated // since 2.7 public static CollectionType construct(Class rawType, JavaType elemT) { // First: may need to fabricate TypeBindings (needed for refining into // concrete collection types, as per [databind#1102]) TypeVariable[] vars = rawType.getTypeParameters(); TypeBindings bindings; if ((vars == null) || (vars.length != 1)) { bindings = TypeBindings.emptyBindings(); } else { bindings = TypeBindings.create(rawType, elemT); } return new CollectionType(rawType, bindings, // !!! TODO: Wrong, does have supertypes, but: _bogusSuperClass(rawType), null, elemT, null, null, false); } @Deprecated // since 2.7 @Override protected JavaType _narrow(Class subclass) { return new CollectionType(subclass, _bindings, _superClass, _superInterfaces, _elementType, null, null, _asStatic); } @Override public JavaType withContentType(JavaType contentType) { if (_elementType == contentType) { return this; } return new CollectionType(_class, _bindings, _superClass, _superInterfaces, contentType, _valueHandler, _typeHandler, _asStatic); } @Override public CollectionType withTypeHandler(Object h) { return new CollectionType(_class, _bindings, _superClass, _superInterfaces, _elementType, _valueHandler, h, _asStatic); } @Override public CollectionType withContentTypeHandler(Object h) { return new CollectionType(_class, _bindings, _superClass, _superInterfaces, _elementType.withTypeHandler(h), _valueHandler, _typeHandler, _asStatic); } @Override public CollectionType withValueHandler(Object h) { return new CollectionType(_class, _bindings, _superClass, _superInterfaces, _elementType, h, _typeHandler, _asStatic); } @Override public CollectionType withContentValueHandler(Object h) { return new CollectionType(_class, _bindings, _superClass, _superInterfaces, _elementType.withValueHandler(h), _valueHandler, _typeHandler, _asStatic); } @Override public CollectionType withStaticTyping() { if (_asStatic) { return this; } return new CollectionType(_class, _bindings, _superClass, _superInterfaces, _elementType.withStaticTyping(), _valueHandler, _typeHandler, true); } @Override public JavaType refine(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { return new CollectionType(rawType, bindings, superClass, superInterfaces, _elementType, _valueHandler, _typeHandler, _asStatic); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return "[collection type; class "+_class.getName()+", contains "+_elementType+"]"; } } MapLikeType.java000066400000000000000000000233011325620701100344570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.lang.reflect.TypeVariable; import java.util.*; import com.fasterxml.jackson.databind.JavaType; /** * Type that represents Map-like types; things that consist of key/value pairs * but that do not necessarily implement {@link java.util.Map}, but that do not * have enough introspection functionality to allow for some level of generic * handling. This specifically allows framework to check for configuration and * annotation settings used for Map types, and pass these to custom handlers * that may be more familiar with actual type. */ public class MapLikeType extends TypeBase { private static final long serialVersionUID = 1L; /** * Type of keys of Map. */ protected final JavaType _keyType; /** * Type of values of Map. */ protected final JavaType _valueType; /* /********************************************************** * Life-cycle /********************************************************** */ protected MapLikeType(Class mapType, TypeBindings bindings, JavaType superClass, JavaType[] superInts, JavaType keyT, JavaType valueT, Object valueHandler, Object typeHandler, boolean asStatic) { super(mapType, bindings, superClass, superInts, keyT.hashCode() ^ valueT.hashCode(), valueHandler, typeHandler, asStatic); _keyType = keyT; _valueType = valueT; } /** * @since 2.7 */ protected MapLikeType(TypeBase base, JavaType keyT, JavaType valueT) { super(base); _keyType = keyT; _valueType = valueT; } /** * Factory method that can be used to "upgrade" a basic type into * collection-like one; usually done via {@link TypeModifier} * * @since 2.7 */ public static MapLikeType upgradeFrom(JavaType baseType, JavaType keyT, JavaType valueT) { // 19-Oct-2015, tatu: Not sure if and how other types could be used as // base; // will cross that bridge if and when need be if (baseType instanceof TypeBase) { return new MapLikeType((TypeBase) baseType, keyT, valueT); } throw new IllegalArgumentException( "Cannot upgrade from an instance of " + baseType.getClass()); } @Deprecated // since 2.7; remove from 2.8 public static MapLikeType construct(Class rawType, JavaType keyT, JavaType valueT) { // First: may need to fabricate TypeBindings (needed for refining into // concrete collection types, as per [databind#1102]) TypeVariable[] vars = rawType.getTypeParameters(); TypeBindings bindings; if ((vars == null) || (vars.length != 2)) { bindings = TypeBindings.emptyBindings(); } else { bindings = TypeBindings.create(rawType, keyT, valueT); } return new MapLikeType(rawType, bindings, _bogusSuperClass(rawType), null, keyT, valueT, null, null, false); } @Deprecated // since 2.7 @Override protected JavaType _narrow(Class subclass) { return new MapLikeType(subclass, _bindings, _superClass, _superInterfaces, _keyType, _valueType, _valueHandler, _typeHandler, _asStatic); } /** * @since 2.7 */ public MapLikeType withKeyType(JavaType keyType) { if (keyType == _keyType) { return this; } return new MapLikeType(_class, _bindings, _superClass, _superInterfaces, keyType, _valueType, _valueHandler, _typeHandler, _asStatic); } @Override public JavaType withContentType(JavaType contentType) { if (_valueType == contentType) { return this; } return new MapLikeType(_class, _bindings, _superClass, _superInterfaces, _keyType, contentType, _valueHandler, _typeHandler, _asStatic); } @Override public MapLikeType withTypeHandler(Object h) { return new MapLikeType(_class, _bindings, _superClass, _superInterfaces, _keyType, _valueType, _valueHandler, h, _asStatic); } @Override public MapLikeType withContentTypeHandler(Object h) { return new MapLikeType(_class, _bindings, _superClass, _superInterfaces, _keyType, _valueType.withTypeHandler(h), _valueHandler, _typeHandler, _asStatic); } @Override public MapLikeType withValueHandler(Object h) { return new MapLikeType(_class, _bindings, _superClass, _superInterfaces, _keyType, _valueType, h, _typeHandler, _asStatic); } @Override public MapLikeType withContentValueHandler(Object h) { return new MapLikeType(_class, _bindings, _superClass, _superInterfaces, _keyType, _valueType.withValueHandler(h), _valueHandler, _typeHandler, _asStatic); } @Override public JavaType withHandlersFrom(JavaType src) { JavaType type = super.withHandlersFrom(src); JavaType srcKeyType = src.getKeyType(); // "withKeyType()" not part of JavaType, hence must verify: if (type instanceof MapLikeType) { if (srcKeyType != null) { JavaType ct = _keyType.withHandlersFrom(srcKeyType); if (ct != _keyType) { type = ((MapLikeType) type).withKeyType(ct); } } } JavaType srcCt = src.getContentType(); if (srcCt != null) { JavaType ct = _valueType.withHandlersFrom(srcCt); if (ct != _valueType) { type = type.withContentType(ct); } } return type; } @Override public MapLikeType withStaticTyping() { if (_asStatic) { return this; } return new MapLikeType(_class, _bindings, _superClass, _superInterfaces, _keyType, _valueType.withStaticTyping(), _valueHandler, _typeHandler, true); } @Override public JavaType refine(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { return new MapLikeType(rawType, bindings, superClass, superInterfaces, _keyType, _valueType, _valueHandler, _typeHandler, _asStatic); } @Override protected String buildCanonicalName() { StringBuilder sb = new StringBuilder(); sb.append(_class.getName()); if (_keyType != null) { sb.append('<'); sb.append(_keyType.toCanonical()); sb.append(','); sb.append(_valueType.toCanonical()); sb.append('>'); } return sb.toString(); } /* /********************************************************** /* Public API /********************************************************** */ @Override public boolean isContainerType() { return true; } @Override public boolean isMapLikeType() { return true; } @Override public JavaType getKeyType() { return _keyType; } @Override public JavaType getContentType() { return _valueType; } @Override public Object getContentValueHandler() { return _valueType.getValueHandler(); } @Override public Object getContentTypeHandler() { return _valueType.getTypeHandler(); } @Override public boolean hasHandlers() { return super.hasHandlers() || _valueType.hasHandlers() || _keyType.hasHandlers(); } @Override public StringBuilder getErasedSignature(StringBuilder sb) { return _classSignature(_class, sb, true); } @Override public StringBuilder getGenericSignature(StringBuilder sb) { _classSignature(_class, sb, false); sb.append('<'); _keyType.getGenericSignature(sb); _valueType.getGenericSignature(sb); sb.append(">;"); return sb; } /* /********************************************************** /* Extended API /********************************************************** */ public MapLikeType withKeyTypeHandler(Object h) { return new MapLikeType(_class, _bindings, _superClass, _superInterfaces, _keyType.withTypeHandler(h), _valueType, _valueHandler, _typeHandler, _asStatic); } public MapLikeType withKeyValueHandler(Object h) { return new MapLikeType(_class, _bindings, _superClass, _superInterfaces, _keyType.withValueHandler(h), _valueType, _valueHandler, _typeHandler, _asStatic); } /** * Method that can be used for checking whether this type is a "real" * Collection type; meaning whether it represents a parameterized subtype of * {@link java.util.Collection} or just something that acts like one. */ public boolean isTrueMapType() { return Map.class.isAssignableFrom(_class); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return String.format("[map-like type; class %s, %s -> %s]", _class.getName(), _keyType, _valueType); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; MapLikeType other = (MapLikeType) o; return (_class == other._class) && _keyType.equals(other._keyType) && _valueType.equals(other._valueType); } } MapType.java000066400000000000000000000126421325620701100336600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.lang.reflect.TypeVariable; import com.fasterxml.jackson.databind.JavaType; /** * Type that represents "true" Java Map types. */ public final class MapType extends MapLikeType { private static final long serialVersionUID = 1L; /* /********************************************************** /* Life-cycle /********************************************************** */ private MapType(Class mapType, TypeBindings bindings, JavaType superClass, JavaType[] superInts, JavaType keyT, JavaType valueT, Object valueHandler, Object typeHandler, boolean asStatic) { super(mapType, bindings, superClass, superInts, keyT, valueT, valueHandler, typeHandler, asStatic); } /** * @since 2.7 */ protected MapType(TypeBase base, JavaType keyT, JavaType valueT) { super(base, keyT, valueT); } /** * @since 2.7 */ public static MapType construct(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInts, JavaType keyT, JavaType valueT) { return new MapType(rawType, bindings, superClass, superInts, keyT, valueT, null, null, false); } @Deprecated // since 2.7 public static MapType construct(Class rawType, JavaType keyT, JavaType valueT) { // First: may need to fabricate TypeBindings (needed for refining into // concrete collection types, as per [databind#1102]) TypeVariable[] vars = rawType.getTypeParameters(); TypeBindings bindings; if ((vars == null) || (vars.length != 2)) { bindings = TypeBindings.emptyBindings(); } else { bindings = TypeBindings.create(rawType, keyT, valueT); } // !!! TODO: Wrong, does have supertypes return new MapType(rawType, bindings, _bogusSuperClass(rawType), null, keyT, valueT, null, null, false); } @Deprecated // since 2.7 @Override protected JavaType _narrow(Class subclass) { return new MapType(subclass, _bindings, _superClass, _superInterfaces, _keyType, _valueType, _valueHandler, _typeHandler, _asStatic); } @Override public MapType withTypeHandler(Object h) { return new MapType(_class, _bindings, _superClass, _superInterfaces, _keyType, _valueType, _valueHandler, h, _asStatic); } @Override public MapType withContentTypeHandler(Object h) { return new MapType(_class, _bindings, _superClass, _superInterfaces, _keyType, _valueType.withTypeHandler(h), _valueHandler, _typeHandler, _asStatic); } @Override public MapType withValueHandler(Object h) { return new MapType(_class, _bindings, _superClass, _superInterfaces, _keyType, _valueType, h, _typeHandler, _asStatic); } @Override public MapType withContentValueHandler(Object h) { return new MapType(_class, _bindings, _superClass, _superInterfaces, _keyType, _valueType.withValueHandler(h), _valueHandler, _typeHandler, _asStatic); } @Override public MapType withStaticTyping() { if (_asStatic) { return this; } return new MapType(_class, _bindings, _superClass, _superInterfaces, _keyType.withStaticTyping(), _valueType.withStaticTyping(), _valueHandler, _typeHandler, true); } @Override public JavaType withContentType(JavaType contentType) { if (_valueType == contentType) { return this; } return new MapType(_class, _bindings, _superClass, _superInterfaces, _keyType, contentType, _valueHandler, _typeHandler, _asStatic); } @Override public MapType withKeyType(JavaType keyType) { if (keyType == _keyType) { return this; } return new MapType(_class, _bindings, _superClass, _superInterfaces, keyType, _valueType, _valueHandler, _typeHandler, _asStatic); } @Override public JavaType refine(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { return new MapType(rawType, bindings, superClass, superInterfaces, _keyType, _valueType, _valueHandler, _typeHandler, _asStatic); } /* /********************************************************** /* Extended API /********************************************************** */ @Override public MapType withKeyTypeHandler(Object h) { return new MapType(_class, _bindings, _superClass, _superInterfaces, _keyType.withTypeHandler(h), _valueType, _valueHandler, _typeHandler, _asStatic); } @Override public MapType withKeyValueHandler(Object h) { return new MapType(_class, _bindings, _superClass, _superInterfaces, _keyType.withValueHandler(h), _valueType, _valueHandler, _typeHandler, _asStatic); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return "[map type; class "+_class.getName()+", "+_keyType+" -> "+_valueType+"]"; } } PlaceholderForType.java000066400000000000000000000052501325620701100360310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import com.fasterxml.jackson.databind.JavaType; /** * Helper type used when introspecting bindings for already resolved types, * needed for specialization. * * @since 2.8.11 */ public class PlaceholderForType extends TypeBase { private static final long serialVersionUID = 1L; protected final int _ordinal; /** * Type assigned during wildcard resolution (which follows type * structure resolution) */ protected JavaType _actualType; public PlaceholderForType(int ordinal) { super(Object.class, TypeBindings.emptyBindings(), TypeFactory.unknownType(), null, 1, // super-class, super-interfaces, hashCode null, null, false); // value/type handler, as-static _ordinal = ordinal; } public JavaType actualType() { return _actualType; } public void actualType(JavaType t) { _actualType = t; } // Override to get better diagnostics @Override protected String buildCanonicalName() { return toString(); } @Override public StringBuilder getGenericSignature(StringBuilder sb) { return getErasedSignature(sb); } @Override public StringBuilder getErasedSignature(StringBuilder sb) { sb.append('$').append(_ordinal+1); return sb; } @Override public JavaType withTypeHandler(Object h) { return _unsupported(); } @Override public JavaType withContentTypeHandler(Object h) { return _unsupported(); } @Override public JavaType withValueHandler(Object h) { return _unsupported(); } @Override public JavaType withContentValueHandler(Object h) { return _unsupported(); } @Override public JavaType withContentType(JavaType contentType) { return _unsupported(); } @Override public JavaType withStaticTyping() { return _unsupported(); } @Override public JavaType refine(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { return _unsupported(); } @SuppressWarnings("deprecation") @Override protected JavaType _narrow(Class subclass) { return _unsupported(); } @Override public boolean isContainerType() { return false; } @Override public String toString() { return getErasedSignature(new StringBuilder()).toString(); } @Override public boolean equals(Object o) { return (o == this); } private T _unsupported() { throw new UnsupportedOperationException("Operation should not be attempted on "+getClass().getName()); } } ReferenceType.java000066400000000000000000000213161325620701100350370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import com.fasterxml.jackson.databind.JavaType; /** * Specialized {@link SimpleType} for types that are referential types, * that is, values that can be dereferenced to another value (or null), * of different type. * Referenced type is accessible using {@link #getContentType()}. * * @since 2.6 */ public class ReferenceType extends SimpleType { private static final long serialVersionUID = 1L; protected final JavaType _referencedType; /** * Essential type used for type ids, for example if type id is needed for * referencing type with polymorphic handling. Typically initialized when * a {@link SimpleType} is upgraded into reference type, but NOT changed * if being sub-classed. * * @since 2.8 */ protected final JavaType _anchorType; protected ReferenceType(Class cls, TypeBindings bindings, JavaType superClass, JavaType[] superInts, JavaType refType, JavaType anchorType, Object valueHandler, Object typeHandler, boolean asStatic) { super(cls, bindings, superClass, superInts, refType.hashCode(), valueHandler, typeHandler, asStatic); _referencedType = refType; _anchorType = (anchorType == null) ? this : anchorType; } /** * Constructor used when upgrading into this type (via {@link #upgradeFrom}, * the usual way for {@link ReferenceType}s to come into existence. * Sets up what is considered the "base" reference type * * @since 2.7 */ protected ReferenceType(TypeBase base, JavaType refType) { super(base); _referencedType = refType; // we'll establish this as the anchor type _anchorType = this; } /** * Factory method that can be used to "upgrade" a basic type into collection-like * one; usually done via {@link TypeModifier} * * @param baseType Resolved non-reference type (usually {@link SimpleType}) that is being upgraded * @param refdType Referenced type; usually the first and only type parameter, but not necessarily * * @since 2.7 */ public static ReferenceType upgradeFrom(JavaType baseType, JavaType refdType) { if (refdType == null) { throw new IllegalArgumentException("Missing referencedType"); } // 19-Oct-2015, tatu: Not sure if and how other types could be used as base; // will cross that bridge if and when need be if (baseType instanceof TypeBase) { return new ReferenceType((TypeBase) baseType, refdType); } throw new IllegalArgumentException("Cannot upgrade from an instance of "+baseType.getClass()); } /** * @since 2.7 */ public static ReferenceType construct(Class cls, TypeBindings bindings, JavaType superClass, JavaType[] superInts, JavaType refType) { return new ReferenceType(cls, bindings, superClass, superInts, refType, null, null, null, false); } @Deprecated // since 2.7 public static ReferenceType construct(Class cls, JavaType refType) { return new ReferenceType(cls, TypeBindings.emptyBindings(), // !!! TODO: missing supertypes null, null, null, refType, null, null, false); } @Override public JavaType withContentType(JavaType contentType) { if (_referencedType == contentType) { return this; } return new ReferenceType(_class, _bindings, _superClass, _superInterfaces, contentType, _anchorType, _valueHandler, _typeHandler, _asStatic); } @Override public ReferenceType withTypeHandler(Object h) { if (h == _typeHandler) { return this; } return new ReferenceType(_class, _bindings, _superClass, _superInterfaces, _referencedType, _anchorType, _valueHandler, h, _asStatic); } @Override public ReferenceType withContentTypeHandler(Object h) { if (h == _referencedType.getTypeHandler()) { return this; } return new ReferenceType(_class, _bindings, _superClass, _superInterfaces, _referencedType.withTypeHandler(h), _anchorType, _valueHandler, _typeHandler, _asStatic); } @Override public ReferenceType withValueHandler(Object h) { if (h == _valueHandler) { return this; } return new ReferenceType(_class, _bindings, _superClass, _superInterfaces, _referencedType, _anchorType, h, _typeHandler,_asStatic); } @Override public ReferenceType withContentValueHandler(Object h) { if (h == _referencedType.getValueHandler()) { return this; } JavaType refdType = _referencedType.withValueHandler(h); return new ReferenceType(_class, _bindings, _superClass, _superInterfaces, refdType, _anchorType, _valueHandler, _typeHandler, _asStatic); } @Override public ReferenceType withStaticTyping() { if (_asStatic) { return this; } return new ReferenceType(_class, _bindings, _superClass, _superInterfaces, _referencedType.withStaticTyping(), _anchorType, _valueHandler, _typeHandler, true); } @Override public JavaType refine(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { return new ReferenceType(rawType, _bindings, superClass, superInterfaces, _referencedType, _anchorType, _valueHandler, _typeHandler, _asStatic); } @Override protected String buildCanonicalName() { StringBuilder sb = new StringBuilder(); sb.append(_class.getName()); sb.append('<'); sb.append(_referencedType.toCanonical()); return sb.toString(); } /* /********************************************************** /* Narrow/widen /********************************************************** */ @Override @Deprecated // since 2.7 protected JavaType _narrow(Class subclass) { // Should we check that there is a sub-class relationship? return new ReferenceType(subclass, _bindings, _superClass, _superInterfaces, _referencedType, _anchorType, _valueHandler, _typeHandler, _asStatic); } /* /********************************************************** /* Public API overrides /********************************************************** */ @Override public JavaType getContentType() { return _referencedType; } @Override public JavaType getReferencedType() { return _referencedType; } @Override public boolean hasContentType() { return true; } @Override public boolean isReferenceType() { return true; } @Override public StringBuilder getErasedSignature(StringBuilder sb) { return _classSignature(_class, sb, true); } @Override public StringBuilder getGenericSignature(StringBuilder sb) { _classSignature(_class, sb, false); sb.append('<'); sb = _referencedType.getGenericSignature(sb); sb.append(">;"); return sb; } /* /********************************************************** /* Extended API /********************************************************** */ public JavaType getAnchorType() { return _anchorType; } /** * Convenience accessor that allows checking whether this is the anchor type * itself; if not, it must be one of supertypes that is also a {@link ReferenceType} */ public boolean isAnchorType() { return (_anchorType == this); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return new StringBuilder(40) .append("[reference type, class ") .append(buildCanonicalName()) .append('<') .append(_referencedType) .append('>') .append(']') .toString(); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; ReferenceType other = (ReferenceType) o; if (other._class != _class) return false; // Otherwise actually mostly worry about referenced type return _referencedType.equals(other._referencedType); } } ResolvedRecursiveType.java000066400000000000000000000066651325620701100366260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import com.fasterxml.jackson.databind.JavaType; /** * Internal placeholder type used for self-references. * * @since 2.7 */ public class ResolvedRecursiveType extends TypeBase { private static final long serialVersionUID = 1L; protected JavaType _referencedType; public ResolvedRecursiveType(Class erasedType, TypeBindings bindings) { super(erasedType, bindings, null, null, 0, null, null, false); } public void setReference(JavaType ref) { // sanity check; should not be called multiple times if (_referencedType != null) { throw new IllegalStateException("Trying to re-set self reference; old value = "+_referencedType+", new = "+ref); } _referencedType = ref; } @Override public JavaType getSuperClass() { if (_referencedType != null) { return _referencedType.getSuperClass(); } return super.getSuperClass(); } public JavaType getSelfReferencedType() { return _referencedType; } @Override public StringBuilder getGenericSignature(StringBuilder sb) { return _referencedType.getGenericSignature(sb); } @Override public StringBuilder getErasedSignature(StringBuilder sb) { return _referencedType.getErasedSignature(sb); } @Override public JavaType withContentType(JavaType contentType) { return this; } @Override public JavaType withTypeHandler(Object h) { return this; } @Override public JavaType withContentTypeHandler(Object h) { return this; } @Override public JavaType withValueHandler(Object h) { return this; } @Override public JavaType withContentValueHandler(Object h) { return this; } @Override public JavaType withStaticTyping() { return this; } @Deprecated // since 2.7 @Override protected JavaType _narrow(Class subclass) { return this; } @Override public JavaType refine(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { return null; } @Override public boolean isContainerType() { return false; } @Override public String toString() { StringBuilder sb = new StringBuilder(40) .append("[recursive type; "); if (_referencedType == null) { sb.append("UNRESOLVED"); } else { // [databind#1301]: Typically resolves to a loop so short-cut // and only include type-erased class sb.append(_referencedType.getRawClass().getName()); } return sb.toString(); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() == getClass()) { // 16-Jun-2017, tatu: as per [databind#1658], cannot do recursive call since // there is likely to be a cycle... // but... true or false? return false; /* // Do NOT ever match unresolved references if (_referencedType == null) { return false; } return (o.getClass() == getClass() && _referencedType.equals(((ResolvedRecursiveType) o).getSelfReferencedType())); */ } return false; } } SimpleType.java000066400000000000000000000263551325620701100344020ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.*; import com.fasterxml.jackson.databind.JavaType; /** * Simple types are defined as anything other than one of recognized * container types (arrays, Collections, Maps). For our needs we * need not know anything further, since we have no way of dealing * with generic types other than Collections and Maps. */ public class SimpleType // note: until 2.6 was final extends TypeBase { private static final long serialVersionUID = 1L; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * Constructor only used by core Jackson databind functionality; * should never be called by application code. *

* As with other direct construction that by-passes {@link TypeFactory}, * no introspection occurs with respect to super-types; caller must be * aware of consequences if using this method. */ protected SimpleType(Class cls) { this(cls, TypeBindings.emptyBindings(), null, null); } protected SimpleType(Class cls, TypeBindings bindings, JavaType superClass, JavaType[] superInts) { this(cls, bindings, superClass, superInts, null, null, false); } /** * Simple copy-constructor, usually used when upgrading/refining a simple type * into more specialized type. * * @since 2.7 */ protected SimpleType(TypeBase base) { super(base); } protected SimpleType(Class cls, TypeBindings bindings, JavaType superClass, JavaType[] superInts, Object valueHandler, Object typeHandler, boolean asStatic) { super(cls, bindings, superClass, superInts, 0, valueHandler, typeHandler, asStatic); } /** * Pass-through constructor used by {@link ReferenceType}. * * @since 2.6 */ protected SimpleType(Class cls, TypeBindings bindings, JavaType superClass, JavaType[] superInts, int extraHash, Object valueHandler, Object typeHandler, boolean asStatic) { super(cls, bindings, superClass, superInts, extraHash, valueHandler, typeHandler, asStatic); } /** * Method used by core Jackson classes: NOT to be used by application code: * it does NOT properly handle inspection of super-types, so neither parent * Classes nor implemented Interfaces are accessible with resulting type * instance. *

* NOTE: public only because it is called by ObjectMapper which is * not in same package */ public static SimpleType constructUnsafe(Class raw) { return new SimpleType(raw, null, // 18-Oct-2015, tatu: Should be ok to omit possible super-types, right? null, null, null, null, false); } /** * Method that should NOT to be used by application code: * it does NOT properly handle inspection of super-types, so neither parent * Classes nor implemented Interfaces are accessible with resulting type * instance. Instead, please use {@link TypeFactory}'s constructType * methods which handle introspection appropriately. *

* Note that prior to 2.7, method usage was not limited and would typically * have worked acceptably: the problem comes from inability to resolve super-type * information, for which {@link TypeFactory} is needed. * * @deprecated Since 2.7 */ @Deprecated public static SimpleType construct(Class cls) { /* Let's add sanity checks, just to ensure no * Map/Collection entries are constructed */ if (Map.class.isAssignableFrom(cls)) { throw new IllegalArgumentException("Cannot construct SimpleType for a Map (class: "+cls.getName()+")"); } if (Collection.class.isAssignableFrom(cls)) { throw new IllegalArgumentException("Cannot construct SimpleType for a Collection (class: "+cls.getName()+")"); } // ... and while we are at it, not array types either if (cls.isArray()) { throw new IllegalArgumentException("Cannot construct SimpleType for an array (class: "+cls.getName()+")"); } TypeBindings b = TypeBindings.emptyBindings(); return new SimpleType(cls, b, _buildSuperClass(cls.getSuperclass(), b), null, null, null, false); } @Override @Deprecated protected JavaType _narrow(Class subclass) { if (_class == subclass) { return this; } // Should we check that there is a sub-class relationship? // 15-Jan-2016, tatu: Almost yes, but there are some complications with // placeholder values (`Void`, `NoClass`), so cannot quite do yet. // TODO: fix in 2.9 if (!_class.isAssignableFrom(subclass)) { /* throw new IllegalArgumentException("Class "+subclass.getName()+" not sub-type of " +_class.getName()); */ return new SimpleType(subclass, _bindings, this, _superInterfaces, _valueHandler, _typeHandler, _asStatic); } // Otherwise, stitch together the hierarchy. First, super-class Class next = subclass.getSuperclass(); if (next == _class) { // straight up parent class? Great. return new SimpleType(subclass, _bindings, this, _superInterfaces, _valueHandler, _typeHandler, _asStatic); } if ((next != null) && _class.isAssignableFrom(next)) { JavaType superb = _narrow(next); return new SimpleType(subclass, _bindings, superb, null, _valueHandler, _typeHandler, _asStatic); } // if not found, try a super-interface Class[] nextI = subclass.getInterfaces(); for (Class iface : nextI) { if (iface == _class) { // directly implemented return new SimpleType(subclass, _bindings, null, new JavaType[] { this }, _valueHandler, _typeHandler, _asStatic); } if (_class.isAssignableFrom(iface)) { // indirect, so recurse JavaType superb = _narrow(iface); return new SimpleType(subclass, _bindings, null, new JavaType[] { superb }, _valueHandler, _typeHandler, _asStatic); } } // should not get here but... throw new IllegalArgumentException("Internal error: Cannot resolve sub-type for Class "+subclass.getName()+" to " +_class.getName()); } @Override public JavaType withContentType(JavaType contentType) { throw new IllegalArgumentException("Simple types have no content types; cannot call withContentType()"); } @Override public SimpleType withTypeHandler(Object h) { if (_typeHandler == h) { return this; } return new SimpleType(_class, _bindings, _superClass, _superInterfaces, _valueHandler, h, _asStatic); } @Override public JavaType withContentTypeHandler(Object h) { // no content type, so: throw new IllegalArgumentException("Simple types have no content types; cannot call withContenTypeHandler()"); } @Override public SimpleType withValueHandler(Object h) { if (h == _valueHandler) { return this; } return new SimpleType(_class, _bindings, _superClass, _superInterfaces, h, _typeHandler, _asStatic); } @Override public SimpleType withContentValueHandler(Object h) { // no content type, so: throw new IllegalArgumentException("Simple types have no content types; cannot call withContenValueHandler()"); } @Override public SimpleType withStaticTyping() { return _asStatic ? this : new SimpleType(_class, _bindings, _superClass, _superInterfaces, _valueHandler, _typeHandler, true); } @Override public JavaType refine(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { // SimpleType means something not-specialized, so: return null; } @Override protected String buildCanonicalName() { StringBuilder sb = new StringBuilder(); sb.append(_class.getName()); final int count = _bindings.size(); if (count > 0) { sb.append('<'); for (int i = 0; i < count; ++i) { JavaType t = containedType(i); if (i > 0) { sb.append(','); } sb.append(t.toCanonical()); } sb.append('>'); } return sb.toString(); } /* /********************************************************** /* Public API /********************************************************** */ @Override public boolean isContainerType() { return false; } @Override public boolean hasContentType() { return false; } @Override public StringBuilder getErasedSignature(StringBuilder sb) { return _classSignature(_class, sb, true); } @Override public StringBuilder getGenericSignature(StringBuilder sb) { _classSignature(_class, sb, false); final int count = _bindings.size(); if (count > 0) { sb.append('<'); for (int i = 0; i < count; ++i) { sb = containedType(i).getGenericSignature(sb); } sb.append('>'); } sb.append(';'); return sb; } /* /********************************************************** /* Internal methods /********************************************************** */ /** * Helper method we need to recursively build skeletal representations * of superclasses. * * @since 2.7 -- remove when not needed (2.8?) */ private static JavaType _buildSuperClass(Class superClass, TypeBindings b) { if (superClass == null) { return null; } if (superClass == Object.class) { return TypeFactory.unknownType(); } JavaType superSuper = _buildSuperClass(superClass.getSuperclass(), b); return new SimpleType(superClass, b, superSuper, null, null, null, false); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { StringBuilder sb = new StringBuilder(40); sb.append("[simple type, class ").append(buildCanonicalName()).append(']'); return sb.toString(); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; SimpleType other = (SimpleType) o; // Classes must be identical... if (other._class != this._class) return false; // And finally, generic bindings, if any TypeBindings b1 = _bindings; TypeBindings b2 = other._bindings; return b1.equals(b2); } } TypeBase.java000066400000000000000000000165331325620701100340200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; public abstract class TypeBase extends JavaType implements JsonSerializable { private static final long serialVersionUID = 1; private final static TypeBindings NO_BINDINGS = TypeBindings.emptyBindings(); private final static JavaType[] NO_TYPES = new JavaType[0]; protected final JavaType _superClass; protected final JavaType[] _superInterfaces; /** * Bindings in effect for this type instance; possibly empty. * Needed when resolving types declared in members of this type * (if any). * * @since 2.7 */ protected final TypeBindings _bindings; /** * Lazily initialized external representation of the type */ volatile transient String _canonicalName; /** * Main constructor to use by extending classes. */ protected TypeBase(Class raw, TypeBindings bindings, JavaType superClass, JavaType[] superInts, int hash, Object valueHandler, Object typeHandler, boolean asStatic) { super(raw, hash, valueHandler, typeHandler, asStatic); _bindings = (bindings == null) ? NO_BINDINGS : bindings; _superClass = superClass; _superInterfaces = superInts; } /** * Copy-constructor used when refining/upgrading type instances. * * @since 2.7 */ protected TypeBase(TypeBase base) { super(base); _superClass = base._superClass; _superInterfaces = base._superInterfaces; _bindings = base._bindings; } @Override public String toCanonical() { String str = _canonicalName; if (str == null) { str = buildCanonicalName(); } return str; } protected String buildCanonicalName() { return _class.getName(); } @Override public abstract StringBuilder getGenericSignature(StringBuilder sb); @Override public abstract StringBuilder getErasedSignature(StringBuilder sb); @Override public TypeBindings getBindings() { return _bindings; } @Override public int containedTypeCount() { return _bindings.size(); } @Override public JavaType containedType(int index) { return _bindings.getBoundType(index); } @Override @Deprecated public String containedTypeName(int index) { return _bindings.getBoundName(index); } @Override public JavaType getSuperClass() { return _superClass; } @Override public List getInterfaces() { if (_superInterfaces == null) { return Collections.emptyList(); } switch (_superInterfaces.length) { case 0: return Collections.emptyList(); case 1: return Collections.singletonList(_superInterfaces[0]); } return Arrays.asList(_superInterfaces); } @Override public final JavaType findSuperType(Class rawTarget) { if (rawTarget == _class) { return this; } // Check super interfaces first: if (rawTarget.isInterface() && (_superInterfaces != null)) { for (int i = 0, count = _superInterfaces.length; i < count; ++i) { JavaType type = _superInterfaces[i].findSuperType(rawTarget); if (type != null) { return type; } } } // and if not found, super class and its supertypes if (_superClass != null) { JavaType type = _superClass.findSuperType(rawTarget); if (type != null) { return type; } } return null; } @Override public JavaType[] findTypeParameters(Class expType) { JavaType match = findSuperType(expType); if (match == null) { return NO_TYPES; } return match.getBindings().typeParameterArray(); } /* /********************************************************** /* JsonSerializable base implementation /********************************************************** */ @Override public void serializeWithType(JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { WritableTypeId typeIdDef = new WritableTypeId(this, JsonToken.VALUE_STRING); typeSer.writeTypePrefix(g, typeIdDef); this.serialize(g, provider); typeSer.writeTypeSuffix(g, typeIdDef); } @Override public void serialize(JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException { gen.writeString(toCanonical()); } /* /********************************************************** /* Methods for sub-classes to use /********************************************************** */ /** * @param trailingSemicolon Whether to add trailing semicolon for non-primitive * (reference) types or not */ protected static StringBuilder _classSignature(Class cls, StringBuilder sb, boolean trailingSemicolon) { if (cls.isPrimitive()) { if (cls == Boolean.TYPE) { sb.append('Z'); } else if (cls == Byte.TYPE) { sb.append('B'); } else if (cls == Short.TYPE) { sb.append('S'); } else if (cls == Character.TYPE) { sb.append('C'); } else if (cls == Integer.TYPE) { sb.append('I'); } else if (cls == Long.TYPE) { sb.append('J'); } else if (cls == Float.TYPE) { sb.append('F'); } else if (cls == Double.TYPE) { sb.append('D'); } else if (cls == Void.TYPE) { sb.append('V'); } else { throw new IllegalStateException("Unrecognized primitive type: "+cls.getName()); } } else { sb.append('L'); String name = cls.getName(); for (int i = 0, len = name.length(); i < len; ++i) { char c = name.charAt(i); if (c == '.') c = '/'; sb.append(c); } if (trailingSemicolon) { sb.append(';'); } } return sb; } /** * Internal helper method used to figure out nominal super-class for * deprecated factory methods / constructors, where we are not given * properly resolved supertype hierarchy. * Will basically give `JavaType` for `java.lang.Object` for classes * other than `java.lafgn.Object`; null for others. * * @since 2.7 */ protected static JavaType _bogusSuperClass(Class cls) { Class parent = cls.getSuperclass(); if (parent == null) { return null; } return TypeFactory.unknownType(); } } TypeBindings.java000066400000000000000000000374131325620701100347030ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.lang.reflect.*; import java.util.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Helper class used for resolving type parameters for given class */ public class TypeBindings implements java.io.Serializable { private static final long serialVersionUID = 1L; private final static String[] NO_STRINGS = new String[0]; private final static JavaType[] NO_TYPES = new JavaType[0]; private final static TypeBindings EMPTY = new TypeBindings(NO_STRINGS, NO_TYPES, null); // // // Pre-resolved instances for minor optimizations // // // Actual member information /** * Array of type (type variable) names. */ private final String[] _names; /** * Types matching names */ private final JavaType[] _types; /** * Names of potentially unresolved type variables. * * @since 2.3 */ private final String[] _unboundVariables; private final int _hashCode; /* /********************************************************************** /* Construction /********************************************************************** */ private TypeBindings(String[] names, JavaType[] types, String[] uvars) { _names = (names == null) ? NO_STRINGS : names; _types = (types == null) ? NO_TYPES : types; if (_names.length != _types.length) { throw new IllegalArgumentException("Mismatching names ("+_names.length+"), types ("+_types.length+")"); } 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; } // Let's just canonicalize serialized EMPTY back to static instance, if need be protected Object readResolve() { if ((_names == null) || (_names.length == 0)) { return EMPTY; } return this; } /** * Factory method for constructing bindings for given class using specified type * parameters. */ public static TypeBindings create(Class erasedType, List typeList) { JavaType[] types = (typeList == null || typeList.isEmpty()) ? NO_TYPES : typeList.toArray(new JavaType[typeList.size()]); return create(erasedType, types); } public static TypeBindings create(Class erasedType, JavaType[] types) { if (types == null) { types = NO_TYPES; } else switch (types.length) { case 1: return create(erasedType, types[0]); case 2: return create(erasedType, types[0], types[1]); } TypeVariable[] vars = erasedType.getTypeParameters(); String[] names; if (vars == null || 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(); } } // Check here to give better error message if (names.length != types.length) { throw new IllegalArgumentException("Cannot create TypeBindings for class "+erasedType.getName() +" with "+types.length+" type parameter" +((types.length == 1) ? "" : "s")+": class expects "+names.length); } return new TypeBindings(names, types, null); } public static TypeBindings create(Class erasedType, JavaType typeArg1) { // 30-Oct-2015, tatu: Minor optimization for relatively common cases TypeVariable[] vars = TypeParamStash.paramsFor1(erasedType); int varLen = (vars == null) ? 0 : vars.length; if (varLen != 1) { throw new IllegalArgumentException("Cannot create TypeBindings for class "+erasedType.getName() +" with 1 type parameter: class expects "+varLen); } return new TypeBindings(new String[] { vars[0].getName() }, new JavaType[] { typeArg1 }, null); } public static TypeBindings create(Class erasedType, JavaType typeArg1, JavaType typeArg2) { // 30-Oct-2015, tatu: Minor optimization for relatively common cases TypeVariable[] vars = TypeParamStash.paramsFor2(erasedType); int varLen = (vars == null) ? 0 : vars.length; if (varLen != 2) { throw new IllegalArgumentException("Cannot create TypeBindings for class "+erasedType.getName() +" with 2 type parameters: class expects "+varLen); } return new TypeBindings(new String[] { vars[0].getName(), vars[1].getName() }, new JavaType[] { typeArg1, typeArg2 }, null); } /** * Alternate factory method that may be called if it is possible that type * does or does not require type parameters; this is mostly useful for * collection- and map-like types. */ public static TypeBindings createIfNeeded(Class erasedType, JavaType typeArg1) { TypeVariable[] vars = erasedType.getTypeParameters(); int varLen = (vars == null) ? 0 : vars.length; if (varLen == 0) { return EMPTY; } if (varLen != 1) { throw new IllegalArgumentException("Cannot create TypeBindings for class "+erasedType.getName() +" with 1 type parameter: class expects "+varLen); } return new TypeBindings(new String[] { vars[0].getName() }, new JavaType[] { typeArg1 }, null); } /** * Alternate factory method that may be called if it is possible that type * does or does not require type parameters; this is mostly useful for * collection- and map-like types. */ public static TypeBindings createIfNeeded(Class erasedType, JavaType[] types) { TypeVariable[] vars = erasedType.getTypeParameters(); if (vars == null || vars.length == 0) { return EMPTY; } if (types == null) { types = NO_TYPES; } int len = vars.length; String[] names = new String[len]; for (int i = 0; i < len; ++i) { names[i] = vars[i].getName(); } // Check here to give better error message if (names.length != types.length) { throw new IllegalArgumentException("Cannot create TypeBindings for class "+erasedType.getName() +" with "+types.length+" type parameter" +((types.length == 1) ? "" : "s")+": class expects "+names.length); } 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 /********************************************************************** */ /** * Find type bound to specified name, if there is one; returns bound type if so, null if not. */ public JavaType findBoundType(String name) { for (int i = 0, len = _names.length; i < len; ++i) { if (name.equals(_names[i])) { JavaType t = _types[i]; if (t instanceof ResolvedRecursiveType) { ResolvedRecursiveType rrt = (ResolvedRecursiveType) t; JavaType t2 = rrt.getSelfReferencedType(); if (t2 != null) { t = t2; } else { /* 25-Feb-2016, tatu: Looks like a potential problem, but alas * we have a test where this should NOT fail and things... seem * to work. So be it. */ /* throw new IllegalStateException(String.format ("Unresolved ResolvedRecursiveType for parameter '%s' (index #%d; erased type %s)", name, i, t.getRawClass())); */ } } return t; } } return null; } public boolean isEmpty() { return (_types.length == 0); } /** * Returns number of bindings contained */ public int size() { return _types.length; } public String getBoundName(int index) { if (index < 0 || index >= _names.length) { return null; } return _names[index]; } public JavaType getBoundType(int index) { if (index < 0 || index >= _types.length) { return null; } return _types[index]; } /** * Accessor for getting bound types in declaration order */ 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; } /** * Factory method that will create an object that can be used as a key for * caching purposes by {@link TypeFactory} * * @since 2.8 */ public Object asKey(Class rawBase) { // safe to pass _types array without copy since it is not exposed via // any access, nor modified by this class return new AsKey(rawBase, _types, _hashCode); } /* /********************************************************************** /* 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].appendBriefDescription(sb); String sig = _types[i].getGenericSignature(); sb.append(sig); } sb.append('>'); return sb.toString(); } @Override public int hashCode() { return _hashCode; } @Override public boolean equals(Object o) { if (o == this) return true; if (!ClassUtil.hasClass(o, getClass())) { return false; } TypeBindings other = (TypeBindings) o; int len = _types.length; if (len != other.size()) { return false; } JavaType[] otherTypes = other._types; for (int i = 0; i < len; ++i) { if (!otherTypes[i].equals(_types[i])) { return false; } } return true; } /* /********************************************************************** /* Package accessible methods /********************************************************************** */ protected JavaType[] typeParameterArray() { return _types; } /* /********************************************************************** /* Helper classes /********************************************************************** */ // 30-Oct-2015, tatu: Surprising, but looks like type parameters access can be bit of // a hot spot. So avoid for a small number of common generic types. Note that we do // need both common abstract types and concrete ones; latter for specialization /** * Helper class that contains simple logic for avoiding repeated lookups via * {@link Class#getTypeParameters()} as that can be a performance issue for * some use cases (wasteful, usually one-off or not reusing mapper). * Partly isolated to avoid initialization for cases where no generic types are * used. */ static class TypeParamStash { private final static TypeVariable[] VARS_ABSTRACT_LIST = AbstractList.class.getTypeParameters(); private final static TypeVariable[] VARS_COLLECTION = Collection.class.getTypeParameters(); private final static TypeVariable[] VARS_ITERABLE = Iterable.class.getTypeParameters(); private final static TypeVariable[] VARS_LIST = List.class.getTypeParameters(); private final static TypeVariable[] VARS_ARRAY_LIST = ArrayList.class.getTypeParameters(); private final static TypeVariable[] VARS_MAP = Map.class.getTypeParameters(); private final static TypeVariable[] VARS_HASH_MAP = HashMap.class.getTypeParameters(); private final static TypeVariable[] VARS_LINKED_HASH_MAP = LinkedHashMap.class.getTypeParameters(); public static TypeVariable[] paramsFor1(Class erasedType) { if (erasedType == Collection.class) { return VARS_COLLECTION; } if (erasedType == List.class) { return VARS_LIST; } if (erasedType == ArrayList.class) { return VARS_ARRAY_LIST; } if (erasedType == AbstractList.class) { return VARS_ABSTRACT_LIST; } if (erasedType == Iterable.class) { return VARS_ITERABLE; } return erasedType.getTypeParameters(); } public static TypeVariable[] paramsFor2(Class erasedType) { if (erasedType == Map.class) { return VARS_MAP; } if (erasedType == HashMap.class) { return VARS_HASH_MAP; } if (erasedType == LinkedHashMap.class) { return VARS_LINKED_HASH_MAP; } return erasedType.getTypeParameters(); } } /** * Helper type used to allow caching of generic types * * @since 2.8 */ final static class AsKey { private final Class _raw; private final JavaType[] _params; private final int _hash; public AsKey(Class raw, JavaType[] params, int hash) { _raw = raw ; _params = params; _hash = hash; } @Override public int hashCode() { return _hash; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; AsKey other = (AsKey) o; if ((_hash == other._hash) && (_raw == other._raw)) { final JavaType[] otherParams = other._params; final int len = _params.length; if (len == otherParams.length) { for (int i = 0; i < len; ++i) { if (!_params[i].equals(otherParams[i])) { return false; } } return true; } } return false; } @Override public String toString() { return _raw.getName()+"<>"; } } } TypeFactory.java000066400000000000000000001634351325620701100345610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.lang.reflect.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.util.ArrayBuilders; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.LRUMap; /** * Class used for creating concrete {@link JavaType} instances, * given various inputs. *

* Instances of this class are accessible using {@link com.fasterxml.jackson.databind.ObjectMapper} * as well as many objects it constructs (like * {@link com.fasterxml.jackson.databind.DeserializationConfig} and * {@link com.fasterxml.jackson.databind.SerializationConfig})), * but usually those objects also * expose convenience methods (constructType). * So, you can do for example: *

 *   JavaType stringType = mapper.constructType(String.class);
 *
* However, more advanced methods are only exposed by factory so that you * may need to use: *
 *   JavaType stringCollection = mapper.getTypeFactory().constructCollectionType(List.class, String.class);
 *
*/ @SuppressWarnings({"rawtypes" }) public final class TypeFactory implements java.io.Serializable { private static final long serialVersionUID = 1L; private final static JavaType[] NO_TYPES = new JavaType[0]; /** * Globally shared singleton. Not accessed directly; non-core * code should use per-ObjectMapper instance (via configuration objects). * Core Jackson code uses {@link #defaultInstance} for accessing it. */ protected final static TypeFactory instance = new TypeFactory(); protected final static TypeBindings EMPTY_BINDINGS = TypeBindings.emptyBindings(); /* /********************************************************** /* Constants for "well-known" classes /********************************************************** */ // // // Let's assume that a small set of core primitive/basic types // // // will not be modified, and can be freely shared to streamline // // // parts of processing private final static Class CLS_STRING = String.class; private final static Class CLS_OBJECT = Object.class; private final static Class CLS_COMPARABLE = Comparable.class; private final static Class CLS_CLASS = Class.class; private final static Class CLS_ENUM = Enum.class; private final static Class CLS_BOOL = Boolean.TYPE; private final static Class CLS_INT = Integer.TYPE; private final static Class CLS_LONG = Long.TYPE; /* /********************************************************** /* Cached pre-constructed JavaType instances /********************************************************** */ // note: these are primitive, hence no super types protected final static SimpleType CORE_TYPE_BOOL = new SimpleType(CLS_BOOL); protected final static SimpleType CORE_TYPE_INT = new SimpleType(CLS_INT); protected final static SimpleType CORE_TYPE_LONG = new SimpleType(CLS_LONG); // and as to String... well, for now, ignore its super types protected final static SimpleType CORE_TYPE_STRING = new SimpleType(CLS_STRING); // @since 2.7 protected final static SimpleType CORE_TYPE_OBJECT = new SimpleType(CLS_OBJECT); /** * Cache {@link Comparable} because it is both parameteric (relatively costly to * resolve) and mostly useless (no special handling), better handle directly * * @since 2.7 */ protected final static SimpleType CORE_TYPE_COMPARABLE = new SimpleType(CLS_COMPARABLE); /** * Cache {@link Enum} because it is parametric AND self-referential (costly to * resolve) and useless in itself (no special handling). * * @since 2.7 */ protected final static SimpleType CORE_TYPE_ENUM = new SimpleType(CLS_ENUM); /** * Cache {@link Class} because it is nominally parametric, but has no really * useful information. * * @since 2.7 */ protected final static SimpleType CORE_TYPE_CLASS = new SimpleType(CLS_CLASS); /** * Since type resolution can be expensive (specifically when resolving * actual generic types), we will use small cache to avoid repetitive * resolution of core types */ protected final LRUMap _typeCache; /* /********************************************************** /* Configuration /********************************************************** */ /** * Registered {@link TypeModifier}s: objects that can change details * of {@link JavaType} instances factory constructs. */ protected final TypeModifier[] _modifiers; protected final TypeParser _parser; /** * ClassLoader used by this factory [databind#624]. */ protected final ClassLoader _classLoader; /* /********************************************************** /* Life-cycle /********************************************************** */ private TypeFactory() { this(null); } /** * @since 2.8 */ protected TypeFactory(LRUMap typeCache) { if (typeCache == null) { typeCache = new LRUMap(16, 200); } _typeCache = typeCache; _parser = new TypeParser(this); _modifiers = null; _classLoader = null; } protected TypeFactory(LRUMap typeCache, TypeParser p, TypeModifier[] mods, ClassLoader classLoader) { if (typeCache == null) { typeCache = new LRUMap(16, 200); } _typeCache = typeCache; // As per [databind#894] must ensure we have back-linkage from TypeFactory: _parser = p.withFactory(this); _modifiers = mods; _classLoader = classLoader; } public TypeFactory withModifier(TypeModifier mod) { LRUMap typeCache = _typeCache; TypeModifier[] mods; if (mod == null) { // mostly for unit tests mods = null; // 30-Jun-2016, tatu: for some reason expected semantics are to clear cache // in this case; can't recall why, but keeping the same typeCache = null; } else if (_modifiers == null) { mods = new TypeModifier[] { mod }; } else { mods = ArrayBuilders.insertInListNoDup(_modifiers, mod); } return new TypeFactory(typeCache, _parser, mods, _classLoader); } public TypeFactory withClassLoader(ClassLoader classLoader) { return new TypeFactory(_typeCache, _parser, _modifiers, classLoader); } /** * Mutant factory method that will construct new {@link TypeFactory} with * identical settings except for different cache; most likely one with * bigger maximum size. * * @since 2.8 */ public TypeFactory withCache(LRUMap cache) { return new TypeFactory(cache, _parser, _modifiers, _classLoader); } /** * Method used to access the globally shared instance, which has * no custom configuration. Used by ObjectMapper to * get the default factory when constructed. */ public static TypeFactory defaultInstance() { return instance; } /** * Method that will clear up any cached type definitions that may * be cached by this {@link TypeFactory} instance. * This method should not be commonly used, that is, only use it * if you know there is a problem with retention of type definitions; * the most likely (and currently only known) problem is retention * of {@link Class} instances via {@link JavaType} reference. * * @since 2.4.1 */ public void clearCache() { _typeCache.clear(); } public ClassLoader getClassLoader() { return _classLoader; } /* /********************************************************** /* Static methods for non-instance-specific functionality /********************************************************** */ /** * Method for constructing a marker type that indicates missing generic * type information, which is handled same as simple type for * java.lang.Object. */ public static JavaType unknownType() { return defaultInstance()._unknownType(); } /** * Static helper method that can be called to figure out type-erased * call for given JDK type. It can be called statically since type resolution * process can never change actual type-erased class; thereby static * default instance is used for determination. */ public static Class rawClass(Type t) { if (t instanceof Class) { return (Class) t; } // Should be able to optimize bit more in future... return defaultInstance().constructType(t).getRawClass(); } /* /********************************************************** /* Low-level helper methods /********************************************************** */ /** * Low-level lookup method moved from {@link com.fasterxml.jackson.databind.util.ClassUtil}, * to allow for overriding of lookup functionality in environments like OSGi. * * @since 2.6 */ public Class findClass(String className) throws ClassNotFoundException { if (className.indexOf('.') < 0) { Class prim = _findPrimitive(className); if (prim != null) { return prim; } } // Two-phase lookup: first using context ClassLoader; then default Throwable prob = null; ClassLoader loader = this.getClassLoader(); if (loader == null) { loader = Thread.currentThread().getContextClassLoader(); } if (loader != null) { try { return classForName(className, true, loader); } catch (Exception e) { prob = ClassUtil.getRootCause(e); } } try { return classForName(className); } catch (Exception e) { if (prob == null) { prob = ClassUtil.getRootCause(e); } } ClassUtil.throwIfRTE(prob); throw new ClassNotFoundException(prob.getMessage(), prob); } protected Class classForName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException { return Class.forName(name, true, loader); } protected Class classForName(String name) throws ClassNotFoundException { return Class.forName(name); } protected Class _findPrimitive(String className) { if ("int".equals(className)) return Integer.TYPE; if ("long".equals(className)) return Long.TYPE; if ("float".equals(className)) return Float.TYPE; if ("double".equals(className)) return Double.TYPE; if ("boolean".equals(className)) return Boolean.TYPE; if ("byte".equals(className)) return Byte.TYPE; if ("char".equals(className)) return Character.TYPE; if ("short".equals(className)) return Short.TYPE; if ("void".equals(className)) return Void.TYPE; return null; } /* /********************************************************** /* Type conversion, parameterization resolution methods /********************************************************** */ /** * Factory method for creating a subtype of given base type, as defined * by specified subclass; but retaining generic type information if any. * Can be used, for example, to get equivalent of "HashMap<String,Integer>" * from "Map<String,Integer>" by giving HashMap.class * as subclass. */ public JavaType constructSpecializedType(JavaType baseType, Class subclass) { // simple optimization to avoid costly introspection if type-erased type does NOT differ final Class rawBase = baseType.getRawClass(); if (rawBase == subclass) { return baseType; } JavaType newType; // also: if we start from untyped, not much to save do { // bogus loop to be able to break if (rawBase == Object.class) { newType = _fromClass(null, subclass, EMPTY_BINDINGS); break; } if (!rawBase.isAssignableFrom(subclass)) { throw new IllegalArgumentException(String.format( "Class %s not subtype of %s", subclass.getName(), baseType)); } // A few special cases where we can simplify handling: // (1) Original target type has no generics -- just resolve subtype if (baseType.getBindings().isEmpty()) { newType = _fromClass(null, subclass, EMPTY_BINDINGS); break; } // (2) A small set of "well-known" List/Map subtypes where can take a short-cut if (baseType.isContainerType()) { if (baseType.isMapLikeType()) { if ((subclass == HashMap.class) || (subclass == LinkedHashMap.class) || (subclass == EnumMap.class) || (subclass == TreeMap.class)) { newType = _fromClass(null, subclass, TypeBindings.create(subclass, baseType.getKeyType(), baseType.getContentType())); break; } } else if (baseType.isCollectionLikeType()) { if ((subclass == ArrayList.class) || (subclass == LinkedList.class) || (subclass == HashSet.class) || (subclass == TreeSet.class)) { newType = _fromClass(null, subclass, TypeBindings.create(subclass, baseType.getContentType())); break; } // 29-Oct-2015, tatu: One further shortcut: there are variants of `EnumSet`, // but they are impl details and we basically do not care... if (rawBase == EnumSet.class) { return baseType; } } } // (3) Sub-class does not take type parameters -- just resolve subtype int typeParamCount = subclass.getTypeParameters().length; if (typeParamCount == 0) { newType = _fromClass(null, subclass, EMPTY_BINDINGS); break; } // (4) If all else fails, do the full traversal using placeholders TypeBindings tb = _bindingsForSubtype(baseType, typeParamCount, subclass); newType = _fromClass(null, subclass, tb); } while (false); // 25-Sep-2016, tatu: As per [databind#1384] also need to ensure handlers get // copied as well newType = newType.withHandlersFrom(baseType); return newType; } private TypeBindings _bindingsForSubtype(JavaType baseType, int typeParamCount, Class subclass) { PlaceholderForType[] placeholders = new PlaceholderForType[typeParamCount]; for (int i = 0; i < typeParamCount; ++i) { placeholders[i] = new PlaceholderForType(i); } TypeBindings b = TypeBindings.create(subclass, placeholders); // First: pseudo-resolve to get placeholders in place: JavaType tmpSub = _fromClass(null, subclass, b); // Then find super-type JavaType baseWithPlaceholders = tmpSub.findSuperType(baseType.getRawClass()); if (baseWithPlaceholders == null) { // should be found but... throw new IllegalArgumentException(String.format( "Internal error: unable to locate supertype (%s) from resolved subtype %s", baseType.getRawClass().getName(), subclass.getName())); } // and traverse type hierarchies to both verify and to resolve placeholders String error = _resolveTypePlaceholders(baseType, baseWithPlaceholders); if (error != null) { throw new IllegalArgumentException("Failed to specialize base type "+baseType.toCanonical()+" as " +subclass.getName()+", problem: "+error); } final JavaType[] typeParams = new JavaType[typeParamCount]; for (int i = 0; i < typeParamCount; ++i) { JavaType t = placeholders[i].actualType(); // 18-Oct-2017, tatu: Looks like sometimes we have incomplete bindings (even if not // common, it is possible if subtype is type-erased class with added type // variable -- see test(s) with "bogus" type(s)). if (t == null) { t = unknownType(); } typeParams[i] = t; } return TypeBindings.create(subclass, typeParams); } private String _resolveTypePlaceholders(JavaType sourceType, JavaType actualType) throws IllegalArgumentException { List expectedTypes = sourceType.getBindings().getTypeParameters(); List actualTypes = actualType.getBindings().getTypeParameters(); for (int i = 0, len = expectedTypes.size(); i < len; ++i) { JavaType exp = expectedTypes.get(i); JavaType act = actualTypes.get(i); if (!_verifyAndResolvePlaceholders(exp, act)) { return String.format("Type parameter #%d/%d differs; can not specialize %s with %s", (i+1), len, exp.toCanonical(), act.toCanonical()); } } return null; } private boolean _verifyAndResolvePlaceholders(JavaType exp, JavaType act) { // See if we have an actual type placeholder to resolve; if yes, replace if (act instanceof PlaceholderForType) { ((PlaceholderForType) act).actualType(exp); return true; } // if not, try to verify compatibility. But note that we can not // use simple equality as we need to resolve recursively if (exp.getRawClass() != act.getRawClass()) { return false; } // But we can check type parameters "blindly" List expectedTypes = exp.getBindings().getTypeParameters(); List actualTypes = act.getBindings().getTypeParameters(); for (int i = 0, len = expectedTypes.size(); i < len; ++i) { JavaType exp2 = expectedTypes.get(i); JavaType act2 = actualTypes.get(i); if (!_verifyAndResolvePlaceholders(exp2, act2)) { return false; } } return true; } /** * Method similar to {@link #constructSpecializedType}, but that creates a * less-specific type of given type. Usually this is as simple as simply * finding super-type with type erasure of superClass, but * there may be need for some additional work-arounds. * * @param superClass * * @since 2.7 */ public JavaType constructGeneralizedType(JavaType baseType, Class superClass) { // simple optimization to avoid costly introspection if type-erased type does NOT differ final Class rawBase = baseType.getRawClass(); if (rawBase == superClass) { return baseType; } JavaType superType = baseType.findSuperType(superClass); if (superType == null) { // Most likely, caller did not verify sub/super-type relationship if (!superClass.isAssignableFrom(rawBase)) { throw new IllegalArgumentException(String.format( "Class %s not a super-type of %s", superClass.getName(), baseType)); } // 01-Nov-2015, tatu: Should never happen, but ch throw new IllegalArgumentException(String.format( "Internal error: class %s not included as super-type for %s", superClass.getName(), baseType)); } return superType; } /** * Factory method for constructing a {@link JavaType} out of its canonical * representation (see {@link JavaType#toCanonical()}). * * @param canonical Canonical string representation of a type * * @throws IllegalArgumentException If canonical representation is malformed, * or class that type represents (including its generic parameters) is * not found */ public JavaType constructFromCanonical(String canonical) throws IllegalArgumentException { return _parser.parse(canonical); } /** * Method that is to figure out actual type parameters that given * class binds to generic types defined by given (generic) * interface or class. * This could mean, for example, trying to figure out * key and value types for Map implementations. * * @param type Sub-type (leaf type) that implements expType */ public JavaType[] findTypeParameters(JavaType type, Class expType) { JavaType match = type.findSuperType(expType); if (match == null) { return NO_TYPES; } return match.getBindings().typeParameterArray(); } /** * @deprecated Since 2.7 resolve raw type first, then find type parameters */ @Deprecated // since 2.7 public JavaType[] findTypeParameters(Class clz, Class expType, TypeBindings bindings) { return findTypeParameters(constructType(clz, bindings), expType); } /** * @deprecated Since 2.7 resolve raw type first, then find type parameters */ @Deprecated // since 2.7 public JavaType[] findTypeParameters(Class clz, Class expType) { return findTypeParameters(constructType(clz), expType); } /** * Method that can be called to figure out more specific of two * types (if they are related; that is, one implements or extends the * other); or if not related, return the primary type. * * @param type1 Primary type to consider * @param type2 Secondary type to consider * * @since 2.2 */ public JavaType moreSpecificType(JavaType type1, JavaType type2) { if (type1 == null) { return type2; } if (type2 == null) { return type1; } Class raw1 = type1.getRawClass(); Class raw2 = type2.getRawClass(); if (raw1 == raw2) { return type1; } // TODO: maybe try sub-classing, to retain generic types? if (raw1.isAssignableFrom(raw2)) { return type2; } return type1; } /* /********************************************************** /* Public factory methods /********************************************************** */ public JavaType constructType(Type type) { return _fromAny(null, type, EMPTY_BINDINGS); } public JavaType constructType(Type type, TypeBindings bindings) { return _fromAny(null, type, bindings); } public JavaType constructType(TypeReference typeRef) { // 19-Oct-2015, tatu: Simpler variant like so should work return _fromAny(null, typeRef.getType(), EMPTY_BINDINGS); // but if not, due to funky sub-classing, type variables, what follows // is a more complete processing a la Java ClassMate. /* final Class refdRawType = typeRef.getClass(); JavaType type = _fromClass(null, refdRawType, EMPTY_BINDINGS); JavaType genType = type.findSuperType(TypeReference.class); if (genType == null) { // sanity check; shouldn't occur throw new IllegalArgumentException("Unparameterized GenericType instance ("+refdRawType.getName()+")"); } TypeBindings b = genType.getBindings(); JavaType[] params = b.typeParameterArray(); if (params.length == 0) { throw new IllegalArgumentException("Unparameterized GenericType instance ("+refdRawType.getName()+")"); } return params[0]; */ } /** * @deprecated Since 2.7 (accidentally removed in 2.7.0; added back in 2.7.1) */ @Deprecated public JavaType constructType(Type type, Class contextClass) { JavaType contextType = (contextClass == null) ? null : constructType(contextClass); return constructType(type, contextType); } /** * @deprecated Since 2.7 (accidentally removed in 2.7.0; added back in 2.7.1) */ @Deprecated public JavaType constructType(Type type, JavaType contextType) { TypeBindings bindings; if (contextType == null) { bindings = EMPTY_BINDINGS; } else { bindings = contextType.getBindings(); // 16-Nov-2016, tatu: Unfortunately as per [databind#1456] this can't // be made to work for some cases used to work (even if accidentally); // however, we can try a simple heuristic to increase chances of // compatibility from 2.6 code if (type.getClass() != Class.class) { // Ok: so, ideally we would test super-interfaces if necessary; // but let's assume most if not all cases are for classes. while (bindings.isEmpty()) { contextType = contextType.getSuperClass(); if (contextType == null) { break; } bindings = contextType.getBindings(); } } } return _fromAny(null, type, bindings); } /* /********************************************************** /* Direct factory methods /********************************************************** */ /** * Method for constructing an {@link ArrayType}. *

* NOTE: type modifiers are NOT called on array type itself; but are called * for element type (and other contained types) */ public ArrayType constructArrayType(Class elementType) { return ArrayType.construct(_fromAny(null, elementType, null), null); } /** * Method for constructing an {@link ArrayType}. *

* NOTE: type modifiers are NOT called on array type itself; but are called * for contained types. */ public ArrayType constructArrayType(JavaType elementType) { return ArrayType.construct(elementType, null); } /** * Method for constructing a {@link CollectionType}. *

* NOTE: type modifiers are NOT called on Collection type itself; but are called * for contained types. */ public CollectionType constructCollectionType(Class collectionClass, Class elementClass) { return constructCollectionType(collectionClass, _fromClass(null, elementClass, EMPTY_BINDINGS)); } /** * Method for constructing a {@link CollectionType}. *

* NOTE: type modifiers are NOT called on Collection type itself; but are called * for contained types. */ public CollectionType constructCollectionType(Class collectionClass, JavaType elementType) { TypeBindings bindings = TypeBindings.createIfNeeded(collectionClass, elementType); CollectionType result = (CollectionType) _fromClass(null, collectionClass, bindings); // 17-May-2017, tatu: As per [databind#1415], we better verify bound values if (but only if) // type being resolved was non-generic (i.e.element type was ignored) if (bindings.isEmpty() && (elementType != null)) { JavaType t = result.findSuperType(Collection.class); JavaType realET = t.getContentType(); if (!realET.equals(elementType)) { throw new IllegalArgumentException(String.format( "Non-generic Collection class %s did not resolve to something with element type %s but %s ", ClassUtil.nameOf(collectionClass), elementType, realET)); } } return result; } /** * Method for constructing a {@link CollectionLikeType}. *

* NOTE: type modifiers are NOT called on constructed type itself; but are called * for contained types. */ public CollectionLikeType constructCollectionLikeType(Class collectionClass, Class elementClass) { return constructCollectionLikeType(collectionClass, _fromClass(null, elementClass, EMPTY_BINDINGS)); } /** * Method for constructing a {@link CollectionLikeType}. *

* NOTE: type modifiers are NOT called on constructed type itself; but are called * for contained types. */ public CollectionLikeType constructCollectionLikeType(Class collectionClass, JavaType elementType) { JavaType type = _fromClass(null, collectionClass, TypeBindings.createIfNeeded(collectionClass, elementType)); if (type instanceof CollectionLikeType) { return (CollectionLikeType) type; } return CollectionLikeType.upgradeFrom(type, elementType); } /** * Method for constructing a {@link MapType} instance *

* NOTE: type modifiers are NOT called on constructed type itself; but are called * for contained types. */ public MapType constructMapType(Class mapClass, Class keyClass, Class valueClass) { JavaType kt, vt; if (mapClass == Properties.class) { kt = vt = CORE_TYPE_STRING; } else { kt = _fromClass(null, keyClass, EMPTY_BINDINGS); vt = _fromClass(null, valueClass, EMPTY_BINDINGS); } return constructMapType(mapClass, kt, vt); } /** * Method for constructing a {@link MapType} instance *

* NOTE: type modifiers are NOT called on constructed type itself; but are called * for contained types. */ public MapType constructMapType(Class mapClass, JavaType keyType, JavaType valueType) { TypeBindings bindings = TypeBindings.createIfNeeded(mapClass, new JavaType[] { keyType, valueType }); MapType result = (MapType) _fromClass(null, mapClass, bindings); // 17-May-2017, tatu: As per [databind#1415], we better verify bound values if (but only if) // type being resolved was non-generic (i.e.element type was ignored) if (bindings.isEmpty()) { JavaType t = result.findSuperType(Map.class); JavaType realKT = t.getKeyType(); if (!realKT.equals(keyType)) { throw new IllegalArgumentException(String.format( "Non-generic Map class %s did not resolve to something with key type %s but %s ", ClassUtil.nameOf(mapClass), keyType, realKT)); } JavaType realVT = t.getContentType(); if (!realVT.equals(valueType)) { throw new IllegalArgumentException(String.format( "Non-generic Map class %s did not resolve to something with value type %s but %s ", ClassUtil.nameOf(mapClass), valueType, realVT)); } } return result; } /** * Method for constructing a {@link MapLikeType} instance *

* NOTE: type modifiers are NOT called on constructed type itself; but are called * for contained types. */ public MapLikeType constructMapLikeType(Class mapClass, Class keyClass, Class valueClass) { return constructMapLikeType(mapClass, _fromClass(null, keyClass, EMPTY_BINDINGS), _fromClass(null, valueClass, EMPTY_BINDINGS)); } /** * Method for constructing a {@link MapLikeType} instance *

* NOTE: type modifiers are NOT called on constructed type itself; but are called * for contained types. */ public MapLikeType constructMapLikeType(Class mapClass, JavaType keyType, JavaType valueType) { // 19-Oct-2015, tatu: Allow case of no-type-variables, since it seems likely to be // a valid use case here JavaType type = _fromClass(null, mapClass, TypeBindings.createIfNeeded(mapClass, new JavaType[] { keyType, valueType })); if (type instanceof MapLikeType) { return (MapLikeType) type; } return MapLikeType.upgradeFrom(type, keyType, valueType); } /** * Method for constructing a type instance with specified parameterization. *

* NOTE: was briefly deprecated for 2.6. */ public JavaType constructSimpleType(Class rawType, JavaType[] parameterTypes) { return _fromClass(null, rawType, TypeBindings.create(rawType, parameterTypes)); } /** * Method for constructing a type instance with specified parameterization. * * @since 2.6 * * @deprecated Since 2.7 */ @Deprecated public JavaType constructSimpleType(Class rawType, Class parameterTarget, JavaType[] parameterTypes) { return constructSimpleType(rawType, parameterTypes); } /** * @since 2.6 */ public JavaType constructReferenceType(Class rawType, JavaType referredType) { return ReferenceType.construct(rawType, null, // no bindings null, null, // or super-class, interfaces? referredType); } /** * Method that use by core Databind functionality, and that should NOT be called * by application code outside databind package. *

* Unchecked here not only means that no checks are made as to whether given class * might be non-simple type (like {@link CollectionType}) but also that most of supertype * information is not gathered. This means that unless called on primitive types or * {@link java.lang.String}, results are probably not what you want to use. * * @deprecated Since 2.8, to indicate users should never call this method. */ @Deprecated // since 2.8 public JavaType uncheckedSimpleType(Class cls) { // 18-Oct-2015, tatu: Not sure how much problem missing super-type info is here return _constructSimple(cls, EMPTY_BINDINGS, null, null); } /** * Factory method for constructing {@link JavaType} that * represents a parameterized type. For example, to represent * type List<Set<Integer>>, you could * call *

     *  JavaType inner = TypeFactory.constructParametricType(Set.class, Set.class, Integer.class);
     *  return TypeFactory.constructParametricType(ArrayList.class, List.class, inner);
     *
*

* The reason for first two arguments to be separate is that parameterization may * apply to a super-type. For example, if generic type was instead to be * constructed for ArrayList<Integer>, the usual call would be: *

     *  TypeFactory.constructParametricType(ArrayList.class, List.class, Integer.class);
     *
* since parameterization is applied to {@link java.util.List}. * In most cases distinction does not matter, but there are types where it does; * one such example is parameterization of types that implement {@link java.util.Iterator}. *

* NOTE: type modifiers are NOT called on constructed type. * * @param parametrized Actual full type * @param parameterClasses Type parameters to apply * * @since 2.5 NOTE: was briefly deprecated for 2.6 */ public JavaType constructParametricType(Class parametrized, Class... parameterClasses) { int len = parameterClasses.length; JavaType[] pt = new JavaType[len]; for (int i = 0; i < len; ++i) { pt[i] = _fromClass(null, parameterClasses[i], EMPTY_BINDINGS); } return constructParametricType(parametrized, pt); } /** * Factory method for constructing {@link JavaType} that * represents a parameterized type. For example, to represent * type List<Set<Integer>>, you could * call *

     *  JavaType inner = TypeFactory.constructParametricType(Set.class, Set.class, Integer.class);
     *  return TypeFactory.constructParametricType(ArrayList.class, List.class, inner);
     *
*

* The reason for first two arguments to be separate is that parameterization may * apply to a super-type. For example, if generic type was instead to be * constructed for ArrayList<Integer>, the usual call would be: *

     *  TypeFactory.constructParametricType(ArrayList.class, List.class, Integer.class);
     *
* since parameterization is applied to {@link java.util.List}. * In most cases distinction does not matter, but there are types where it does; * one such example is parameterization of types that implement {@link java.util.Iterator}. *

* NOTE: type modifiers are NOT called on constructed type. * * @param rawType Actual type-erased type * @param parameterTypes Type parameters to apply * * @since 2.5 NOTE: was briefly deprecated for 2.6 */ public JavaType constructParametricType(Class rawType, JavaType... parameterTypes) { return _fromClass(null, rawType, TypeBindings.create(rawType, parameterTypes)); } /** * @since 2.5 -- but will probably deprecated in 2.7 or 2.8 (not needed with 2.7) * * @deprecated since 2.9 Use {@link #constructParametricType(Class,JavaType...)} instead */ @Deprecated public JavaType constructParametrizedType(Class parametrized, Class parametersFor, JavaType... parameterTypes) { return constructParametricType(parametrized, parameterTypes); } /** * @since 2.5 -- but will probably deprecated in 2.7 or 2.8 (not needed with 2.7) * * @deprecated since 2.9 Use {@link #constructParametricType(Class,Class...)} instead */ @Deprecated public JavaType constructParametrizedType(Class parametrized, Class parametersFor, Class... parameterClasses) { return constructParametricType(parametrized, parameterClasses); } /* /********************************************************** /* Direct factory methods for "raw" variants, used when /* parameterization is unknown /********************************************************** */ /** * Method that can be used to construct "raw" Collection type; meaning that its * parameterization is unknown. * This is similar to using Object.class parameterization, * and is equivalent to calling: *

     *  typeFactory.constructCollectionType(collectionClass, typeFactory.unknownType());
     *
*

* This method should only be used if parameterization is completely unavailable. */ public CollectionType constructRawCollectionType(Class collectionClass) { return constructCollectionType(collectionClass, unknownType()); } /** * Method that can be used to construct "raw" Collection-like type; meaning that its * parameterization is unknown. * This is similar to using Object.class parameterization, * and is equivalent to calling: *

     *  typeFactory.constructCollectionLikeType(collectionClass, typeFactory.unknownType());
     *
*

* This method should only be used if parameterization is completely unavailable. */ public CollectionLikeType constructRawCollectionLikeType(Class collectionClass) { return constructCollectionLikeType(collectionClass, unknownType()); } /** * Method that can be used to construct "raw" Map type; meaning that its * parameterization is unknown. * This is similar to using Object.class parameterization, * and is equivalent to calling: *

     *  typeFactory.constructMapType(collectionClass, typeFactory.unknownType(), typeFactory.unknownType());
     *
*

* This method should only be used if parameterization is completely unavailable. */ public MapType constructRawMapType(Class mapClass) { return constructMapType(mapClass, unknownType(), unknownType()); } /** * Method that can be used to construct "raw" Map-like type; meaning that its * parameterization is unknown. * This is similar to using Object.class parameterization, * and is equivalent to calling: *

     *  typeFactory.constructMapLikeType(collectionClass, typeFactory.unknownType(), typeFactory.unknownType());
     *
*

* This method should only be used if parameterization is completely unavailable. */ public MapLikeType constructRawMapLikeType(Class mapClass) { return constructMapLikeType(mapClass, unknownType(), unknownType()); } /* /********************************************************** /* Low-level factory methods /********************************************************** */ private JavaType _mapType(Class rawClass, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { JavaType kt, vt; // 28-May-2015, tatu: Properties are special, as per [databind#810]; fake "correct" parameter sig if (rawClass == Properties.class) { kt = vt = CORE_TYPE_STRING; } else { List typeParams = bindings.getTypeParameters(); // ok to have no types ("raw") switch (typeParams.size()) { case 0: // acceptable? kt = vt = _unknownType(); break; case 2: kt = typeParams.get(0); vt = typeParams.get(1); break; default: throw new IllegalArgumentException("Strange Map type "+rawClass.getName()+": cannot determine type parameters"); } } return MapType.construct(rawClass, bindings, superClass, superInterfaces, kt, vt); } private JavaType _collectionType(Class rawClass, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { List typeParams = bindings.getTypeParameters(); // ok to have no types ("raw") JavaType ct; if (typeParams.isEmpty()) { ct = _unknownType(); } else if (typeParams.size() == 1) { ct = typeParams.get(0); } else { throw new IllegalArgumentException("Strange Collection type "+rawClass.getName()+": cannot determine type parameters"); } return CollectionType.construct(rawClass, bindings, superClass, superInterfaces, ct); } private JavaType _referenceType(Class rawClass, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { List typeParams = bindings.getTypeParameters(); // ok to have no types ("raw") JavaType ct; if (typeParams.isEmpty()) { ct = _unknownType(); } else if (typeParams.size() == 1) { ct = typeParams.get(0); } else { throw new IllegalArgumentException("Strange Reference type "+rawClass.getName()+": cannot determine type parameters"); } return ReferenceType.construct(rawClass, bindings, superClass, superInterfaces, ct); } /** * Factory method to call when no special {@link JavaType} is needed, * no generic parameters are passed. Default implementation may check * pre-constructed values for "well-known" types, but if none found * will simply call {@link #_newSimpleType} * * @since 2.7 */ protected JavaType _constructSimple(Class raw, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { if (bindings.isEmpty()) { JavaType result = _findWellKnownSimple(raw); if (result != null) { return result; } } return _newSimpleType(raw, bindings, superClass, superInterfaces); } /** * Factory method that is to create a new {@link SimpleType} with no * checks whatsoever. Default implementation calls the single argument * constructor of {@link SimpleType}. * * @since 2.7 */ protected JavaType _newSimpleType(Class raw, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { return new SimpleType(raw, bindings, superClass, superInterfaces); } protected JavaType _unknownType() { /* 15-Sep-2015, tatu: Prior to 2.7, we constructed new instance for each call. * This may have been due to potential mutability of the instance; but that * should not be issue any more, and creation is somewhat wasteful. So let's * try reusing singleton/flyweight instance. */ return CORE_TYPE_OBJECT; } /** * Helper method called to see if requested, non-generic-parameterized * type is one of common, "well-known" types, instances of which are * pre-constructed and do not need dynamic caching. * * @since 2.7 */ protected JavaType _findWellKnownSimple(Class clz) { if (clz.isPrimitive()) { if (clz == CLS_BOOL) return CORE_TYPE_BOOL; if (clz == CLS_INT) return CORE_TYPE_INT; if (clz == CLS_LONG) return CORE_TYPE_LONG; } else { if (clz == CLS_STRING) return CORE_TYPE_STRING; if (clz == CLS_OBJECT) return CORE_TYPE_OBJECT; // since 2.7 } return null; } /* /********************************************************** /* Actual type resolution, traversal /********************************************************** */ /** * Factory method that can be used if type information is passed * as Java typing returned from getGenericXxx methods * (usually for a return or argument type). */ protected JavaType _fromAny(ClassStack context, Type type, TypeBindings bindings) { JavaType resultType; // simple class? if (type instanceof Class) { // Important: remove possible bindings since this is type-erased thingy resultType = _fromClass(context, (Class) type, EMPTY_BINDINGS); } // But if not, need to start resolving. else if (type instanceof ParameterizedType) { resultType = _fromParamType(context, (ParameterizedType) type, bindings); } else if (type instanceof JavaType) { // [databind#116] // no need to modify further if we already had JavaType return (JavaType) type; } else if (type instanceof GenericArrayType) { resultType = _fromArrayType(context, (GenericArrayType) type, bindings); } else if (type instanceof TypeVariable) { resultType = _fromVariable(context, (TypeVariable) type, bindings); } else if (type instanceof WildcardType) { resultType = _fromWildcard(context, (WildcardType) type, bindings); } else { // sanity check throw new IllegalArgumentException("Unrecognized Type: "+((type == null) ? "[null]" : type.toString())); } /* 21-Feb-2016, nateB/tatu: as per [databind#1129] (applied for 2.7.2), * we do need to let all kinds of types to be refined, esp. for Scala module. */ if (_modifiers != null) { TypeBindings b = resultType.getBindings(); if (b == null) { b = EMPTY_BINDINGS; } for (TypeModifier mod : _modifiers) { JavaType t = mod.modifyType(resultType, type, b, this); if (t == null) { throw new IllegalStateException(String.format( "TypeModifier %s (of type %s) return null for type %s", mod, mod.getClass().getName(), resultType)); } resultType = t; } } return resultType; } /** * @param bindings Mapping of formal parameter declarations (for generic * types) into actual types */ protected JavaType _fromClass(ClassStack context, Class rawType, TypeBindings bindings) { // Very first thing: small set of core types we know well: JavaType result = _findWellKnownSimple(rawType); if (result != null) { return result; } // Barring that, we may have recently constructed an instance final Object key; if ((bindings == null) || bindings.isEmpty()) { key = rawType; } else { key = bindings.asKey(rawType); } result = _typeCache.get(key); // ok, cache object is synced if (result != null) { return result; } // 15-Oct-2015, tatu: recursive reference? if (context == null) { context = new ClassStack(rawType); } else { ClassStack prev = context.find(rawType); if (prev != null) { // Self-reference: needs special handling, then... ResolvedRecursiveType selfRef = new ResolvedRecursiveType(rawType, EMPTY_BINDINGS); prev.addSelfReference(selfRef); return selfRef; } // no, but need to update context to allow for proper cycle resolution context = context.child(rawType); } // First: do we have an array type? if (rawType.isArray()) { result = ArrayType.construct(_fromAny(context, rawType.getComponentType(), bindings), bindings); } else { // If not, need to proceed by first resolving parent type hierarchy JavaType superClass; JavaType[] superInterfaces; if (rawType.isInterface()) { superClass = null; superInterfaces = _resolveSuperInterfaces(context, rawType, bindings); } else { // Note: even Enums can implement interfaces, so cannot drop those superClass = _resolveSuperClass(context, rawType, bindings); superInterfaces = _resolveSuperInterfaces(context, rawType, bindings); } // 19-Oct-2015, tatu: Bit messy, but we need to 'fix' java.util.Properties here... if (rawType == Properties.class) { result = MapType.construct(rawType, bindings, superClass, superInterfaces, CORE_TYPE_STRING, CORE_TYPE_STRING); } // And then check what flavor of type we got. Start by asking resolved // super-type if refinement is all that is needed? else if (superClass != null) { result = superClass.refine(rawType, bindings, superClass, superInterfaces); } // if not, perhaps we are now resolving a well-known class or interface? if (result == null) { result = _fromWellKnownClass(context, rawType, bindings, superClass, superInterfaces); if (result == null) { result = _fromWellKnownInterface(context, rawType, bindings, superClass, superInterfaces); if (result == null) { // but if nothing else, "simple" class for now: result = _newSimpleType(rawType, bindings, superClass, superInterfaces); } } } } context.resolveSelfReferences(result); // 16-Jul-2016, tatu: [databind#1302] is solved different way, but ideally we shouldn't // cache anything with partially resolved `ResolvedRecursiveType`... so maybe improve if (!result.hasHandlers()) { _typeCache.putIfAbsent(key, result); // cache object syncs } return result; } protected JavaType _resolveSuperClass(ClassStack context, Class rawType, TypeBindings parentBindings) { Type parent = ClassUtil.getGenericSuperclass(rawType); if (parent == null) { return null; } return _fromAny(context, parent, parentBindings); } protected JavaType[] _resolveSuperInterfaces(ClassStack context, Class rawType, TypeBindings parentBindings) { Type[] types = ClassUtil.getGenericInterfaces(rawType); if (types == null || types.length == 0) { return NO_TYPES; } int len = types.length; JavaType[] resolved = new JavaType[len]; for (int i = 0; i < len; ++i) { Type type = types[i]; resolved[i] = _fromAny(context, type, parentBindings); } return resolved; } /** * Helper class used to check whether exact class for which type is being constructed * is one of well-known base interfaces or classes that indicates alternate * {@link JavaType} implementation. */ protected JavaType _fromWellKnownClass(ClassStack context, Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { if (bindings == null) { bindings = EMPTY_BINDINGS; } // Quite simple when we resolving exact class/interface; start with that if (rawType == Map.class) { return _mapType(rawType, bindings, superClass, superInterfaces); } if (rawType == Collection.class) { return _collectionType(rawType, bindings, superClass, superInterfaces); } // and since 2.6 one referential type if (rawType == AtomicReference.class) { return _referenceType(rawType, bindings, superClass, superInterfaces); } // 01-Nov-2015, tatu: As of 2.7, couple of potential `CollectionLikeType`s (like // `Iterable`, `Iterator`), and `MapLikeType`s (`Map.Entry`) are not automatically // detected, related to difficulties in propagating type upwards (Iterable, for // example, is a weak, tag-on type). They may be detectable in future. return null; } protected JavaType _fromWellKnownInterface(ClassStack context, Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { // But that's not all: may be possible current type actually implements an // interface type. So... final int intCount = superInterfaces.length; for (int i = 0; i < intCount; ++i) { JavaType result = superInterfaces[i].refine(rawType, bindings, superClass, superInterfaces); if (result != null) { return result; } } return null; } /** * This method deals with parameterized types, that is, * first class generic classes. */ protected JavaType _fromParamType(ClassStack context, ParameterizedType ptype, TypeBindings parentBindings) { // Assumption here is we'll always get Class, not one of other Types Class rawType = (Class) ptype.getRawType(); // 29-Oct-2015, tatu: For performance reasons, let's streamline handling of // couple of not-so-useful parametric types if (rawType == CLS_ENUM) { return CORE_TYPE_ENUM; } if (rawType == CLS_COMPARABLE) { return CORE_TYPE_COMPARABLE; } if (rawType == CLS_CLASS) { return CORE_TYPE_CLASS; } // First: what is the actual base type? One odd thing is that 'getRawType' // returns Type, not Class as one might expect. But let's assume it is // always of type Class: if not, need to add more code to resolve it to Class. Type[] args = ptype.getActualTypeArguments(); int paramCount = (args == null) ? 0 : args.length; TypeBindings newBindings; if (paramCount == 0) { newBindings = EMPTY_BINDINGS; } else { JavaType[] pt = new JavaType[paramCount]; for (int i = 0; i < paramCount; ++i) { pt[i] = _fromAny(context, args[i], parentBindings); } newBindings = TypeBindings.create(rawType, pt); } return _fromClass(context, rawType, newBindings); } protected JavaType _fromArrayType(ClassStack context, GenericArrayType type, TypeBindings bindings) { JavaType elementType = _fromAny(context, type.getGenericComponentType(), bindings); return ArrayType.construct(elementType, bindings); } protected JavaType _fromVariable(ClassStack context, TypeVariable var, TypeBindings bindings) { // ideally should find it via bindings: final String name = var.getName(); if (bindings == null) throw new Error("No Bindings!"); JavaType type = bindings.findBoundType(name); if (type != null) { return type; } // but if not, use bounds... note that approach here is simplistic; not taking // into account possible multiple bounds, nor consider upper bounds. if (bindings.hasUnbound(name)) { return CORE_TYPE_OBJECT; } bindings = bindings.withUnboundVariable(name); Type[] bounds = var.getBounds(); return _fromAny(context, bounds[0], bindings); } protected JavaType _fromWildcard(ClassStack context, WildcardType type, TypeBindings bindings) { /* Similar to challenges with TypeVariable, we may have multiple upper bounds. * But it is also possible that if upper bound defaults to Object, we might * want to consider lower bounds instead. * For now, we won't try anything more advanced; above is just for future reference. */ return _fromAny(context, type.getUpperBounds()[0], bindings); } } TypeModifier.java000066400000000000000000000031321325620701100346730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.lang.reflect.Type; import com.fasterxml.jackson.databind.JavaType; /** * Class that defines API that can be used to modify details of * {@link JavaType} instances constructed using {@link TypeFactory}. * Registered modifiers are called in order, to let them modify (or * replace) basic type instance factory constructs. * This is typically needed to support creation of * {@link MapLikeType} and {@link CollectionLikeType} instances, * as those cannot be constructed in generic fashion. */ public abstract class TypeModifier { /** * Method called to let modifier change constructed type definition. * Note that this is only guaranteed to be called for * non-container types ("simple" types not recognized as arrays, * java.util.Collection or java.util.Map). * * @param type Instance to modify * @param jdkType JDK type that was used to construct instance to modify * @param context Type resolution context used for the type * @param typeFactory Type factory that can be used to construct parameter type; note, * however, that care must be taken to avoid infinite loops -- specifically, do not * construct instance of primary type itself * * @return Actual type instance to use; usually either type (as is or with * modifications), or a newly constructed type instance based on it. Cannot be null. */ public abstract JavaType modifyType(JavaType type, Type jdkType, TypeBindings context, TypeFactory typeFactory); } TypeParser.java000066400000000000000000000104551325620701100343770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Simple recursive-descent parser for parsing canonical {@link JavaType} * representations and constructing type instances. */ public class TypeParser implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final TypeFactory _factory; public TypeParser(TypeFactory f) { _factory = f; } /** * @since 2.6.2 */ public TypeParser withFactory(TypeFactory f) { return (f == _factory) ? this : new TypeParser(f); } public JavaType parse(String canonical) throws IllegalArgumentException { MyTokenizer tokens = new MyTokenizer(canonical.trim()); JavaType type = parseType(tokens); // must be end, now if (tokens.hasMoreTokens()) { throw _problem(tokens, "Unexpected tokens after complete type"); } return type; } protected JavaType parseType(MyTokenizer tokens) throws IllegalArgumentException { if (!tokens.hasMoreTokens()) { throw _problem(tokens, "Unexpected end-of-string"); } Class base = findClass(tokens.nextToken(), tokens); // either end (ok, non generic type), or generics if (tokens.hasMoreTokens()) { String token = tokens.nextToken(); if ("<".equals(token)) { List parameterTypes = parseTypes(tokens); TypeBindings b = TypeBindings.create(base, parameterTypes); return _factory._fromClass(null, base, b); } // can be comma that separates types, or closing '>' tokens.pushBack(token); } return _factory._fromClass(null, base, TypeBindings.emptyBindings()); } protected List parseTypes(MyTokenizer tokens) throws IllegalArgumentException { ArrayList types = new ArrayList(); while (tokens.hasMoreTokens()) { types.add(parseType(tokens)); if (!tokens.hasMoreTokens()) break; String token = tokens.nextToken(); if (">".equals(token)) return types; if (!",".equals(token)) { throw _problem(tokens, "Unexpected token '"+token+"', expected ',' or '>')"); } } throw _problem(tokens, "Unexpected end-of-string"); } protected Class findClass(String className, MyTokenizer tokens) { try { return _factory.findClass(className); } catch (Exception e) { ClassUtil.throwIfRTE(e); throw _problem(tokens, "Cannot locate class '"+className+"', problem: "+e.getMessage()); } } protected IllegalArgumentException _problem(MyTokenizer tokens, String msg) { return new IllegalArgumentException(String.format("Failed to parse type '%s' (remaining: '%s'): %s", tokens.getAllInput(), tokens.getRemainingInput(), msg)); } final static class MyTokenizer extends StringTokenizer { protected final String _input; protected int _index; protected String _pushbackToken; public MyTokenizer(String str) { super(str, "<,>", true); _input = str; } @Override public boolean hasMoreTokens() { return (_pushbackToken != null) || super.hasMoreTokens(); } @Override public String nextToken() { String token; if (_pushbackToken != null) { token = _pushbackToken; _pushbackToken = null; } else { token = super.nextToken(); _index += token.length(); token = token.trim(); } return token; } public void pushBack(String token) { _pushbackToken = token; // let's NOT change index for now, since token may have been trim()ed } public String getAllInput() { return _input; } // public String getUsedInput() { return _input.substring(0, _index); } public String getRemainingInput() { return _input.substring(_index); } } } package-info.java000066400000000000000000000007371325620701100346270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/type/** * Package that contains concrete implementations of * {@link com.fasterxml.jackson.databind.JavaType}, as * well as the factory ({@link com.fasterxml.jackson.databind.type.TypeFactory}) for * constructing instances from various input data types * (like {@link java.lang.Class}, {@link java.lang.reflect.Type}) * and programmatically (for structured types, arrays, * {@link java.util.List}s and {@link java.util.Map}s). */ package com.fasterxml.jackson.databind.type; jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/util/000077500000000000000000000000001325620701100315045ustar00rootroot00000000000000AccessPattern.java000066400000000000000000000017361325620701100350360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; /** * Enumeration used to indicate required access pattern for providers: * this can sometimes be used to optimize out dynamic calls. * The main difference is between constant values (which can be resolved once) * and dynamic ones (which must be resolved anew every time). */ public enum AccessPattern { /** * Value that indicates that provider never returns anything other than * Java `null`. */ ALWAYS_NULL, /** * Value that indicates that provider will always return a constant * value, regardless of when it is called; and also that it never * uses `context` argument (which may then be passed as `null`) */ CONSTANT, /** * Value that indicates that provider may return different values * at different times (often a freshly constructed empty container), * and thus must be called every time "null replacement" value is * needed. */ DYNAMIC ; } Annotations.java000066400000000000000000000016131325620701100345660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.lang.annotation.Annotation; /** * Interface that defines interface for accessing contents of a * collection of annotations. This is needed when introspecting * annotation-based features from different kinds of things, not * just objects that Java Reflection interface exposes. *

* Standard mutable implementation is {@link com.fasterxml.jackson.databind.introspect.AnnotationMap} */ public interface Annotations { /** * Main access method used to find value for given annotation. */ public A get(Class cls); /** * @since 2.9 */ public boolean has(Class cls); /** * @since 2.9 */ public boolean hasOneOf(Class[] annoClasses); /** * Returns number of annotation entries in this collection. */ public int size(); } ArrayBuilders.java000066400000000000000000000171461325620701100350510ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.lang.reflect.Array; import java.util.*; /** * Helper class that contains set of distinct builders for different * arrays of primitive values. It also provides trivially simple * reuse scheme, which assumes that caller knows not to use instances * concurrently (which works ok with primitive arrays since they can * not contain other non-primitive types). * Also note that instances are not thread safe; the intent is that * a builder is constructed on per-call (deserialization) basis. */ public final class ArrayBuilders { private BooleanBuilder _booleanBuilder = null; // note: no need for char[] builder, assume they are Strings private ByteBuilder _byteBuilder = null; private ShortBuilder _shortBuilder = null; private IntBuilder _intBuilder = null; private LongBuilder _longBuilder = null; private FloatBuilder _floatBuilder = null; private DoubleBuilder _doubleBuilder = null; public ArrayBuilders() { } public BooleanBuilder getBooleanBuilder() { if (_booleanBuilder == null) { _booleanBuilder = new BooleanBuilder(); } return _booleanBuilder; } public ByteBuilder getByteBuilder() { if (_byteBuilder == null) { _byteBuilder = new ByteBuilder(); } return _byteBuilder; } public ShortBuilder getShortBuilder() { if (_shortBuilder == null) { _shortBuilder = new ShortBuilder(); } return _shortBuilder; } public IntBuilder getIntBuilder() { if (_intBuilder == null) { _intBuilder = new IntBuilder(); } return _intBuilder; } public LongBuilder getLongBuilder() { if (_longBuilder == null) { _longBuilder = new LongBuilder(); } return _longBuilder; } public FloatBuilder getFloatBuilder() { if (_floatBuilder == null) { _floatBuilder = new FloatBuilder(); } return _floatBuilder; } public DoubleBuilder getDoubleBuilder() { if (_doubleBuilder == null) { _doubleBuilder = new DoubleBuilder(); } return _doubleBuilder; } /* /********************************************************** /* Impl classes /********************************************************** */ public final static class BooleanBuilder extends PrimitiveArrayBuilder { public BooleanBuilder() { } @Override public final boolean[] _constructArray(int len) { return new boolean[len]; } } public final static class ByteBuilder extends PrimitiveArrayBuilder { public ByteBuilder() { } @Override public final byte[] _constructArray(int len) { return new byte[len]; } } public final static class ShortBuilder extends PrimitiveArrayBuilder { public ShortBuilder() { } @Override public final short[] _constructArray(int len) { return new short[len]; } } public final static class IntBuilder extends PrimitiveArrayBuilder { public IntBuilder() { } @Override public final int[] _constructArray(int len) { return new int[len]; } } public final static class LongBuilder extends PrimitiveArrayBuilder { public LongBuilder() { } @Override public final long[] _constructArray(int len) { return new long[len]; } } public final static class FloatBuilder extends PrimitiveArrayBuilder { public FloatBuilder() { } @Override public final float[] _constructArray(int len) { return new float[len]; } } public final static class DoubleBuilder extends PrimitiveArrayBuilder { public DoubleBuilder() { } @Override public final double[] _constructArray(int len) { return new double[len]; } } /* /********************************************************** /* Static helper methods /********************************************************** */ /** * Helper method used for constructing simple value comparator used for * comparing arrays for content equality. *

* Note: current implementation is not optimized for speed; if performance * ever becomes an issue, it is possible to construct much more efficient * typed instances (one for Object[] and sub-types; one per primitive type). * * @since 2.2 Moved from earlier Comparators class */ public static Object getArrayComparator(final Object defaultValue) { final int length = Array.getLength(defaultValue); final Class defaultValueType = defaultValue.getClass(); return new Object() { @Override public boolean equals(Object other) { if (other == this) return true; if (!ClassUtil.hasClass(other, defaultValueType)) { return false; } if (Array.getLength(other) != length) return false; // so far so good: compare actual equality; but only shallow one for (int i = 0; i < length; ++i) { Object value1 = Array.get(defaultValue, i); Object value2 = Array.get(other, i); if (value1 == value2) continue; if (value1 != null) { if (!value1.equals(value2)) { return false; } } } return true; } }; } public static HashSet arrayToSet(T[] elements) { if (elements != null) { int len = elements.length; HashSet result = new HashSet(len); for (int i = 0; i < len; ++i) { result.add(elements[i]); } return result; } return new HashSet(); } /** * Helper method for constructing a new array that contains specified * element followed by contents of the given array but never contains * duplicates. * If element already existed, one of two things happens: if the element * was already the first one in array, array is returned as is; but * if not, a new copy is created in which element has moved as the head. */ @SuppressWarnings("unchecked") public static T[] insertInListNoDup(T[] array, T element) { final int len = array.length; // First: see if the element already exists for (int ix = 0; ix < len; ++ix) { if (array[ix] == element) { // if at head already, return as is if (ix == 0) { return array; } // otherwise move things around T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len); System.arraycopy(array, 0, result, 1, ix); result[0] = element; ++ix; int left = len - ix; if (left > 0) { System.arraycopy(array, ix, result, ix, left); } return result; } } // but if not, allocate new array, move T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len+1); if (len > 0) { System.arraycopy(array, 0, result, 1, len); } result[0] = element; return result; } } ArrayIterator.java000066400000000000000000000014551325620701100350650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.Iterator; import java.util.NoSuchElementException; /** * Iterator implementation used to efficiently expose contents of an * Array as read-only iterator. */ public class ArrayIterator implements Iterator, Iterable { private final T[] _a; private int _index; public ArrayIterator(T[] a) { _a = a; _index = 0; } @Override public boolean hasNext() { return _index < _a.length; } @Override public T next() { if (_index >= _a.length) { throw new NoSuchElementException(); } return _a[_index++]; } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public Iterator iterator() { return this; } }BeanUtil.java000066400000000000000000000242261325620701100340010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; /** * Helper class that contains functionality needed by both serialization * and deserialization side. */ public class BeanUtil { /* /********************************************************** /* Handling property names /********************************************************** */ /** * @since 2.5 */ public static String okNameForGetter(AnnotatedMethod am, boolean stdNaming) { String name = am.getName(); String str = okNameForIsGetter(am, name, stdNaming); if (str == null) { str = okNameForRegularGetter(am, name, stdNaming); } return str; } /** * @since 2.5 */ public static String okNameForRegularGetter(AnnotatedMethod am, String name, boolean stdNaming) { if (name.startsWith("get")) { /* 16-Feb-2009, tatu: To handle [JACKSON-53], need to block * CGLib-provided method "getCallbacks". Not sure of exact * safe criteria to get decent coverage without false matches; * but for now let's assume there's no reason to use any * such getter from CGLib. * But let's try this approach... */ if ("getCallbacks".equals(name)) { if (isCglibGetCallbacks(am)) { return null; } } else if ("getMetaClass".equals(name)) { // 30-Apr-2009, tatu: Need to suppress serialization of a cyclic reference if (isGroovyMetaClassGetter(am)) { return null; } } return stdNaming ? stdManglePropertyName(name, 3) : legacyManglePropertyName(name, 3); } return null; } /** * @since 2.5 */ public static String okNameForIsGetter(AnnotatedMethod am, String name, boolean stdNaming) { if (name.startsWith("is")) { // plus, must return a boolean Class rt = am.getRawType(); if (rt == Boolean.class || rt == Boolean.TYPE) { return stdNaming ? stdManglePropertyName(name, 2) : legacyManglePropertyName(name, 2); } } return null; } /** * @since 2.5 */ @Deprecated // since 2.9, not used any more public static String okNameForSetter(AnnotatedMethod am, boolean stdNaming) { String name = okNameForMutator(am, "set", stdNaming); if ((name != null) // 26-Nov-2009, tatu: need to suppress this internal groovy method && (!"metaClass".equals(name) || !isGroovyMetaClassSetter(am))) { return name; } return null; } /** * @since 2.5 */ public static String okNameForMutator(AnnotatedMethod am, String prefix, boolean stdNaming) { String name = am.getName(); if (name.startsWith(prefix)) { return stdNaming ? stdManglePropertyName(name, prefix.length()) : legacyManglePropertyName(name, prefix.length()); } return null; } /* /********************************************************** /* Value defaulting helpers /********************************************************** */ /** * Accessor used to find out "default value" to use for comparing values to * serialize, to determine whether to exclude value from serialization with * inclusion type of {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_DEFAULT}. *

* Default logic is such that for primitives and wrapper types for primitives, expected * defaults (0 for `int` and `java.lang.Integer`) are returned; for Strings, empty String, * and for structured (Maps, Collections, arrays) and reference types, criteria * {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_DEFAULT} * is used. * * @since 2.7 */ public static Object getDefaultValue(JavaType type) { // 06-Nov-2015, tatu: Returning null is fine for Object types; but need special // handling for primitives since they are never passed as nulls. Class cls = type.getRawClass(); // 30-Sep-2016, tatu: Also works for Wrappers, so both `Integer.TYPE` and `Integer.class` // would return `Integer.TYPE` Class prim = ClassUtil.primitiveType(cls); if (prim != null) { return ClassUtil.defaultValue(prim); } if (type.isContainerType() || type.isReferenceType()) { return JsonInclude.Include.NON_EMPTY; } if (cls == String.class) { return ""; } // 09-Mar-2016, tatu: Not sure how far this path we want to go but for now // let's add `java.util.Date` and `java.util.Calendar`, as per [databind#1550] if (type.isTypeOrSubTypeOf(Date.class)) { return new Date(0L); } if (type.isTypeOrSubTypeOf(Calendar.class)) { Calendar c = new GregorianCalendar(); c.setTimeInMillis(0L); return c; } return null; } /* /********************************************************** /* Special case handling /********************************************************** */ /** * This method was added to address the need to weed out * CGLib-injected "getCallbacks" method. * At this point caller has detected a potential getter method * with name "getCallbacks" and we need to determine if it is * indeed injectect by Cglib. We do this by verifying that the * result type is "net.sf.cglib.proxy.Callback[]" */ protected static boolean isCglibGetCallbacks(AnnotatedMethod am) { Class rt = am.getRawType(); // Ok, first: must return an array type if (rt.isArray()) { /* And that type needs to be "net.sf.cglib.proxy.Callback". * Theoretically could just be a type that implements it, but * for now let's keep things simple, fix if need be. */ Class compType = rt.getComponentType(); // Actually, let's just verify it's a "net.sf.cglib.*" class/interface String pkgName = ClassUtil.getPackageName(compType); if (pkgName != null) { if (pkgName.contains(".cglib")) { return pkgName.startsWith("net.sf.cglib") // also, as per [JACKSON-177] || pkgName.startsWith("org.hibernate.repackage.cglib") // and [core#674] || pkgName.startsWith("org.springframework.cglib"); } } } return false; } /** * Similar to {@link #isCglibGetCallbacks}, need to suppress * a cyclic reference. */ protected static boolean isGroovyMetaClassSetter(AnnotatedMethod am) { Class argType = am.getRawParameterType(0); String pkgName = ClassUtil.getPackageName(argType); return (pkgName != null) && pkgName.startsWith("groovy.lang"); } /** * Another helper method to deal with Groovy's problematic metadata accessors */ protected static boolean isGroovyMetaClassGetter(AnnotatedMethod am) { String pkgName = ClassUtil.getPackageName(am.getRawType()); return (pkgName != null) && pkgName.startsWith("groovy.lang"); } /* /********************************************************** /* Actual name mangling methods /********************************************************** */ /** * Method called to figure out name of the property, given * corresponding suggested name based on a method or field name. * * @param basename Name of accessor/mutator method, not including prefix * ("get"/"is"/"set") */ protected static String legacyManglePropertyName(final String basename, final int offset) { final int end = basename.length(); if (end == offset) { // empty name, nope return null; } // next check: is the first character upper case? If not, return as is char c = basename.charAt(offset); char d = Character.toLowerCase(c); if (c == d) { return basename.substring(offset); } // otherwise, lower case initial chars. Common case first, just one char StringBuilder sb = new StringBuilder(end - offset); sb.append(d); int i = offset+1; for (; i < end; ++i) { c = basename.charAt(i); d = Character.toLowerCase(c); if (c == d) { sb.append(basename, i, end); break; } sb.append(d); } return sb.toString(); } /** * @since 2.5 */ protected static String stdManglePropertyName(final String basename, final int offset) { final int end = basename.length(); if (end == offset) { // empty name, nope return null; } // first: if it doesn't start with capital, return as-is char c0 = basename.charAt(offset); char c1 = Character.toLowerCase(c0); if (c0 == c1) { return basename.substring(offset); } // 17-Dec-2014, tatu: As per [databind#653], need to follow more // closely Java Beans spec; specifically, if two first are upper-case, // then no lower-casing should be done. if ((offset + 1) < end) { if (Character.isUpperCase(basename.charAt(offset+1))) { return basename.substring(offset); } } StringBuilder sb = new StringBuilder(end - offset); sb.append(c1); sb.append(basename, offset+1, end); return sb.toString(); } } ByteBufferBackedInputStream.java000066400000000000000000000015051325620701100376140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; /** * Simple {@link InputStream} implementation that exposes currently * available content of a {@link ByteBuffer}. */ public class ByteBufferBackedInputStream extends InputStream { protected final ByteBuffer _b; public ByteBufferBackedInputStream(ByteBuffer buf) { _b = buf; } @Override public int available() { return _b.remaining(); } @Override public int read() throws IOException { return _b.hasRemaining() ? (_b.get() & 0xFF) : -1; } @Override public int read(byte[] bytes, int off, int len) throws IOException { if (!_b.hasRemaining()) return -1; len = Math.min(len, _b.remaining()); _b.get(bytes, off, len); return len; } }ByteBufferBackedOutputStream.java000066400000000000000000000011071325620701100400130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.*; import java.nio.ByteBuffer; /** * Simple {@link OutputStream} implementation that appends content * written in given {@link ByteBuffer} instance. */ public class ByteBufferBackedOutputStream extends OutputStream { protected final ByteBuffer _b; public ByteBufferBackedOutputStream(ByteBuffer buf) { _b = buf; } @Override public void write(int b) throws IOException { _b.put((byte) b); } @Override public void write(byte[] bytes, int off, int len) throws IOException { _b.put(bytes, off, len); } } ClassUtil.java000066400000000000000000001224071325620701100342010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.Closeable; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.*; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; public final class ClassUtil { private final static Class CLS_OBJECT = Object.class; private final static Annotation[] NO_ANNOTATIONS = new Annotation[0]; private final static Ctor[] NO_CTORS = new Ctor[0]; private final static Iterator EMPTY_ITERATOR = Collections.emptyIterator(); /* /********************************************************** /* Simple factory methods /********************************************************** */ /** * @since 2.7 */ @SuppressWarnings("unchecked") public static Iterator emptyIterator() { return (Iterator) EMPTY_ITERATOR; } /* /********************************************************** /* Methods that deal with inheritance /********************************************************** */ /** * Method that will find all sub-classes and implemented interfaces * of a given class or interface. Classes are listed in order of * precedence, starting with the immediate super-class, followed by * interfaces class directly declares to implemented, and then recursively * followed by parent of super-class and so forth. * Note that Object.class is not included in the list * regardless of whether endBefore argument is defined or not. * * @param endBefore Super-type to NOT include in results, if any; when * encountered, will be ignored (and no super types are checked). * * @since 2.7 */ public static List findSuperTypes(JavaType type, Class endBefore, boolean addClassItself) { if ((type == null) || type.hasRawClass(endBefore) || type.hasRawClass(Object.class)) { return Collections.emptyList(); } List result = new ArrayList(8); _addSuperTypes(type, endBefore, result, addClassItself); return result; } /** * @since 2.7 */ public static List> findRawSuperTypes(Class cls, Class endBefore, boolean addClassItself) { if ((cls == null) || (cls == endBefore) || (cls == Object.class)) { return Collections.emptyList(); } List> result = new ArrayList>(8); _addRawSuperTypes(cls, endBefore, result, addClassItself); return result; } /** * Method for finding all super classes (but not super interfaces) of given class, * starting with the immediate super class and ending in the most distant one. * Class itself is included if addClassItself is true. * * @since 2.7 */ public static List> findSuperClasses(Class cls, Class endBefore, boolean addClassItself) { List> result = new LinkedList>(); if ((cls != null) && (cls != endBefore)) { if (addClassItself) { result.add(cls); } while ((cls = cls.getSuperclass()) != null) { if (cls == endBefore) { break; } result.add(cls); } } return result; } @Deprecated // since 2.7 public static List> findSuperTypes(Class cls, Class endBefore) { return findSuperTypes(cls, endBefore, new ArrayList>(8)); } @Deprecated // since 2.7 public static List> findSuperTypes(Class cls, Class endBefore, List> result) { _addRawSuperTypes(cls, endBefore, result, false); return result; } private static void _addSuperTypes(JavaType type, Class endBefore, Collection result, boolean addClassItself) { if (type == null) { return; } final Class cls = type.getRawClass(); if (cls == endBefore || cls == Object.class) { return; } if (addClassItself) { if (result.contains(type)) { // already added, no need to check supers return; } result.add(type); } for (JavaType intCls : type.getInterfaces()) { _addSuperTypes(intCls, endBefore, result, true); } _addSuperTypes(type.getSuperClass(), endBefore, result, true); } private static void _addRawSuperTypes(Class cls, Class endBefore, Collection> result, boolean addClassItself) { if (cls == endBefore || cls == null || cls == Object.class) { return; } if (addClassItself) { if (result.contains(cls)) { // already added, no need to check supers return; } result.add(cls); } for (Class intCls : _interfaces(cls)) { _addRawSuperTypes(intCls, endBefore, result, true); } _addRawSuperTypes(cls.getSuperclass(), endBefore, result, true); } /* /********************************************************** /* Class type detection methods /********************************************************** */ /** * @return Null if class might be a bean; type String (that identifies * why it's not a bean) if not */ public static String canBeABeanType(Class type) { // First: language constructs that ain't beans: if (type.isAnnotation()) { return "annotation"; } if (type.isArray()) { return "array"; } if (type.isEnum()) { return "enum"; } if (type.isPrimitive()) { return "primitive"; } // Anything else? Seems valid, then return null; } public static String isLocalType(Class type, boolean allowNonStatic) { /* As per [JACKSON-187], GAE seems to throw SecurityExceptions * here and there... and GAE itself has a bug, too * (see []). Bah. So we need to catch some wayward exceptions on GAE */ try { // one more: method locals, anonymous, are not good: if (hasEnclosingMethod(type)) { return "local/anonymous"; } /* But how about non-static inner classes? Can't construct * easily (theoretically, we could try to check if parent * happens to be enclosing... but that gets convoluted) */ if (!allowNonStatic) { if (!Modifier.isStatic(type.getModifiers())) { if (getEnclosingClass(type) != null) { return "non-static member class"; } } } } catch (SecurityException e) { } catch (NullPointerException e) { } return null; } /** * Method for finding enclosing class for non-static inner classes */ public static Class getOuterClass(Class type) { // as above, GAE has some issues... try { // one more: method locals, anonymous, are not good: if (hasEnclosingMethod(type)) { return null; } if (!Modifier.isStatic(type.getModifiers())) { return getEnclosingClass(type); } } catch (SecurityException e) { } return null; } /** * Helper method used to weed out dynamic Proxy types; types that do * not expose concrete method API that we could use to figure out * automatic Bean (property) based serialization. */ public static boolean isProxyType(Class type) { // As per [databind#57], should NOT disqualify JDK proxy: /* // Then: well-known proxy (etc) classes if (Proxy.isProxyClass(type)) { return true; } */ String name = type.getName(); // Hibernate uses proxies heavily as well: if (name.startsWith("net.sf.cglib.proxy.") || name.startsWith("org.hibernate.proxy.")) { return true; } // Not one of known proxies, nope: return false; } /** * Helper method that checks if given class is a concrete one; * that is, not an interface or abstract class. */ public static boolean isConcrete(Class type) { int mod = type.getModifiers(); return (mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0; } public static boolean isConcrete(Member member) { int mod = member.getModifiers(); return (mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0; } public static boolean isCollectionMapOrArray(Class type) { if (type.isArray()) return true; if (Collection.class.isAssignableFrom(type)) return true; if (Map.class.isAssignableFrom(type)) return true; return false; } public static boolean isBogusClass(Class cls) { return (cls == Void.class || cls == Void.TYPE || cls == com.fasterxml.jackson.databind.annotation.NoClass.class); } public static boolean isNonStaticInnerClass(Class cls) { return !Modifier.isStatic(cls.getModifiers()) && (getEnclosingClass(cls) != null); } /** * @since 2.7 */ public static boolean isObjectOrPrimitive(Class cls) { return (cls == CLS_OBJECT) || cls.isPrimitive(); } /** * @since 2.9 */ public static boolean hasClass(Object inst, Class raw) { // 10-Nov-2016, tatu: Could use `Class.isInstance()` if we didn't care // about being exactly that type return (inst != null) && (inst.getClass() == raw); } /** * @since 2.9 */ public static void verifyMustOverride(Class expType, Object instance, String method) { if (instance.getClass() != expType) { throw new IllegalStateException(String.format( "Sub-class %s (of class %s) must override method '%s'", instance.getClass().getName(), expType.getName(), method)); } } /* /********************************************************** /* Method type detection methods /********************************************************** */ /** * @deprecated Since 2.6 not used; may be removed before 3.x */ @Deprecated // since 2.6 public static boolean hasGetterSignature(Method m) { // First: static methods can't be getters if (Modifier.isStatic(m.getModifiers())) { return false; } // Must take no args Class[] pts = m.getParameterTypes(); if (pts != null && pts.length != 0) { return false; } // Can't be a void method if (Void.TYPE == m.getReturnType()) { return false; } // Otherwise looks ok: return true; } /* /********************************************************** /* Exception handling; simple re-throw /********************************************************** */ /** * Helper method that will check if argument is an {@link Error}, * and if so, (re)throw it; otherwise just return * * @since 2.9 */ public static Throwable throwIfError(Throwable t) { if (t instanceof Error) { throw (Error) t; } return t; } /** * Helper method that will check if argument is an {@link RuntimeException}, * and if so, (re)throw it; otherwise just return * * @since 2.9 */ public static Throwable throwIfRTE(Throwable t) { if (t instanceof RuntimeException) { throw (RuntimeException) t; } return t; } /** * Helper method that will check if argument is an {@link IOException}, * and if so, (re)throw it; otherwise just return * * @since 2.9 */ public static Throwable throwIfIOE(Throwable t) throws IOException { if (t instanceof IOException) { throw (IOException) t; } return t; } /* /********************************************************** /* Exception handling; other /********************************************************** */ /** * Method that can be used to find the "root cause", innermost * of chained (wrapped) exceptions. */ public static Throwable getRootCause(Throwable t) { while (t.getCause() != null) { t = t.getCause(); } return t; } /** * Method that works like by calling {@link #getRootCause} and then * either throwing it (if instanceof {@link IOException}), or * return. * * @since 2.8 */ public static Throwable throwRootCauseIfIOE(Throwable t) throws IOException { return throwIfIOE(getRootCause(t)); } /** * Method that will wrap 't' as an {@link IllegalArgumentException} if it * is a checked exception; otherwise (runtime exception or error) throw as is */ public static void throwAsIAE(Throwable t) { throwAsIAE(t, t.getMessage()); } /** * Method that will wrap 't' as an {@link IllegalArgumentException} (and with * specified message) if it * is a checked exception; otherwise (runtime exception or error) throw as is */ public static void throwAsIAE(Throwable t, String msg) { throwIfRTE(t); throwIfError(t); throw new IllegalArgumentException(msg, t); } /** * @since 2.9 */ public static T throwAsMappingException(DeserializationContext ctxt, IOException e0) throws JsonMappingException { if (e0 instanceof JsonMappingException) { throw (JsonMappingException) e0; } JsonMappingException e = JsonMappingException.from(ctxt, e0.getMessage()); e.initCause(e0); throw e; } /** * Method that will locate the innermost exception for given Throwable; * and then wrap it as an {@link IllegalArgumentException} if it * is a checked exception; otherwise (runtime exception or error) throw as is */ public static void unwrapAndThrowAsIAE(Throwable t) { throwAsIAE(getRootCause(t)); } /** * Method that will locate the innermost exception for given Throwable; * and then wrap it as an {@link IllegalArgumentException} if it * is a checked exception; otherwise (runtime exception or error) throw as is */ public static void unwrapAndThrowAsIAE(Throwable t, String msg) { throwAsIAE(getRootCause(t), msg); } /** * Helper method that encapsulate logic in trying to close output generator * in case of failure; useful mostly in forcing flush()ing as otherwise * error conditions tend to be hard to diagnose. However, it is often the * case that output state may be corrupt so we need to be prepared for * secondary exception without masking original one. * * @since 2.8 */ public static void closeOnFailAndThrowAsIOE(JsonGenerator g, Exception fail) throws IOException { /* 04-Mar-2014, tatu: Let's try to prevent auto-closing of * structures, which typically causes more damage. */ g.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT); try { g.close(); } catch (Exception e) { fail.addSuppressed(e); } throwIfIOE(fail); throwIfRTE(fail); throw new RuntimeException(fail); } /** * Helper method that encapsulate logic in trying to close given {@link Closeable} * in case of failure; useful mostly in forcing flush()ing as otherwise * error conditions tend to be hard to diagnose. However, it is often the * case that output state may be corrupt so we need to be prepared for * secondary exception without masking original one. * * @since 2.8 */ public static void closeOnFailAndThrowAsIOE(JsonGenerator g, Closeable toClose, Exception fail) throws IOException { if (g != null) { g.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT); try { g.close(); } catch (Exception e) { fail.addSuppressed(e); } } if (toClose != null) { try { toClose.close(); } catch (Exception e) { fail.addSuppressed(e); } } throwIfIOE(fail); throwIfRTE(fail); throw new RuntimeException(fail); } /* /********************************************************** /* Instantiation /********************************************************** */ /** * Method that can be called to try to create an instantiate of * specified type. Instantiation is done using default no-argument * constructor. * * @param canFixAccess Whether it is possible to try to change access * rights of the default constructor (in case it is not publicly * accessible) or not. * * @throws IllegalArgumentException If instantiation fails for any reason; * except for cases where constructor throws an unchecked exception * (which will be passed as is) */ public static T createInstance(Class cls, boolean canFixAccess) throws IllegalArgumentException { Constructor ctor = findConstructor(cls, canFixAccess); if (ctor == null) { throw new IllegalArgumentException("Class "+cls.getName()+" has no default (no arg) constructor"); } try { return ctor.newInstance(); } catch (Exception e) { ClassUtil.unwrapAndThrowAsIAE(e, "Failed to instantiate class "+cls.getName()+", problem: "+e.getMessage()); return null; } } public static Constructor findConstructor(Class cls, boolean forceAccess) throws IllegalArgumentException { try { Constructor ctor = cls.getDeclaredConstructor(); if (forceAccess) { checkAndFixAccess(ctor, forceAccess); } else { // Has to be public... if (!Modifier.isPublic(ctor.getModifiers())) { throw new IllegalArgumentException("Default constructor for "+cls.getName()+" is not accessible (non-public?): not allowed to try modify access via Reflection: cannot instantiate type"); } } return ctor; } catch (NoSuchMethodException e) { ; } catch (Exception e) { ClassUtil.unwrapAndThrowAsIAE(e, "Failed to find default constructor of class "+cls.getName()+", problem: "+e.getMessage()); } return null; } /* /********************************************************** /* Class name, description access /********************************************************** */ /** * @since 2.9 */ public static Class classOf(Object inst) { if (inst == null) { return null; } return inst.getClass(); } /** * @since 2.9 */ public static Class rawClass(JavaType t) { if (t == null) { return null; } return t.getRawClass(); } /** * @since 2.9 */ public static T nonNull(T valueOrNull, T defaultValue) { return (valueOrNull == null) ? defaultValue : valueOrNull; } /** * @since 2.9 */ public static String nullOrToString(Object value) { if (value == null) { return null; } return value.toString(); } /** * @since 2.9 */ public static String nonNullString(String str) { if (str == null) { return ""; } return str; } /** * Returns either quoted value (with double-quotes) -- if argument non-null * String -- or String NULL (no quotes) (if null). * * @since 2.9 */ public static String quotedOr(Object str, String forNull) { if (str == null) { return forNull; } return String.format("\"%s\"", str); } /* /********************************************************** /* Type name, name, desc handling methods /********************************************************** */ /** * Helper method used to construct appropriate description * when passed either type (Class) or an instance; in latter * case, class of instance is to be used. */ public static String getClassDescription(Object classOrInstance) { if (classOrInstance == null) { return "unknown"; } Class cls = (classOrInstance instanceof Class) ? (Class) classOrInstance : classOrInstance.getClass(); return nameOf(cls); } /** * Helper method used to construct appropriate description * when passed either type (Class) or an instance; in latter * case, class of instance is to be used. * * @since 2.9 */ public static String classNameOf(Object inst) { if (inst == null) { return "[null]"; } return nameOf(inst.getClass()); } /** * Returns either `cls.getName()` (if `cls` not null), * or "[null]" if `cls` is null. * * @since 2.9 */ public static String nameOf(Class cls) { if (cls == null) { return "[null]"; } int index = 0; while (cls.isArray()) { ++index; cls = cls.getComponentType(); } String base = cls.isPrimitive() ? cls.getSimpleName() : cls.getName(); if (index > 0) { StringBuilder sb = new StringBuilder(base); do { sb.append("[]"); } while (--index > 0); base = sb.toString(); } return backticked(base); } /** * Returns either backtick-quoted `named.getName()` (if `named` not null), * or "[null]" if `named` is null. * * @since 2.9 */ public static String nameOf(Named named) { if (named == null) { return "[null]"; } return backticked(named.getName()); } /** * Returns either `text` or [null]. * * @since 2.9 */ public static String backticked(String text) { if (text == null) { return "[null]"; } return new StringBuilder(text.length()+2).append('`').append(text).append('`').toString(); } /* /********************************************************** /* Primitive type support /********************************************************** */ /** * Helper method used to get default value for wrappers used for primitive types * (0 for Integer etc) */ public static Object defaultValue(Class cls) { if (cls == Integer.TYPE) { return Integer.valueOf(0); } if (cls == Long.TYPE) { return Long.valueOf(0L); } if (cls == Boolean.TYPE) { return Boolean.FALSE; } if (cls == Double.TYPE) { return Double.valueOf(0.0); } if (cls == Float.TYPE) { return Float.valueOf(0.0f); } if (cls == Byte.TYPE) { return Byte.valueOf((byte) 0); } if (cls == Short.TYPE) { return Short.valueOf((short) 0); } if (cls == Character.TYPE) { return '\0'; } throw new IllegalArgumentException("Class "+cls.getName()+" is not a primitive type"); } /** * Helper method for finding wrapper type for given primitive type (why isn't * there one in JDK?) */ public static Class wrapperType(Class primitiveType) { if (primitiveType == Integer.TYPE) { return Integer.class; } if (primitiveType == Long.TYPE) { return Long.class; } if (primitiveType == Boolean.TYPE) { return Boolean.class; } if (primitiveType == Double.TYPE) { return Double.class; } if (primitiveType == Float.TYPE) { return Float.class; } if (primitiveType == Byte.TYPE) { return Byte.class; } if (primitiveType == Short.TYPE) { return Short.class; } if (primitiveType == Character.TYPE) { return Character.class; } throw new IllegalArgumentException("Class "+primitiveType.getName()+" is not a primitive type"); } /** * Method that can be used to find primitive type for given class if (but only if) * it is either wrapper type or primitive type; returns `null` if type is neither. * * @since 2.7 */ public static Class primitiveType(Class type) { if (type.isPrimitive()) { return type; } if (type == Integer.class) { return Integer.TYPE; } if (type == Long.class) { return Long.TYPE; } if (type == Boolean.class) { return Boolean.TYPE; } if (type == Double.class) { return Double.TYPE; } if (type == Float.class) { return Float.TYPE; } if (type == Byte.class) { return Byte.TYPE; } if (type == Short.class) { return Short.TYPE; } if (type == Character.class) { return Character.TYPE; } return null; } /* /********************************************************** /* Access checking/handling methods /********************************************************** */ /** * Equivalent to call: *

     *   checkAndFixAccess(member, false);
     *
* * @deprecated Since 2.7 call variant that takes boolean flag. */ @Deprecated public static void checkAndFixAccess(Member member) { checkAndFixAccess(member, false); } /** * Method that is called if a {@link Member} may need forced access, * to force a field, method or constructor to be accessible: this * is done by calling {@link AccessibleObject#setAccessible(boolean)}. * * @param member Accessor to call setAccessible() on. * @param force Whether to always try to make accessor accessible (true), * or only if needed as per access rights (false) * * @since 2.7 */ public static void checkAndFixAccess(Member member, boolean force) { // We know all members are also accessible objects... AccessibleObject ao = (AccessibleObject) member; /* 14-Jan-2009, tatu: It seems safe and potentially beneficial to * always to make it accessible (latter because it will force * skipping checks we have no use for...), so let's always call it. */ try { if (force || (!Modifier.isPublic(member.getModifiers()) || !Modifier.isPublic(member.getDeclaringClass().getModifiers()))) { ao.setAccessible(true); } } catch (SecurityException se) { // 17-Apr-2009, tatu: Related to [JACKSON-101]: this can fail on platforms like // Google App Engine); so let's only fail if we really needed it... if (!ao.isAccessible()) { Class declClass = member.getDeclaringClass(); throw new IllegalArgumentException("Cannot access "+member+" (from class "+declClass.getName()+"; failed to set access: "+se.getMessage()); } } } /* /********************************************************** /* Enum type detection /********************************************************** */ /** * Helper method that can be used to dynamically figure out * enumeration type of given {@link EnumSet}, without having * access to its declaration. * Code is needed to work around design flaw in JDK. */ public static Class> findEnumType(EnumSet s) { // First things first: if not empty, easy to determine if (!s.isEmpty()) { return findEnumType(s.iterator().next()); } // Otherwise need to locate using an internal field return EnumTypeLocator.instance.enumTypeFor(s); } /** * Helper method that can be used to dynamically figure out * enumeration type of given {@link EnumSet}, without having * access to its declaration. * Code is needed to work around design flaw in JDK. */ public static Class> findEnumType(EnumMap m) { if (!m.isEmpty()) { return findEnumType(m.keySet().iterator().next()); } // Otherwise need to locate using an internal field return EnumTypeLocator.instance.enumTypeFor(m); } /** * Helper method that can be used to dynamically figure out formal * enumeration type (class) for given enumeration. This is either * class of enum instance (for "simple" enumerations), or its * superclass (for enums with instance fields or methods) */ @SuppressWarnings("unchecked") public static Class> findEnumType(Enum en) { // enums with "body" are sub-classes of the formal type Class ec = en.getClass(); if (ec.getSuperclass() != Enum.class) { ec = ec.getSuperclass(); } return (Class>) ec; } /** * Helper method that can be used to dynamically figure out formal * enumeration type (class) for given class of an enumeration value. * This is either class of enum instance (for "simple" enumerations), * or its superclass (for enums with instance fields or methods) */ @SuppressWarnings("unchecked") public static Class> findEnumType(Class cls) { // enums with "body" are sub-classes of the formal type if (cls.getSuperclass() != Enum.class) { cls = cls.getSuperclass(); } return (Class>) cls; } /** * A method that will look for the first Enum value annotated with the given Annotation. *

* If there's more than one value annotated, the first one found will be returned. Which one exactly is used is undetermined. * * @param enumClass The Enum class to scan for a value with the given annotation * @param annotationClass The annotation to look for. * @return the Enum value annotated with the given Annotation or {@code null} if none is found. * @throws IllegalArgumentException if there's a reflection issue accessing the Enum * @since 2.8 */ public static Enum findFirstAnnotatedEnumValue(Class> enumClass, Class annotationClass) { Field[] fields = getDeclaredFields(enumClass); for (Field field : fields) { if (field.isEnumConstant()) { Annotation defaultValueAnnotation = field.getAnnotation(annotationClass); if (defaultValueAnnotation != null) { final String name = field.getName(); for (Enum enumValue : enumClass.getEnumConstants()) { if (name.equals(enumValue.name())) { return enumValue; } } } } } return null; } /* /********************************************************** /* Jackson-specific stuff /********************************************************** */ /** * Method that can be called to determine if given Object is the default * implementation Jackson uses; as opposed to a custom serializer installed by * a module or calling application. Determination is done using * {@link JacksonStdImpl} annotation on handler (serializer, deserializer etc) * class. *

* NOTE: passing `null` is legal, and will result in true * being returned. */ public static boolean isJacksonStdImpl(Object impl) { return (impl == null) || isJacksonStdImpl(impl.getClass()); } public static boolean isJacksonStdImpl(Class implClass) { return (implClass.getAnnotation(JacksonStdImpl.class) != null); } /* /********************************************************** /* Access to various Class definition aspects; possibly /* cacheable; and attempts was made in 2.7.0 - 2.7.7; however /* unintented retention (~= memory leak) wrt [databind#1363] /* resulted in removal of caching /********************************************************** */ /** * @since 2.7 */ public static String getPackageName(Class cls) { Package pkg = cls.getPackage(); return (pkg == null) ? null : pkg.getName(); } /** * @since 2.7 */ public static boolean hasEnclosingMethod(Class cls) { return !isObjectOrPrimitive(cls) && (cls.getEnclosingMethod() != null); } /** * @since 2.7 */ public static Field[] getDeclaredFields(Class cls) { return cls.getDeclaredFields(); } /** * @since 2.7 */ public static Method[] getDeclaredMethods(Class cls) { return cls.getDeclaredMethods(); } /** * @since 2.7 */ public static Annotation[] findClassAnnotations(Class cls) { if (isObjectOrPrimitive(cls)) { return NO_ANNOTATIONS; } return cls.getDeclaredAnnotations(); } /** * Helper method that gets methods declared in given class; usually a simple thing, * but sometimes (as per [databind#785]) more complicated, depending on classloader * setup. * * @since 2.9 */ public static Method[] getClassMethods(Class cls) { try { return ClassUtil.getDeclaredMethods(cls); } catch (final NoClassDefFoundError ex) { // One of the methods had a class that was not found in the cls.getClassLoader. // Maybe the developer was nice and has a different class loader for this context. final ClassLoader loader = Thread.currentThread().getContextClassLoader(); if (loader == null){ // Nope... this is going to end poorly throw ex; } final Class contextClass; try { contextClass = loader.loadClass(cls.getName()); } catch (ClassNotFoundException e) { ex.addSuppressed(e); throw ex; } return contextClass.getDeclaredMethods(); // Cross fingers } } /** * @since 2.7 */ public static Ctor[] getConstructors(Class cls) { // Note: can NOT skip abstract classes as they may be used with mix-ins // and for regular use shouldn't really matter. if (cls.isInterface() || isObjectOrPrimitive(cls)) { return NO_CTORS; } Constructor[] rawCtors = cls.getDeclaredConstructors(); final int len = rawCtors.length; Ctor[] result = new Ctor[len]; for (int i = 0; i < len; ++i) { result[i] = new Ctor(rawCtors[i]); } return result; } // // // Then methods that do NOT cache access but were considered // // // (and could be added to do caching if it was proven effective) /** * @since 2.7 */ public static Class getDeclaringClass(Class cls) { return isObjectOrPrimitive(cls) ? null : cls.getDeclaringClass(); } /** * @since 2.7 */ public static Type getGenericSuperclass(Class cls) { return cls.getGenericSuperclass(); } /** * @since 2.7 */ public static Type[] getGenericInterfaces(Class cls) { return cls.getGenericInterfaces(); } /** * @since 2.7 */ public static Class getEnclosingClass(Class cls) { // Caching does not seem worthwhile, as per profiling return isObjectOrPrimitive(cls) ? null : cls.getEnclosingClass(); } private static Class[] _interfaces(Class cls) { return cls.getInterfaces(); } /* /********************************************************** /* Helper classes /********************************************************** */ /** * Inner class used to contain gory details of how we can determine * details of instances of common JDK types like {@link EnumMap}s. */ private static class EnumTypeLocator { final static EnumTypeLocator instance = new EnumTypeLocator(); private final Field enumSetTypeField; private final Field enumMapTypeField; private EnumTypeLocator() { //JDK uses following fields to store information about actual Enumeration // type for EnumSets, EnumMaps... enumSetTypeField = locateField(EnumSet.class, "elementType", Class.class); enumMapTypeField = locateField(EnumMap.class, "elementType", Class.class); } @SuppressWarnings("unchecked") public Class> enumTypeFor(EnumSet set) { if (enumSetTypeField != null) { return (Class>) get(set, enumSetTypeField); } throw new IllegalStateException("Cannot figure out type for EnumSet (odd JDK platform?)"); } @SuppressWarnings("unchecked") public Class> enumTypeFor(EnumMap set) { if (enumMapTypeField != null) { return (Class>) get(set, enumMapTypeField); } throw new IllegalStateException("Cannot figure out type for EnumMap (odd JDK platform?)"); } private Object get(Object bean, Field field) { try { return field.get(bean); } catch (Exception e) { throw new IllegalArgumentException(e); } } private static Field locateField(Class fromClass, String expectedName, Class type) { Field found = null; // First: let's see if we can find exact match: Field[] fields = getDeclaredFields(fromClass); for (Field f : fields) { if (expectedName.equals(f.getName()) && f.getType() == type) { found = f; break; } } // And if not, if there is just one field with the type, that field if (found == null) { for (Field f : fields) { if (f.getType() == type) { // If more than one, can't choose if (found != null) return null; found = f; } } } if (found != null) { // it's non-public, need to force accessible try { found.setAccessible(true); } catch (Throwable t) { } } return found; } } /* /********************************************************** /* Helper classed used for caching /********************************************************** */ /** * Value class used for caching Constructor declarations; used because * caching done by JDK appears to be somewhat inefficient for some use cases. * * @since 2.7 */ public final static class Ctor { public final Constructor _ctor; private Annotation[] _annotations; private Annotation[][] _paramAnnotations; private int _paramCount = -1; public Ctor(Constructor ctor) { _ctor = ctor; } public Constructor getConstructor() { return _ctor; } public int getParamCount() { int c = _paramCount; if (c < 0) { c = _ctor.getParameterTypes().length; _paramCount = c; } return c; } public Class getDeclaringClass() { return _ctor.getDeclaringClass(); } public Annotation[] getDeclaredAnnotations() { Annotation[] result = _annotations; if (result == null) { result = _ctor.getDeclaredAnnotations(); _annotations = result; } return result; } public Annotation[][] getParameterAnnotations() { Annotation[][] result = _paramAnnotations; if (result == null) { result = _ctor.getParameterAnnotations(); _paramAnnotations = result; } return result; } } } CompactStringObjectMap.java000066400000000000000000000110651325620701100366350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.*; /** * Specialized lookup class that implements functionality similar to * {@link java.util.Map}, but for special case of key always being * {@link java.lang.String} and using more compact (and memory-access * friendly) hashing scheme. Assumption is also that keys are typically * intern()ed. *

* Generics are not used to avoid bridge methods and since these maps * are not exposed as part of external API. * * @since 2.6 */ public final class CompactStringObjectMap implements java.io.Serializable // since 2.6.2 { private static final long serialVersionUID = 1L; /** * Shared instance that can be used when there are no contents to Map. */ private final static CompactStringObjectMap EMPTY = new CompactStringObjectMap(1, 0, new Object[4]); private final int _hashMask, _spillCount; private final Object[] _hashArea; private CompactStringObjectMap(int hashMask, int spillCount, Object[] hashArea) { _hashMask = hashMask; _spillCount = spillCount; _hashArea = hashArea; } public static CompactStringObjectMap construct(Map all) { if (all.isEmpty()) { // can this happen? return EMPTY; } // First: calculate size of primary hash area final int size = findSize(all.size()); final int mask = size-1; // and allocate enough to contain primary/secondary, expand for spillovers as need be int alloc = (size + (size>>1)) * 2; Object[] hashArea = new Object[alloc]; int spillCount = 0; for (Map.Entry entry : all.entrySet()) { String key = entry.getKey(); int slot = key.hashCode() & mask; int ix = slot+slot; // primary slot not free? if (hashArea[ix] != null) { // secondary? ix = (size + (slot >> 1)) << 1; if (hashArea[ix] != null) { // ok, spill over. ix = ((size + (size >> 1) ) << 1) + spillCount; spillCount += 2; if (ix >= hashArea.length) { hashArea = Arrays.copyOf(hashArea, hashArea.length + 4); } } } hashArea[ix] = key; hashArea[ix+1] = entry.getValue(); } return new CompactStringObjectMap(mask, spillCount, hashArea); } private final static int findSize(int size) { if (size <= 5) { return 8; } if (size <= 12) { return 16; } int needed = size + (size >> 2); // at most 80% full int result = 32; while (result < needed) { result += result; } return result; } public Object find(String key) { int slot = key.hashCode() & _hashMask; int ix = (slot<<1); Object match = _hashArea[ix]; if ((match == key) || key.equals(match)) { return _hashArea[ix+1]; } return _find2(key, slot, match); } private final Object _find2(String key, int slot, Object match) { if (match == null) { return null; } int hashSize = _hashMask+1; int ix = hashSize + (slot>>1) << 1; match = _hashArea[ix]; if (key.equals(match)) { return _hashArea[ix+1]; } if (match != null) { // _findFromSpill(...) int i = (hashSize + (hashSize>>1)) << 1; for (int end = i + _spillCount; i < end; i += 2) { match = _hashArea[i]; if ((match == key) || key.equals(match)) { return _hashArea[i+1]; } } } return null; } /** * @since 2.9 */ public Object findCaseInsensitive(String key) { for (int i = 0, end = _hashArea.length; i < end; i += 2) { Object k2 = _hashArea[i]; if (k2 != null) { String s = (String) k2; if (s.equalsIgnoreCase(key)) { return _hashArea[i+1]; } } } return null; } public List keys() { final int end = _hashArea.length; List keys = new ArrayList(end >> 2); for (int i = 0; i < end; i += 2) { Object key = _hashArea[i]; if (key != null) { keys.add((String) key); } } return keys; } } ConstantValueInstantiator.java000066400000000000000000000017771325620701100374720ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.IOException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.ValueInstantiator; /** * Trivial {@link ValueInstantiator} implementation that will simply return constant * {@code Object} it is configured with. May be used as-is, or as base class to override * simplistic behavior further. * * @since 2.9.4 */ public class ConstantValueInstantiator extends ValueInstantiator { protected final Object _value; public ConstantValueInstantiator(Object value) { _value = value; } @Override public Class getValueClass() { return _value.getClass(); } @Override // yes, since default ctor works public boolean canInstantiate() { return true; } @Override public boolean canCreateUsingDefault() { return true; } @Override public Object createUsingDefault(DeserializationContext ctxt) throws IOException { return _value; } } Converter.java000066400000000000000000000043021325620701100342360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Helper interface for things that convert Objects of * one type to another. *

* NOTE: implementors are strongly encouraged to extend {@link StdConverter} * instead of directly implementing {@link Converter}, since that can * help with default implementation of typically boiler-plate code. * * @param Type of values converter takes * @param Result type from conversion * * @see com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer * @see com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer * * @since 2.1 */ public interface Converter { /** * Main conversion method. */ public OUT convert(IN value); /** * Method that can be used to find out actual input (source) type; this * usually can be determined from type parameters, but may need * to be implemented differently from programmatically defined * converters (which cannot change static type parameter bindings). * * @since 2.2 */ public JavaType getInputType(TypeFactory typeFactory); /** * Method that can be used to find out actual output (target) type; this * usually can be determined from type parameters, but may need * to be implemented differently from programmatically defined * converters (which cannot change static type parameter bindings). * * @since 2.2 */ public JavaType getOutputType(TypeFactory typeFactory); /* /********************************************************** /* Helper class(es) /********************************************************** */ /** * This marker class is only to be used with annotations, to * indicate that no converter is to be used. *

* Specifically, this class is to be used as the marker for * annotation {@link com.fasterxml.jackson.databind.annotation.JsonSerialize}, * property converter (and related) * * @since 2.2 */ public abstract static class None implements Converter { } } EnumResolver.java000066400000000000000000000144341325620701100347240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.*; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; /** * Helper class used to resolve String values (either JSON Object field * names or regular String values) into Java Enum instances. */ public class EnumResolver implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final Class> _enumClass; protected final Enum[] _enums; protected final HashMap> _enumsById; protected final Enum _defaultValue; protected EnumResolver(Class> enumClass, Enum[] enums, HashMap> map, Enum defaultValue) { _enumClass = enumClass; _enums = enums; _enumsById = map; _defaultValue = defaultValue; } /** * Factory method for constructing resolver that maps from Enum.name() into * Enum value */ public static EnumResolver constructFor(Class> enumCls, AnnotationIntrospector ai) { Enum[] enumValues = enumCls.getEnumConstants(); if (enumValues == null) { throw new IllegalArgumentException("No enum constants for class "+enumCls.getName()); } String[] names = ai.findEnumValues(enumCls, enumValues, new String[enumValues.length]); HashMap> map = new HashMap>(); for (int i = 0, len = enumValues.length; i < len; ++i) { String name = names[i]; if (name == null) { name = enumValues[i].name(); } map.put(name, enumValues[i]); } Enum defaultEnum = ai.findDefaultEnumValue(enumCls); return new EnumResolver(enumCls, enumValues, map, defaultEnum); } /** * @deprecated Since 2.8, use {@link #constructUsingToString(Class, AnnotationIntrospector)} instead */ @Deprecated public static EnumResolver constructUsingToString(Class> enumCls) { return constructUsingToString(enumCls, null); } /** * Factory method for constructing resolver that maps from Enum.toString() into * Enum value * * @since 2.8 */ public static EnumResolver constructUsingToString(Class> enumCls, AnnotationIntrospector ai) { Enum[] enumValues = enumCls.getEnumConstants(); HashMap> map = new HashMap>(); // from last to first, so that in case of duplicate values, first wins for (int i = enumValues.length; --i >= 0; ) { Enum e = enumValues[i]; map.put(e.toString(), e); } Enum defaultEnum = (ai == null) ? null : ai.findDefaultEnumValue(enumCls); return new EnumResolver(enumCls, enumValues, map, defaultEnum); } /** * @since 2.9 */ public static EnumResolver constructUsingMethod(Class> enumCls, AnnotatedMember accessor, AnnotationIntrospector ai) { Enum[] enumValues = enumCls.getEnumConstants(); HashMap> map = new HashMap>(); // from last to first, so that in case of duplicate values, first wins for (int i = enumValues.length; --i >= 0; ) { Enum en = enumValues[i]; try { Object o = accessor.getValue(en); if (o != null) { map.put(o.toString(), en); } } catch (Exception e) { throw new IllegalArgumentException("Failed to access @JsonValue of Enum value "+en+": "+e.getMessage()); } } Enum defaultEnum = (ai != null) ? ai.findDefaultEnumValue(enumCls) : null; return new EnumResolver(enumCls, enumValues, map, defaultEnum); } /** * This method is needed because of the dynamic nature of constructing Enum * resolvers. */ @SuppressWarnings({ "unchecked" }) public static EnumResolver constructUnsafe(Class rawEnumCls, AnnotationIntrospector ai) { /* This is oh so wrong... but at least ugliness is mostly hidden in just * this one place. */ Class> enumCls = (Class>) rawEnumCls; return constructFor(enumCls, ai); } /** * Method that needs to be used instead of {@link #constructUsingToString} * if static type of enum is not known. * * @since 2.8 */ @SuppressWarnings({ "unchecked" }) public static EnumResolver constructUnsafeUsingToString(Class rawEnumCls, AnnotationIntrospector ai) { // oh so wrong... not much that can be done tho Class> enumCls = (Class>) rawEnumCls; return constructUsingToString(enumCls, ai); } /** * Method used when actual String serialization is indicated using @JsonValue * on a method. * * @since 2.9 */ @SuppressWarnings({ "unchecked" }) public static EnumResolver constructUnsafeUsingMethod(Class rawEnumCls, AnnotatedMember accessor, AnnotationIntrospector ai) { // wrong as ever but: Class> enumCls = (Class>) rawEnumCls; return constructUsingMethod(enumCls, accessor, ai); } public CompactStringObjectMap constructLookup() { return CompactStringObjectMap.construct(_enumsById); } public Enum findEnum(String key) { return _enumsById.get(key); } public Enum getEnum(int index) { if (index < 0 || index >= _enums.length) { return null; } return _enums[index]; } public Enum getDefaultValue(){ return _defaultValue; } public Enum[] getRawEnums() { return _enums; } public List> getEnums() { ArrayList> enums = new ArrayList>(_enums.length); for (Enum e : _enums) { enums.add(e); } return enums; } /** * @since 2.7.3 */ public Collection getEnumIds() { return _enumsById.keySet(); } public Class> getEnumClass() { return _enumClass; } public int lastValidIndex() { return _enums.length-1; } } EnumValues.java000066400000000000000000000100341325620701100343520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.*; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; /** * Helper class used for storing String serializations of * enumerations. */ public final class EnumValues implements java.io.Serializable { private static final long serialVersionUID = 1; private final Class> _enumClass; private final Enum[] _values; private final SerializableString[] _textual; private transient EnumMap _asMap; private EnumValues(Class> enumClass, SerializableString[] textual) { _enumClass = enumClass; _values = enumClass.getEnumConstants(); _textual = textual; } /** * NOTE: do NOT call this if configuration may change, and choice between toString() * and name() might change dynamically. */ public static EnumValues construct(SerializationConfig config, Class> enumClass) { if (config.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) { return constructFromToString(config, enumClass); } return constructFromName(config, enumClass); } public static EnumValues constructFromName(MapperConfig config, Class> enumClass) { // Enum types with per-instance sub-classes need special handling Class> enumCls = ClassUtil.findEnumType(enumClass); Enum[] enumValues = enumCls.getEnumConstants(); if (enumValues == null) { throw new IllegalArgumentException("Cannot determine enum constants for Class "+enumClass.getName()); } String[] names = config.getAnnotationIntrospector().findEnumValues(enumCls, enumValues, new String[enumValues.length]); SerializableString[] textual = new SerializableString[enumValues.length]; for (int i = 0, len = enumValues.length; i < len; ++i) { Enum en = enumValues[i]; String name = names[i]; if (name == null) { name = en.name(); } textual[en.ordinal()] = config.compileString(name); } return new EnumValues(enumClass, textual); } public static EnumValues constructFromToString(MapperConfig config, Class> enumClass) { Class> cls = ClassUtil.findEnumType(enumClass); Enum[] values = cls.getEnumConstants(); if (values != null) { SerializableString[] textual = new SerializableString[values.length]; for (Enum en : values) { textual[en.ordinal()] = config.compileString(en.toString()); } return new EnumValues(enumClass, textual); } throw new IllegalArgumentException("Cannot determine enum constants for Class "+enumClass.getName()); } public SerializableString serializedValueFor(Enum key) { return _textual[key.ordinal()]; } public Collection values() { return Arrays.asList(_textual); } /** * Convenience accessor for getting raw Enum instances. * * @since 2.6 */ public List> enums() { return Arrays.asList(_values); } /** * Method used for serialization and introspection by core Jackson code. */ @SuppressWarnings({ "unchecked", "rawtypes" }) public EnumMap internalMap() { EnumMap result = _asMap; if (result == null) { // Alas, need to create it in a round-about way, due to typing constraints... Map,SerializableString> map = new LinkedHashMap,SerializableString>(); for (Enum en : _values) { map.put(en, _textual[en.ordinal()]); } result = new EnumMap(map); } return result; } /** * @since 2.2 */ public Class> getEnumClass() { return _enumClass; } } ISO8601DateFormat.java000066400000000000000000000030321325620701100352060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.text.*; import java.util.Date; import java.util.GregorianCalendar; /** * Provide a fast thread-safe formatter/parser DateFormat for ISO8601 dates ONLY. * It was mainly done to be used with Jackson JSON Processor. *

* Watch out for clone implementation that returns itself. *

* All other methods but parse and format and clone are undefined behavior. * * @deprecated Use {@link com.fasterxml.jackson.databind.util.StdDateFormat} instead */ @Deprecated // since 2.9 public class ISO8601DateFormat extends DateFormat { private static final long serialVersionUID = 1L; public ISO8601DateFormat() { this.numberFormat = new DecimalFormat();; this.calendar = new GregorianCalendar();; } @Override public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { toAppendTo.append(ISO8601Utils.format(date)); return toAppendTo; } @Override public Date parse(String source, ParsePosition pos) { try { return ISO8601Utils.parse(source, pos); } catch (ParseException e) { return null; } } //supply our own parse(String) since pos isn't updated during parsing, //but the exception should have the right error offset. @Override public Date parse(String source) throws ParseException { return ISO8601Utils.parse(source, new ParsePosition(0)); } @Override public Object clone() { return this; } } ISO8601Utils.java000066400000000000000000000315611325620701100342700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.text.ParseException; import java.text.ParsePosition; import java.util.*; /** * Utilities methods for manipulating dates in iso8601 format. This is much much faster and GC friendly than using SimpleDateFormat so * highly suitable if you (un)serialize lots of date objects. * * Supported parse format: [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh[:]mm]] * * @see this specification */ @Deprecated // since 2.9 public class ISO8601Utils { protected final static int DEF_8601_LEN = "yyyy-MM-ddThh:mm:ss.SSS+00:00".length(); /** * Timezone we use for 'Z' in ISO-8601 date/time values: since 2.7 * {@link #TIMEZONE_UTC}; with earlier versions up to 2.7 was {@link #TIMEZONE_GMT}. */ private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); /* /********************************************************** /* Formatting /********************************************************** */ /** * Format a date into 'yyyy-MM-ddThh:mm:ssZ' (default timezone, no milliseconds precision) * * @param date the date to format * @return the date formatted as 'yyyy-MM-ddThh:mm:ssZ' */ public static String format(Date date) { return format(date, false, TIMEZONE_Z); } /** * Format a date into 'yyyy-MM-ddThh:mm:ss[.sss]Z' (GMT timezone) * * @param date the date to format * @param millis true to include millis precision otherwise false * @return the date formatted as 'yyyy-MM-ddThh:mm:ss[.sss]Z' */ public static String format(Date date, boolean millis) { return format(date, millis, TIMEZONE_Z); } @Deprecated // since 2.9 public static String format(Date date, boolean millis, TimeZone tz) { return format(date, millis, tz, Locale.US); } /** * Format date into yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm] * * @param date the date to format * @param millis true to include millis precision otherwise false * @param tz timezone to use for the formatting (UTC will produce 'Z') * @return the date formatted as yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm] * * @since 2.9 */ public static String format(Date date, boolean millis, TimeZone tz, Locale loc) { Calendar calendar = new GregorianCalendar(tz, loc); calendar.setTime(date); // estimate capacity of buffer as close as we can (yeah, that's pedantic ;) StringBuilder sb = new StringBuilder(30); sb.append(String.format( "%04d-%02d-%02dT%02d:%02d:%02d", calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND) )); if (millis) { sb.append(String.format(".%03d", calendar.get(Calendar.MILLISECOND))); } int offset = tz.getOffset(calendar.getTimeInMillis()); if (offset != 0) { int hours = Math.abs((offset / (60 * 1000)) / 60); int minutes = Math.abs((offset / (60 * 1000)) % 60); sb.append(String.format("%c%02d:%02d", (offset < 0 ? '-' : '+'), hours, minutes)); } else { sb.append('Z'); } return sb.toString(); } /* /********************************************************** /* Parsing /********************************************************** */ /** * Parse a date from ISO-8601 formatted string. It expects a format * [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]] * * @param date ISO string to parse in the appropriate format. * @param pos The position to start parsing from, updated to where parsing stopped. * @return the parsed date * @throws ParseException if the date is not in the appropriate format */ public static Date parse(String date, ParsePosition pos) throws ParseException { Exception fail = null; try { int offset = pos.getIndex(); // extract year int year = parseInt(date, offset, offset += 4); if (checkOffset(date, offset, '-')) { offset += 1; } // extract month int month = parseInt(date, offset, offset += 2); if (checkOffset(date, offset, '-')) { offset += 1; } // extract day int day = parseInt(date, offset, offset += 2); // default time value int hour = 0; int minutes = 0; int seconds = 0; int milliseconds = 0; // always use 0 otherwise returned date will include millis of current time // if the value has no time component (and no time zone), we are done boolean hasT = checkOffset(date, offset, 'T'); if (!hasT && (date.length() <= offset)) { Calendar calendar = new GregorianCalendar(year, month - 1, day); pos.setIndex(offset); return calendar.getTime(); } if (hasT) { // extract hours, minutes, seconds and milliseconds hour = parseInt(date, offset += 1, offset += 2); if (checkOffset(date, offset, ':')) { offset += 1; } minutes = parseInt(date, offset, offset += 2); if (checkOffset(date, offset, ':')) { offset += 1; } // second and milliseconds can be optional if (date.length() > offset) { char c = date.charAt(offset); if (c != 'Z' && c != '+' && c != '-') { seconds = parseInt(date, offset, offset += 2); if (seconds > 59 && seconds < 63) seconds = 59; // truncate up to 3 leap seconds // milliseconds can be optional in the format if (checkOffset(date, offset, '.')) { offset += 1; int endOffset = indexOfNonDigit(date, offset + 1); // assume at least one digit int parseEndOffset = Math.min(endOffset, offset + 3); // parse up to 3 digits int fraction = parseInt(date, offset, parseEndOffset); // compensate for "missing" digits switch (parseEndOffset - offset) { // number of digits parsed case 2: milliseconds = fraction * 10; break; case 1: milliseconds = fraction * 100; break; default: milliseconds = fraction; } offset = endOffset; } } } } // extract timezone if (date.length() <= offset) { throw new IllegalArgumentException("No time zone indicator"); } TimeZone timezone = null; char timezoneIndicator = date.charAt(offset); if (timezoneIndicator == 'Z') { timezone = TIMEZONE_Z; offset += 1; } else if (timezoneIndicator == '+' || timezoneIndicator == '-') { String timezoneOffset = date.substring(offset); offset += timezoneOffset.length(); // 18-Jun-2015, tatu: Minor simplification, skip offset of "+0000"/"+00:00" if ("+0000".equals(timezoneOffset) || "+00:00".equals(timezoneOffset)) { timezone = TIMEZONE_Z; } else { // 18-Jun-2015, tatu: Looks like offsets only work from GMT, not UTC... // not sure why, but that's the way it looks. Further, Javadocs for // `java.util.TimeZone` specifically instruct use of GMT as base for // custom timezones... odd. String timezoneId = "GMT" + timezoneOffset; // String timezoneId = "UTC" + timezoneOffset; timezone = TimeZone.getTimeZone(timezoneId); String act = timezone.getID(); if (!act.equals(timezoneId)) { /* 22-Jan-2015, tatu: Looks like canonical version has colons, but we may be given * one without. If so, don't sweat. * Yes, very inefficient. Hopefully not hit often. * If it becomes a perf problem, add 'loose' comparison instead. */ String cleaned = act.replace(":", ""); if (!cleaned.equals(timezoneId)) { throw new IndexOutOfBoundsException("Mismatching time zone indicator: "+timezoneId+" given, resolves to " +timezone.getID()); } } } } else { throw new IndexOutOfBoundsException("Invalid time zone indicator '" + timezoneIndicator+"'"); } Calendar calendar = new GregorianCalendar(timezone); calendar.setLenient(false); calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, month - 1); calendar.set(Calendar.DAY_OF_MONTH, day); calendar.set(Calendar.HOUR_OF_DAY, hour); calendar.set(Calendar.MINUTE, minutes); calendar.set(Calendar.SECOND, seconds); calendar.set(Calendar.MILLISECOND, milliseconds); pos.setIndex(offset); return calendar.getTime(); // If we get a ParseException it'll already have the right message/offset. // Other exception types can convert here. } catch (Exception e) { fail = e; } String input = (date == null) ? null : ('"' + date + '"'); String msg = fail.getMessage(); if (msg == null || msg.isEmpty()) { msg = "("+fail.getClass().getName()+")"; } ParseException ex = new ParseException("Failed to parse date " + input + ": " + msg, pos.getIndex()); ex.initCause(fail); throw ex; } /** * Check if the expected character exist at the given offset in the value. * * @param value the string to check at the specified offset * @param offset the offset to look for the expected character * @param expected the expected character * @return true if the expected character exist at the given offset */ private static boolean checkOffset(String value, int offset, char expected) { return (offset < value.length()) && (value.charAt(offset) == expected); } /** * Parse an integer located between 2 given offsets in a string * * @param value the string to parse * @param beginIndex the start index for the integer in the string * @param endIndex the end index for the integer in the string * @return the int * @throws NumberFormatException if the value is not a number */ private static int parseInt(String value, int beginIndex, int endIndex) throws NumberFormatException { if (beginIndex < 0 || endIndex > value.length() || beginIndex > endIndex) { throw new NumberFormatException(value); } // use same logic as in Integer.parseInt() but less generic we're not supporting negative values int i = beginIndex; int result = 0; int digit; if (i < endIndex) { digit = Character.digit(value.charAt(i++), 10); if (digit < 0) { throw new NumberFormatException("Invalid number: " + value.substring(beginIndex, endIndex)); } result = -digit; } while (i < endIndex) { digit = Character.digit(value.charAt(i++), 10); if (digit < 0) { throw new NumberFormatException("Invalid number: " + value.substring(beginIndex, endIndex)); } result *= 10; result -= digit; } return -result; } /** * Returns the index of the first character in the string that is not a digit, starting at offset. */ private static int indexOfNonDigit(String string, int offset) { for (int i = offset; i < string.length(); i++) { char c = string.charAt(i); if (c < '0' || c > '9') return i; } return string.length(); } } JSONPObject.java000066400000000000000000000067001325620701100343130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * Container class that can be used to wrap any Object instances (including * nulls), and will serialize embedded in * JSONP wrapping. * * @see com.fasterxml.jackson.databind.util.JSONWrappedObject */ public class JSONPObject implements JsonSerializable { /** * JSONP function name to use for serialization */ protected final String _function; /** * Value to be serialized as JSONP padded; can be null. */ protected final Object _value; /** * Optional static type to use for serialization; if null, runtime * type is used. Can be used to specify declared type which defines * serializer to use, as well as aspects of extra type information * to include (if any). */ protected final JavaType _serializationType; public JSONPObject(String function, Object value) { this(function, value, (JavaType) null); } public JSONPObject(String function, Object value, JavaType asType) { _function = function; _value = value; _serializationType = asType; } /* /********************************************************** /* JsonSerializable(WithType) implementation /********************************************************** */ @Override public void serializeWithType(JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { // No type for JSONP wrapping: value serializer will handle typing for value: serialize(gen, provider); } @Override public void serialize(JsonGenerator gen, SerializerProvider provider) throws IOException { // First, wrapping: gen.writeRaw(_function); gen.writeRaw('('); if (_value == null) { provider.defaultSerializeNull(gen); } else { // NOTE: Escape line-separator characters that break JSONP only if no custom character escapes are set. // If custom escapes are in place JSONP-breaking characters will not be escaped and it is recommended to // add escaping for those (see JsonpCharacterEscapes class). boolean override = (gen.getCharacterEscapes() == null); if (override) { gen.setCharacterEscapes(JsonpCharacterEscapes.instance()); } try { if (_serializationType != null) { provider.findTypedValueSerializer(_serializationType, true, null).serialize(_value, gen, provider); } else { provider.findTypedValueSerializer(_value.getClass(), true, null).serialize(_value, gen, provider); } } finally { if (override) { gen.setCharacterEscapes(null); } } } gen.writeRaw(')'); } /* /************************************************************** /* Accessors /************************************************************** */ public String getFunction() { return _function; } public Object getValue() { return _value; } public JavaType getSerializationType() { return _serializationType; } } JSONWrappedObject.java000066400000000000000000000067241325620701100355240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * General-purpose wrapper class that can be used to decorate serialized * value with arbitrary literal prefix and suffix. This can be used for * example to construct arbitrary Javascript values (similar to how basic * function name and parenthesis are used with JSONP). * * @see com.fasterxml.jackson.databind.util.JSONPObject */ public class JSONWrappedObject implements JsonSerializable { /** * Literal String to output before serialized value. * Will not be quoted when serializing value. */ protected final String _prefix; /** * Literal String to output after serialized value. * Will not be quoted when serializing value. */ protected final String _suffix; /** * Value to be serialized as JSONP padded; can be null. */ protected final Object _value; /** * Optional static type to use for serialization; if null, runtime * type is used. Can be used to specify declared type which defines * serializer to use, as well as aspects of extra type information * to include (if any). */ protected final JavaType _serializationType; public JSONWrappedObject(String prefix, String suffix, Object value) { this(prefix, suffix, value, (JavaType) null); } /** * Constructor that should be used when specific serialization type to use * is important, and needs to be passed instead of just using runtime * (type-erased) type of the value. */ public JSONWrappedObject(String prefix, String suffix, Object value, JavaType asType) { _prefix = prefix; _suffix = suffix; _value = value; _serializationType = asType; } /* /************************************************************** /* JsonSerializable(WithType) implementation /************************************************************** */ @Override public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) throws IOException, JsonProcessingException { // No type for JSONP wrapping: value serializer will handle typing for value: serialize(jgen, provider); } @Override public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { // First, wrapping: if (_prefix != null) jgen.writeRaw(_prefix); if (_value == null) { provider.defaultSerializeNull(jgen); } else if (_serializationType != null) { provider.findTypedValueSerializer(_serializationType, true, null).serialize(_value, jgen, provider); } else { Class cls = _value.getClass(); provider.findTypedValueSerializer(cls, true, null).serialize(_value, jgen, provider); } if (_suffix != null) jgen.writeRaw(_suffix); } /* /************************************************************** /* Accessors /************************************************************** */ public String getPrefix() { return _prefix; } public String getSuffix() { return _suffix; } public Object getValue() { return _value; } public JavaType getSerializationType() { return _serializationType; } } LRUMap.java000066400000000000000000000064251325620701100333770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.*; import java.util.concurrent.ConcurrentHashMap; /** * Helper for simple bounded maps used for reusing lookup values. *

* Note that serialization behavior is such that contents are NOT serialized, * on assumption that all use cases are for caching where persistence * does not make sense. The only thing serialized is the cache size of Map. *

* NOTE: since version 2.4.2, this is NOT an LRU-based at all; reason * being that it is not possible to use JDK components that do LRU _AND_ perform * well wrt synchronization on multi-core systems. So we choose efficient synchronization * over potentially more efficient handling of entries. *

* And yes, there are efficient LRU implementations such as * concurrentlinkedhashmap; * but at this point we really try to keep external deps to minimum. But perhaps * a shaded variant may be used one day. */ public class LRUMap implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final transient int _maxEntries; protected final transient ConcurrentHashMap _map; public LRUMap(int initialEntries, int maxEntries) { // We'll use concurrency level of 4, seems reasonable _map = new ConcurrentHashMap(initialEntries, 0.8f, 4); _maxEntries = maxEntries; } public V put(K key, V value) { if (_map.size() >= _maxEntries) { // double-locking, yes, but safe here; trying to avoid "clear storms" synchronized (this) { if (_map.size() >= _maxEntries) { clear(); } } } return _map.put(key, value); } /** * @since 2.5 */ public V putIfAbsent(K key, V value) { // not 100% optimal semantically, but better from correctness (never exceeds // defined maximum) and close enough all in all: if (_map.size() >= _maxEntries) { synchronized (this) { if (_map.size() >= _maxEntries) { clear(); } } } return _map.putIfAbsent(key, value); } // NOTE: key is of type Object only to retain binary backwards-compatibility public V get(Object key) { return _map.get(key); } public void clear() { _map.clear(); } public int size() { return _map.size(); } /* /********************************************************** /* Serializable overrides /********************************************************** */ /** * Ugly hack, to work through the requirement that _value is indeed final, * and that JDK serialization won't call ctor(s) if Serializable is implemented. * * @since 2.1 */ protected transient int _jdkSerializeMaxEntries; private void readObject(ObjectInputStream in) throws IOException { _jdkSerializeMaxEntries = in.readInt(); } private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(_jdkSerializeMaxEntries); } protected Object readResolve() { return new LRUMap(_jdkSerializeMaxEntries, _jdkSerializeMaxEntries); } } LinkedNode.java000066400000000000000000000024341325620701100343070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; /** * Node of a forward-only linked list. * * @author tatu */ public final class LinkedNode { private final T value; private LinkedNode next; public LinkedNode(T value, LinkedNode next) { this.value = value; this.next = next; } public void linkNext(LinkedNode n) { if (next != null) { // sanity check throw new IllegalStateException(); } next = n; } public LinkedNode next() { return next; } public T value() { return value; } /** * Convenience method that can be used to check if a linked list * with given head node (which may be null to indicate empty list) * contains given value * * @param Type argument that defines contents of the linked list parameter * @param node Head node of the linked list * @param value Value to look for * @return True if linked list contains the value, false otherwise */ public static boolean contains(LinkedNode node, ST value) { while (node != null) { if (node.value() == value) { return true; } node = node.next(); } return false; } } NameTransformer.java000066400000000000000000000120051325620701100353710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; /** * Helper class used to encapsulate details of name mangling, transforming * of names using different strategies (prefixes, suffixes). * Default implementation is "no-operation" (aka identity transformation). */ public abstract class NameTransformer { /** * Singleton "no-operation" transformer which simply returns given * name as is. Used commonly as placeholder or marker. */ public final static NameTransformer NOP = new NopTransformer(); protected final static class NopTransformer extends NameTransformer implements java.io.Serializable { private static final long serialVersionUID = 1L; @Override public String transform(String name) { return name; } @Override public String reverse(String transformed) { // identity transformation is always reversible: return transformed; } } protected NameTransformer() { } /** * Factory method for constructing a simple transformer based on * prefix and/or suffix. */ public static NameTransformer simpleTransformer(final String prefix, final String suffix) { boolean hasPrefix = (prefix != null) && (prefix.length() > 0); boolean hasSuffix = (suffix != null) && (suffix.length() > 0); if (hasPrefix) { if (hasSuffix) { return new NameTransformer() { @Override public String transform(String name) { return prefix + name + suffix; } @Override public String reverse(String transformed) { if (transformed.startsWith(prefix)) { String str = transformed.substring(prefix.length()); if (str.endsWith(suffix)) { return str.substring(0, str.length() - suffix.length()); } } return null; } @Override public String toString() { return "[PreAndSuffixTransformer('"+prefix+"','"+suffix+"')]"; } }; } return new NameTransformer() { @Override public String transform(String name) { return prefix + name; } @Override public String reverse(String transformed) { if (transformed.startsWith(prefix)) { return transformed.substring(prefix.length()); } return null; } @Override public String toString() { return "[PrefixTransformer('"+prefix+"')]"; } }; } if (hasSuffix) { return new NameTransformer() { @Override public String transform(String name) { return name + suffix; } @Override public String reverse(String transformed) { if (transformed.endsWith(suffix)) { return transformed.substring(0, transformed.length() - suffix.length()); } return null; } @Override public String toString() { return "[SuffixTransformer('"+suffix+"')]"; } }; } return NOP; } /** * Method that constructs transformer that applies given transformers * as a sequence; essentially combines separate transform operations * into one logical transformation. */ public static NameTransformer chainedTransformer(NameTransformer t1, NameTransformer t2) { return new Chained(t1, t2); } /** * Method called when (forward) transformation is needed. */ public abstract String transform(String name); /** * Method called when reversal of transformation is needed; should return * null if this is not possible, that is, given name cannot have been * result of calling {@link #transform} of this object. */ public abstract String reverse(String transformed); public static class Chained extends NameTransformer implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final NameTransformer _t1, _t2; public Chained(NameTransformer t1, NameTransformer t2) { _t1 = t1; _t2 = t2; } @Override public String transform(String name) { return _t1.transform(_t2.transform(name)); } @Override public String reverse(String transformed) { transformed = _t1.reverse(transformed); if (transformed != null) { transformed = _t2.reverse(transformed); } return transformed; } @Override public String toString() { return "[ChainedTransformer("+_t1+", "+_t2+")]"; } } } jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/util/Named.java000066400000000000000000000002471325620701100333760ustar00rootroot00000000000000package com.fasterxml.jackson.databind.util; /** * Simple tag interface mostly to allow sorting by name. */ public interface Named { public String getName(); } ObjectBuffer.java000066400000000000000000000161211325620701100346310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.lang.reflect.Array; import java.util.List; /** * Helper class to use for constructing Object arrays by appending entries * to create arrays of various lengths (length that is not known a priori). */ public final class ObjectBuffer { // // // Config constants /** * Also: let's expand by doubling up until 64k chunks (which is 16k entries for * 32-bit machines) */ private final static int SMALL_CHUNK = (1 << 14); /** * Let's limit maximum size of chunks we use; helps avoid excessive allocation * overhead for huge data sets. * For now, let's limit to quarter million entries, 1 meg chunks for 32-bit * machines. */ private final static int MAX_CHUNK = (1 << 18); // // // Data storage private LinkedNode _head; private LinkedNode _tail; /** * Number of total buffered entries in this buffer, counting all instances * within linked list formed by following {@link #_head}. */ private int _size; // // // Simple reuse /** * Reusable Object array, stored here after buffer has been released having * been used previously. */ private Object[] _freeBuffer; /* /********************************************************** /* Construction /********************************************************** */ public ObjectBuffer() { } /* /********************************************************** /* Public API /********************************************************** */ /** * Method called to start buffering process. Will ensure that the buffer * is empty, and then return an object array to start chunking content on */ public Object[] resetAndStart() { _reset(); if (_freeBuffer == null) { return (_freeBuffer = new Object[12]); } return _freeBuffer; } /** * @since 2.9 */ public Object[] resetAndStart(Object[] base, int count) { _reset(); if ((_freeBuffer == null) || (_freeBuffer.length < count)) { _freeBuffer = new Object[Math.max(12, count)]; } System.arraycopy(base, 0, _freeBuffer, 0, count); return _freeBuffer; } /** * Method called to add a full Object array as a chunk buffered within * this buffer, and to obtain a new array to fill. Caller is not to use * the array it gives; but to use the returned array for continued * buffering. * * @param fullChunk Completed chunk that the caller is requesting * to append to this buffer. It is generally chunk that was * returned by an earlier call to {@link #resetAndStart} or * {@link #appendCompletedChunk} (although this is not required or * enforced) * * @return New chunk buffer for caller to fill */ public Object[] appendCompletedChunk(Object[] fullChunk) { LinkedNode next = new LinkedNode(fullChunk, null); if (_head == null) { // first chunk _head = _tail = next; } else { // have something already _tail.linkNext(next); _tail = next; } int len = fullChunk.length; _size += len; // double the size for small chunks if (len < SMALL_CHUNK) { len += len; } else if (len < MAX_CHUNK) { // but by +25% for larger (to limit overhead) len += (len >> 2); } return new Object[len]; } /** * Method called to indicate that the buffering process is now * complete; and to construct a combined exactly-sized result * array. Additionally the buffer itself will be reset to * reduce memory retention. *

* Resulting array will be of generic Object[] type: * if a typed array is needed, use the method with additional * type argument. */ public Object[] completeAndClearBuffer(Object[] lastChunk, int lastChunkEntries) { int totalSize = lastChunkEntries + _size; Object[] result = new Object[totalSize]; _copyTo(result, totalSize, lastChunk, lastChunkEntries); _reset(); return result; } /** * Type-safe alternative to * {@link #completeAndClearBuffer(Object[], int)}, to allow * for constructing explicitly typed result array. * * @param componentType Type of elements included in the buffer. Will be * used for constructing the result array. */ public T[] completeAndClearBuffer(Object[] lastChunk, int lastChunkEntries, Class componentType) { int totalSize = lastChunkEntries + _size; @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(componentType, totalSize); _copyTo(result, totalSize, lastChunk, lastChunkEntries); _reset(); return result; } public void completeAndClearBuffer(Object[] lastChunk, int lastChunkEntries, List resultList) { for (LinkedNode n = _head; n != null; n = n.next()) { Object[] curr = n.value(); for (int i = 0, len = curr.length; i < len; ++i) { resultList.add(curr[i]); } } // and then the last one for (int i = 0; i < lastChunkEntries; ++i) { resultList.add(lastChunk[i]); } _reset(); } /** * Helper method that can be used to check how much free capacity * will this instance start with. Can be used to choose the best * instance to reuse, based on size of reusable object chunk * buffer holds reference to. */ public int initialCapacity() { return (_freeBuffer == null) ? 0 : _freeBuffer.length; } /** * Method that can be used to check how many Objects have been buffered * within this buffer. */ public int bufferedSize() { return _size; } /* /********************************************************** /* Internal methods /********************************************************** */ protected void _reset() { // can we reuse the last (and thereby biggest) array for next time? if (_tail != null) { _freeBuffer = _tail.value(); } // either way, must discard current contents _head = _tail = null; _size = 0; } protected final void _copyTo(Object resultArray, int totalSize, Object[] lastChunk, int lastChunkEntries) { int ptr = 0; for (LinkedNode n = _head; n != null; n = n.next()) { Object[] curr = n.value(); int len = curr.length; System.arraycopy(curr, 0, resultArray, ptr, len); ptr += len; } System.arraycopy(lastChunk, 0, resultArray, ptr, lastChunkEntries); ptr += lastChunkEntries; // sanity check (could have failed earlier due to out-of-bounds, too) if (ptr != totalSize) { throw new IllegalStateException("Should have gotten "+totalSize+" entries, got "+ptr); } } } PrimitiveArrayBuilder.java000066400000000000000000000122401325620701100365450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; /** * Base class for specialized primitive array builders. */ public abstract class PrimitiveArrayBuilder { /** * Let's start with small chunks; typical usage is for small arrays anyway. */ final static int INITIAL_CHUNK_SIZE = 12; /** * Also: let's expand by doubling up until 64k chunks (which is 16k entries for * 32-bit machines) */ final static int SMALL_CHUNK_SIZE = (1 << 14); /** * Let's limit maximum size of chunks we use; helps avoid excessive allocation * overhead for huge data sets. * For now, let's limit to quarter million entries, 1 meg chunks for 32-bit * machines. */ final static int MAX_CHUNK_SIZE = (1 << 18); // // // Data storage protected T _freeBuffer; protected Node _bufferHead; protected Node _bufferTail; /** * Number of total buffered entries in this buffer, counting all instances * within linked list formed by following {@link #_bufferHead}. */ protected int _bufferedEntryCount; // // // Recycled instances of sub-classes // // // Life-cycle protected PrimitiveArrayBuilder() { } /* /********************************************************** /* Public API /********************************************************** */ public int bufferedSize() { return _bufferedEntryCount; } public T resetAndStart() { _reset(); return (_freeBuffer == null) ? _constructArray(INITIAL_CHUNK_SIZE) : _freeBuffer; } /** * @return Length of the next chunk to allocate */ public final T appendCompletedChunk(T fullChunk, int fullChunkLength) { Node next = new Node(fullChunk, fullChunkLength); if (_bufferHead == null) { // first chunk _bufferHead = _bufferTail = next; } else { // have something already _bufferTail.linkNext(next); _bufferTail = next; } _bufferedEntryCount += fullChunkLength; int nextLen = fullChunkLength; // start with last chunk size // double the size for small chunks if (nextLen < SMALL_CHUNK_SIZE) { nextLen += nextLen; } else { // but by +25% for larger (to limit overhead) nextLen += (nextLen >> 2); } return _constructArray(nextLen); } public T completeAndClearBuffer(T lastChunk, int lastChunkEntries) { int totalSize = lastChunkEntries + _bufferedEntryCount; T resultArray = _constructArray(totalSize); int ptr = 0; for (Node n = _bufferHead; n != null; n = n.next()) { ptr = n.copyData(resultArray, ptr); } System.arraycopy(lastChunk, 0, resultArray, ptr, lastChunkEntries); ptr += lastChunkEntries; // sanity check (could have failed earlier due to out-of-bounds, too) if (ptr != totalSize) { throw new IllegalStateException("Should have gotten "+totalSize+" entries, got "+ptr); } return resultArray; } /* /********************************************************** /* Abstract methods for sub-classes to implement /********************************************************** */ protected abstract T _constructArray(int len); /* /********************************************************** /* Internal methods /********************************************************** */ protected void _reset() { // can we reuse the last (and thereby biggest) array for next time? if (_bufferTail != null) { _freeBuffer = _bufferTail.getData(); } // either way, must discard current contents _bufferHead = _bufferTail = null; _bufferedEntryCount = 0; } /* /********************************************************** /* Helper classes /********************************************************** */ /** * For actual buffering beyond the current buffer, we can actually * use shared class which only deals with opaque "untyped" chunks. * This works because {@link java.lang.System#arraycopy} does not * take type; hence we can implement some aspects of primitive data * handling in generic fashion. */ final static class Node { /** * Data stored in this node. */ final T _data; /** * Number entries in the (untyped) array. Offset is assumed to be 0. */ final int _dataLength; Node _next; public Node(T data, int dataLen) { _data = data; _dataLength = dataLen; } public T getData() { return _data; } public int copyData(T dst, int ptr) { System.arraycopy(_data, 0, dst, ptr, _dataLength); ptr += _dataLength; return ptr; } public Node next() { return _next; } public void linkNext(Node next) { if (_next != null) { // sanity check throw new IllegalStateException(); } _next = next; } } } RawValue.java000066400000000000000000000075741325620701100340330ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.databind.JsonSerializable; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; /** * Helper class used to encapsulate "raw values", pre-encoded textual content * that can be output as opaque value with no quoting/escaping, using * {@link com.fasterxml.jackson.core.JsonGenerator#writeRawValue(String)}. * It may be stored in {@link TokenBuffer}, as well as in Tree Model * ({@link com.fasterxml.jackson.databind.JsonNode}) * * @since 2.6 */ public class RawValue implements JsonSerializable { /** * Contents to serialize. Untyped because there are multiple types that are * supported: {@link java.lang.String}, {@link JsonSerializable}, {@link SerializableString}. */ protected Object _value; public RawValue(String v) { _value = v; } public RawValue(SerializableString v) { _value = v; } public RawValue(JsonSerializable v) { _value = v; } /** * Constructor that may be used by sub-classes, and allows passing value * types other than ones for which explicit constructor exists. Caller has to * take care that values of types not supported by base implementation are * handled properly, usually by overriding some of existing serialization * methods. */ protected RawValue(Object value, boolean bogus) { _value = value; } /** * Accessor for returning enclosed raw value in whatever form it was created in * (usually {@link java.lang.String}, {link SerializableString}, or any {@link JsonSerializable}). */ public Object rawValue() { return _value; } @Override public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException { if (_value instanceof JsonSerializable) { ((JsonSerializable) _value).serialize(gen, serializers); } else { _serialize(gen); } } @Override public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException { if (_value instanceof JsonSerializable) { ((JsonSerializable) _value).serializeWithType(gen, serializers, typeSer); } else if (_value instanceof SerializableString) { /* Since these are not really to be deserialized (with or without type info), * just re-route as regular write, which will create one... hopefully it works */ serialize(gen, serializers); } } public void serialize(JsonGenerator gen) throws IOException { if (_value instanceof JsonSerializable) { // No SerializerProvider passed, must go via generator, callback gen.writeObject(_value); } else { _serialize(gen); } } protected void _serialize(JsonGenerator gen) throws IOException { if (_value instanceof SerializableString) { gen.writeRawValue((SerializableString) _value); } else { gen.writeRawValue(String.valueOf(_value)); } } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof RawValue)) return false; RawValue other = (RawValue) o; if (_value == other._value) { return true; } return (_value != null) && _value.equals(other._value); } @Override public int hashCode() { return (_value == null) ? 0 : _value.hashCode(); } @Override public String toString() { return String.format("[RawValue of type %s]", ClassUtil.classNameOf(_value)); } } RootNameLookup.java000066400000000000000000000041461325620701100352130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.type.ClassKey; /** * Helper class for caching resolved root names. */ public class RootNameLookup implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * For efficient operation, let's try to minimize number of times we * need to introspect root element name to use. */ protected transient LRUMap _rootNames; public RootNameLookup() { _rootNames = new LRUMap(20, 200); } public PropertyName findRootName(JavaType rootType, MapperConfig config) { return findRootName(rootType.getRawClass(), config); } public PropertyName findRootName(Class rootType, MapperConfig config) { ClassKey key = new ClassKey(rootType); PropertyName name = _rootNames.get(key); if (name != null) { return name; } BeanDescription beanDesc = config.introspectClassAnnotations(rootType); AnnotationIntrospector intr = config.getAnnotationIntrospector(); AnnotatedClass ac = beanDesc.getClassInfo(); name = intr.findRootName(ac); // No answer so far? Let's just default to using simple class name if (name == null || !name.hasSimpleName()) { // Should we strip out enclosing class tho? For now, nope: name = PropertyName.construct(rootType.getSimpleName()); } _rootNames.put(key, name); return name; } /* /********************************************************** /* Serializable overrides /********************************************************** */ /** * Need to override to reproduce cache object via constructor, instead * of serialize/deserialize (since we do NOT want to retain cached data) */ protected Object readResolve() { return new RootNameLookup(); } } SimpleBeanPropertyDefinition.java000066400000000000000000000203541325620701100400710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.Collections; import java.util.Iterator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Simple immutable {@link BeanPropertyDefinition} implementation that can * be wrapped around a {@link AnnotatedMember} that is a simple * accessor (getter) or mutator (setter, constructor parameter) * (or both, for fields). */ public class SimpleBeanPropertyDefinition extends BeanPropertyDefinition { protected final AnnotationIntrospector _annotationIntrospector; /** * Member that defines logical property. Assumption is that it * should be a 'simple' accessor; meaning a zero-argument getter, * single-argument setter or constructor parameter. *

* NOTE: for "virtual" properties, this is null. */ protected final AnnotatedMember _member; /** * @since 2.5 */ protected final PropertyMetadata _metadata; /** * @since 2.5 */ protected final PropertyName _fullName; /** * @since 2.5 */ protected final JsonInclude.Value _inclusion; /* /********************************************************** /* Construction /********************************************************** */ /** * @since 2.9 */ protected SimpleBeanPropertyDefinition(AnnotationIntrospector intr, AnnotatedMember member, PropertyName fullName, PropertyMetadata metadata, JsonInclude.Value inclusion) { _annotationIntrospector = intr; _member = member; _fullName = fullName; _metadata = (metadata == null) ? PropertyMetadata.STD_OPTIONAL: metadata; _inclusion = inclusion; } /** * @since 2.2 */ public static SimpleBeanPropertyDefinition construct(MapperConfig config, AnnotatedMember member) { return new SimpleBeanPropertyDefinition(config.getAnnotationIntrospector(), member, PropertyName.construct(member.getName()), null, EMPTY_INCLUDE); } /** * @since 2.5 */ public static SimpleBeanPropertyDefinition construct(MapperConfig config, AnnotatedMember member, PropertyName name) { return construct(config, member, name, null, EMPTY_INCLUDE); } /** * Method called to create instance for virtual properties. * * @since 2.5 */ public static SimpleBeanPropertyDefinition construct(MapperConfig config, AnnotatedMember member, PropertyName name, PropertyMetadata metadata, JsonInclude.Include inclusion) { JsonInclude.Value inclValue = ((inclusion == null) || (inclusion == JsonInclude.Include.USE_DEFAULTS)) ? EMPTY_INCLUDE : JsonInclude.Value.construct(inclusion, null); return new SimpleBeanPropertyDefinition(config.getAnnotationIntrospector(), member, name, metadata, inclValue); } /** * @since 2.7 */ public static SimpleBeanPropertyDefinition construct(MapperConfig config, AnnotatedMember member, PropertyName name, PropertyMetadata metadata, JsonInclude.Value inclusion) { return new SimpleBeanPropertyDefinition(config.getAnnotationIntrospector(), member, name, metadata, inclusion); } /* /********************************************************** /* Fluent factories /********************************************************** */ @Override public BeanPropertyDefinition withSimpleName(String newName) { if (_fullName.hasSimpleName(newName) && !_fullName.hasNamespace()) { return this; } return new SimpleBeanPropertyDefinition(_annotationIntrospector, _member, new PropertyName(newName), _metadata, _inclusion); } @Override public BeanPropertyDefinition withName(PropertyName newName) { if (_fullName.equals(newName)) { return this; } return new SimpleBeanPropertyDefinition(_annotationIntrospector, _member, newName, _metadata, _inclusion); } /** * @since 2.5 */ public BeanPropertyDefinition withMetadata(PropertyMetadata metadata) { if (metadata.equals(_metadata)) { return this; } return new SimpleBeanPropertyDefinition(_annotationIntrospector, _member, _fullName, metadata, _inclusion); } /** * @since 2.5 */ public BeanPropertyDefinition withInclusion(JsonInclude.Value inclusion) { if (_inclusion == inclusion) { return this; } return new SimpleBeanPropertyDefinition(_annotationIntrospector, _member, _fullName, _metadata, inclusion); } /* /********************************************************** /* Basic property information, name, type /********************************************************** */ @Override public String getName() { return _fullName.getSimpleName(); } @Override public PropertyName getFullName() { return _fullName; } @Override public boolean hasName(PropertyName name) { return _fullName.equals(name); } @Override public String getInternalName() { return getName(); } @Override public PropertyName getWrapperName() { if ((_annotationIntrospector == null) || (_member == null)) { return null; } return _annotationIntrospector.findWrapperName(_member); } // hmmh. what should we claim here? @Override public boolean isExplicitlyIncluded() { return false; } @Override public boolean isExplicitlyNamed() { return false; } /** * We will indicate that property is optional, since there is nothing * to indicate whether it might be required. */ @Override public PropertyMetadata getMetadata() { return _metadata; } @Override public JavaType getPrimaryType() { if (_member == null) { return TypeFactory.unknownType(); } return _member.getType(); } @Override public Class getRawPrimaryType() { if (_member == null) { return Object.class; } return _member.getRawType(); } @Override public JsonInclude.Value findInclusion() { return _inclusion; } /* /********************************************************** /* Access to accessors (fields, methods etc) /********************************************************** */ @Override public boolean hasGetter() { return (getGetter() != null); } @Override public boolean hasSetter() { return (getSetter() != null); } @Override public boolean hasField() { return (_member instanceof AnnotatedField); } @Override public boolean hasConstructorParameter() { return (_member instanceof AnnotatedParameter); } @Override public AnnotatedMethod getGetter() { if ((_member instanceof AnnotatedMethod) && ((AnnotatedMethod) _member).getParameterCount() == 0) { return (AnnotatedMethod) _member; } return null; } @Override public AnnotatedMethod getSetter() { if ((_member instanceof AnnotatedMethod) && ((AnnotatedMethod) _member).getParameterCount() == 1) { return (AnnotatedMethod) _member; } return null; } @Override public AnnotatedField getField() { return (_member instanceof AnnotatedField) ? (AnnotatedField) _member : null; } @Override public AnnotatedParameter getConstructorParameter() { return (_member instanceof AnnotatedParameter) ? (AnnotatedParameter) _member : null; } @Override public Iterator getConstructorParameters() { AnnotatedParameter param = getConstructorParameter(); if (param == null) { return ClassUtil.emptyIterator(); } return Collections.singleton(param).iterator(); } @Override public AnnotatedMember getPrimaryMember() { return _member; } } StdConverter.java000066400000000000000000000025311325620701100347130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Standard implementation of {@link Converter} that supports explicit * type access, instead of relying type detection of generic type * parameters. * * @since 2.2 */ public abstract class StdConverter implements Converter { /* /********************************************************** /* Partial Converter API implementation /********************************************************** */ @Override public abstract OUT convert(IN value); @Override public JavaType getInputType(TypeFactory typeFactory) { return _findConverterType(typeFactory).containedType(0); } @Override public JavaType getOutputType(TypeFactory typeFactory) { return _findConverterType(typeFactory).containedType(1); } protected JavaType _findConverterType(TypeFactory tf) { JavaType thisType = tf.constructType(getClass()); JavaType convType = thisType.findSuperType(Converter.class); if (convType == null || convType.containedTypeCount() < 2) { throw new IllegalStateException("Cannot find OUT type parameter for Converter of type "+getClass().getName()); } return convType; } } StdDateFormat.java000066400000000000000000000627621325620701100350060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.text.DateFormat; import java.text.FieldPosition; import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.fasterxml.jackson.core.io.NumberInput; /** * Default {@link DateFormat} implementation used by standard Date * serializers and deserializers. For serialization defaults to using * an ISO-8601 compliant format (format String "yyyy-MM-dd'T'HH:mm:ss.SSSZ") * and for deserialization, both ISO-8601 and RFC-1123. */ @SuppressWarnings("serial") public class StdDateFormat extends DateFormat { /* 24-Jun-2017, tatu: Finally rewrote deserialization to use basic Regex * instead of SimpleDateFormat; partly for better concurrency, partly * for easier enforcing of specific rules. Heavy lifting done by Calendar, * anyway. */ protected final static String PATTERN_PLAIN_STR = "\\d\\d\\d\\d[-]\\d\\d[-]\\d\\d"; protected final static Pattern PATTERN_PLAIN = Pattern.compile(PATTERN_PLAIN_STR); protected final static Pattern PATTERN_ISO8601; static { Pattern p = null; try { p = Pattern.compile(PATTERN_PLAIN_STR +"[T]\\d\\d[:]\\d\\d(?:[:]\\d\\d)?" // hours, minutes, optional seconds +"(\\.\\d+)?" // optional second fractions +"(Z|[+-]\\d\\d(?:[:]?\\d\\d)?)?" // optional timeoffset/Z ); } catch (Throwable t) { throw new RuntimeException(t); } PATTERN_ISO8601 = p; } /** * Defines a commonly used date format that conforms * to ISO-8601 date formatting standard, when it includes basic undecorated * timezone definition. */ public final static String DATE_FORMAT_STR_ISO8601 = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; /** * ISO-8601 with just the Date part, no time: needed for error messages */ protected final static String DATE_FORMAT_STR_PLAIN = "yyyy-MM-dd"; /** * This constant defines the date format specified by * RFC 1123 / RFC 822. Used for parsing via `SimpleDateFormat` as well as * error messages. */ protected final static String DATE_FORMAT_STR_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz"; /** * For error messages we'll also need a list of all formats. */ protected final static String[] ALL_FORMATS = new String[] { DATE_FORMAT_STR_ISO8601, "yyyy-MM-dd'T'HH:mm:ss.SSS", // ISO-8601 but no timezone DATE_FORMAT_STR_RFC1123, DATE_FORMAT_STR_PLAIN }; /** * By default we use UTC for everything, with Jackson 2.7 and later * (2.6 and earlier relied on GMT) */ protected final static TimeZone DEFAULT_TIMEZONE; static { DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC"); // since 2.7 } protected final static Locale DEFAULT_LOCALE = Locale.US; protected final static DateFormat DATE_FORMAT_RFC1123; protected final static DateFormat DATE_FORMAT_ISO8601; /* Let's construct "blueprint" date format instances: cannot be used * as is, due to thread-safety issues, but can be used for constructing * actual instances more cheaply (avoids re-parsing). */ static { // Another important thing: let's force use of default timezone for // baseline DataFormat objects DATE_FORMAT_RFC1123 = new SimpleDateFormat(DATE_FORMAT_STR_RFC1123, DEFAULT_LOCALE); DATE_FORMAT_RFC1123.setTimeZone(DEFAULT_TIMEZONE); DATE_FORMAT_ISO8601 = new SimpleDateFormat(DATE_FORMAT_STR_ISO8601, DEFAULT_LOCALE); DATE_FORMAT_ISO8601.setTimeZone(DEFAULT_TIMEZONE); } /** * A singleton instance can be used for cloning purposes, as a blueprint of sorts. */ public final static StdDateFormat instance = new StdDateFormat(); /** * Blueprint "Calendar" instance for use during formatting. Cannot be used as is, * due to thread-safety issues, but can be used for constructing actual instances * more cheaply by cloning. * * @since 2.9.1 */ protected static final Calendar CALENDAR = new GregorianCalendar(DEFAULT_TIMEZONE, DEFAULT_LOCALE); /** * Caller may want to explicitly override timezone to use; if so, * we will have non-null value here. */ protected transient TimeZone _timezone; protected final Locale _locale; /** * Explicit override for leniency, if specified. *

* Cannot be `final` because {@link #setLenient(boolean)} returns * `void`. * * @since 2.7 */ protected Boolean _lenient; /** * Lazily instantiated calendar used by this instance for serialization ({@link #format(Date)}). * * @since 2.9.1 */ private transient Calendar _calendar; private transient DateFormat _formatRFC1123; /** * Whether the TZ offset must be formatted with a colon between hours and minutes ({@code HH:mm} format) * * @since 2.9.1 */ private boolean _tzSerializedWithColon = false; /* /********************************************************** /* Life cycle, accessing singleton "standard" formats /********************************************************** */ public StdDateFormat() { _locale = DEFAULT_LOCALE; } @Deprecated // since 2.7 public StdDateFormat(TimeZone tz, Locale loc) { _timezone = tz; _locale = loc; } protected StdDateFormat(TimeZone tz, Locale loc, Boolean lenient) { this(tz, loc, lenient, false); } /** * @since 2.9.1 */ protected StdDateFormat(TimeZone tz, Locale loc, Boolean lenient, boolean formatTzOffsetWithColon) { _timezone = tz; _locale = loc; _lenient = lenient; _tzSerializedWithColon = formatTzOffsetWithColon; } public static TimeZone getDefaultTimeZone() { return DEFAULT_TIMEZONE; } /** * Method used for creating a new instance with specified timezone; * if no timezone specified, defaults to the default timezone (UTC). */ public StdDateFormat withTimeZone(TimeZone tz) { if (tz == null) { tz = DEFAULT_TIMEZONE; } if ((tz == _timezone) || tz.equals(_timezone)) { return this; } return new StdDateFormat(tz, _locale, _lenient, _tzSerializedWithColon); } /** * "Mutant factory" method that will return an instance that uses specified * {@code Locale}: * either {@code this} instance (if setting would not change), or newly * constructed instance with different {@code Locale} to use. */ public StdDateFormat withLocale(Locale loc) { if (loc.equals(_locale)) { return this; } return new StdDateFormat(_timezone, loc, _lenient, _tzSerializedWithColon); } /** * "Mutant factory" method that will return an instance that has specified leniency * setting: either {@code this} instance (if setting would not change), or newly * constructed instance. * * @since 2.9 */ public StdDateFormat withLenient(Boolean b) { if (_equals(b, _lenient)) { return this; } return new StdDateFormat(_timezone, _locale, b, _tzSerializedWithColon); } /** * "Mutant factory" method that will return an instance that has specified * handling of colon when serializing timezone (timezone either written * like {@code +0500} or {@code +05:00}): * either {@code this} instance (if setting would not change), or newly * constructed instance with desired setting for colon inclusion. *

* NOTE: does NOT affect deserialization as colon is optional accepted * but not required -- put another way, either serialization is accepted * by this class. * * @since 2.9.1 */ public StdDateFormat withColonInTimeZone(boolean b) { if (_tzSerializedWithColon == b) { return this; } return new StdDateFormat(_timezone, _locale, _lenient, b); } @Override public StdDateFormat clone() { // Although there is that much state to share, we do need to // orchestrate a bit, mostly since timezones may be changed return new StdDateFormat(_timezone, _locale, _lenient, _tzSerializedWithColon); } /** * Method for getting a non-shared DateFormat instance * that uses specified timezone and can handle simple ISO-8601 * compliant date format. * * @since 2.4 * * @deprecated Since 2.9 */ @Deprecated // since 2.9 public static DateFormat getISO8601Format(TimeZone tz, Locale loc) { return _cloneFormat(DATE_FORMAT_ISO8601, DATE_FORMAT_STR_ISO8601, tz, loc, null); } /** * Method for getting a non-shared DateFormat instance * that uses specific timezone and can handle RFC-1123 * compliant date format. * * @since 2.4 * * @deprecated Since 2.9 */ @Deprecated // since 2.9 public static DateFormat getRFC1123Format(TimeZone tz, Locale loc) { return _cloneFormat(DATE_FORMAT_RFC1123, DATE_FORMAT_STR_RFC1123, tz, loc, null); } /* /********************************************************** /* Public API, configuration /********************************************************** */ @Override // since 2.6 public TimeZone getTimeZone() { return _timezone; } @Override public void setTimeZone(TimeZone tz) { /* DateFormats are timezone-specific (via Calendar contained), * so need to reset instances if timezone changes: */ if (!tz.equals(_timezone)) { _clearFormats(); _timezone = tz; } } /** * Need to override since we need to keep track of leniency locally, * and not via underlying {@link Calendar} instance like base class * does. */ @Override // since 2.7 public void setLenient(boolean enabled) { Boolean newValue = Boolean.valueOf(enabled); if (!_equals(newValue, _lenient)) { _lenient = newValue; // and since leniency settings may have been used: _clearFormats(); } } @Override // since 2.7 public boolean isLenient() { // default is, I believe, true return (_lenient == null) || _lenient.booleanValue(); } /** * Accessor for checking whether this instance would include colon * within timezone serialization or not: if {code true}, timezone offset * is serialized like {@code -06:00}; if {code false} as {@code -0600}. *

* NOTE: only relevant for serialization (formatting), as deserialization * (parsing) always accepts optional colon but does not require it, regardless * of this setting. * * @return {@code true} if a colon is to be inserted between the hours and minutes * of the TZ offset when serializing as String; otherwise {@code false} * * @since 2.9.1 */ public boolean isColonIncludedInTimeZone() { return _tzSerializedWithColon; } /* /********************************************************** /* Public API, parsing /********************************************************** */ @Override public Date parse(String dateStr) throws ParseException { dateStr = dateStr.trim(); ParsePosition pos = new ParsePosition(0); Date dt = _parseDate(dateStr, pos); if (dt != null) { return dt; } StringBuilder sb = new StringBuilder(); for (String f : ALL_FORMATS) { if (sb.length() > 0) { sb.append("\", \""); } else { sb.append('"'); } sb.append(f); } sb.append('"'); throw new ParseException (String.format("Cannot parse date \"%s\": not compatible with any of standard forms (%s)", dateStr, sb.toString()), pos.getErrorIndex()); } // 24-Jun-2017, tatu: I don't think this ever gets called. So could... just not implement? @Override public Date parse(String dateStr, ParsePosition pos) { try { return _parseDate(dateStr, pos); } catch (ParseException e) { // may look weird but this is what `DateFormat` suggest to do... } return null; } protected Date _parseDate(String dateStr, ParsePosition pos) throws ParseException { if (looksLikeISO8601(dateStr)) { // also includes "plain" return parseAsISO8601(dateStr, pos); } // Also consider "stringified" simple time stamp int i = dateStr.length(); while (--i >= 0) { char ch = dateStr.charAt(i); if (ch < '0' || ch > '9') { // 07-Aug-2013, tatu: And [databind#267] points out that negative numbers should also work if (i > 0 || ch != '-') { break; } } } if ((i < 0) // let's just assume negative numbers are fine (can't be RFC-1123 anyway); check length for positive && (dateStr.charAt(0) == '-' || NumberInput.inLongRange(dateStr, false))) { return _parseDateFromLong(dateStr, pos); } // Otherwise, fall back to using RFC 1123. NOTE: call will NOT throw, just returns `null` return parseAsRFC1123(dateStr, pos); } /* /********************************************************** /* Public API, writing /********************************************************** */ @Override public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { TimeZone tz = _timezone; if (tz == null) { tz = DEFAULT_TIMEZONE; } _format(tz, _locale, date, toAppendTo); return toAppendTo; } protected void _format(TimeZone tz, Locale loc, Date date, StringBuffer buffer) { Calendar cal = _getCalendar(tz); cal.setTime(date); pad4(buffer, cal.get(Calendar.YEAR)); buffer.append('-'); pad2(buffer, cal.get(Calendar.MONTH) + 1); buffer.append('-'); pad2(buffer, cal.get(Calendar.DAY_OF_MONTH)); buffer.append('T'); pad2(buffer, cal.get(Calendar.HOUR_OF_DAY)); buffer.append(':'); pad2(buffer, cal.get(Calendar.MINUTE)); buffer.append(':'); pad2(buffer, cal.get(Calendar.SECOND)); buffer.append('.'); pad3(buffer, cal.get(Calendar.MILLISECOND)); int offset = tz.getOffset(cal.getTimeInMillis()); if (offset != 0) { int hours = Math.abs((offset / (60 * 1000)) / 60); int minutes = Math.abs((offset / (60 * 1000)) % 60); buffer.append(offset < 0 ? '-' : '+'); pad2(buffer, hours); if( _tzSerializedWithColon ) { buffer.append(':'); } pad2(buffer, minutes); } else { // 24-Jun-2017, tatu: While `Z` would be conveniently short, older specs // mandate use of full `+0000` // formatted.append('Z'); if( _tzSerializedWithColon ) { buffer.append("+00:00"); } else { buffer.append("+0000"); } } } private static void pad2(StringBuffer buffer, int value) { int tens = value / 10; if (tens == 0) { buffer.append('0'); } else { buffer.append((char) ('0' + tens)); value -= 10 * tens; } buffer.append((char) ('0' + value)); } private static void pad3(StringBuffer buffer, int value) { int h = value / 100; if (h == 0) { buffer.append('0'); } else { buffer.append((char) ('0' + h)); value -= (h * 100); } pad2(buffer, value); } private static void pad4(StringBuffer buffer, int value) { int h = value / 100; if (h == 0) { buffer.append('0').append('0'); } else { pad2(buffer, h); value -= (100 * h); } pad2(buffer, value); } /* /********************************************************** /* Std overrides /********************************************************** */ @Override public String toString() { return String.format("DateFormat %s: (timezone: %s, locale: %s, lenient: %s)", getClass().getName(), _timezone, _locale, _lenient); } public String toPattern() { // same as SimpleDateFormat StringBuilder sb = new StringBuilder(100); sb.append("[one of: '") .append(DATE_FORMAT_STR_ISO8601) .append("', '") .append(DATE_FORMAT_STR_RFC1123) .append("' (") ; sb.append(Boolean.FALSE.equals(_lenient) ? "strict" : "lenient") .append(")]"); return sb.toString(); } @Override // since 2.7[.2], as per [databind#1130] public boolean equals(Object o) { return (o == this); } @Override // since 2.7[.2], as per [databind#1130] public int hashCode() { return System.identityHashCode(this); } /* /********************************************************** /* Helper methods, parsing /********************************************************** */ /** * Helper method used to figure out if input looks like valid * ISO-8601 string. */ protected boolean looksLikeISO8601(String dateStr) { if (dateStr.length() >= 7 // really need 10, but... && Character.isDigit(dateStr.charAt(0)) && Character.isDigit(dateStr.charAt(3)) && dateStr.charAt(4) == '-' && Character.isDigit(dateStr.charAt(5)) ) { return true; } return false; } private Date _parseDateFromLong(String longStr, ParsePosition pos) throws ParseException { long ts; try { ts = NumberInput.parseLong(longStr); } catch (NumberFormatException e) { throw new ParseException(String.format( "Timestamp value %s out of 64-bit value range", longStr), pos.getErrorIndex()); } return new Date(ts); } protected Date parseAsISO8601(String dateStr, ParsePosition pos) throws ParseException { try { return _parseAsISO8601(dateStr, pos); } catch (IllegalArgumentException e) { throw new ParseException(String.format("Cannot parse date \"%s\", problem: %s", dateStr, e.getMessage()), pos.getErrorIndex()); } } protected Date _parseAsISO8601(String dateStr, ParsePosition bogus) throws IllegalArgumentException, ParseException { final int totalLen = dateStr.length(); // actually, one short-cut: if we end with "Z", must be UTC TimeZone tz = DEFAULT_TIMEZONE; if ((_timezone != null) && ('Z' != dateStr.charAt(totalLen-1))) { tz = _timezone; } Calendar cal = _getCalendar(tz); cal.clear(); String formatStr; if (totalLen <= 10) { Matcher m = PATTERN_PLAIN.matcher(dateStr); if (m.matches()) { int year = _parse4D(dateStr, 0); int month = _parse2D(dateStr, 5)-1; int day = _parse2D(dateStr, 8); cal.set(year, month, day, 0, 0, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTime(); } formatStr = DATE_FORMAT_STR_PLAIN; } else { Matcher m = PATTERN_ISO8601.matcher(dateStr); if (m.matches()) { // Important! START with optional time zone; otherwise Calendar will explode int start = m.start(2); int end = m.end(2); int len = end-start; if (len > 1) { // 0 -> none, 1 -> 'Z' // NOTE: first char is sign; then 2 digits, then optional colon, optional 2 digits int offsetSecs = _parse2D(dateStr, start+1) * 3600; // hours if (len >= 5) { offsetSecs += _parse2D(dateStr, end-2) * 60; // minutes } if (dateStr.charAt(start) == '-') { offsetSecs *= -1000; } else { offsetSecs *= 1000; } cal.set(Calendar.ZONE_OFFSET, offsetSecs); // 23-Jun-2017, tatu: Not sure why, but this appears to be needed too: cal.set(Calendar.DST_OFFSET, 0); } int year = _parse4D(dateStr, 0); int month = _parse2D(dateStr, 5)-1; int day = _parse2D(dateStr, 8); // So: 10 chars for date, then `T`, so starts at 11 int hour = _parse2D(dateStr, 11); int minute = _parse2D(dateStr, 14); // Seconds are actually optional... so int seconds; if ((totalLen > 16) && dateStr.charAt(16) == ':') { seconds = _parse2D(dateStr, 17); } else { seconds = 0; } cal.set(year, month, day, hour, minute, seconds); // Optional milliseconds start = m.start(1) + 1; end = m.end(1); int msecs = 0; if (start >= end) { // no fractional cal.set(Calendar.MILLISECOND, 0); } else { // first char is '.', but rest.... msecs = 0; final int fractLen = end-start; switch (fractLen) { default: // [databind#1745] Allow longer fractions... for now, cap at nanoseconds tho if (fractLen > 9) { // only allow up to nanos throw new ParseException(String.format( "Cannot parse date \"%s\": invalid fractional seconds '%s'; can use at most 9 digits", dateStr, m.group(1).substring(1) ), start); } // fall through case 3: msecs += (dateStr.charAt(start+2) - '0'); case 2: msecs += 10 * (dateStr.charAt(start+1) - '0'); case 1: msecs += 100 * (dateStr.charAt(start) - '0'); break; case 0: break; } cal.set(Calendar.MILLISECOND, msecs); } return cal.getTime(); } formatStr = DATE_FORMAT_STR_ISO8601; } throw new ParseException (String.format("Cannot parse date \"%s\": while it seems to fit format '%s', parsing fails (leniency? %s)", dateStr, formatStr, _lenient), // [databind#1742]: Might be able to give actual location, some day, but for now // we can't give anything more indicative 0); } private static int _parse4D(String str, int index) { return (1000 * (str.charAt(index) - '0')) + (100 * (str.charAt(index+1) - '0')) + (10 * (str.charAt(index+2) - '0')) + (str.charAt(index+3) - '0'); } private static int _parse2D(String str, int index) { return (10 * (str.charAt(index) - '0')) + (str.charAt(index+1) - '0'); } protected Date parseAsRFC1123(String dateStr, ParsePosition pos) { if (_formatRFC1123 == null) { _formatRFC1123 = _cloneFormat(DATE_FORMAT_RFC1123, DATE_FORMAT_STR_RFC1123, _timezone, _locale, _lenient); } return _formatRFC1123.parse(dateStr, pos); } /* /********************************************************** /* Helper methods, other /********************************************************** */ private final static DateFormat _cloneFormat(DateFormat df, String format, TimeZone tz, Locale loc, Boolean lenient) { if (!loc.equals(DEFAULT_LOCALE)) { df = new SimpleDateFormat(format, loc); df.setTimeZone((tz == null) ? DEFAULT_TIMEZONE : tz); } else { df = (DateFormat) df.clone(); if (tz != null) { df.setTimeZone(tz); } } if (lenient != null) { df.setLenient(lenient.booleanValue()); } return df; } protected void _clearFormats() { _formatRFC1123 = null; } protected Calendar _getCalendar(TimeZone tz) { Calendar cal = _calendar; if (cal == null ) { _calendar = cal = (Calendar)CALENDAR.clone(); } if (!cal.getTimeZone().equals(tz) ) { cal.setTimeZone(tz); } cal.setLenient(isLenient()); return cal; } protected static boolean _equals(T value1, T value2) { if (value1 == value2) { return true; } return (value1 != null) && value1.equals(value2); } } TokenBuffer.java000066400000000000000000002007421325620701100345070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.TreeMap; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.base.ParserMinimalBase; import com.fasterxml.jackson.core.json.JsonWriteContext; import com.fasterxml.jackson.core.util.ByteArrayBuilder; import com.fasterxml.jackson.databind.*; /** * Utility class used for efficient storage of {@link JsonToken} * sequences, needed for temporary buffering. * Space efficient for different sequence lengths (especially so for smaller * ones; but not significantly less efficient for larger), highly efficient * for linear iteration and appending. Implemented as segmented/chunked * linked list of tokens; only modifications are via appends. *

* Note that before version 2.0, this class was located in the "core" * bundle, not data-binding; but since it was only used by data binding, * was moved here to reduce size of core package */ public class TokenBuffer /* Won't use JsonGeneratorBase, to minimize overhead for validity * checking */ extends JsonGenerator { protected final static int DEFAULT_GENERATOR_FEATURES = JsonGenerator.Feature.collectDefaults(); /* /********************************************************** /* Configuration /********************************************************** */ /** * Object codec to use for stream-based object * conversion through parser/generator interfaces. If null, * such methods cannot be used. */ protected ObjectCodec _objectCodec; /** * Parse context from "parent" parser (one from which content to buffer is read, * if specified). Used, if available, when reading content, to present full * context as if content was read from the original parser: this is useful * in error reporting and sometimes processing as well. */ protected JsonStreamContext _parentContext; /** * Bit flag composed of bits that indicate which * {@link com.fasterxml.jackson.core.JsonGenerator.Feature}s * are enabled. *

* NOTE: most features have no effect on this class */ protected int _generatorFeatures; protected boolean _closed; /** * @since 2.3 */ protected boolean _hasNativeTypeIds; /** * @since 2.3 */ protected boolean _hasNativeObjectIds; /** * @since 2.3 */ protected boolean _mayHaveNativeIds; /** * Flag set during construction, if use of {@link BigDecimal} is to be forced * on all floating-point values. * * @since 2.7 */ protected boolean _forceBigDecimal; /* /********************************************************** /* Token buffering state /********************************************************** */ /** * First segment, for contents this buffer has */ protected Segment _first; /** * Last segment of this buffer, one that is used * for appending more tokens */ protected Segment _last; /** * Offset within last segment, */ protected int _appendAt; /** * If native type ids supported, this is the id for following * value (or first token of one) to be written. */ protected Object _typeId; /** * If native object ids supported, this is the id for following * value (or first token of one) to be written. */ protected Object _objectId; /** * Do we currently have a native type or object id buffered? */ protected boolean _hasNativeId = false; /* /********************************************************** /* Output state /********************************************************** */ protected JsonWriteContext _writeContext; /* /********************************************************** /* Life-cycle /********************************************************** */ /** * @param codec Object codec to use for stream-based object * conversion through parser/generator interfaces. If null, * such methods cannot be used. * @param hasNativeIds Whether resulting {@link JsonParser} (if created) * is considered to support native type and object ids */ public TokenBuffer(ObjectCodec codec, boolean hasNativeIds) { _objectCodec = codec; _generatorFeatures = DEFAULT_GENERATOR_FEATURES; _writeContext = JsonWriteContext.createRootContext(null); // at first we have just one segment _first = _last = new Segment(); _appendAt = 0; _hasNativeTypeIds = hasNativeIds; _hasNativeObjectIds = hasNativeIds; _mayHaveNativeIds = _hasNativeTypeIds | _hasNativeObjectIds; } /** * @since 2.3 */ public TokenBuffer(JsonParser p) { this(p, null); } /** * @since 2.7 */ public TokenBuffer(JsonParser p, DeserializationContext ctxt) { _objectCodec = p.getCodec(); _parentContext = p.getParsingContext(); _generatorFeatures = DEFAULT_GENERATOR_FEATURES; _writeContext = JsonWriteContext.createRootContext(null); // at first we have just one segment _first = _last = new Segment(); _appendAt = 0; _hasNativeTypeIds = p.canReadTypeId(); _hasNativeObjectIds = p.canReadObjectId(); _mayHaveNativeIds = _hasNativeTypeIds | _hasNativeObjectIds; _forceBigDecimal = (ctxt == null) ? false : ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS); } /** * Convenience method, equivalent to: *

     * TokenBuffer b = new TokenBuffer(p);
     * b.copyCurrentStructure(p);
     * return b;
     *
* * @since 2.9 */ public static TokenBuffer asCopyOfValue(JsonParser p) throws IOException { TokenBuffer b = new TokenBuffer(p); b.copyCurrentStructure(p); return b; } /** * Method that allows explicitly specifying parent parse context to associate * with contents of this buffer. Usually context is assigned at construction, * based on given parser; but it is not always available, and may not contain * intended context. * * @since 2.9 */ public TokenBuffer overrideParentContext(JsonStreamContext ctxt) { _parentContext = ctxt; return this; } /** * @since 2.7 */ public TokenBuffer forceUseOfBigDecimal(boolean b) { _forceBigDecimal = b; return this; } @Override public Version version() { return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION; } /** * Method used to create a {@link JsonParser} that can read contents * stored in this buffer. Will use default _objectCodec for * object conversions. *

* Note: instances are not synchronized, that is, they are not thread-safe * if there are concurrent appends to the underlying buffer. * * @return Parser that can be used for reading contents stored in this buffer */ public JsonParser asParser() { return asParser(_objectCodec); } /** * Same as: *

     *  JsonParser p = asParser();
     *  p.nextToken();
     *  return p;
     *
* * @since 2.9 */ public JsonParser asParserOnFirstToken() throws IOException { JsonParser p = asParser(_objectCodec); p.nextToken(); return p; } /** * Method used to create a {@link JsonParser} that can read contents * stored in this buffer. *

* Note: instances are not synchronized, that is, they are not thread-safe * if there are concurrent appends to the underlying buffer. * * @param codec Object codec to use for stream-based object * conversion through parser/generator interfaces. If null, * such methods cannot be used. * * @return Parser that can be used for reading contents stored in this buffer */ public JsonParser asParser(ObjectCodec codec) { return new Parser(_first, codec, _hasNativeTypeIds, _hasNativeObjectIds, _parentContext); } /** * @param src Parser to use for accessing source information * like location, configured codec */ public JsonParser asParser(JsonParser src) { Parser p = new Parser(_first, src.getCodec(), _hasNativeTypeIds, _hasNativeObjectIds, _parentContext); p.setLocation(src.getTokenLocation()); return p; } /* /********************************************************** /* Additional accessors /********************************************************** */ public JsonToken firstToken() { // no need to null check; never create without `_first` return _first.type(0); } /* /********************************************************** /* Other custom methods not needed for implementing interfaces /********************************************************** */ /** * Helper method that will append contents of given buffer into this * buffer. * Not particularly optimized; can be made faster if there is need. * * @return This buffer */ @SuppressWarnings("resource") public TokenBuffer append(TokenBuffer other) throws IOException { // Important? If source has native ids, need to store if (!_hasNativeTypeIds) { _hasNativeTypeIds = other.canWriteTypeId(); } if (!_hasNativeObjectIds) { _hasNativeObjectIds = other.canWriteObjectId(); } _mayHaveNativeIds = _hasNativeTypeIds | _hasNativeObjectIds; JsonParser p = other.asParser(); while (p.nextToken() != null) { copyCurrentStructure(p); } return this; } /** * Helper method that will write all contents of this buffer * using given {@link JsonGenerator}. *

* Note: this method would be enough to implement * JsonSerializer for TokenBuffer type; * but we cannot have upwards * references (from core to mapper package); and as such we also * cannot take second argument. */ public void serialize(JsonGenerator gen) throws IOException { Segment segment = _first; int ptr = -1; final boolean checkIds = _mayHaveNativeIds; boolean hasIds = checkIds && (segment.hasIds()); while (true) { if (++ptr >= Segment.TOKENS_PER_SEGMENT) { ptr = 0; segment = segment.next(); if (segment == null) break; hasIds = checkIds && (segment.hasIds()); } JsonToken t = segment.type(ptr); if (t == null) break; if (hasIds) { Object id = segment.findObjectId(ptr); if (id != null) { gen.writeObjectId(id); } id = segment.findTypeId(ptr); if (id != null) { gen.writeTypeId(id); } } // Note: copied from 'copyCurrentEvent'... switch (t) { case START_OBJECT: gen.writeStartObject(); break; case END_OBJECT: gen.writeEndObject(); break; case START_ARRAY: gen.writeStartArray(); break; case END_ARRAY: gen.writeEndArray(); break; case FIELD_NAME: { // 13-Dec-2010, tatu: Maybe we should start using different type tokens to reduce casting? Object ob = segment.get(ptr); if (ob instanceof SerializableString) { gen.writeFieldName((SerializableString) ob); } else { gen.writeFieldName((String) ob); } } break; case VALUE_STRING: { Object ob = segment.get(ptr); if (ob instanceof SerializableString) { gen.writeString((SerializableString) ob); } else { gen.writeString((String) ob); } } break; case VALUE_NUMBER_INT: { Object n = segment.get(ptr); if (n instanceof Integer) { gen.writeNumber((Integer) n); } else if (n instanceof BigInteger) { gen.writeNumber((BigInteger) n); } else if (n instanceof Long) { gen.writeNumber((Long) n); } else if (n instanceof Short) { gen.writeNumber((Short) n); } else { gen.writeNumber(((Number) n).intValue()); } } break; case VALUE_NUMBER_FLOAT: { Object n = segment.get(ptr); if (n instanceof Double) { gen.writeNumber(((Double) n).doubleValue()); } else if (n instanceof BigDecimal) { gen.writeNumber((BigDecimal) n); } else if (n instanceof Float) { gen.writeNumber(((Float) n).floatValue()); } else if (n == null) { gen.writeNull(); } else if (n instanceof String) { gen.writeNumber((String) n); } else { throw new JsonGenerationException(String.format( "Unrecognized value type for VALUE_NUMBER_FLOAT: %s, cannot serialize", n.getClass().getName()), gen); } } break; case VALUE_TRUE: gen.writeBoolean(true); break; case VALUE_FALSE: gen.writeBoolean(false); break; case VALUE_NULL: gen.writeNull(); break; case VALUE_EMBEDDED_OBJECT: { Object value = segment.get(ptr); // 01-Sep-2016, tatu: as per [databind#1361], should use `writeEmbeddedObject()`; // however, may need to consider alternatives for some well-known types // first if (value instanceof RawValue) { ((RawValue) value).serialize(gen); } else if (value instanceof JsonSerializable) { gen.writeObject(value); } else { gen.writeEmbeddedObject(value); } } break; default: throw new RuntimeException("Internal error: should never end up through this code path"); } } } /** * Helper method used by standard deserializer. * * @since 2.3 */ public TokenBuffer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.getCurrentTokenId() != JsonToken.FIELD_NAME.id()) { copyCurrentStructure(p); return this; } /* 28-Oct-2014, tatu: As per [databind#592], need to support a special case of starting from * FIELD_NAME, which is taken to mean that we are missing START_OBJECT, but need * to assume one did exist. */ JsonToken t; writeStartObject(); do { copyCurrentStructure(p); } while ((t = p.nextToken()) == JsonToken.FIELD_NAME); if (t != JsonToken.END_OBJECT) { ctxt.reportWrongTokenException(TokenBuffer.class, JsonToken.END_OBJECT, "Expected END_OBJECT after copying contents of a JsonParser into TokenBuffer, got "+t); // never gets here } writeEndObject(); return this; } @Override @SuppressWarnings("resource") public String toString() { // Let's print up to 100 first tokens... final int MAX_COUNT = 100; StringBuilder sb = new StringBuilder(); sb.append("[TokenBuffer: "); /* sb.append("NativeTypeIds=").append(_hasNativeTypeIds).append(","); sb.append("NativeObjectIds=").append(_hasNativeObjectIds).append(","); */ JsonParser jp = asParser(); int count = 0; final boolean hasNativeIds = _hasNativeTypeIds || _hasNativeObjectIds; while (true) { JsonToken t; try { t = jp.nextToken(); if (t == null) break; if (hasNativeIds) { _appendNativeIds(sb); } if (count < MAX_COUNT) { if (count > 0) { sb.append(", "); } sb.append(t.toString()); if (t == JsonToken.FIELD_NAME) { sb.append('('); sb.append(jp.getCurrentName()); sb.append(')'); } } } catch (IOException ioe) { // should never occur throw new IllegalStateException(ioe); } ++count; } if (count >= MAX_COUNT) { sb.append(" ... (truncated ").append(count-MAX_COUNT).append(" entries)"); } sb.append(']'); return sb.toString(); } private final void _appendNativeIds(StringBuilder sb) { Object objectId = _last.findObjectId(_appendAt-1); if (objectId != null) { sb.append("[objectId=").append(String.valueOf(objectId)).append(']'); } Object typeId = _last.findTypeId(_appendAt-1); if (typeId != null) { sb.append("[typeId=").append(String.valueOf(typeId)).append(']'); } } /* /********************************************************** /* JsonGenerator implementation: configuration /********************************************************** */ @Override public JsonGenerator enable(Feature f) { _generatorFeatures |= f.getMask(); return this; } @Override public JsonGenerator disable(Feature f) { _generatorFeatures &= ~f.getMask(); return this; } //public JsonGenerator configure(SerializationFeature f, boolean state) { } @Override public boolean isEnabled(Feature f) { return (_generatorFeatures & f.getMask()) != 0; } @Override public int getFeatureMask() { return _generatorFeatures; } @Override @Deprecated public JsonGenerator setFeatureMask(int mask) { _generatorFeatures = mask; return this; } @Override public JsonGenerator overrideStdFeatures(int values, int mask) { int oldState = getFeatureMask(); _generatorFeatures = (oldState & ~mask) | (values & mask); return this; } @Override public JsonGenerator useDefaultPrettyPrinter() { // No-op: we don't indent return this; } @Override public JsonGenerator setCodec(ObjectCodec oc) { _objectCodec = oc; return this; } @Override public ObjectCodec getCodec() { return _objectCodec; } @Override public final JsonWriteContext getOutputContext() { return _writeContext; } /* /********************************************************** /* JsonGenerator implementation: capability introspection /********************************************************** */ /** * Since we can efficiently store byte[], yes. */ @Override public boolean canWriteBinaryNatively() { return true; } /* /********************************************************** /* JsonGenerator implementation: low-level output handling /********************************************************** */ @Override public void flush() throws IOException { /* NOP */ } @Override public void close() throws IOException { _closed = true; } @Override public boolean isClosed() { return _closed; } /* /********************************************************** /* JsonGenerator implementation: write methods, structural /********************************************************** */ @Override public final void writeStartArray() throws IOException { _writeContext.writeValue(); _append(JsonToken.START_ARRAY); _writeContext = _writeContext.createChildArrayContext(); } @Override public final void writeEndArray() throws IOException { _append(JsonToken.END_ARRAY); // Let's allow unbalanced tho... i.e. not run out of root level, ever JsonWriteContext c = _writeContext.getParent(); if (c != null) { _writeContext = c; } } @Override public final void writeStartObject() throws IOException { _writeContext.writeValue(); _append(JsonToken.START_OBJECT); _writeContext = _writeContext.createChildObjectContext(); } @Override // since 2.8 public void writeStartObject(Object forValue) throws IOException { _writeContext.writeValue(); _append(JsonToken.START_OBJECT); JsonWriteContext ctxt = _writeContext.createChildObjectContext(); _writeContext = ctxt; if (forValue != null) { ctxt.setCurrentValue(forValue); } } @Override public final void writeEndObject() throws IOException { _append(JsonToken.END_OBJECT); // Let's allow unbalanced tho... i.e. not run out of root level, ever JsonWriteContext c = _writeContext.getParent(); if (c != null) { _writeContext = c; } } @Override public final void writeFieldName(String name) throws IOException { _writeContext.writeFieldName(name); _append(JsonToken.FIELD_NAME, name); } @Override public void writeFieldName(SerializableString name) throws IOException { _writeContext.writeFieldName(name.getValue()); _append(JsonToken.FIELD_NAME, name); } /* /********************************************************** /* JsonGenerator implementation: write methods, textual /********************************************************** */ @Override public void writeString(String text) throws IOException { if (text == null) { writeNull(); } else { _appendValue(JsonToken.VALUE_STRING, text); } } @Override public void writeString(char[] text, int offset, int len) throws IOException { writeString(new String(text, offset, len)); } @Override public void writeString(SerializableString text) throws IOException { if (text == null) { writeNull(); } else { _appendValue(JsonToken.VALUE_STRING, text); } } @Override public void writeRawUTF8String(byte[] text, int offset, int length) throws IOException { // could add support for buffering if we really want it... _reportUnsupportedOperation(); } @Override public void writeUTF8String(byte[] text, int offset, int length) throws IOException { // could add support for buffering if we really want it... _reportUnsupportedOperation(); } @Override public void writeRaw(String text) throws IOException { _reportUnsupportedOperation(); } @Override public void writeRaw(String text, int offset, int len) throws IOException { _reportUnsupportedOperation(); } @Override public void writeRaw(SerializableString text) throws IOException { _reportUnsupportedOperation(); } @Override public void writeRaw(char[] text, int offset, int len) throws IOException { _reportUnsupportedOperation(); } @Override public void writeRaw(char c) throws IOException { _reportUnsupportedOperation(); } @Override public void writeRawValue(String text) throws IOException { _appendValue(JsonToken.VALUE_EMBEDDED_OBJECT, new RawValue(text)); } @Override public void writeRawValue(String text, int offset, int len) throws IOException { if (offset > 0 || len != text.length()) { text = text.substring(offset, offset+len); } _appendValue(JsonToken.VALUE_EMBEDDED_OBJECT, new RawValue(text)); } @Override public void writeRawValue(char[] text, int offset, int len) throws IOException { _appendValue(JsonToken.VALUE_EMBEDDED_OBJECT, new String(text, offset, len)); } /* /********************************************************** /* JsonGenerator implementation: write methods, primitive types /********************************************************** */ @Override public void writeNumber(short i) throws IOException { _appendValue(JsonToken.VALUE_NUMBER_INT, Short.valueOf(i)); } @Override public void writeNumber(int i) throws IOException { _appendValue(JsonToken.VALUE_NUMBER_INT, Integer.valueOf(i)); } @Override public void writeNumber(long l) throws IOException { _appendValue(JsonToken.VALUE_NUMBER_INT, Long.valueOf(l)); } @Override public void writeNumber(double d) throws IOException { _appendValue(JsonToken.VALUE_NUMBER_FLOAT, Double.valueOf(d)); } @Override public void writeNumber(float f) throws IOException { _appendValue(JsonToken.VALUE_NUMBER_FLOAT, Float.valueOf(f)); } @Override public void writeNumber(BigDecimal dec) throws IOException { if (dec == null) { writeNull(); } else { _appendValue(JsonToken.VALUE_NUMBER_FLOAT, dec); } } @Override public void writeNumber(BigInteger v) throws IOException { if (v == null) { writeNull(); } else { _appendValue(JsonToken.VALUE_NUMBER_INT, v); } } @Override public void writeNumber(String encodedValue) throws IOException { /* 03-Dec-2010, tatu: related to [JACKSON-423], should try to keep as numeric * identity as long as possible */ _appendValue(JsonToken.VALUE_NUMBER_FLOAT, encodedValue); } @Override public void writeBoolean(boolean state) throws IOException { _appendValue(state ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE); } @Override public void writeNull() throws IOException { _appendValue(JsonToken.VALUE_NULL); } /* /*********************************************************** /* JsonGenerator implementation: write methods for POJOs/trees /*********************************************************** */ @Override public void writeObject(Object value) throws IOException { if (value == null) { writeNull(); return; } Class raw = value.getClass(); if (raw == byte[].class || (value instanceof RawValue)) { _appendValue(JsonToken.VALUE_EMBEDDED_OBJECT, value); return; } if (_objectCodec == null) { /* 28-May-2014, tatu: Tricky choice here; if no codec, should we * err out, or just embed? For now, do latter. */ // throw new JsonMappingException("No ObjectCodec configured for TokenBuffer, writeObject() called"); _appendValue(JsonToken.VALUE_EMBEDDED_OBJECT, value); } else { _objectCodec.writeValue(this, value); } } @Override public void writeTree(TreeNode node) throws IOException { if (node == null) { writeNull(); return; } if (_objectCodec == null) { // as with 'writeObject()', is codec optional? _appendValue(JsonToken.VALUE_EMBEDDED_OBJECT, node); } else { _objectCodec.writeTree(this, node); } } /* /*********************************************************** /* JsonGenerator implementation; binary /*********************************************************** */ @Override public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) throws IOException { /* 31-Dec-2009, tatu: can do this using multiple alternatives; but for * now, let's try to limit number of conversions. * The only (?) tricky thing is that of whether to preserve variant, * seems pointless, so let's not worry about it unless there's some * compelling reason to. */ byte[] copy = new byte[len]; System.arraycopy(data, offset, copy, 0, len); writeObject(copy); } /** * Although we could support this method, it does not necessarily make * sense: we cannot make good use of streaming because buffer must * hold all the data. Because of this, currently this will simply * throw {@link UnsupportedOperationException} */ @Override public int writeBinary(Base64Variant b64variant, InputStream data, int dataLength) { throw new UnsupportedOperationException(); } /* /*********************************************************** /* JsonGenerator implementation: native ids /*********************************************************** */ @Override public boolean canWriteTypeId() { return _hasNativeTypeIds; } @Override public boolean canWriteObjectId() { return _hasNativeObjectIds; } @Override public void writeTypeId(Object id) { _typeId = id; _hasNativeId = true; } @Override public void writeObjectId(Object id) { _objectId = id; _hasNativeId = true; } @Override // since 2.8 public void writeEmbeddedObject(Object object) throws IOException { _appendValue(JsonToken.VALUE_EMBEDDED_OBJECT, object); } /* /********************************************************** /* JsonGenerator implementation; pass-through copy /********************************************************** */ @Override public void copyCurrentEvent(JsonParser p) throws IOException { if (_mayHaveNativeIds) { _checkNativeIds(p); } switch (p.getCurrentToken()) { case START_OBJECT: writeStartObject(); break; case END_OBJECT: writeEndObject(); break; case START_ARRAY: writeStartArray(); break; case END_ARRAY: writeEndArray(); break; case FIELD_NAME: writeFieldName(p.getCurrentName()); break; case VALUE_STRING: if (p.hasTextCharacters()) { writeString(p.getTextCharacters(), p.getTextOffset(), p.getTextLength()); } else { writeString(p.getText()); } break; case VALUE_NUMBER_INT: switch (p.getNumberType()) { case INT: writeNumber(p.getIntValue()); break; case BIG_INTEGER: writeNumber(p.getBigIntegerValue()); break; default: writeNumber(p.getLongValue()); } break; case VALUE_NUMBER_FLOAT: if (_forceBigDecimal) { /* 10-Oct-2015, tatu: Ideally we would first determine whether underlying * number is already decoded into a number (in which case might as well * access as number); or is still retained as text (in which case we * should further defer decoding that may not need BigDecimal): */ writeNumber(p.getDecimalValue()); } else { switch (p.getNumberType()) { case BIG_DECIMAL: writeNumber(p.getDecimalValue()); break; case FLOAT: writeNumber(p.getFloatValue()); break; default: writeNumber(p.getDoubleValue()); } } break; case VALUE_TRUE: writeBoolean(true); break; case VALUE_FALSE: writeBoolean(false); break; case VALUE_NULL: writeNull(); break; case VALUE_EMBEDDED_OBJECT: writeObject(p.getEmbeddedObject()); break; default: throw new RuntimeException("Internal error: should never end up through this code path"); } } @Override public void copyCurrentStructure(JsonParser p) throws IOException { JsonToken t = p.getCurrentToken(); // Let's handle field-name separately first if (t == JsonToken.FIELD_NAME) { if (_mayHaveNativeIds) { _checkNativeIds(p); } writeFieldName(p.getCurrentName()); t = p.nextToken(); // fall-through to copy the associated value } if (_mayHaveNativeIds) { _checkNativeIds(p); } switch (t) { case START_ARRAY: writeStartArray(); while (p.nextToken() != JsonToken.END_ARRAY) { copyCurrentStructure(p); } writeEndArray(); break; case START_OBJECT: writeStartObject(); while (p.nextToken() != JsonToken.END_OBJECT) { copyCurrentStructure(p); } writeEndObject(); break; default: // others are simple: copyCurrentEvent(p); } } private final void _checkNativeIds(JsonParser jp) throws IOException { if ((_typeId = jp.getTypeId()) != null) { _hasNativeId = true; } if ((_objectId = jp.getObjectId()) != null) { _hasNativeId = true; } } /* /********************************************************** /* Internal methods /********************************************************** */ protected final void _append(JsonToken type) { Segment next = _hasNativeId ? _last.append(_appendAt, type, _objectId, _typeId) : _last.append(_appendAt, type); if (next == null) { ++_appendAt; } else { _last = next; _appendAt = 1; // since we added first at 0 } } protected final void _append(JsonToken type, Object value) { Segment next = _hasNativeId ? _last.append(_appendAt, type, value, _objectId, _typeId) : _last.append(_appendAt, type, value); if (next == null) { ++_appendAt; } else { _last = next; _appendAt = 1; } } /** * Similar to {@link #_append(JsonToken)} but also updates context with * knowledge that a scalar value was written * * @since 2.6.4 */ protected final void _appendValue(JsonToken type) { _writeContext.writeValue(); Segment next = _hasNativeId ? _last.append(_appendAt, type, _objectId, _typeId) : _last.append(_appendAt, type); if (next == null) { ++_appendAt; } else { _last = next; _appendAt = 1; // since we added first at 0 } } /** * Similar to {@link #_append(JsonToken,Object)} but also updates context with * knowledge that a scalar value was written * * @since 2.6.4 */ protected final void _appendValue(JsonToken type, Object value) { _writeContext.writeValue(); Segment next = _hasNativeId ? _last.append(_appendAt, type, value, _objectId, _typeId) : _last.append(_appendAt, type, value); if (next == null) { ++_appendAt; } else { _last = next; _appendAt = 1; } } // 21-Oct-2016, tatu: Does not seem to be used or needed /* protected final void _appendRaw(int rawType, Object value) { Segment next = _hasNativeId ? _last.appendRaw(_appendAt, rawType, value, _objectId, _typeId) : _last.appendRaw(_appendAt, rawType, value); if (next == null) { ++_appendAt; } else { _last = next; _appendAt = 1; } } */ @Override protected void _reportUnsupportedOperation() { throw new UnsupportedOperationException("Called operation not supported for TokenBuffer"); } /* /********************************************************** /* Supporting classes /********************************************************** */ protected final static class Parser extends ParserMinimalBase { /* /********************************************************** /* Configuration /********************************************************** */ protected ObjectCodec _codec; /** * @since 2.3 */ protected final boolean _hasNativeTypeIds; /** * @since 2.3 */ protected final boolean _hasNativeObjectIds; protected final boolean _hasNativeIds; /* /********************************************************** /* Parsing state /********************************************************** */ /** * Currently active segment */ protected Segment _segment; /** * Pointer to current token within current segment */ protected int _segmentPtr; /** * Information about parser context, context in which * the next token is to be parsed (root, array, object). */ protected TokenBufferReadContext _parsingContext; protected boolean _closed; protected transient ByteArrayBuilder _byteBuilder; protected JsonLocation _location = null; /* /********************************************************** /* Construction, init /********************************************************** */ @Deprecated // since 2.9 public Parser(Segment firstSeg, ObjectCodec codec, boolean hasNativeTypeIds, boolean hasNativeObjectIds) { this(firstSeg, codec, hasNativeTypeIds, hasNativeObjectIds, null); } public Parser(Segment firstSeg, ObjectCodec codec, boolean hasNativeTypeIds, boolean hasNativeObjectIds, JsonStreamContext parentContext) { super(0); _segment = firstSeg; _segmentPtr = -1; // not yet read _codec = codec; _parsingContext = TokenBufferReadContext.createRootContext(parentContext); _hasNativeTypeIds = hasNativeTypeIds; _hasNativeObjectIds = hasNativeObjectIds; _hasNativeIds = (hasNativeTypeIds | hasNativeObjectIds); } public void setLocation(JsonLocation l) { _location = l; } @Override public ObjectCodec getCodec() { return _codec; } @Override public void setCodec(ObjectCodec c) { _codec = c; } @Override public Version version() { return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION; } /* /********************************************************** /* Extended API beyond JsonParser /********************************************************** */ public JsonToken peekNextToken() throws IOException { // closed? nothing more to peek, either if (_closed) return null; Segment seg = _segment; int ptr = _segmentPtr+1; if (ptr >= Segment.TOKENS_PER_SEGMENT) { ptr = 0; seg = (seg == null) ? null : seg.next(); } return (seg == null) ? null : seg.type(ptr); } /* /********************************************************** /* Closeable implementation /********************************************************** */ @Override public void close() throws IOException { if (!_closed) { _closed = true; } } /* /********************************************************** /* Public API, traversal /********************************************************** */ @Override public JsonToken nextToken() throws IOException { // If we are closed, nothing more to do if (_closed || (_segment == null)) return null; // Ok, then: any more tokens? if (++_segmentPtr >= Segment.TOKENS_PER_SEGMENT) { _segmentPtr = 0; _segment = _segment.next(); if (_segment == null) { return null; } } _currToken = _segment.type(_segmentPtr); // Field name? Need to update context if (_currToken == JsonToken.FIELD_NAME) { Object ob = _currentObject(); String name = (ob instanceof String) ? ((String) ob) : ob.toString(); _parsingContext.setCurrentName(name); } else if (_currToken == JsonToken.START_OBJECT) { _parsingContext = _parsingContext.createChildObjectContext(); } else if (_currToken == JsonToken.START_ARRAY) { _parsingContext = _parsingContext.createChildArrayContext(); } else if (_currToken == JsonToken.END_OBJECT || _currToken == JsonToken.END_ARRAY) { // Closing JSON Object/Array? Close matching context _parsingContext = _parsingContext.parentOrCopy(); } return _currToken; } @Override public String nextFieldName() throws IOException { // inlined common case from nextToken() if (_closed || (_segment == null)) { return null; } int ptr = _segmentPtr+1; if ((ptr < Segment.TOKENS_PER_SEGMENT) && (_segment.type(ptr) == JsonToken.FIELD_NAME)) { _segmentPtr = ptr; _currToken = JsonToken.FIELD_NAME; Object ob = _segment.get(ptr); // inlined _currentObject(); String name = (ob instanceof String) ? ((String) ob) : ob.toString(); _parsingContext.setCurrentName(name); return name; } return (nextToken() == JsonToken.FIELD_NAME) ? getCurrentName() : null; } @Override public boolean isClosed() { return _closed; } /* /********************************************************** /* Public API, token accessors /********************************************************** */ @Override public JsonStreamContext getParsingContext() { return _parsingContext; } @Override public JsonLocation getTokenLocation() { return getCurrentLocation(); } @Override public JsonLocation getCurrentLocation() { return (_location == null) ? JsonLocation.NA : _location; } @Override public String getCurrentName() { // 25-Jun-2015, tatu: as per [databind#838], needs to be same as ParserBase if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { JsonStreamContext parent = _parsingContext.getParent(); return parent.getCurrentName(); } return _parsingContext.getCurrentName(); } @Override public void overrideCurrentName(String name) { // Simple, but need to look for START_OBJECT/ARRAY's "off-by-one" thing: JsonStreamContext ctxt = _parsingContext; if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { ctxt = ctxt.getParent(); } if (ctxt instanceof TokenBufferReadContext) { try { ((TokenBufferReadContext) ctxt).setCurrentName(name); } catch (IOException e) { throw new RuntimeException(e); } } } /* /********************************************************** /* Public API, access to token information, text /********************************************************** */ @Override public String getText() { // common cases first: if (_currToken == JsonToken.VALUE_STRING || _currToken == JsonToken.FIELD_NAME) { Object ob = _currentObject(); if (ob instanceof String) { return (String) ob; } return ClassUtil.nullOrToString(ob); } if (_currToken == null) { return null; } switch (_currToken) { case VALUE_NUMBER_INT: case VALUE_NUMBER_FLOAT: return ClassUtil.nullOrToString(_currentObject()); default: return _currToken.asString(); } } @Override public char[] getTextCharacters() { String str = getText(); return (str == null) ? null : str.toCharArray(); } @Override public int getTextLength() { String str = getText(); return (str == null) ? 0 : str.length(); } @Override public int getTextOffset() { return 0; } @Override public boolean hasTextCharacters() { // We never have raw buffer available, so: return false; } /* /********************************************************** /* Public API, access to token information, numeric /********************************************************** */ @Override public boolean isNaN() { // can only occur for floating-point numbers if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) { Object value = _currentObject(); if (value instanceof Double) { Double v = (Double) value; return v.isNaN() || v.isInfinite(); } if (value instanceof Float) { Float v = (Float) value; return v.isNaN() || v.isInfinite(); } } return false; } @Override public BigInteger getBigIntegerValue() throws IOException { Number n = getNumberValue(); if (n instanceof BigInteger) { return (BigInteger) n; } if (getNumberType() == NumberType.BIG_DECIMAL) { return ((BigDecimal) n).toBigInteger(); } // int/long is simple, but let's also just truncate float/double: return BigInteger.valueOf(n.longValue()); } @Override public BigDecimal getDecimalValue() throws IOException { Number n = getNumberValue(); if (n instanceof BigDecimal) { return (BigDecimal) n; } switch (getNumberType()) { case INT: case LONG: return BigDecimal.valueOf(n.longValue()); case BIG_INTEGER: return new BigDecimal((BigInteger) n); default: } // float or double return BigDecimal.valueOf(n.doubleValue()); } @Override public double getDoubleValue() throws IOException { return getNumberValue().doubleValue(); } @Override public float getFloatValue() throws IOException { return getNumberValue().floatValue(); } @Override public int getIntValue() throws IOException { Number n = (_currToken == JsonToken.VALUE_NUMBER_INT) ? ((Number) _currentObject()) : getNumberValue(); if ((n instanceof Integer) || _smallerThanInt(n)) { return n.intValue(); } return _convertNumberToInt(n); } @Override public long getLongValue() throws IOException { Number n = (_currToken == JsonToken.VALUE_NUMBER_INT) ? ((Number) _currentObject()) : getNumberValue(); if ((n instanceof Long) || _smallerThanLong(n)) { return n.longValue(); } return _convertNumberToLong(n); } @Override public NumberType getNumberType() throws IOException { Number n = getNumberValue(); if (n instanceof Integer) return NumberType.INT; if (n instanceof Long) return NumberType.LONG; if (n instanceof Double) return NumberType.DOUBLE; if (n instanceof BigDecimal) return NumberType.BIG_DECIMAL; if (n instanceof BigInteger) return NumberType.BIG_INTEGER; if (n instanceof Float) return NumberType.FLOAT; if (n instanceof Short) return NumberType.INT; // should be SHORT return null; } @Override public final Number getNumberValue() throws IOException { _checkIsNumber(); Object value = _currentObject(); if (value instanceof Number) { return (Number) value; } // Difficult to really support numbers-as-Strings; but let's try. // NOTE: no access to DeserializationConfig, unfortunately, so cannot // try to determine Double/BigDecimal preference... if (value instanceof String) { String str = (String) value; if (str.indexOf('.') >= 0) { return Double.parseDouble(str); } return Long.parseLong(str); } if (value == null) { return null; } throw new IllegalStateException("Internal error: entry should be a Number, but is of type " +value.getClass().getName()); } private final boolean _smallerThanInt(Number n) { return (n instanceof Short) || (n instanceof Byte); } private final boolean _smallerThanLong(Number n) { return (n instanceof Integer) || (n instanceof Short) || (n instanceof Byte); } // 02-Jan-2017, tatu: Modified from method(s) in `ParserBase` protected int _convertNumberToInt(Number n) throws IOException { if (n instanceof Long) { long l = n.longValue(); int result = (int) l; if (((long) result) != l) { reportOverflowInt(); } return result; } if (n instanceof BigInteger) { BigInteger big = (BigInteger) n; if (BI_MIN_INT.compareTo(big) > 0 || BI_MAX_INT.compareTo(big) < 0) { reportOverflowInt(); } } else if ((n instanceof Double) || (n instanceof Float)) { double d = n.doubleValue(); // Need to check boundaries if (d < MIN_INT_D || d > MAX_INT_D) { reportOverflowInt(); } return (int) d; } else if (n instanceof BigDecimal) { BigDecimal big = (BigDecimal) n; if (BD_MIN_INT.compareTo(big) > 0 || BD_MAX_INT.compareTo(big) < 0) { reportOverflowInt(); } } else { _throwInternal(); } return n.intValue(); } protected long _convertNumberToLong(Number n) throws IOException { if (n instanceof BigInteger) { BigInteger big = (BigInteger) n; if (BI_MIN_LONG.compareTo(big) > 0 || BI_MAX_LONG.compareTo(big) < 0) { reportOverflowLong(); } } else if ((n instanceof Double) || (n instanceof Float)) { double d = n.doubleValue(); // Need to check boundaries if (d < MIN_LONG_D || d > MAX_LONG_D) { reportOverflowLong(); } return (long) d; } else if (n instanceof BigDecimal) { BigDecimal big = (BigDecimal) n; if (BD_MIN_LONG.compareTo(big) > 0 || BD_MAX_LONG.compareTo(big) < 0) { reportOverflowLong(); } } else { _throwInternal(); } return n.longValue(); } /* /********************************************************** /* Public API, access to token information, other /********************************************************** */ @Override public Object getEmbeddedObject() { if (_currToken == JsonToken.VALUE_EMBEDDED_OBJECT) { return _currentObject(); } return null; } @Override @SuppressWarnings("resource") public byte[] getBinaryValue(Base64Variant b64variant) throws IOException, JsonParseException { // First: maybe we some special types? if (_currToken == JsonToken.VALUE_EMBEDDED_OBJECT) { // Embedded byte array would work nicely... Object ob = _currentObject(); if (ob instanceof byte[]) { return (byte[]) ob; } // fall through to error case } if (_currToken != JsonToken.VALUE_STRING) { throw _constructError("Current token ("+_currToken+") not VALUE_STRING (or VALUE_EMBEDDED_OBJECT with byte[]), cannot access as binary"); } final String str = getText(); if (str == null) { return null; } ByteArrayBuilder builder = _byteBuilder; if (builder == null) { _byteBuilder = builder = new ByteArrayBuilder(100); } else { _byteBuilder.reset(); } _decodeBase64(str, builder, b64variant); return builder.toByteArray(); } @Override public int readBinaryValue(Base64Variant b64variant, OutputStream out) throws IOException { byte[] data = getBinaryValue(b64variant); if (data != null) { out.write(data, 0, data.length); return data.length; } return 0; } /* /********************************************************** /* Public API, native ids /********************************************************** */ @Override public boolean canReadObjectId() { return _hasNativeObjectIds; } @Override public boolean canReadTypeId() { return _hasNativeTypeIds; } @Override public Object getTypeId() { return _segment.findTypeId(_segmentPtr); } @Override public Object getObjectId() { return _segment.findObjectId(_segmentPtr); } /* /********************************************************** /* Internal methods /********************************************************** */ protected final Object _currentObject() { return _segment.get(_segmentPtr); } protected final void _checkIsNumber() throws JsonParseException { if (_currToken == null || !_currToken.isNumeric()) { throw _constructError("Current token ("+_currToken+") not numeric, cannot use numeric value accessors"); } } @Override protected void _handleEOF() throws JsonParseException { _throwInternal(); } } /** * Individual segment of TokenBuffer that can store up to 16 tokens * (limited by 4 bits per token type marker requirement). * Current implementation uses fixed length array; could alternatively * use 16 distinct fields and switch statement (slightly more efficient * storage, slightly slower access) */ protected final static class Segment { public final static int TOKENS_PER_SEGMENT = 16; /** * Static array used for fast conversion between token markers and * matching {@link JsonToken} instances */ private final static JsonToken[] TOKEN_TYPES_BY_INDEX; static { // ... here we know that there are <= 15 values in JsonToken enum TOKEN_TYPES_BY_INDEX = new JsonToken[16]; JsonToken[] t = JsonToken.values(); // and reserve entry 0 for "not available" System.arraycopy(t, 1, TOKEN_TYPES_BY_INDEX, 1, Math.min(15, t.length - 1)); } // // // Linking protected Segment _next; // // // State /** * Bit field used to store types of buffered tokens; 4 bits per token. * Value 0 is reserved for "not in use" */ protected long _tokenTypes; // Actual tokens protected final Object[] _tokens = new Object[TOKENS_PER_SEGMENT]; /** * Lazily constructed Map for storing native type and object ids, if any */ protected TreeMap _nativeIds; public Segment() { } // // // Accessors public JsonToken type(int index) { long l = _tokenTypes; if (index > 0) { l >>= (index << 2); } int ix = ((int) l) & 0xF; return TOKEN_TYPES_BY_INDEX[ix]; } public int rawType(int index) { long l = _tokenTypes; if (index > 0) { l >>= (index << 2); } int ix = ((int) l) & 0xF; return ix; } public Object get(int index) { return _tokens[index]; } public Segment next() { return _next; } /** * Accessor for checking whether this segment may have native * type or object ids. */ public boolean hasIds() { return _nativeIds != null; } // // // Mutators public Segment append(int index, JsonToken tokenType) { if (index < TOKENS_PER_SEGMENT) { set(index, tokenType); return null; } _next = new Segment(); _next.set(0, tokenType); return _next; } public Segment append(int index, JsonToken tokenType, Object objectId, Object typeId) { if (index < TOKENS_PER_SEGMENT) { set(index, tokenType, objectId, typeId); return null; } _next = new Segment(); _next.set(0, tokenType, objectId, typeId); return _next; } public Segment append(int index, JsonToken tokenType, Object value) { if (index < TOKENS_PER_SEGMENT) { set(index, tokenType, value); return null; } _next = new Segment(); _next.set(0, tokenType, value); return _next; } public Segment append(int index, JsonToken tokenType, Object value, Object objectId, Object typeId) { if (index < TOKENS_PER_SEGMENT) { set(index, tokenType, value, objectId, typeId); return null; } _next = new Segment(); _next.set(0, tokenType, value, objectId, typeId); return _next; } /* public Segment appendRaw(int index, int rawTokenType, Object value) { if (index < TOKENS_PER_SEGMENT) { set(index, rawTokenType, value); return null; } _next = new Segment(); _next.set(0, rawTokenType, value); return _next; } public Segment appendRaw(int index, int rawTokenType, Object value, Object objectId, Object typeId) { if (index < TOKENS_PER_SEGMENT) { set(index, rawTokenType, value, objectId, typeId); return null; } _next = new Segment(); _next.set(0, rawTokenType, value, objectId, typeId); return _next; } private void set(int index, int rawTokenType, Object value, Object objectId, Object typeId) { _tokens[index] = value; long typeCode = (long) rawTokenType; if (index > 0) { typeCode <<= (index << 2); } _tokenTypes |= typeCode; assignNativeIds(index, objectId, typeId); } private void set(int index, int rawTokenType, Object value) { _tokens[index] = value; long typeCode = (long) rawTokenType; if (index > 0) { typeCode <<= (index << 2); } _tokenTypes |= typeCode; } */ private void set(int index, JsonToken tokenType) { /* Assumption here is that there are no overwrites, just appends; * and so no masking is needed (nor explicit setting of null) */ long typeCode = tokenType.ordinal(); if (index > 0) { typeCode <<= (index << 2); } _tokenTypes |= typeCode; } private void set(int index, JsonToken tokenType, Object objectId, Object typeId) { long typeCode = tokenType.ordinal(); if (index > 0) { typeCode <<= (index << 2); } _tokenTypes |= typeCode; assignNativeIds(index, objectId, typeId); } private void set(int index, JsonToken tokenType, Object value) { _tokens[index] = value; long typeCode = tokenType.ordinal(); if (index > 0) { typeCode <<= (index << 2); } _tokenTypes |= typeCode; } private void set(int index, JsonToken tokenType, Object value, Object objectId, Object typeId) { _tokens[index] = value; long typeCode = tokenType.ordinal(); if (index > 0) { typeCode <<= (index << 2); } _tokenTypes |= typeCode; assignNativeIds(index, objectId, typeId); } private final void assignNativeIds(int index, Object objectId, Object typeId) { if (_nativeIds == null) { _nativeIds = new TreeMap(); } if (objectId != null) { _nativeIds.put(_objectIdIndex(index), objectId); } if (typeId != null) { _nativeIds.put(_typeIdIndex(index), typeId); } } /** * @since 2.3 */ private Object findObjectId(int index) { return (_nativeIds == null) ? null : _nativeIds.get(_objectIdIndex(index)); } /** * @since 2.3 */ private Object findTypeId(int index) { return (_nativeIds == null) ? null : _nativeIds.get(_typeIdIndex(index)); } private final int _typeIdIndex(int i) { return i+i; } private final int _objectIdIndex(int i) { return i+i+1; } } } TokenBufferReadContext.java000066400000000000000000000105411325620701100366440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.json.JsonReadContext; /** * Implementation of {@link JsonStreamContext} used by {@link TokenBuffer} * to link back to the original context to try to keep location information * consistent between source location and buffered content when it's re-read * from the buffer. * * @since 2.9 */ public class TokenBufferReadContext extends JsonStreamContext { protected final JsonStreamContext _parent; protected final JsonLocation _startLocation; // Benefit for reusing? // protected JsonReadContext _child; /* /********************************************************** /* Location/state information (minus source reference) /********************************************************** */ protected String _currentName; protected Object _currentValue; protected TokenBufferReadContext(JsonStreamContext base, Object srcRef) { super(base); _parent = base.getParent(); _currentName = base.getCurrentName(); _currentValue = base.getCurrentValue(); if (base instanceof JsonReadContext) { JsonReadContext rc = (JsonReadContext) base; _startLocation = rc.getStartLocation(srcRef); } else { _startLocation = JsonLocation.NA; } } protected TokenBufferReadContext(JsonStreamContext base, JsonLocation startLoc) { super(base); _parent = base.getParent(); _currentName = base.getCurrentName(); _currentValue = base.getCurrentValue(); _startLocation = startLoc; } /** * Constructor for case where there is no real surrounding context: just create * virtual ROOT */ protected TokenBufferReadContext() { super(TYPE_ROOT, -1); _parent = null; _startLocation = JsonLocation.NA; } protected TokenBufferReadContext(TokenBufferReadContext parent, int type, int index) { super(type, index); _parent = parent; _startLocation = parent._startLocation; } @Override public Object getCurrentValue() { return _currentValue; } @Override public void setCurrentValue(Object v) { _currentValue = v; } /* /********************************************************** /* Factory methods /********************************************************** */ public static TokenBufferReadContext createRootContext(JsonStreamContext origContext) { // First: possible to have no current context; if so, just create bogus ROOT context if (origContext == null) { return new TokenBufferReadContext(); } return new TokenBufferReadContext(origContext, null); } public TokenBufferReadContext createChildArrayContext() { return new TokenBufferReadContext(this, TYPE_ARRAY, -1); } public TokenBufferReadContext createChildObjectContext() { return new TokenBufferReadContext(this, TYPE_OBJECT, -1); } /** * Helper method we need to handle discontinuity between "real" contexts buffer * creates, and ones from parent: problem being they are of different types. */ public TokenBufferReadContext parentOrCopy() { // 30-Apr-2017, tatu: This is bit awkward since part on ancestor stack is of different // type (usually `JsonReadContext`)... and so for unbalanced buffers (with extra // END_OBJECT / END_ARRAY), we may need to create if (_parent instanceof TokenBufferReadContext) { return (TokenBufferReadContext) _parent; } if (_parent == null) { // unlikely, but just in case let's support return new TokenBufferReadContext(); } return new TokenBufferReadContext(_parent, _startLocation); } /* /********************************************************** /* Abstract method implementation /********************************************************** */ @Override public String getCurrentName() { return _currentName; } // @since 2.9 @Override public boolean hasCurrentName() { return _currentName != null; } @Override public JsonStreamContext getParent() { return _parent; } public void setCurrentName(String name) throws JsonProcessingException { _currentName = name; } } TypeKey.java000066400000000000000000000063511325620701100336670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import com.fasterxml.jackson.databind.JavaType; /** * Key that offers two "modes"; one with raw class, as used for * cases were raw class type is available (for example, when using * runtime type); and one with full generics-including. */ public class TypeKey { protected int _hashCode; protected Class _class; protected JavaType _type; /** * Indicator of whether serializer stored has a type serializer * wrapper around it or not; if not, it is "untyped" serializer; * if it has, it is "typed" */ protected boolean _isTyped; public TypeKey() { } public TypeKey(TypeKey src) { _hashCode = src._hashCode; _class = src._class; _type = src._type; _isTyped = src._isTyped; } public TypeKey(Class key, boolean typed) { _class = key; _type = null; _isTyped = typed; _hashCode = typed ? typedHash(key) : untypedHash(key); } public TypeKey(JavaType key, boolean typed) { _type = key; _class = null; _isTyped = typed; _hashCode = typed ? typedHash(key) : untypedHash(key); } public final static int untypedHash(Class cls) { return cls.getName().hashCode(); } public final static int typedHash(Class cls) { return cls.getName().hashCode()+1; } public final static int untypedHash(JavaType type) { return type.hashCode() - 1; } public final static int typedHash(JavaType type) { return type.hashCode() - 2; } public final void resetTyped(Class cls) { _type = null; _class = cls; _isTyped = true; _hashCode = typedHash(cls); } public final void resetUntyped(Class cls) { _type = null; _class = cls; _isTyped = false; _hashCode = untypedHash(cls); } public final void resetTyped(JavaType type) { _type = type; _class = null; _isTyped = true; _hashCode = typedHash(type); } public final void resetUntyped(JavaType type) { _type = type; _class = null; _isTyped = false; _hashCode = untypedHash(type); } public boolean isTyped() { return _isTyped; } public Class getRawType() { return _class; } public JavaType getType() { return _type; } @Override public final int hashCode() { return _hashCode; } @Override public final String toString() { if (_class != null) { return "{class: "+_class.getName()+", typed? "+_isTyped+"}"; } return "{type: "+_type+", typed? "+_isTyped+"}"; } // note: we assume key is never used for anything other than as map key, so: @Override public final boolean equals(Object o) { if (o == null) return false; if (o == this) return true; if (o.getClass() != getClass()) { return false; } TypeKey other = (TypeKey) o; if (other._isTyped == _isTyped) { if (_class != null) { return other._class == _class; } return _type.equals(other._type); } return false; } }ViewMatcher.java000066400000000000000000000035741325620701100345170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; /** * Helper class used for checking whether a property is visible * in the active view */ public class ViewMatcher implements java.io.Serializable { private static final long serialVersionUID = 1L; protected final static ViewMatcher EMPTY = new ViewMatcher(); public boolean isVisibleForView(Class activeView) { return false; } public static ViewMatcher construct(Class[] views) { if (views == null) { return EMPTY; } switch (views.length) { case 0: return EMPTY; case 1: return new Single(views[0]); } return new Multi(views); } /* /********************************************************** /* Concrete sub-classes /********************************************************** */ private final static class Single extends ViewMatcher { private static final long serialVersionUID = 1L; private final Class _view; public Single(Class v) { _view = v; } @Override public boolean isVisibleForView(Class activeView) { return (activeView == _view) || _view.isAssignableFrom(activeView); } } private final static class Multi extends ViewMatcher implements java.io.Serializable { private static final long serialVersionUID = 1L; private final Class[] _views; public Multi(Class[] v) { _views = v; } @Override public boolean isVisibleForView(Class activeView) { for (int i = 0, len = _views.length; i < len; ++i) { Class view = _views[i]; if ((activeView == view) || view.isAssignableFrom(activeView)) { return true; } } return false; } } } package-info.java000066400000000000000000000001341325620701100346120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/java/com/fasterxml/jackson/databind/util/** * Utility classes for Mapper package. */ package com.fasterxml.jackson.databind.util; jackson-databind-jackson-databind-2.9.5/src/main/resources/000077500000000000000000000000001325620701100236375ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/resources/META-INF/000077500000000000000000000000001325620701100247775ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/resources/META-INF/LICENSE000066400000000000000000000005011325620701100260000ustar00rootroot00000000000000This copy of Jackson JSON processor databind module 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-databind-jackson-databind-2.9.5/src/main/resources/META-INF/NOTICE000066400000000000000000000014711325620701100257060ustar00rootroot00000000000000# 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 be 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-databind-jackson-databind-2.9.5/src/main/resources/META-INF/services/000077500000000000000000000000001325620701100266225ustar00rootroot00000000000000com.fasterxml.jackson.core.ObjectCodec000066400000000000000000000000541325620701100357700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/main/resources/META-INF/servicescom.fasterxml.jackson.databind.ObjectMapper jackson-databind-jackson-databind-2.9.5/src/test/000077500000000000000000000000001325620701100216605ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/000077500000000000000000000000001325620701100226015ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/000077500000000000000000000000001325620701100233575ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/000077500000000000000000000000001325620701100253645ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/000077500000000000000000000000001325620701100270145ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/000077500000000000000000000000001325620701100305625ustar00rootroot00000000000000BaseMapTest.java000066400000000000000000000224451325620701100335250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.*; import java.util.*; import static org.junit.Assert.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; import com.fasterxml.jackson.databind.type.TypeFactory; public abstract class BaseMapTest extends BaseTest { private final static Object SINGLETON_OBJECT = new Object(); /* /********************************************************** /* Shared helper classes /********************************************************** */ public static class BogusSchema implements FormatSchema { @Override public String getSchemaType() { return "TestFormat"; } } /** * Simple wrapper around boolean types, usually to test value * conversions or wrapping */ protected static class BooleanWrapper { public Boolean b; public BooleanWrapper() { } public BooleanWrapper(Boolean value) { b = value; } } protected static class IntWrapper { public int i; public IntWrapper() { } public IntWrapper(int value) { i = value; } } protected static class LongWrapper { public long l; public LongWrapper() { } public LongWrapper(long value) { l = value; } } protected static class DoubleWrapper { public double d; public DoubleWrapper() { } public DoubleWrapper(double value) { d = value; } } /** * Simple wrapper around String type, usually to test value * conversions or wrapping */ protected static class StringWrapper { public String str; public StringWrapper() { } public StringWrapper(String value) { str = value; } } protected static class ObjectWrapper { final Object object; protected ObjectWrapper(final Object object) { this.object = object; } public Object getObject() { return object; } @JsonCreator static ObjectWrapper jsonValue(final Object object) { return new ObjectWrapper(object); } } protected static class ListWrapper { public List list; public ListWrapper(@SuppressWarnings("unchecked") T... values) { list = new ArrayList(); for (T value : values) { list.add(value); } } } protected static class MapWrapper { public Map map; public MapWrapper() { } public MapWrapper(Map m) { map = m; } public MapWrapper(K key, V value) { map = new LinkedHashMap<>(); map.put(key, value); } } protected static class ArrayWrapper { public T[] array; public ArrayWrapper(T[] v) { array = v; } } /** * Enumeration type with sub-classes per value. */ protected enum EnumWithSubClass { A { @Override public void foobar() { } } ,B { @Override public void foobar() { } } ; public abstract void foobar(); } public enum ABC { A, B, C; } // since 2.8 public static class Point { public int x, y; protected Point() { } // for deser public Point(int x0, int y0) { x = x0; y = y0; } @Override public boolean equals(Object o) { if (!(o instanceof Point)) { return false; } Point other = (Point) o; return (other.x == x) && (other.y == y); } @Override public String toString() { return String.format("[x=%d, y=%d]", x, y); } } /* /********************************************************** /* Shared serializers /********************************************************** */ @SuppressWarnings("serial") public static class UpperCasingSerializer extends StdScalarSerializer { public UpperCasingSerializer() { super(String.class); } @Override public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeString(value.toUpperCase()); } } @SuppressWarnings("serial") public static class LowerCasingDeserializer extends StdScalarDeserializer { public LowerCasingDeserializer() { super(String.class); } @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { return p.getText().toLowerCase(); } } /* /********************************************************** /* Construction /********************************************************** */ protected BaseMapTest() { super(); } /* /********************************************************** /* Factory methods /********************************************************** */ private static ObjectMapper SHARED_MAPPER; protected ObjectMapper objectMapper() { if (SHARED_MAPPER == null) { SHARED_MAPPER = newObjectMapper(); } return SHARED_MAPPER; } protected ObjectWriter objectWriter() { return objectMapper().writer(); } protected ObjectReader objectReader() { return objectMapper().reader(); } protected ObjectReader objectReader(Class cls) { return objectMapper().readerFor(cls); } // @since 2.9 protected static ObjectMapper newObjectMapper() { return new ObjectMapper(); } // @since 2.7 protected TypeFactory newTypeFactory() { // this is a work-around; no null modifier added return TypeFactory.defaultInstance().withModifier(null); } /* /********************************************************** /* Additional assert methods /********************************************************** */ protected void assertEquals(int[] exp, int[] act) { assertArrayEquals(exp, act); } protected void assertEquals(byte[] exp, byte[] act) { assertArrayEquals(exp, act); } /** * Helper method for verifying 3 basic cookie cutter cases; * identity comparison (true), and against null (false), * or object of different type (false) */ protected void assertStandardEquals(Object o) { assertTrue(o.equals(o)); assertFalse(o.equals(null)); assertFalse(o.equals(SINGLETON_OBJECT)); // just for fun, let's also call hash code... o.hashCode(); } /* /********************************************************** /* Helper methods, serialization /********************************************************** */ @SuppressWarnings("unchecked") protected Map writeAndMap(ObjectMapper m, Object value) throws IOException { String str = m.writeValueAsString(value); return (Map) m.readValue(str, Map.class); } protected String serializeAsString(ObjectMapper m, Object value) throws IOException { return m.writeValueAsString(value); } protected String serializeAsString(Object value) throws IOException { return serializeAsString(objectMapper(), value); } protected String asJSONObjectValueString(Object... args) throws IOException { return asJSONObjectValueString(objectMapper(), args); } protected String asJSONObjectValueString(ObjectMapper m, Object... args) throws IOException { LinkedHashMap map = new LinkedHashMap(); for (int i = 0, len = args.length; i < len; i += 2) { map.put(args[i], args[i+1]); } return m.writeValueAsString(map); } /* /********************************************************** /* Helper methods, deserialization /********************************************************** */ protected T readAndMapFromString(String input, Class cls) throws IOException { return readAndMapFromString(objectMapper(), input, cls); } protected T readAndMapFromString(ObjectMapper m, String input, Class cls) throws IOException { return (T) m.readValue("\""+input+"\"", cls); } /* /********************************************************** /* Helper methods, other /********************************************************** */ protected TimeZone getUTCTimeZone() { return TimeZone.getTimeZone("GMT"); } protected byte[] utf8Bytes(String str) { try { return str.getBytes("UTF-8"); } catch (IOException e) { throw new IllegalArgumentException(e); } } protected static String aposToQuotes(String json) { return json.replace("'", "\""); } protected static String quotesToApos(String json) { return json.replace("\"", "'"); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/BaseTest.java000066400000000000000000000336371325620701100331530ustar00rootroot00000000000000package com.fasterxml.jackson.databind; import java.io.*; import java.util.Arrays; import junit.framework.TestCase; import com.fasterxml.jackson.core.*; //import static org.junit.Assert.*; public abstract class BaseTest extends TestCase { /* /********************************************************** /* Some sample documents: /********************************************************** */ protected final static int SAMPLE_SPEC_VALUE_WIDTH = 800; protected final static int SAMPLE_SPEC_VALUE_HEIGHT = 600; protected final static String SAMPLE_SPEC_VALUE_TITLE = "View from 15th Floor"; protected final static String SAMPLE_SPEC_VALUE_TN_URL = "http://www.example.com/image/481989943"; protected final static int SAMPLE_SPEC_VALUE_TN_HEIGHT = 125; protected final static String SAMPLE_SPEC_VALUE_TN_WIDTH = "100"; protected final static int SAMPLE_SPEC_VALUE_TN_ID1 = 116; protected final static int SAMPLE_SPEC_VALUE_TN_ID2 = 943; protected final static int SAMPLE_SPEC_VALUE_TN_ID3 = 234; protected final static int SAMPLE_SPEC_VALUE_TN_ID4 = 38793; protected final static String SAMPLE_DOC_JSON_SPEC = "{\n" +" \"Image\" : {\n" +" \"Width\" : "+SAMPLE_SPEC_VALUE_WIDTH+",\n" +" \"Height\" : "+SAMPLE_SPEC_VALUE_HEIGHT+"," +"\"Title\" : \""+SAMPLE_SPEC_VALUE_TITLE+"\",\n" +" \"Thumbnail\" : {\n" +" \"Url\" : \""+SAMPLE_SPEC_VALUE_TN_URL+"\",\n" +"\"Height\" : "+SAMPLE_SPEC_VALUE_TN_HEIGHT+",\n" +" \"Width\" : \""+SAMPLE_SPEC_VALUE_TN_WIDTH+"\"\n" +" },\n" +" \"IDs\" : ["+SAMPLE_SPEC_VALUE_TN_ID1+","+SAMPLE_SPEC_VALUE_TN_ID2+","+SAMPLE_SPEC_VALUE_TN_ID3+","+SAMPLE_SPEC_VALUE_TN_ID4+"]\n" +" }" +"}" ; /* /********************************************************** /* Helper classes (beans) /********************************************************** */ /** * Sample class from Jackson tutorial ("JacksonInFiveMinutes") */ protected static class FiveMinuteUser { public enum Gender { MALE, FEMALE }; public static class Name { private String _first, _last; public Name() { } public Name(String f, String l) { _first = f; _last = l; } public String getFirst() { return _first; } public String getLast() { return _last; } public void setFirst(String s) { _first = s; } public void setLast(String s) { _last = s; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null || o.getClass() != getClass()) return false; Name other = (Name) o; return _first.equals(other._first) && _last.equals(other._last); } } private Gender _gender; private Name _name; private boolean _isVerified; private byte[] _userImage; public FiveMinuteUser() { } public FiveMinuteUser(String first, String last, boolean verified, Gender g, byte[] data) { _name = new Name(first, last); _isVerified = verified; _gender = g; _userImage = data; } public Name getName() { return _name; } public boolean isVerified() { return _isVerified; } public Gender getGender() { return _gender; } public byte[] getUserImage() { return _userImage; } public void setName(Name n) { _name = n; } public void setVerified(boolean b) { _isVerified = b; } public void setGender(Gender g) { _gender = g; } public void setUserImage(byte[] b) { _userImage = b; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null || o.getClass() != getClass()) return false; FiveMinuteUser other = (FiveMinuteUser) o; if (_isVerified != other._isVerified) return false; if (_gender != other._gender) return false; if (!_name.equals(other._name)) return false; byte[] otherImage = other._userImage; if (otherImage.length != _userImage.length) return false; for (int i = 0, len = _userImage.length; i < len; ++i) { if (_userImage[i] != otherImage[i]) { return false; } } return true; } } /* /********************************************************** /* High-level helpers /********************************************************** */ protected void verifyJsonSpecSampleDoc(JsonParser jp, boolean verifyContents) throws IOException { verifyJsonSpecSampleDoc(jp, verifyContents, true); } protected void verifyJsonSpecSampleDoc(JsonParser jp, boolean verifyContents, boolean requireNumbers) throws IOException { if (!jp.hasCurrentToken()) { jp.nextToken(); } assertToken(JsonToken.START_OBJECT, jp.getCurrentToken()); // main object assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Image' if (verifyContents) { verifyFieldName(jp, "Image"); } assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'image' object assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width' if (verifyContents) { verifyFieldName(jp, "Width"); } verifyIntToken(jp.nextToken(), requireNumbers); if (verifyContents) { verifyIntValue(jp, SAMPLE_SPEC_VALUE_WIDTH); } assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height' if (verifyContents) { verifyFieldName(jp, "Height"); } verifyIntToken(jp.nextToken(), requireNumbers); if (verifyContents) { verifyIntValue(jp, SAMPLE_SPEC_VALUE_HEIGHT); } assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Title' if (verifyContents) { verifyFieldName(jp, "Title"); } assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(SAMPLE_SPEC_VALUE_TITLE, getAndVerifyText(jp)); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Thumbnail' if (verifyContents) { verifyFieldName(jp, "Thumbnail"); } assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'thumbnail' object assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Url' if (verifyContents) { verifyFieldName(jp, "Url"); } assertToken(JsonToken.VALUE_STRING, jp.nextToken()); if (verifyContents) { assertEquals(SAMPLE_SPEC_VALUE_TN_URL, getAndVerifyText(jp)); } assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height' if (verifyContents) { verifyFieldName(jp, "Height"); } verifyIntToken(jp.nextToken(), requireNumbers); if (verifyContents) { verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_HEIGHT); } assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width' if (verifyContents) { verifyFieldName(jp, "Width"); } // Width value is actually a String in the example assertToken(JsonToken.VALUE_STRING, jp.nextToken()); if (verifyContents) { assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, getAndVerifyText(jp)); } assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'thumbnail' object assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'IDs' assertToken(JsonToken.START_ARRAY, jp.nextToken()); // 'ids' array verifyIntToken(jp.nextToken(), requireNumbers); // ids[0] if (verifyContents) { verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID1); } verifyIntToken(jp.nextToken(), requireNumbers); // ids[1] if (verifyContents) { verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID2); } verifyIntToken(jp.nextToken(), requireNumbers); // ids[2] if (verifyContents) { verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID3); } verifyIntToken(jp.nextToken(), requireNumbers); // ids[3] if (verifyContents) { verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID4); } assertToken(JsonToken.END_ARRAY, jp.nextToken()); // 'ids' array assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'image' object assertToken(JsonToken.END_OBJECT, jp.nextToken()); // main object } private void verifyIntToken(JsonToken t, boolean requireNumbers) { if (t == JsonToken.VALUE_NUMBER_INT) { return; } if (requireNumbers) { // to get error assertToken(JsonToken.VALUE_NUMBER_INT, t); } // if not number, must be String if (t != JsonToken.VALUE_STRING) { fail("Expected INT or STRING value, got "+t); } } protected void verifyFieldName(JsonParser jp, String expName) throws IOException { assertEquals(expName, jp.getText()); assertEquals(expName, jp.getCurrentName()); } protected void verifyIntValue(JsonParser jp, long expValue) throws IOException { // First, via textual assertEquals(String.valueOf(expValue), jp.getText()); } /* /********************************************************** /* Parser/generator construction /********************************************************** */ protected JsonParser createParserUsingReader(String input) throws IOException, JsonParseException { return createParserUsingReader(new JsonFactory(), input); } protected JsonParser createParserUsingReader(JsonFactory f, String input) throws IOException { return f.createParser(new StringReader(input)); } protected JsonParser createParserUsingStream(String input, String encoding) throws IOException { return createParserUsingStream(new JsonFactory(), input, encoding); } protected JsonParser createParserUsingStream(JsonFactory f, String input, String encoding) throws IOException { /* 23-Apr-2008, tatus: UTF-32 is not supported by JDK, have to * use our own codec too (which is not optimal since there's * a chance both encoder and decoder might have bugs, but ones * that cancel each other out or such) */ byte[] data; if (encoding.equalsIgnoreCase("UTF-32")) { data = encodeInUTF32BE(input); } else { data = input.getBytes(encoding); } InputStream is = new ByteArrayInputStream(data); return f.createParser(is); } /* /********************************************************** /* Additional assertion methods /********************************************************** */ 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 assertType(Object ob, Class expType) { if (ob == null) { fail("Expected an object of type "+expType.getName()+", got null"); } Class cls = ob.getClass(); if (!expType.isAssignableFrom(cls)) { fail("Expected type "+expType.getName()+", got "+cls.getName()); } } protected void assertValidLocation(JsonLocation location) { assertNotNull("Should have non-null location", location); assertTrue("Should have positive line number", location.getLineNr() > 0); } 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 (of type "+e.getClass().getName() +") with message \""+msg+"\""); } /** * Method that gets textual contents of the current token using * available methods, and ensures results are consistent, before * returning them */ protected String getAndVerifyText(JsonParser jp) throws IOException, JsonParseException { // Ok, let's verify other accessors int actLen = jp.getTextLength(); char[] ch = jp.getTextCharacters(); String str2 = new String(ch, jp.getTextOffset(), actLen); String str = jp.getText(); if (str.length() != actLen) { fail("Internal problem (jp.token == "+jp.getCurrentToken()+"): jp.getText().length() ['"+str+"'] == "+str.length()+"; jp.getTextLength() == "+actLen); } assertEquals("String access via getText(), getTextXxx() must be the same", str, str2); return str; } /* /********************************************************** /* And other helpers /********************************************************** */ protected byte[] encodeInUTF32BE(String input) { int len = input.length(); byte[] result = new byte[len * 4]; int ptr = 0; for (int i = 0; i < len; ++i, ptr += 4) { char c = input.charAt(i); result[ptr] = result[ptr+1] = (byte) 0; result[ptr+2] = (byte) (c >> 8); result[ptr+3] = (byte) c; } return result; } public String quote(String str) { return '"'+str+'"'; } } BrokenStringReader.java000066400000000000000000000010201325620701100350710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.*; public class BrokenStringReader extends FilterReader { final String _message; public BrokenStringReader(String content, String msg) { super(new StringReader(content)); _message = msg; } @Override public int read(char[] cbuf, int off, int len) throws IOException { int i = super.read(cbuf, off, len); if (i < 0) { throw new IOException(_message); } return i; } } BrokenStringWriter.java000066400000000000000000000012261325620701100351530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.*; public class BrokenStringWriter extends FilterWriter { final String _message; public BrokenStringWriter(String msg) { super(new StringWriter()); _message = msg; } @Override public void write(char[] cbuf, int off, int len) throws IOException { throw new IOException(_message); } @Override public void write(int c) throws IOException { throw new IOException(_message); } @Override public void write(String str, int off, int len) throws IOException { throw new IOException(_message); } } FullStreamReadTest.java000066400000000000000000000157061325620701100350710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.util.*; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.exc.MismatchedInputException; public class FullStreamReadTest extends BaseMapTest { private final static String JSON_OK_ARRAY = " [ 1, 2, 3] "; private final static String JSON_OK_ARRAY_WITH_COMMENT = JSON_OK_ARRAY + " // stuff "; private final static String JSON_FAIL_ARRAY = JSON_OK_ARRAY + " [ ]"; /* /********************************************************** /* Test methods, config /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testMapperAcceptTrailing() throws Exception { assertFalse(MAPPER.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)); // by default, should be ok to read, all _verifyArray(MAPPER.readTree(JSON_OK_ARRAY)); _verifyArray(MAPPER.readTree(JSON_OK_ARRAY_WITH_COMMENT)); _verifyArray(MAPPER.readTree(JSON_FAIL_ARRAY)); // and also via "untyped" _verifyCollection(MAPPER.readValue(JSON_OK_ARRAY, List.class)); _verifyCollection(MAPPER.readValue(JSON_OK_ARRAY_WITH_COMMENT, List.class)); _verifyCollection(MAPPER.readValue(JSON_FAIL_ARRAY, List.class)); } public void testMapperFailOnTrailing() throws Exception { // but things change if we enforce checks ObjectMapper strict = newObjectMapper() .enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS); assertTrue(strict.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)); // some still ok _verifyArray(strict.readTree(JSON_OK_ARRAY)); _verifyCollection(strict.readValue(JSON_OK_ARRAY, List.class)); // but if real content exists, will fail try { strict.readTree(JSON_FAIL_ARRAY); fail("Should not have passed"); } catch (MismatchedInputException e) { verifyException(e, "Trailing token (of type START_ARRAY)"); verifyException(e, "value (bound as `com.fasterxml.jackson.databind.JsonNode`)"); } try { strict.readValue(JSON_FAIL_ARRAY, List.class); fail("Should not have passed"); } catch (MismatchedInputException e) { verifyException(e, "Trailing token (of type START_ARRAY)"); verifyException(e, "value (bound as `java.util.List`)"); } // others fail conditionally: will fail on comments unless enabled try { strict.readValue(JSON_OK_ARRAY_WITH_COMMENT, List.class); fail("Should not have passed"); } catch (JsonParseException e) { verifyException(e, "Unexpected character"); verifyException(e, "maybe a (non-standard) comment"); } try { strict.readTree(JSON_OK_ARRAY_WITH_COMMENT); fail("Should not have passed"); } catch (JsonParseException e) { verifyException(e, "Unexpected character"); verifyException(e, "maybe a (non-standard) comment"); } ObjectMapper strictWithComments = strict.copy(); strictWithComments.enable(JsonParser.Feature.ALLOW_COMMENTS); _verifyArray(strictWithComments.readTree(JSON_OK_ARRAY_WITH_COMMENT)); _verifyCollection(strictWithComments.readValue(JSON_OK_ARRAY_WITH_COMMENT, List.class)); } public void testReaderAcceptTrailing() throws Exception { ObjectReader R = MAPPER.reader(); assertFalse(R.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)); _verifyArray(R.readTree(JSON_OK_ARRAY)); _verifyArray(R.readTree(JSON_OK_ARRAY_WITH_COMMENT)); _verifyArray(R.readTree(JSON_FAIL_ARRAY)); ObjectReader rColl = R.forType(List.class); _verifyCollection((List)rColl.readValue(JSON_OK_ARRAY)); _verifyCollection((List)rColl.readValue(JSON_OK_ARRAY_WITH_COMMENT)); _verifyCollection((List)rColl.readValue(JSON_FAIL_ARRAY)); } public void testReaderFailOnTrailing() throws Exception { ObjectReader strictR = MAPPER.reader().with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS); ObjectReader strictRForList = strictR.forType(List.class); _verifyArray(strictR.readTree(JSON_OK_ARRAY)); _verifyCollection((List)strictRForList.readValue(JSON_OK_ARRAY)); // Will fail hard if there is a trailing token try { strictRForList.readValue(JSON_FAIL_ARRAY); fail("Should not have passed"); } catch (MismatchedInputException e) { verifyException(e, "Trailing token (of type START_ARRAY)"); verifyException(e, "value (bound as `java.util.List`)"); } try { strictR.readTree(JSON_FAIL_ARRAY); fail("Should not have passed"); } catch (MismatchedInputException e) { verifyException(e, "Trailing token (of type START_ARRAY)"); verifyException(e, "value (bound as `com.fasterxml.jackson.databind.JsonNode`)"); } // ... also verify that same happens with "value to update" try { strictR.withValueToUpdate(new ArrayList()) .readValue(JSON_FAIL_ARRAY); fail("Should not have passed"); } catch (MismatchedInputException e) { verifyException(e, "Trailing token (of type START_ARRAY)"); verifyException(e, "value (bound as `java.util.ArrayList`)"); } // others conditionally: will fail on comments unless enabled try { strictRForList.readValue(JSON_OK_ARRAY_WITH_COMMENT); fail("Should not have passed"); } catch (JsonParseException e) { verifyException(e, "Unexpected character"); verifyException(e, "maybe a (non-standard) comment"); } try { strictR.readTree(JSON_OK_ARRAY_WITH_COMMENT); fail("Should not have passed"); } catch (JsonParseException e) { verifyException(e, "Unexpected character"); verifyException(e, "maybe a (non-standard) comment"); } // but works if comments enabled etc ObjectReader strictRWithComments = strictR.with(JsonParser.Feature.ALLOW_COMMENTS); _verifyCollection((List)strictRWithComments.forType(List.class).readValue(JSON_OK_ARRAY_WITH_COMMENT)); _verifyArray(strictRWithComments.readTree(JSON_OK_ARRAY_WITH_COMMENT)); } private void _verifyArray(JsonNode n) throws Exception { assertTrue(n.isArray()); assertEquals(3, n.size()); } private void _verifyCollection(List coll) throws Exception { assertEquals(3, coll.size()); assertEquals(Integer.valueOf(1), coll.get(0)); assertEquals(Integer.valueOf(2), coll.get(1)); assertEquals(Integer.valueOf(3), coll.get(2)); } } MapperViaParserTest.java000066400000000000000000000116071325620701100352540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.IOException; import java.io.StringReader; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.CharacterEscapes; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.databind.ObjectMapper; public class MapperViaParserTest extends BaseMapTest { final static int TWO_BYTE_ESCAPED = 0x111; final static int THREE_BYTE_ESCAPED = 0x1111; final static SerializedString TWO_BYTE_ESCAPED_STRING = new SerializedString("&111;"); final static SerializedString THREE_BYTE_ESCAPED_STRING = new SerializedString("&1111;"); final static class Pojo { int _x; public void setX(int x) { _x = x; } } /* /******************************************************** /* Helper types /******************************************************** */ /** * Trivial simple custom escape definition set. */ static class MyEscapes extends CharacterEscapes { private static final long serialVersionUID = 1L; private final int[] _asciiEscapes; public MyEscapes() { _asciiEscapes = standardAsciiEscapesForJSON(); _asciiEscapes['a'] = 'A'; // to basically give us "\A" _asciiEscapes['b'] = CharacterEscapes.ESCAPE_STANDARD; // too force "\u0062" _asciiEscapes['d'] = CharacterEscapes.ESCAPE_CUSTOM; } @Override public int[] getEscapeCodesForAscii() { return _asciiEscapes; } @Override public SerializableString getEscapeSequence(int ch) { if (ch == 'd') { return new SerializedString("[D]"); } if (ch == TWO_BYTE_ESCAPED) { return TWO_BYTE_ESCAPED_STRING; } if (ch == THREE_BYTE_ESCAPED) { return THREE_BYTE_ESCAPED_STRING; } return null; } } /* /******************************************************** /* Unit tests /******************************************************** */ public void testPojoReading() throws IOException { JsonFactory jf = new MappingJsonFactory(); final String JSON = "{ \"x\" : 9 }"; JsonParser jp = jf.createParser(new StringReader(JSON)); // let's try first by advancing: assertToken(JsonToken.START_OBJECT, jp.nextToken()); Pojo p = jp.readValueAs(Pojo.class); assertEquals(9, p._x); jp.close(); // and without jp = jf.createParser(new StringReader(JSON)); p = jp.readValueAs(Pojo.class); assertEquals(9, p._x); jp.close(); } /** * Test similar to above, but instead reads a sequence of values */ public void testIncrementalPojoReading() throws IOException { JsonFactory jf = new MappingJsonFactory(); final String JSON = "[ 1, true, null, \"abc\" ]"; JsonParser jp = jf.createParser(new StringReader(JSON)); // let's advance past array start to prevent full binding assertToken(JsonToken.START_ARRAY, jp.nextToken()); assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertEquals(Integer.valueOf(1), jp.readValueAs(Integer.class)); assertEquals(Boolean.TRUE, jp.readValueAs(Boolean.class)); /* note: null can be returned both when there is no more * data in current scope, AND when Json null literal is * bound! */ assertNull(jp.readValueAs(Object.class)); // but we can verify that it was Json null by: assertEquals(JsonToken.VALUE_NULL, jp.getLastClearedToken()); assertEquals("abc", jp.readValueAs(String.class)); // this null is for actually hitting the END_ARRAY assertNull(jp.readValueAs(Object.class)); assertEquals(JsonToken.END_ARRAY, jp.getLastClearedToken()); // afrer which there should be nothing to advance to: assertNull(jp.nextToken()); jp.close(); } @SuppressWarnings("resource") public void testPojoReadingFailing() throws IOException { // regular factory can't do it, without a call to setCodec() JsonFactory jf = new JsonFactory(); try { final String JSON = "{ \"x\" : 9 }"; JsonParser jp = jf.createParser(new StringReader(JSON)); Pojo p = jp.readValueAs(Pojo.class); fail("Expected an exception: got "+p); } catch (IllegalStateException e) { verifyException(e, "No ObjectCodec defined"); } } // for [JACKSON-672] public void testEscapingUsingMapper() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true); mapper.writeValueAsString(String.valueOf((char) 257)); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/MediaItem.java000066400000000000000000000100341325620701100332610ustar00rootroot00000000000000package com.fasterxml.jackson.databind; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder({"content", "images"}) 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 /********************************************************** */ @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder({"uri","title","width","height","size"}) 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; } } @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder({"uri","title","width","height","format","duration","size","bitrate","persons","player","copyright"}) 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; } } } ObjectMapperTest.java000066400000000000000000000376501325620701100345740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.util.MinimalPrettyPrinter; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.fasterxml.jackson.databind.introspect.VisibilityChecker; import com.fasterxml.jackson.databind.node.*; public class ObjectMapperTest extends BaseMapTest { static class Bean { int value = 3; public void setX(int v) { value = v; } protected Bean() { } public Bean(int v) { value = v; } } static class EmptyBean { } @SuppressWarnings("serial") static class MyAnnotationIntrospector extends JacksonAnnotationIntrospector { } // for [databind#689] @SuppressWarnings("serial") static class FooPrettyPrinter extends MinimalPrettyPrinter { public FooPrettyPrinter() { super(" /*foo*/ "); } @Override public void writeArrayValueSeparator(JsonGenerator g) throws IOException { g.writeRaw(" , "); } } // for [databind#206] @SuppressWarnings("serial") static class NoCopyMapper extends ObjectMapper { } final ObjectMapper MAPPER = new ObjectMapper(); /* /********************************************************** /* Test methods, config /********************************************************** */ public void testFactorFeatures() { assertTrue(MAPPER.isEnabled(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES)); } public void testGeneratorFeatures() { // and also for mapper ObjectMapper mapper = new ObjectMapper(); assertFalse(mapper.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII)); assertTrue(mapper.isEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES)); mapper.disable(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM, JsonGenerator.Feature.QUOTE_FIELD_NAMES); } public void testParserFeatures() { // and also for mapper ObjectMapper mapper = new ObjectMapper(); assertTrue(mapper.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); assertFalse(mapper.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); mapper.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE, JsonParser.Feature.STRICT_DUPLICATE_DETECTION); assertFalse(mapper.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); } /* /********************************************************** /* Test methods, mapper.copy() /********************************************************** */ // [databind#28]: ObjectMapper.copy() public void testCopy() throws Exception { ObjectMapper m = new ObjectMapper(); assertTrue(m.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); m.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); assertFalse(m.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); InjectableValues inj = new InjectableValues.Std(); m.setInjectableValues(inj); assertFalse(m.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); m.enable(JsonParser.Feature.ALLOW_COMMENTS); assertTrue(m.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); // // First: verify that handling of features is decoupled: ObjectMapper m2 = m.copy(); assertFalse(m2.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); m2.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); assertTrue(m2.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); assertSame(inj, m2.getInjectableValues()); // but should NOT change the original assertFalse(m.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); // nor vice versa: assertFalse(m.isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE)); assertFalse(m2.isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE)); m.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); assertTrue(m.isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE)); assertFalse(m2.isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE)); // // Also, underlying JsonFactory instances should be distinct assertNotSame(m.getFactory(), m2.getFactory()); // [databind#122]: Need to ensure mix-ins are not shared assertEquals(0, m.getSerializationConfig().mixInCount()); assertEquals(0, m2.getSerializationConfig().mixInCount()); assertEquals(0, m.getDeserializationConfig().mixInCount()); assertEquals(0, m2.getDeserializationConfig().mixInCount()); m.addMixIn(String.class, Integer.class); assertEquals(1, m.getSerializationConfig().mixInCount()); assertEquals(0, m2.getSerializationConfig().mixInCount()); assertEquals(1, m.getDeserializationConfig().mixInCount()); assertEquals(0, m2.getDeserializationConfig().mixInCount()); // [databind#913]: Ensure JsonFactory Features copied assertTrue(m2.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); } // [databind#1580] public void testCopyOfConfigOverrides() throws Exception { ObjectMapper m = new ObjectMapper(); SerializationConfig config = m.getSerializationConfig(); assertEquals(JsonInclude.Value.empty(), config.getDefaultPropertyInclusion()); assertEquals(JsonSetter.Value.empty(), config.getDefaultSetterInfo()); assertNull(config.getDefaultMergeable()); VisibilityChecker defaultVis = config.getDefaultVisibilityChecker(); assertEquals(VisibilityChecker.Std.class, defaultVis.getClass()); // change JsonInclude.Value customIncl = JsonInclude.Value.empty().withValueInclusion(JsonInclude.Include.NON_DEFAULT); m.setDefaultPropertyInclusion(customIncl); JsonSetter.Value customSetter = JsonSetter.Value.forValueNulls(Nulls.SKIP); m.setDefaultSetterInfo(customSetter); m.setDefaultMergeable(Boolean.TRUE); VisibilityChecker customVis = VisibilityChecker.Std.defaultInstance() .withFieldVisibility(Visibility.ANY); m.setVisibility(customVis); assertSame(customVis, m.getVisibilityChecker()); // and verify that copy retains these settings ObjectMapper m2 = m.copy(); SerializationConfig config2 = m2.getSerializationConfig(); assertSame(customIncl, config2.getDefaultPropertyInclusion()); assertSame(customSetter, config2.getDefaultSetterInfo()); assertEquals(Boolean.TRUE, config2.getDefaultMergeable()); assertSame(customVis, config2.getDefaultVisibilityChecker()); } public void testFailedCopy() throws Exception { NoCopyMapper src = new NoCopyMapper(); try { src.copy(); fail("Should not pass"); } catch (IllegalStateException e) { verifyException(e, "does not override copy()"); } } public void testAnnotationIntrospectorCopyin() { ObjectMapper m = new ObjectMapper(); m.setAnnotationIntrospector(new MyAnnotationIntrospector()); assertEquals(MyAnnotationIntrospector.class, m.getDeserializationConfig().getAnnotationIntrospector().getClass()); ObjectMapper m2 = m.copy(); assertEquals(MyAnnotationIntrospector.class, m2.getDeserializationConfig().getAnnotationIntrospector().getClass()); assertEquals(MyAnnotationIntrospector.class, m2.getSerializationConfig().getAnnotationIntrospector().getClass()); } /* /********************************************************** /* Test methods, other /********************************************************** */ public void testProps() { ObjectMapper m = new ObjectMapper(); // should have default factory assertNotNull(m.getNodeFactory()); JsonNodeFactory nf = new JsonNodeFactory(true); m.setNodeFactory(nf); assertNull(m.getInjectableValues()); assertSame(nf, m.getNodeFactory()); } // Test to ensure that we can check property ordering defaults... public void testConfigForPropertySorting() throws Exception { ObjectMapper m = new ObjectMapper(); // sort-alphabetically is disabled by default: assertFalse(m.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)); SerializationConfig sc = m.getSerializationConfig(); assertFalse(sc.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)); assertFalse(sc.shouldSortPropertiesAlphabetically()); DeserializationConfig dc = m.getDeserializationConfig(); assertFalse(dc.shouldSortPropertiesAlphabetically()); // but when enabled, should be visible: m.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); sc = m.getSerializationConfig(); assertTrue(sc.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)); assertTrue(sc.shouldSortPropertiesAlphabetically()); dc = m.getDeserializationConfig(); // and not just via SerializationConfig, but also via DeserializationConfig assertTrue(dc.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)); assertTrue(dc.shouldSortPropertiesAlphabetically()); } public void testJsonFactoryLinkage() { // first, implicit factory, giving implicit linkage assertSame(MAPPER, MAPPER.getFactory().getCodec()); // and then explicit factory, which should also be implicitly linked JsonFactory f = new JsonFactory(); ObjectMapper m = new ObjectMapper(f); assertSame(f, m.getFactory()); assertSame(m, f.getCodec()); } public void testProviderConfig() throws Exception { ObjectMapper m = new ObjectMapper(); final String JSON = "{ \"x\" : 3 }"; assertEquals(0, m._deserializationContext._cache.cachedDeserializersCount()); // and then should get one constructed for: Bean bean = m.readValue(JSON, Bean.class); assertNotNull(bean); // Since 2.6, serializer for int also cached: assertEquals(2, m._deserializationContext._cache.cachedDeserializersCount()); m._deserializationContext._cache.flushCachedDeserializers(); assertEquals(0, m._deserializationContext._cache.cachedDeserializersCount()); // 07-Nov-2014, tatu: As per [databind#604] verify that Maps also get cached m = new ObjectMapper(); List stuff = m.readValue("[ ]", List.class); assertNotNull(stuff); // may look odd, but due to "Untyped" deserializer thing, we actually have // 4 deserializers (int, List, Map, Object) assertEquals(4, m._deserializationContext._cache.cachedDeserializersCount()); } // For [databind#689] public void testCustomDefaultPrettyPrinter() throws Exception { final ObjectMapper m = new ObjectMapper(); final int[] input = new int[] { 1, 2 }; // without anything else, compact: assertEquals("[1,2]", m.writeValueAsString(input)); // or with default, get... defaults: m.enable(SerializationFeature.INDENT_OUTPUT); assertEquals("[ 1, 2 ]", m.writeValueAsString(input)); assertEquals("[ 1, 2 ]", m.writerWithDefaultPrettyPrinter().writeValueAsString(input)); assertEquals("[ 1, 2 ]", m.writer().withDefaultPrettyPrinter().writeValueAsString(input)); // but then with our custom thingy... m.setDefaultPrettyPrinter(new FooPrettyPrinter()); assertEquals("[1 , 2]", m.writeValueAsString(input)); assertEquals("[1 , 2]", m.writerWithDefaultPrettyPrinter().writeValueAsString(input)); assertEquals("[1 , 2]", m.writer().withDefaultPrettyPrinter().writeValueAsString(input)); // and yet, can disable too assertEquals("[1,2]", m.writer().without(SerializationFeature.INDENT_OUTPUT) .writeValueAsString(input)); } // For [databind#703], [databind#978] public void testNonSerializabilityOfObject() { ObjectMapper m = new ObjectMapper(); assertFalse(m.canSerialize(Object.class)); // but this used to pass, incorrectly, second time around assertFalse(m.canSerialize(Object.class)); // [databind#978]: Different answer if empty Beans ARE allowed m = new ObjectMapper(); m.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); assertTrue(m.canSerialize(Object.class)); assertTrue(MAPPER.writer().without(SerializationFeature.FAIL_ON_EMPTY_BEANS) .canSerialize(Object.class)); assertFalse(MAPPER.writer().with(SerializationFeature.FAIL_ON_EMPTY_BEANS) .canSerialize(Object.class)); } // for [databind#756] public void testEmptyBeanSerializability() { // with default settings, error assertFalse(MAPPER.writer().with(SerializationFeature.FAIL_ON_EMPTY_BEANS) .canSerialize(EmptyBean.class)); // but with changes assertTrue(MAPPER.writer().without(SerializationFeature.FAIL_ON_EMPTY_BEANS) .canSerialize(EmptyBean.class)); } // for [databind#898] public void testSerializerProviderAccess() throws Exception { // ensure we have "fresh" instance, just in case ObjectMapper mapper = new ObjectMapper(); JsonSerializer ser = mapper.getSerializerProviderInstance() .findValueSerializer(Bean.class); assertNotNull(ser); assertEquals(Bean.class, ser.handledType()); } // for [databind#1074] public void testCopyOfParserFeatures() throws Exception { // ensure we have "fresh" instance to start with ObjectMapper mapper = new ObjectMapper(); assertFalse(mapper.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); assertTrue(mapper.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); ObjectMapper copy = mapper.copy(); assertTrue(copy.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); // also verify there's no back-linkage copy.configure(JsonParser.Feature.ALLOW_COMMENTS, false); assertFalse(copy.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); assertTrue(mapper.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); } // since 2.8 public void testDataOutputViaMapper() throws Exception { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ObjectNode input = MAPPER.createObjectNode(); input.put("a", 1); DataOutput data = new DataOutputStream(bytes); final String exp = "{\"a\":1}"; MAPPER.writeValue(data, input); assertEquals(exp, bytes.toString("UTF-8")); // and also via ObjectWriter... bytes.reset(); data = new DataOutputStream(bytes); MAPPER.writer().writeValue(data, input); assertEquals(exp, bytes.toString("UTF-8")); } // since 2.8 @SuppressWarnings("unchecked") public void testDataInputViaMapper() throws Exception { byte[] src = "{\"a\":1}".getBytes("UTF-8"); DataInput input = new DataInputStream(new ByteArrayInputStream(src)); Map map = (Map) MAPPER.readValue(input, Map.class); assertEquals(Integer.valueOf(1), map.get("a")); input = new DataInputStream(new ByteArrayInputStream(src)); // and via ObjectReader map = MAPPER.readerFor(Map.class) .readValue(input); assertEquals(Integer.valueOf(1), map.get("a")); input = new DataInputStream(new ByteArrayInputStream(src)); JsonNode n = MAPPER.readerFor(Map.class) .readTree(input); assertNotNull(n); } } ObjectReaderTest.java000066400000000000000000000260531325620701100345450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.StringWriter; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.cfg.ContextAttributes; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; public class ObjectReaderTest extends BaseMapTest { final ObjectMapper MAPPER = new ObjectMapper(); static class POJO { public Map name; } public void testSimpleViaParser() throws Exception { final String JSON = "[1]"; JsonParser p = MAPPER.getFactory().createParser(JSON); Object ob = MAPPER.readerFor(Object.class) .readValue(p); p.close(); assertTrue(ob instanceof List); } public void testSimpleAltSources() throws Exception { final String JSON = "[1]"; final byte[] BYTES = JSON.getBytes("UTF-8"); Object ob = MAPPER.readerFor(Object.class) .readValue(BYTES); assertTrue(ob instanceof List); ob = MAPPER.readerFor(Object.class) .readValue(BYTES, 0, BYTES.length); assertTrue(ob instanceof List); assertEquals(1, ((List) ob).size()); } public void testParserFeatures() throws Exception { final String JSON = "[ /* foo */ 7 ]"; // default won't accept comments, let's change that: ObjectReader reader = MAPPER.readerFor(int[].class) .with(JsonParser.Feature.ALLOW_COMMENTS); int[] value = reader.readValue(JSON); assertNotNull(value); assertEquals(1, value.length); assertEquals(7, value[0]); // but also can go back try { reader.without(JsonParser.Feature.ALLOW_COMMENTS).readValue(JSON); fail("Should not have passed"); } catch (JsonProcessingException e) { verifyException(e, "foo"); } } public void testNodeHandling() throws Exception { JsonNodeFactory nodes = new JsonNodeFactory(true); ObjectReader r = MAPPER.reader().with(nodes); // but also no further changes if attempting again assertSame(r, r.with(nodes)); assertTrue(r.createArrayNode().isArray()); assertTrue(r.createObjectNode().isObject()); } public void testFeatureSettings() throws Exception { ObjectReader r = MAPPER.reader(); assertFalse(r.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); assertFalse(r.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); r = r.withoutFeatures(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); assertFalse(r.isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)); assertFalse(r.isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)); r = r.withFeatures(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); assertTrue(r.isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)); assertTrue(r.isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)); // alternative method too... can't recall why two assertSame(r, r.with(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)); } public void testMiscSettings() throws Exception { ObjectReader r = MAPPER.reader(); assertSame(MAPPER.getFactory(), r.getFactory()); JsonFactory f = new JsonFactory(); r = r.with(f); assertSame(f, r.getFactory()); assertSame(r, r.with(f)); assertNotNull(r.getTypeFactory()); assertNull(r.getInjectableValues()); r = r.withAttributes(Collections.emptyMap()); ContextAttributes attrs = r.getAttributes(); assertNotNull(attrs); assertNull(attrs.getAttribute("abc")); assertSame(r, r.withoutAttribute("foo")); ObjectReader newR = r.forType(MAPPER.constructType(String.class)); assertNotSame(r, newR); assertSame(newR, newR.forType(String.class)); DeserializationProblemHandler probH = new DeserializationProblemHandler() { }; newR = r.withHandler(probH); assertNotSame(r, newR); assertSame(newR, newR.withHandler(probH)); r = newR; } @SuppressWarnings("deprecation") public void testDeprecatedSettings() throws Exception { ObjectReader r = MAPPER.reader(); // and deprecated variants ObjectReader newR = r.forType(MAPPER.constructType(String.class)); assertSame(newR, newR.withType(String.class)); assertSame(newR, newR.withType(MAPPER.constructType(String.class))); newR = newR.withRootName(PropertyName.construct("foo")); assertNotSame(r, newR); assertSame(newR, newR.withRootName(PropertyName.construct("foo"))); } public void testNoPrefetch() throws Exception { ObjectReader r = MAPPER.reader() .without(DeserializationFeature.EAGER_DESERIALIZER_FETCH); Number n = r.forType(Integer.class).readValue("123 "); assertEquals(Integer.valueOf(123), n); } /* /********************************************************** /* Test methods, JsonPointer /********************************************************** */ public void testNoPointerLoading() throws Exception { final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}"; JsonNode tree = MAPPER.readTree(source); JsonNode node = tree.at("/foo/bar/caller"); POJO pojo = MAPPER.treeToValue(node, POJO.class); assertTrue(pojo.name.containsKey("value")); assertEquals(1234, pojo.name.get("value")); } public void testPointerLoading() throws Exception { final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}"; ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller"); POJO pojo = reader.readValue(source); assertTrue(pojo.name.containsKey("value")); assertEquals(1234, pojo.name.get("value")); } public void testPointerLoadingAsJsonNode() throws Exception { final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}"; ObjectReader reader = MAPPER.readerFor(POJO.class).at(JsonPointer.compile("/foo/bar/caller")); JsonNode node = reader.readTree(source); assertTrue(node.has("name")); assertEquals("{\"value\":1234}", node.get("name").toString()); } public void testPointerLoadingMappingIteratorOne() throws Exception { final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}"; ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller"); MappingIterator itr = reader.readValues(source); POJO pojo = itr.next(); assertTrue(pojo.name.containsKey("value")); assertEquals(1234, pojo.name.get("value")); assertFalse(itr.hasNext()); itr.close(); } public void testPointerLoadingMappingIteratorMany() throws Exception { final String source = "{\"foo\":{\"bar\":{\"caller\":[{\"name\":{\"value\":1234}}, {\"name\":{\"value\":5678}}]}}}"; ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller"); MappingIterator itr = reader.readValues(source); POJO pojo = itr.next(); assertTrue(pojo.name.containsKey("value")); assertEquals(1234, pojo.name.get("value")); assertTrue(itr.hasNext()); pojo = itr.next(); assertNotNull(pojo.name); assertTrue(pojo.name.containsKey("value")); assertEquals(5678, pojo.name.get("value")); assertFalse(itr.hasNext()); itr.close(); } // [databind#1637] public void testPointerWithArrays() throws Exception { final String json = aposToQuotes("{\n'wrapper1': {\n" + " 'set1': ['one', 'two', 'three'],\n" + " 'set2': ['four', 'five', 'six']\n" + "},\n" + "'wrapper2': {\n" + " 'set1': ['one', 'two', 'three'],\n" + " 'set2': ['four', 'five', 'six']\n" + "}\n}"); final Pojo1637 testObject = MAPPER.readerFor(Pojo1637.class) .at("/wrapper1") .readValue(json); assertNotNull(testObject); assertNotNull(testObject.set1); assertTrue(!testObject.set1.isEmpty()); assertNotNull(testObject.set2); assertTrue(!testObject.set2.isEmpty()); } public static class Pojo1637 { public Set set1; public Set set2; } /* /********************************************************** /* Test methods, ObjectCodec /********************************************************** */ public void testTreeToValue() throws Exception { ArrayNode n = MAPPER.createArrayNode(); n.add("xyz"); ObjectReader r = MAPPER.readerFor(String.class); List list = r.treeToValue(n, List.class); assertEquals(1, list.size()); } public void testCodecUnsupportedWrites() throws Exception { ObjectReader r = MAPPER.readerFor(String.class); JsonGenerator g = MAPPER.getFactory().createGenerator(new StringWriter()); ObjectNode n = MAPPER.createObjectNode(); try { r.writeTree(g, n); fail("Should not pass"); } catch (UnsupportedOperationException e) { ; } try { r.writeValue(g, "Foo"); fail("Should not pass"); } catch (UnsupportedOperationException e) { ; } g.close(); g.close(); } /* /********************************************************** /* Test methods, failures, other /********************************************************** */ public void testMissingType() throws Exception { ObjectReader r = MAPPER.reader(); try { r.readValue("1"); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "No value type configured"); } } public void testSchema() throws Exception { ObjectReader r = MAPPER.readerFor(String.class); // Ok to try to set `null` schema, always: r = r.with((FormatSchema) null); try { // but not schema that doesn't match format (no schema exists for json) r = r.with(new BogusSchema()) .readValue(quote("foo")); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot use FormatSchema"); } } } ObjectWriterTest.java000066400000000000000000000246551325620701100346250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.IOException; import java.io.StringWriter; import java.util.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.databind.node.ObjectNode; /** * Unit tests for checking features added to {@link ObjectWriter}, such * as adding of explicit pretty printer. */ public class ObjectWriterTest extends BaseMapTest { static class CloseableValue implements Closeable { public int x; public boolean closed; @Override public void close() throws IOException { closed = true; } } final ObjectMapper MAPPER = new ObjectMapper(); @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") static class PolyBase { } @JsonTypeName("A") static class ImplA extends PolyBase { public int value; public ImplA(int v) { value = v; } } @JsonTypeName("B") static class ImplB extends PolyBase { public int b; public ImplB(int v) { b = v; } } /* /********************************************************** /* Test methods, normal operation /********************************************************** */ public void testPrettyPrinter() throws Exception { ObjectWriter writer = MAPPER.writer(); HashMap data = new HashMap(); data.put("a", 1); // default: no indentation assertEquals("{\"a\":1}", writer.writeValueAsString(data)); // and then with standard writer = writer.withDefaultPrettyPrinter(); // pretty printer uses system-specific line feeds, so we do that as well. String lf = System.getProperty("line.separator"); assertEquals("{" + lf + " \"a\" : 1" + lf + "}", writer.writeValueAsString(data)); // and finally, again without indentation writer = writer.with((PrettyPrinter) null); assertEquals("{\"a\":1}", writer.writeValueAsString(data)); } public void testPrefetch() throws Exception { ObjectWriter writer = MAPPER.writer(); assertFalse(writer.hasPrefetchedSerializer()); writer = writer.forType(String.class); assertTrue(writer.hasPrefetchedSerializer()); } public void testObjectWriterFeatures() throws Exception { ObjectWriter writer = MAPPER.writer() .without(JsonGenerator.Feature.QUOTE_FIELD_NAMES); Map map = new HashMap(); map.put("a", 1); assertEquals("{a:1}", writer.writeValueAsString(map)); // but can also reconfigure assertEquals("{\"a\":1}", writer.with(JsonGenerator.Feature.QUOTE_FIELD_NAMES) .writeValueAsString(map)); } public void testObjectWriterWithNode() throws Exception { ObjectNode stuff = MAPPER.createObjectNode(); stuff.put("a", 5); ObjectWriter writer = MAPPER.writerFor(JsonNode.class); String json = writer.writeValueAsString(stuff); assertEquals("{\"a\":5}", json); } public void testPolymorphicWithTyping() throws Exception { ObjectWriter writer = MAPPER.writerFor(PolyBase.class); String json; json = writer.writeValueAsString(new ImplA(3)); assertEquals(aposToQuotes("{'type':'A','value':3}"), json); json = writer.writeValueAsString(new ImplB(-5)); assertEquals(aposToQuotes("{'type':'B','b':-5}"), json); } public void testCanSerialize() throws Exception { assertTrue(MAPPER.writer().canSerialize(String.class)); assertTrue(MAPPER.writer().canSerialize(String.class, null)); } public void testNoPrefetch() throws Exception { ObjectWriter w = MAPPER.writer() .without(SerializationFeature.EAGER_SERIALIZER_FETCH); ByteArrayOutputStream out = new ByteArrayOutputStream(); w.writeValue(out, Integer.valueOf(3)); out.close(); assertEquals("3", out.toString("UTF-8")); } public void testWithCloseCloseable() throws Exception { ObjectWriter w = MAPPER.writer() .with(SerializationFeature.CLOSE_CLOSEABLE); assertTrue(w.isEnabled(SerializationFeature.CLOSE_CLOSEABLE)); CloseableValue input = new CloseableValue(); assertFalse(input.closed); byte[] json = w.writeValueAsBytes(input); assertNotNull(json); assertTrue(input.closed); input.close(); // and via explicitly passed generator JsonGenerator g = MAPPER.getFactory().createGenerator(new StringWriter()); input = new CloseableValue(); assertFalse(input.closed); w.writeValue(g, input); assertTrue(input.closed); g.close(); input.close(); } public void testViewSettings() throws Exception { ObjectWriter w = MAPPER.writer(); ObjectWriter newW = w.withView(String.class); assertNotSame(w, newW); assertSame(newW, newW.withView(String.class)); newW = w.with(Locale.CANADA); assertNotSame(w, newW); assertSame(newW, newW.with(Locale.CANADA)); } public void testMiscSettings() throws Exception { ObjectWriter w = MAPPER.writer(); assertSame(MAPPER.getFactory(), w.getFactory()); assertFalse(w.hasPrefetchedSerializer()); assertNotNull(w.getTypeFactory()); JsonFactory f = new JsonFactory(); w = w.with(f); assertSame(f, w.getFactory()); ObjectWriter newW = w.with(Base64Variants.MODIFIED_FOR_URL); assertNotSame(w, newW); assertSame(newW, newW.with(Base64Variants.MODIFIED_FOR_URL)); w = w.withAttributes(Collections.emptyMap()); w = w.withAttribute("a", "b"); assertEquals("b", w.getAttributes().getAttribute("a")); w = w.withoutAttribute("a"); assertNull(w.getAttributes().getAttribute("a")); FormatSchema schema = new BogusSchema(); try { newW = w.with(schema); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot use FormatSchema"); } } public void testRootValueSettings() throws Exception { ObjectWriter w = MAPPER.writer(); // First, root name: ObjectWriter newW = w.withRootName("foo"); assertNotSame(w, newW); assertSame(newW, newW.withRootName(PropertyName.construct("foo"))); w = newW; newW = w.withRootName((String) null); assertNotSame(w, newW); assertSame(newW, newW.withRootName((PropertyName) null)); // Then root value separator w = w.withRootValueSeparator(new SerializedString(",")); assertSame(w, w.withRootValueSeparator(new SerializedString(","))); assertSame(w, w.withRootValueSeparator(",")); newW = w.withRootValueSeparator("/"); assertNotSame(w, newW); assertSame(newW, newW.withRootValueSeparator("/")); newW = w.withRootValueSeparator((String) null); assertNotSame(w, newW); newW = w.withRootValueSeparator((SerializableString) null); assertNotSame(w, newW); } public void testFeatureSettings() throws Exception { ObjectWriter w = MAPPER.writer(); assertFalse(w.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); assertFalse(w.isEnabled(JsonGenerator.Feature.STRICT_DUPLICATE_DETECTION)); ObjectWriter newW = w.with(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS, SerializationFeature.INDENT_OUTPUT); assertNotSame(w, newW); assertTrue(newW.isEnabled(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS)); assertTrue(newW.isEnabled(SerializationFeature.INDENT_OUTPUT)); assertSame(newW, newW.with(SerializationFeature.INDENT_OUTPUT)); assertSame(newW, newW.withFeatures(SerializationFeature.INDENT_OUTPUT)); newW = w.withFeatures(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS, SerializationFeature.INDENT_OUTPUT); assertNotSame(w, newW); newW = w.without(SerializationFeature.FAIL_ON_EMPTY_BEANS, SerializationFeature.EAGER_SERIALIZER_FETCH); assertNotSame(w, newW); assertFalse(newW.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)); assertFalse(newW.isEnabled(SerializationFeature.EAGER_SERIALIZER_FETCH)); assertSame(newW, newW.without(SerializationFeature.FAIL_ON_EMPTY_BEANS)); assertSame(newW, newW.withoutFeatures(SerializationFeature.FAIL_ON_EMPTY_BEANS)); assertNotSame(w, w.withoutFeatures(SerializationFeature.FAIL_ON_EMPTY_BEANS, SerializationFeature.EAGER_SERIALIZER_FETCH)); } public void testGeneratorFeatures() throws Exception { ObjectWriter w = MAPPER.writer(); assertFalse(w.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII)); assertNotSame(w, w.with(JsonGenerator.Feature.ESCAPE_NON_ASCII)); assertNotSame(w, w.withFeatures(JsonGenerator.Feature.ESCAPE_NON_ASCII)); assertTrue(w.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET)); assertNotSame(w, w.without(JsonGenerator.Feature.AUTO_CLOSE_TARGET)); assertNotSame(w, w.withoutFeatures(JsonGenerator.Feature.AUTO_CLOSE_TARGET)); } /* /********************************************************** /* Test methods, failures /********************************************************** */ public void testArgumentChecking() throws Exception { final ObjectWriter w = MAPPER.writer(); try { w.acceptJsonFormatVisitor((JavaType) null, null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "type must be provided"); } } public void testSchema() throws Exception { try { MAPPER.writerFor(String.class) .with(new BogusSchema()) .writeValueAsBytes("foo"); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot use FormatSchema"); } } } RoundtripTest.java000066400000000000000000000031311325620701100341720ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; public class RoundtripTest extends BaseMapTest { private final ObjectMapper MAPPER = new ObjectMapper(); public void testMedaItemRoundtrip() throws Exception { MediaItem.Content c = new MediaItem.Content(); c.setBitrate(9600); c.setCopyright("none"); c.setDuration(360000L); c.setFormat("lzf"); c.setHeight(640); c.setSize(128000L); c.setTitle("Amazing Stuff For Something Or Oth\u00CBr!"); c.setUri("http://multi.fario.us/index.html"); c.setWidth(1400); c.addPerson("Joe Sixp\u00e2ck"); c.addPerson("Ezekiel"); c.addPerson("Sponge-Bob Squarepant\u00DF"); MediaItem input = new MediaItem(c); input.addPhoto(new MediaItem.Photo()); input.addPhoto(new MediaItem.Photo()); input.addPhoto(new MediaItem.Photo()); String json = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(input); MediaItem output = MAPPER.readValue(new java.io.StringReader(json), MediaItem.class); assertNotNull(output); assertNotNull(output.getImages()); assertEquals(input.getImages().size(), output.getImages().size()); assertNotNull(output.getContent()); assertEquals(input.getContent().getTitle(), output.getContent().getTitle()); assertEquals(input.getContent().getUri(), output.getContent().getUri()); // compare re-serialization as a simple check as well assertEquals(json, MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(output)); } } TestFormatSchema.java000066400000000000000000000170311325620701100345610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.base.ParserBase; import com.fasterxml.jackson.core.base.GeneratorBase; import com.fasterxml.jackson.databind.ObjectMapper; /** * Basic tests to ensure that {@link FormatSchema} instances are properly * passed to {@link JsonGenerator} and {@link JsonParser} instances if * mapper, reader or writer is configured with one. */ public class TestFormatSchema extends BaseMapTest { /* /********************************************************************** /* Helper classes /********************************************************************** */ static class MySchema implements FormatSchema { @Override public String getSchemaType() { return "test"; } } static class FactoryWithSchema extends JsonFactory { @Override public String getFormatName() { return "test"; } @Override public boolean canUseSchema(FormatSchema schema) { return (schema instanceof MySchema); } private static final long serialVersionUID = 1L; @Override protected JsonParser _createParser(Reader r, IOContext ctxt) throws IOException, JsonParseException { return new ParserWithSchema(ctxt, _parserFeatures); } @Override protected JsonGenerator _createGenerator(Writer out, IOContext ctxt) throws IOException { return new GeneratorWithSchema(_generatorFeatures, _objectCodec); } } // Ugly, but easiest way to get schema back is to throw exception... @SuppressWarnings("serial") static class SchemaException extends RuntimeException { public final FormatSchema _schema; public SchemaException(FormatSchema s) { _schema = s; } } static class ParserWithSchema extends ParserBase { public ParserWithSchema(IOContext ioCtxt, int features) { super(ioCtxt, features); } @Override public void setSchema(FormatSchema schema) { throw new SchemaException(schema); } @Override protected void _finishString() throws IOException, JsonParseException { } @Override public byte[] getBinaryValue(Base64Variant b64variant) { return null; } @Override public byte[] getEmbeddedObject() { return null; } @Override public String getText() throws IOException, JsonParseException { return null; } @Override public char[] getTextCharacters() throws IOException { return null; } @Override public int getTextLength() throws IOException, JsonParseException { return 0; } @Override public int getTextOffset() throws IOException, JsonParseException { return 0; } @Override public JsonToken nextToken() throws IOException, JsonParseException { return null; } @Override public ObjectCodec getCodec() { return null; } @Override public void setCodec(ObjectCodec c) { } @Override protected void _closeInput() throws IOException { } @Override public int readBinaryValue(Base64Variant b64variant, OutputStream out) { return 0; } } static class GeneratorWithSchema extends GeneratorBase { public GeneratorWithSchema(int features, ObjectCodec codec) { super(features, codec); } @Override public void setSchema(FormatSchema schema) { throw new SchemaException(schema); } @Override protected void _releaseBuffers() { } @Override protected void _verifyValueWrite(String typeMsg) throws IOException { } @Override public void flush() throws IOException { } @Override public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) throws IOException { } @Override public void writeBoolean(boolean state) throws IOException { } @Override public void writeFieldName(String name) throws IOException { } @Override public void writeNull() throws IOException, JsonGenerationException { } @Override public void writeNumber(short v) throws IOException { } @Override public void writeNumber(int v) throws IOException { } @Override public void writeNumber(long v) throws IOException { } @Override public void writeNumber(BigInteger v) throws IOException { } @Override public void writeNumber(double d) throws IOException { } @Override public void writeNumber(float f) throws IOException { } @Override public void writeNumber(BigDecimal dec) throws IOException { } @Override public void writeNumber(String encodedValue) throws IOException { } @Override public void writeRaw(String text) throws IOException { } @Override public void writeRaw(String text, int offset, int len) { } @Override public void writeRaw(char[] text, int offset, int len) { } @Override public void writeRaw(char c) throws IOException { } @Override public void writeRawUTF8String(byte[] text, int offset, int length) { } @Override public void writeString(String text) throws IOException { } @Override public void writeString(char[] text, int offset, int len) { } @Override public void writeUTF8String(byte[] text, int offset, int length) { } @Override public void writeStartArray() { } @Override public void writeEndArray() throws IOException, JsonGenerationException { } @Override public void writeStartObject() { } @Override public void writeEndObject() { } @Override public int writeBinary(Base64Variant b64variant, InputStream data, int dataLength) { return -1; } } /* /********************************************************************** /* Unit tests /********************************************************************** */ public void testFormatForParsers() throws Exception { ObjectMapper mapper = new ObjectMapper(new FactoryWithSchema()); MySchema s = new MySchema(); StringReader r = new StringReader("{}"); // bit ugly, but can't think of cleaner simple way to check this... try { mapper.reader(s).forType(Object.class).readValue(r); fail("Excpected exception"); } catch (SchemaException e) { assertSame(s, e._schema); } } public void testFormatForGenerators() throws Exception { ObjectMapper mapper = new ObjectMapper(new FactoryWithSchema()); MySchema s = new MySchema(); StringWriter sw = new StringWriter(); // bit ugly, but can't think of cleaner simple way to check this... try { mapper.writer(s).writeValue(sw, "Foobar"); fail("Excpected exception"); } catch (SchemaException e) { assertSame(s, e._schema); } } } TestHandlerInstantiation.java000066400000000000000000000207351325620701100363370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.*; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; import com.fasterxml.jackson.databind.type.TypeFactory; public class TestHandlerInstantiation extends BaseMapTest { /* /********************************************************************** /* Helper classes, beans /********************************************************************** */ @JsonDeserialize(using=MyBeanDeserializer.class) @JsonSerialize(using=MyBeanSerializer.class) static class MyBean { public String value; public MyBean() { this(null); } public MyBean(String s) { value = s; } } @SuppressWarnings("serial") @JsonDeserialize(keyUsing=MyKeyDeserializer.class) static class MyMap extends HashMap { } @JsonTypeInfo(use=Id.CUSTOM, include=As.WRAPPER_ARRAY) @JsonTypeIdResolver(TestCustomIdResolver.class) static class TypeIdBean { public int x; public TypeIdBean() { } public TypeIdBean(int x) { this.x = x; } } static class TypeIdBeanWrapper { public TypeIdBean bean; public TypeIdBeanWrapper() { this(null); } public TypeIdBeanWrapper(TypeIdBean b) { bean = b; } } /* /********************************************************************** /* Helper classes, serializers/deserializers/resolvers /********************************************************************** */ static class MyBeanDeserializer extends JsonDeserializer { public String _prefix = ""; public MyBeanDeserializer(String p) { _prefix = p; } @Override public MyBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return new MyBean(_prefix+jp.getText()); } } static class MyKeyDeserializer extends KeyDeserializer { public MyKeyDeserializer() { } @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException { return "KEY"; } } static class MyBeanSerializer extends JsonSerializer { public String _prefix = ""; public MyBeanSerializer(String p) { _prefix = p; } @Override public void serialize(MyBean value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString(_prefix + value.value); } } // copied from "TestCustomTypeIdResolver" static class TestCustomIdResolver extends TypeIdResolverBase { static List initTypes; final String _id; public TestCustomIdResolver(String idForBean) { _id = idForBean; } @Override public Id getMechanism() { return Id.CUSTOM; } @Override public String idFromValue(Object value) { if (value.getClass() == TypeIdBean.class) { return _id; } return "unknown"; } @Override public String idFromValueAndType(Object value, Class type) { return idFromValue(value); } @Override public void init(JavaType baseType) { if (initTypes != null) { initTypes.add(baseType); } } @Override public JavaType typeFromId(DatabindContext context, String id) { if (id.equals(_id)) { return TypeFactory.defaultInstance().constructType(TypeIdBean.class); } return null; } @Override public String idFromBaseType() { return "xxx"; } } /* /********************************************************************** /* Helper classes, handler instantiator /********************************************************************** */ static class MyInstantiator extends HandlerInstantiator { private final String _prefix; public MyInstantiator(String p) { _prefix = p; } @Override public JsonDeserializer deserializerInstance(DeserializationConfig config, Annotated annotated, Class deserClass) { if (deserClass == MyBeanDeserializer.class) { return new MyBeanDeserializer(_prefix); } return null; } @Override public KeyDeserializer keyDeserializerInstance(DeserializationConfig config, Annotated annotated, Class keyDeserClass) { if (keyDeserClass == MyKeyDeserializer.class) { return new MyKeyDeserializer(); } return null; } @Override public JsonSerializer serializerInstance(SerializationConfig config, Annotated annotated, Class serClass) { if (serClass == MyBeanSerializer.class) { return new MyBeanSerializer(_prefix); } return null; } @Override public TypeIdResolver typeIdResolverInstance(MapperConfig config, Annotated annotated, Class resolverClass) { if (resolverClass == TestCustomIdResolver.class) { return new TestCustomIdResolver("!!!"); } return null; } @Override public TypeResolverBuilder typeResolverBuilderInstance(MapperConfig config, Annotated annotated, Class builderClass) { return null; } } /* /********************************************************************** /* Unit tests /********************************************************************** */ public void testDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setHandlerInstantiator(new MyInstantiator("abc:")); MyBean result = mapper.readValue(quote("123"), MyBean.class); assertEquals("abc:123", result.value); } public void testKeyDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setHandlerInstantiator(new MyInstantiator("abc:")); MyMap map = mapper.readValue("{\"a\":\"b\"}", MyMap.class); // easiest to test by just serializing... assertEquals("{\"KEY\":\"b\"}", mapper.writeValueAsString(map)); } public void testSerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setHandlerInstantiator(new MyInstantiator("xyz:")); assertEquals(quote("xyz:456"), mapper.writeValueAsString(new MyBean("456"))); } public void testTypeIdResolver() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setHandlerInstantiator(new MyInstantiator("foobar")); String json = mapper.writeValueAsString(new TypeIdBeanWrapper(new TypeIdBean(123))); // should now use our custom id scheme: assertEquals("{\"bean\":[\"!!!\",{\"x\":123}]}", json); // and bring it back too: TypeIdBeanWrapper result = mapper.readValue(json, TypeIdBeanWrapper.class); TypeIdBean bean = result.bean; assertEquals(123, bean.x); } } TestJDKSerialization.java000066400000000000000000000176721325620701100353710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.LRUMap; /** * Tests to verify that most core Jackson components can be serialized * using default JDK serialization: this feature is useful for some * platforms, such as Android, where memory management is handled * much more aggressively. */ public class TestJDKSerialization extends BaseMapTest { static class MyPojo { public int x; protected int y; public MyPojo() { } public MyPojo(int x0, int y0) { x = x0; y = y0; } public int getY() { return y; } public void setY(int y) { this.y = y; } } // for [databind#899] static class EnumPOJO { public ABC abc = ABC.B; public Map stuff = new LinkedHashMap(); } static class AnyBean { HashMap _map; public AnyBean() { _map = new HashMap(); } @JsonAnySetter AnyBean addEntry(String key, Object value) { _map.put(key, value); return this; } @JsonAnyGetter public Map properties() { return _map; } } /* /********************************************************** /* Tests for individual objects /********************************************************** */ /* 18-Oct-2013, tatu: Not sure why, but looks like sharing the default * ObjectMapper here can lead to strange unit test suite failures, so * let's create a private copy for this class only. */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testConfigs() throws IOException { byte[] base = jdkSerialize(MAPPER.getDeserializationConfig().getBaseSettings()); assertNotNull(jdkDeserialize(base)); // first things first: underlying BaseSettings DeserializationConfig origDC = MAPPER.getDeserializationConfig(); SerializationConfig origSC = MAPPER.getSerializationConfig(); byte[] dcBytes = jdkSerialize(origDC); byte[] scBytes = jdkSerialize(origSC); DeserializationConfig dc = jdkDeserialize(dcBytes); assertNotNull(dc); assertEquals(dc._deserFeatures, origDC._deserFeatures); SerializationConfig sc = jdkDeserialize(scBytes); assertNotNull(sc); assertEquals(sc._serFeatures, origSC._serFeatures); } // for [databind#899] public void testEnumHandlers() throws IOException { ObjectMapper mapper = new ObjectMapper(); // ensure we have serializers and/or deserializers, first String json = mapper.writerFor(EnumPOJO.class) .writeValueAsString(new EnumPOJO()); EnumPOJO result = mapper.readerFor(EnumPOJO.class) .readValue(json); assertNotNull(result); // and then use JDK serialization to freeze/thaw objects byte[] bytes = jdkSerialize(mapper); ObjectMapper mapper2 = jdkDeserialize(bytes); assertNotNull(mapper2); bytes = jdkSerialize(mapper.readerFor(EnumPOJO.class)); ObjectReader r = jdkDeserialize(bytes); assertNotNull(r); /* 14-Aug-2015, tatu: Looks like pre-loading JsonSerializer is problematic * at this point; comment out for now. Try to fix later on. */ bytes = jdkSerialize(mapper.writerFor(EnumPOJO.class)); ObjectWriter w = jdkDeserialize(bytes); assertNotNull(w); // plus, ensure objects are usable: String json2 = w.writeValueAsString(new EnumPOJO()); assertEquals(json, json2); EnumPOJO result2 = r.readValue(json2); assertNotNull(result2); } public void testObjectWriter() throws IOException { ObjectWriter origWriter = MAPPER.writer(); final String EXP_JSON = "{\"x\":2,\"y\":3}"; final MyPojo p = new MyPojo(2, 3); assertEquals(EXP_JSON, origWriter.writeValueAsString(p)); String json = origWriter.writeValueAsString(new AnyBean() .addEntry("a", "b")); assertNotNull(json); byte[] bytes = jdkSerialize(origWriter); ObjectWriter writer2 = jdkDeserialize(bytes); assertEquals(EXP_JSON, writer2.writeValueAsString(p)); } public void testObjectReader() throws IOException { ObjectReader origReader = MAPPER.readerFor(MyPojo.class); String JSON = "{\"x\":1,\"y\":2}"; MyPojo p1 = origReader.readValue(JSON); assertEquals(2, p1.y); ObjectReader anyReader = MAPPER.readerFor(AnyBean.class); AnyBean any = anyReader.readValue(JSON); assertEquals(Integer.valueOf(2), any.properties().get("y")); byte[] readerBytes = jdkSerialize(origReader); ObjectReader reader2 = jdkDeserialize(readerBytes); MyPojo p2 = reader2.readValue(JSON); assertEquals(2, p2.y); ObjectReader anyReader2 = jdkDeserialize(jdkSerialize(anyReader)); AnyBean any2 = anyReader2.readValue(JSON); assertEquals(Integer.valueOf(2), any2.properties().get("y")); } public void testObjectMapper() throws IOException { final String EXP_JSON = "{\"x\":2,\"y\":3}"; final MyPojo p = new MyPojo(2, 3); assertEquals(EXP_JSON, MAPPER.writeValueAsString(p)); byte[] bytes = jdkSerialize(MAPPER); ObjectMapper mapper2 = jdkDeserialize(bytes); assertEquals(EXP_JSON, mapper2.writeValueAsString(p)); MyPojo p2 = mapper2.readValue(EXP_JSON, MyPojo.class); assertEquals(p.x, p2.x); assertEquals(p.y, p2.y); } public void testTypeFactory() throws Exception { TypeFactory orig = TypeFactory.defaultInstance(); JavaType t = orig.constructType(JavaType.class); assertNotNull(t); byte[] bytes = jdkSerialize(orig); TypeFactory result = jdkDeserialize(bytes); assertNotNull(result); t = orig.constructType(JavaType.class); assertEquals(JavaType.class, t.getRawClass()); } public void testLRUMap() throws Exception { LRUMap map = new LRUMap(32, 32); map.put("a", 1); byte[] bytes = jdkSerialize(map); LRUMap result = jdkDeserialize(bytes); // transient implementation, will be read as empty assertEquals(0, result.size()); // but should be possible to re-populate result.put("a", 2); assertEquals(1, result.size()); } /* /********************************************************** /* Helper methods /********************************************************** */ protected byte[] jdkSerialize(Object o) throws IOException { ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000); ObjectOutputStream obOut = new ObjectOutputStream(bytes); obOut.writeObject(o); obOut.close(); return bytes.toByteArray(); } @SuppressWarnings("unchecked") protected T jdkDeserialize(byte[] raw) throws IOException { ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(raw)); try { return (T) objIn.readObject(); } catch (ClassNotFoundException e) { fail("Missing class: "+e.getMessage()); return null; } finally { objIn.close(); } } } TestRootName.java000066400000000000000000000113201325620701100337270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.ObjectMapper; /** * Unit tests dealing with handling of "root element wrapping", * including configuration of root name to use. */ public class TestRootName extends BaseMapTest { @JsonRootName("rudy") static class Bean { public int a = 3; } @JsonRootName("") static class RootBeanWithEmpty { public int a = 2; } /* /********************************************************** /* Unit tests /********************************************************** */ public void testRootViaMapper() throws Exception { ObjectMapper mapper = rootMapper(); String json = mapper.writeValueAsString(new Bean()); assertEquals("{\"rudy\":{\"a\":3}}", json); Bean bean = mapper.readValue(json, Bean.class); assertNotNull(bean); // also same with explicitly "not defined"... json = mapper.writeValueAsString(new RootBeanWithEmpty()); assertEquals("{\"RootBeanWithEmpty\":{\"a\":2}}", json); RootBeanWithEmpty bean2 = mapper.readValue(json, RootBeanWithEmpty.class); assertNotNull(bean2); assertEquals(2, bean2.a); } public void testRootViaWriterAndReader() throws Exception { ObjectMapper mapper = rootMapper(); String json = mapper.writer().writeValueAsString(new Bean()); assertEquals("{\"rudy\":{\"a\":3}}", json); Bean bean = mapper.readerFor(Bean.class).readValue(json); assertNotNull(bean); } public void testReconfiguringOfWrapping() throws Exception { ObjectMapper mapper = new ObjectMapper(); // default: no wrapping final Bean input = new Bean(); String jsonUnwrapped = mapper.writeValueAsString(input); assertEquals("{\"a\":3}", jsonUnwrapped); // secondary: wrapping String jsonWrapped = mapper.writer(SerializationFeature.WRAP_ROOT_VALUE) .writeValueAsString(input); assertEquals("{\"rudy\":{\"a\":3}}", jsonWrapped); // and then similarly for readers: Bean result = mapper.readValue(jsonUnwrapped, Bean.class); assertNotNull(result); try { // must not have extra wrapping result = mapper.readerFor(Bean.class).with(DeserializationFeature.UNWRAP_ROOT_VALUE) .readValue(jsonUnwrapped); fail("Should have failed"); } catch (JsonMappingException e) { verifyException(e, "Root name 'a'"); } // except wrapping may be expected: result = mapper.readerFor(Bean.class).with(DeserializationFeature.UNWRAP_ROOT_VALUE) .readValue(jsonWrapped); assertNotNull(result); } // [JACKSON-764] public void testRootUsingExplicitConfig() throws Exception { ObjectMapper mapper = new ObjectMapper(); ObjectWriter writer = mapper.writer().withRootName("wrapper"); String json = writer.writeValueAsString(new Bean()); assertEquals("{\"wrapper\":{\"a\":3}}", json); ObjectReader reader = mapper.readerFor(Bean.class).withRootName("wrapper"); Bean bean = reader.readValue(json); assertNotNull(bean); // also: verify that we can override SerializationFeature as well: ObjectMapper wrapping = rootMapper(); json = wrapping.writer().withRootName("something").writeValueAsString(new Bean()); assertEquals("{\"something\":{\"a\":3}}", json); json = wrapping.writer().withRootName("").writeValueAsString(new Bean()); assertEquals("{\"a\":3}", json); // 21-Apr-2015, tatu: Alternative available with 2.6 as well: json = wrapping.writer().withoutRootName().writeValueAsString(new Bean()); assertEquals("{\"a\":3}", json); bean = wrapping.readerFor(Bean.class).withRootName("").readValue(json); assertNotNull(bean); assertEquals(3, bean.a); bean = wrapping.readerFor(Bean.class).withoutRootName().readValue("{\"a\":4}"); assertNotNull(bean); assertEquals(4, bean.a); // and back to defaults bean = wrapping.readerFor(Bean.class).readValue("{\"rudy\":{\"a\":7}}"); assertNotNull(bean); assertEquals(7, bean.a); } /* /********************************************************** /* Helper methods /********************************************************** */ private ObjectMapper rootMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true); mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); return mapper; } } TestVersions.java000066400000000000000000000023231325620701100340160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databindpackage com.fasterxml.jackson.databind; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.Versioned; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.fasterxml.jackson.databind.cfg.PackageVersion; /** * Tests to ensure that we get proper Version information via * things defined as Versioned. */ public class TestVersions extends BaseMapTest { public void testMapperVersions() { ObjectMapper mapper = new ObjectMapper(); assertVersion(mapper); assertVersion(mapper.reader()); assertVersion(mapper.writer()); assertVersion(new JacksonAnnotationIntrospector()); } /* /********************************************************** /* Helper methods /********************************************************** */ private void assertVersion(Versioned vers) { Version v = vers.version(); assertFalse("Should find version information (got "+v+")", v.isUnknownVersion()); Version exp = PackageVersion.VERSION; assertEquals(exp.toFullString(), v.toFullString()); assertEquals(exp, v); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/access/000077500000000000000000000000001325620701100320235ustar00rootroot00000000000000TestAnyGetterAccess.java000066400000000000000000000036521325620701100365010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/accesspackage com.fasterxml.jackson.databind.access; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Separate tests located in different package than code being * exercised; needed to trigger some access-related failures. */ public class TestAnyGetterAccess extends BaseMapTest { /* /********************************************************** /* Helper bean classes /********************************************************** */ static class DynaBean { public int id; protected HashMap other = new HashMap(); @JsonAnyGetter public Map any() { return other; } @JsonAnySetter public void set(String name, String value) { other.put(name, value); } } static class PrivateThing { @JsonAnyGetter public Map getProperties() { HashMap map = new HashMap(); map.put("a", "A"); return map; } } /* /********************************************************** /* Test cases /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testDynaBean() throws Exception { DynaBean b = new DynaBean(); b.id = 123; b.set("name", "Billy"); assertEquals("{\"id\":123,\"name\":\"Billy\"}", MAPPER.writeValueAsString(b)); DynaBean result = MAPPER.readValue("{\"id\":2,\"name\":\"Joe\"}", DynaBean.class); assertEquals(2, result.id); assertEquals("Joe", result.other.get("name")); } public void testPrivate() throws Exception { String json = MAPPER.writeValueAsString(new PrivateThing()); assertEquals("{\"a\":\"A\"}", json); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/big/000077500000000000000000000000001325620701100313235ustar00rootroot00000000000000TestBiggerData.java000066400000000000000000000055661325620701100347540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/bigpackage com.fasterxml.jackson.databind.big; import java.util.*; import com.fasterxml.jackson.databind.*; public class TestBiggerData extends BaseMapTest { static class Citm { public Map areaNames; public Map audienceSubCategoryNames; public Map blockNames; public Map seatCategoryNames; public Map subTopicNames; public Map subjectNames; public Map topicNames; public Map topicSubTopics; public Map venueNames; public Map events; public List performances; } static class Event { public int id; public String name; public String description; public String subtitle; public String logo; public int subjectCode; public int[] topicIds; public LinkedHashSet subTopicIds; } static class Performance { public int id; public int eventId; public String name; public String description; public String logo; public List prices; public List seatCategories; public long start; public String seatMapImage; public String venueCode; } static class Price { public int amount; public int audienceSubCategoryId; public int seatCategoryId; } static class SeatCategory { public int seatCategoryId; public List areas; } static class Area { public int areaId; public int[] blockIds; } /* /********************************************************** /* Test methods /********************************************************** */ public void testReading() throws Exception { ObjectMapper mapper = objectMapper(); Citm citm = mapper.readValue(getClass().getResourceAsStream("/data/citm_catalog.json"), Citm.class); assertNotNull(citm); assertNotNull(citm.areaNames); assertEquals(17, citm.areaNames.size()); assertNotNull(citm.events); assertEquals(184, citm.events.size()); assertNotNull(citm.seatCategoryNames); assertEquals(64, citm.seatCategoryNames.size()); assertNotNull(citm.subTopicNames); assertEquals(19, citm.subTopicNames.size()); assertNotNull(citm.subjectNames); assertEquals(0, citm.subjectNames.size()); assertNotNull(citm.topicNames); assertEquals(4, citm.topicNames.size()); assertNotNull(citm.topicSubTopics); assertEquals(4, citm.topicSubTopics.size()); assertNotNull(citm.venueNames); assertEquals(1, citm.venueNames.size()); } public void testRoundTrip() throws Exception { ObjectMapper mapper = objectMapper(); Citm citm = mapper.readValue(getClass().getResourceAsStream("/data/citm_catalog.json"), Citm.class); ObjectWriter w = mapper.writerWithDefaultPrettyPrinter(); String json1 = w.writeValueAsString(citm); Citm citm2 = mapper.readValue(json1, Citm.class); String json2 = w.writeValueAsString(citm2); assertEquals(json1, json2); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/cfg/000077500000000000000000000000001325620701100313215ustar00rootroot00000000000000BogusFormatFeature.java000066400000000000000000000011321325620701100356460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import com.fasterxml.jackson.core.FormatFeature; public enum BogusFormatFeature implements FormatFeature { FF_ENABLED_BY_DEFAULT(true), FF_DISABLED_BY_DEFAULT(false); private boolean _default; private BogusFormatFeature(boolean d) { _default = d; } @Override public boolean enabledByDefault() { return _default; } @Override public int getMask() { return (1 << ordinal()); } @Override public boolean enabledIn(int flags) { return (flags & getMask()) != 0; } } ConfigObjectsTest.java000066400000000000000000000017071325620701100354710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.SubtypeResolver; import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver; public class ConfigObjectsTest extends BaseMapTest { static class Base { } static class Sub extends Base { } public void testSubtypeResolver() throws Exception { ObjectMapper mapper = new ObjectMapper(); SubtypeResolver res = mapper.getSubtypeResolver(); assertTrue(res instanceof StdSubtypeResolver); StdSubtypeResolver repl = new StdSubtypeResolver(); repl.registerSubtypes(Sub.class); mapper.setSubtypeResolver(repl); assertSame(repl, mapper.getSubtypeResolver()); } public void testMics() throws Exception { assertFalse(MapperFeature.AUTO_DETECT_FIELDS.enabledIn(0)); assertTrue(MapperFeature.AUTO_DETECT_FIELDS.enabledIn(-1)); } } DatabindContextTest.java000066400000000000000000000013071325620701100360210ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import com.fasterxml.jackson.databind.*; public class DatabindContextTest extends BaseMapTest { private final ObjectMapper MAPPER = objectMapper(); public void testDeserializationContext() throws Exception { DeserializationContext ctxt = MAPPER.getDeserializationContext(); // should be ok to try to resolve `null` assertNull(ctxt.constructType((Class) null)); assertNull(ctxt.constructType((java.lang.reflect.Type) null)); } public void testSerializationContext() throws Exception { SerializerProvider ctxt = MAPPER.getSerializerProvider(); assertNull(ctxt.constructType(null)); } } DeserializationConfigTest.java000066400000000000000000000133541325620701100372270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import java.util.Collections; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.ClassIntrospector; public class DeserializationConfigTest extends BaseMapTest { private final ObjectMapper MAPPER = new ObjectMapper(); public void testFeatureDefaults() { ObjectMapper m = new ObjectMapper(); DeserializationConfig cfg = m.getDeserializationConfig(); // Expected defaults: assertTrue(cfg.isEnabled(MapperFeature.USE_ANNOTATIONS)); assertTrue(cfg.isEnabled(MapperFeature.AUTO_DETECT_SETTERS)); assertTrue(cfg.isEnabled(MapperFeature.AUTO_DETECT_CREATORS)); assertTrue(cfg.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS)); assertTrue(cfg.isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)); assertFalse(cfg.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)); assertFalse(cfg.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)); assertTrue(cfg.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); } public void testBasicFeatures() throws Exception { DeserializationConfig config = MAPPER.getDeserializationConfig(); assertTrue(config.hasDeserializationFeatures(DeserializationFeature.EAGER_DESERIALIZER_FETCH.getMask())); assertFalse(config.hasDeserializationFeatures(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY.getMask())); assertTrue(config.hasSomeOfFeatures(DeserializationFeature.EAGER_DESERIALIZER_FETCH.getMask() + DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY.getMask())); assertFalse(config.hasSomeOfFeatures(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY.getMask())); // if no changes then same config object assertSame(config, config.without()); assertSame(config, config.with()); assertSame(config, config.with(MAPPER.getSubtypeResolver())); // and then change DeserializationConfig newConfig = config.with(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); assertNotSame(config, newConfig); config = newConfig; // but another attempt with no real change returns same assertSame(config, config.with(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); assertNotSame(config, config.with(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, false)); assertNotSame(config, config.with(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES)); } public void testParserFeatures() throws Exception { DeserializationConfig config = MAPPER.getDeserializationConfig(); assertNotSame(config, config.with(JsonParser.Feature.ALLOW_COMMENTS)); assertNotSame(config, config.withFeatures(JsonParser.Feature.ALLOW_COMMENTS, JsonParser.Feature.ALLOW_MISSING_VALUES)); assertNotSame(config, config.without(JsonParser.Feature.ALLOW_COMMENTS)); assertNotSame(config, config.withoutFeatures(JsonParser.Feature.ALLOW_COMMENTS, JsonParser.Feature.ALLOW_MISSING_VALUES)); } public void testFormatFeatures() throws Exception { DeserializationConfig config = MAPPER.getDeserializationConfig(); assertNotSame(config, config.with(BogusFormatFeature.FF_DISABLED_BY_DEFAULT)); assertNotSame(config, config.withFeatures(BogusFormatFeature.FF_DISABLED_BY_DEFAULT, BogusFormatFeature.FF_ENABLED_BY_DEFAULT)); assertNotSame(config, config.without(BogusFormatFeature.FF_ENABLED_BY_DEFAULT)); assertNotSame(config, config.withoutFeatures(BogusFormatFeature.FF_DISABLED_BY_DEFAULT, BogusFormatFeature.FF_ENABLED_BY_DEFAULT)); } /* Test to verify that we don't overflow number of features; if we * hit the limit, need to change implementation -- this test just * gives low-water mark */ public void testEnumIndexes() { int max = 0; for (DeserializationFeature f : DeserializationFeature.values()) { max = Math.max(max, f.ordinal()); } if (max >= 31) { // 31 is actually ok; 32 not fail("Max number of DeserializationFeature enums reached: "+max); } } public void testOverrideIntrospectors() { ObjectMapper m = new ObjectMapper(); DeserializationConfig cfg = m.getDeserializationConfig(); // and finally, ensure we could override introspectors cfg = cfg.with((ClassIntrospector) null); // no way to verify tho cfg = cfg.with((AnnotationIntrospector) null); assertNull(cfg.getAnnotationIntrospector()); } public void testMisc() throws Exception { DeserializationConfig config = MAPPER.getDeserializationConfig(); assertEquals(JsonInclude.Value.empty(), config.getDefaultPropertyInclusion()); assertEquals(JsonInclude.Value.empty(), config.getDefaultPropertyInclusion(String.class)); assertSame(config, config.withRootName((PropertyName) null)); // defaults to 'none' DeserializationConfig newConfig = config.withRootName(PropertyName.construct("foobar")); assertNotSame(config, newConfig); config = newConfig; assertSame(config, config.withRootName(PropertyName.construct("foobar"))); assertSame(config, config.with(config.getAttributes())); assertNotSame(config, config.with(new ContextAttributes.Impl(Collections.singletonMap("a", "b")))); // should also be able to introspect: assertNotNull(config.introspectDirectClassAnnotations(getClass())); } } SerConfigTest.java000066400000000000000000000072021325620701100346250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/cfgpackage com.fasterxml.jackson.databind.cfg; import java.util.Collections; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; public class SerConfigTest extends BaseMapTest { private final ObjectMapper MAPPER = new ObjectMapper(); public void testSerConfig() throws Exception { SerializationConfig config = MAPPER.getSerializationConfig(); assertTrue(config.hasSerializationFeatures(SerializationFeature.FAIL_ON_EMPTY_BEANS.getMask())); assertFalse(config.hasSerializationFeatures(SerializationFeature.CLOSE_CLOSEABLE.getMask())); assertEquals(JsonInclude.Value.empty(), config.getDefaultPropertyInclusion()); assertEquals(JsonInclude.Value.empty(), config.getDefaultPropertyInclusion(String.class)); assertFalse(config.useRootWrapping()); // if no changes then same config object assertSame(config, config.without()); assertSame(config, config.with()); assertSame(config, config.with(MAPPER.getSubtypeResolver())); // and then change SerializationConfig newConfig = config.with(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); assertNotSame(config, newConfig); config = newConfig; assertSame(config, config.with(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); assertNotSame(config, config.with(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, false)); assertNotSame(config, config.with(SerializationFeature.INDENT_OUTPUT, SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)); assertSame(config, config.withRootName((PropertyName) null)); // defaults to 'none' newConfig = config.withRootName(PropertyName.construct("foobar")); assertNotSame(config, newConfig); assertTrue(newConfig.useRootWrapping()); assertSame(config, config.with(config.getAttributes())); assertNotSame(config, config.with(new ContextAttributes.Impl(Collections.singletonMap("a", "b")))); assertNotNull(config.introspectDirectClassAnnotations(getClass())); } public void testGeneratorFeatures() throws Exception { SerializationConfig config = MAPPER.getSerializationConfig(); JsonFactory f = MAPPER.getFactory(); assertFalse(config.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII, f)); assertNotSame(config, config.with(JsonGenerator.Feature.ESCAPE_NON_ASCII)); SerializationConfig newConfig = config.withFeatures(JsonGenerator.Feature.ESCAPE_NON_ASCII, JsonGenerator.Feature.IGNORE_UNKNOWN); assertNotSame(config, newConfig); assertTrue(newConfig.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII, f)); assertNotSame(config, config.without(JsonGenerator.Feature.ESCAPE_NON_ASCII)); assertNotSame(config, config.withoutFeatures(JsonGenerator.Feature.ESCAPE_NON_ASCII, JsonGenerator.Feature.IGNORE_UNKNOWN)); } public void testFormatFeatures() throws Exception { SerializationConfig config = MAPPER.getSerializationConfig(); assertNotSame(config, config.with(BogusFormatFeature.FF_DISABLED_BY_DEFAULT)); assertNotSame(config, config.withFeatures(BogusFormatFeature.FF_DISABLED_BY_DEFAULT, BogusFormatFeature.FF_ENABLED_BY_DEFAULT)); assertNotSame(config, config.without(BogusFormatFeature.FF_ENABLED_BY_DEFAULT)); assertNotSame(config, config.withoutFeatures(BogusFormatFeature.FF_DISABLED_BY_DEFAULT, BogusFormatFeature.FF_ENABLED_BY_DEFAULT)); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/contextual/000077500000000000000000000000001325620701100327505ustar00rootroot00000000000000TestContextAttributeWithDeser.java000066400000000000000000000062331325620701100415270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/contextualpackage com.fasterxml.jackson.databind.contextual; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; public class TestContextAttributeWithDeser extends BaseMapTest { final static String KEY = "foobar"; @SuppressWarnings("serial") static class PrefixStringDeserializer extends StdScalarDeserializer { protected PrefixStringDeserializer() { super(String.class); } @Override public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { Integer I = (Integer) ctxt.getAttribute(KEY); if (I == null) { I = Integer.valueOf(0); } int i = I.intValue(); ctxt.setAttribute(KEY, Integer.valueOf(i + 1)); return jp.getText()+"/"+i; } } static class TestPOJO { @JsonDeserialize(using=PrefixStringDeserializer.class) public String value; } /* /********************************************************** /* Test methods /********************************************************** */ final ObjectMapper MAPPER = objectMapper(); public void testSimplePerCall() throws Exception { final String INPUT = aposToQuotes("[{'value':'a'},{'value':'b'}]"); TestPOJO[] pojos = MAPPER.readerFor(TestPOJO[].class).readValue(INPUT); assertEquals(2, pojos.length); assertEquals("a/0", pojos[0].value); assertEquals("b/1", pojos[1].value); // and verify that state does not linger TestPOJO[] pojos2 = MAPPER.readerFor(TestPOJO[].class).readValue(INPUT); assertEquals(2, pojos2.length); assertEquals("a/0", pojos2[0].value); assertEquals("b/1", pojos2[1].value); } public void testSimpleDefaults() throws Exception { final String INPUT = aposToQuotes("{'value':'x'}"); TestPOJO pojo = MAPPER.readerFor(TestPOJO.class) .withAttribute(KEY, Integer.valueOf(3)) .readValue(INPUT); assertEquals("x/3", pojo.value); // as above, should not carry on state TestPOJO pojo2 = MAPPER.readerFor(TestPOJO.class) .withAttribute(KEY, Integer.valueOf(5)) .readValue(INPUT); assertEquals("x/5", pojo2.value); } public void testHierarchic() throws Exception { final String INPUT = aposToQuotes("[{'value':'x'},{'value':'y'}]"); ObjectReader r = MAPPER.readerFor(TestPOJO[].class).withAttribute(KEY, Integer.valueOf(2)); TestPOJO[] pojos = r.readValue(INPUT); assertEquals(2, pojos.length); assertEquals("x/2", pojos[0].value); assertEquals("y/3", pojos[1].value); // and once more to verify transiency of per-call state TestPOJO[] pojos2 = r.readValue(INPUT); assertEquals(2, pojos2.length); assertEquals("x/2", pojos2[0].value); assertEquals("y/3", pojos2[1].value); } } TestContextAttributeWithSer.java000066400000000000000000000055521325620701100412210ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/contextualpackage com.fasterxml.jackson.databind.contextual; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; public class TestContextAttributeWithSer extends BaseMapTest { final static String KEY = "foobar"; @SuppressWarnings("serial") static class PrefixStringSerializer extends StdScalarSerializer { protected PrefixStringSerializer() { super(String.class); } @Override public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException { Integer I = (Integer) provider.getAttribute(KEY); if (I == null) { I = Integer.valueOf(0); } int i = I.intValue(); provider.setAttribute(KEY, Integer.valueOf(i + 1)); jgen.writeString("" +i+":"+value); } } static class TestPOJO { @JsonSerialize(using=PrefixStringSerializer.class) public String value; public TestPOJO(String str) { value = str; } } /* /********************************************************** /* Test methods /********************************************************** */ final ObjectMapper MAPPER = objectMapper(); public void testSimplePerCall() throws Exception { final String EXP = aposToQuotes("[{'value':'0:a'},{'value':'1:b'}]"); ObjectWriter w = MAPPER.writer(); final TestPOJO[] INPUT = new TestPOJO[] { new TestPOJO("a"), new TestPOJO("b") }; assertEquals(EXP, w.writeValueAsString(INPUT)); // also: ensure that we don't retain per-call state accidentally: assertEquals(EXP, w.writeValueAsString(INPUT)); } public void testSimpleDefaults() throws Exception { final String EXP = aposToQuotes("{'value':'3:xyz'}"); final TestPOJO INPUT = new TestPOJO("xyz"); String json = MAPPER.writer().withAttribute(KEY, Integer.valueOf(3)) .writeValueAsString(INPUT); assertEquals(EXP, json); String json2 = MAPPER.writer().withAttribute(KEY, Integer.valueOf(3)) .writeValueAsString(INPUT); assertEquals(EXP, json2); } public void testHierarchic() throws Exception { final TestPOJO[] INPUT = new TestPOJO[] { new TestPOJO("a"), new TestPOJO("b") }; final String EXP = aposToQuotes("[{'value':'2:a'},{'value':'3:b'}]"); ObjectWriter w = MAPPER.writer().withAttribute(KEY, Integer.valueOf(2)); assertEquals(EXP, w.writeValueAsString(INPUT)); // and verify state clearing: assertEquals(EXP, w.writeValueAsString(INPUT)); } } TestContextualDeserialization.java000066400000000000000000000251441325620701100415770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/contextualpackage com.fasterxml.jackson.databind.contextual; import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; /** * Test cases to verify that it is possible to define deserializers * that can use contextual information (like field/method * annotations) for configuration. */ @SuppressWarnings("serial") public class TestContextualDeserialization extends BaseMapTest { @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation public @interface Name { public String value(); } static class StringValue { protected String value; public StringValue(String v) { value = v; } } static class ContextualBean { @Name("NameA") public StringValue a; @Name("NameB") public StringValue b; } static class ContextualCtorBean { protected String a, b; @JsonCreator public ContextualCtorBean( @Name("CtorA") @JsonProperty("a") StringValue a, @Name("CtorB") @JsonProperty("b") StringValue b) { this.a = a.value; this.b = b.value; } } @Name("Class") static class ContextualClassBean { public StringValue a; @Name("NameB") public StringValue b; } static class ContextualArrayBean { @Name("array") public StringValue[] beans; } static class ContextualListBean { @Name("list") public List beans; } static class ContextualMapBean { @Name("map") public Map beans; } static class MyContextualDeserializer extends JsonDeserializer implements ContextualDeserializer { protected final String _fieldName; public MyContextualDeserializer() { this(""); } public MyContextualDeserializer(String fieldName) { _fieldName = fieldName; } @Override public StringValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { return new StringValue(""+_fieldName+"="+jp.getText()); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { String name = (property == null) ? "NULL" : property.getName(); return new MyContextualDeserializer(name); } } /** * Alternative that uses annotation for choosing name to use */ static class AnnotatedContextualDeserializer extends JsonDeserializer implements ContextualDeserializer { protected final String _fieldName; public AnnotatedContextualDeserializer() { this(""); } public AnnotatedContextualDeserializer(String fieldName) { _fieldName = fieldName; } @Override public StringValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { return new StringValue(""+_fieldName+"="+jp.getText()); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { Name ann = property.getAnnotation(Name.class); if (ann == null) { ann = property.getContextAnnotation(Name.class); } String propertyName = (ann == null) ? "UNKNOWN" : ann.value(); return new MyContextualDeserializer(propertyName); } } static class GenericStringDeserializer extends StdScalarDeserializer implements ContextualDeserializer { final String _value; public GenericStringDeserializer() { this("N/A"); } protected GenericStringDeserializer(String value) { super(String.class); _value = value; } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) { return new GenericStringDeserializer(String.valueOf(ctxt.getContextualType().getRawClass().getSimpleName())); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) { return _value; } } static class GenericBean { @JsonDeserialize(contentUsing=GenericStringDeserializer.class) public Map stuff; } /* /********************************************************** /* Unit tests /********************************************************** */ public void testSimple() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addDeserializer(StringValue.class, new MyContextualDeserializer()); mapper.registerModule(module); ContextualBean bean = mapper.readValue("{\"a\":\"1\",\"b\":\"2\"}", ContextualBean.class); assertEquals("a=1", bean.a.value); assertEquals("b=2", bean.b.value); // try again, to ensure caching etc works bean = mapper.readValue("{\"a\":\"3\",\"b\":\"4\"}", ContextualBean.class); assertEquals("a=3", bean.a.value); assertEquals("b=4", bean.b.value); } public void testSimpleWithAnnotations() throws Exception { ObjectMapper mapper = _mapperWithAnnotatedContextual(); ContextualBean bean = mapper.readValue("{\"a\":\"1\",\"b\":\"2\"}", ContextualBean.class); assertEquals("NameA=1", bean.a.value); assertEquals("NameB=2", bean.b.value); // try again, to ensure caching etc works bean = mapper.readValue("{\"a\":\"x\",\"b\":\"y\"}", ContextualBean.class); assertEquals("NameA=x", bean.a.value); assertEquals("NameB=y", bean.b.value); } public void testSimpleWithClassAnnotations() throws Exception { ObjectMapper mapper = _mapperWithAnnotatedContextual(); ContextualClassBean bean = mapper.readValue("{\"a\":\"1\",\"b\":\"2\"}", ContextualClassBean.class); assertEquals("Class=1", bean.a.value); assertEquals("NameB=2", bean.b.value); // and again bean = mapper.readValue("{\"a\":\"123\",\"b\":\"345\"}", ContextualClassBean.class); assertEquals("Class=123", bean.a.value); assertEquals("NameB=345", bean.b.value); } public void testAnnotatedCtor() throws Exception { ObjectMapper mapper = _mapperWithAnnotatedContextual(); ContextualCtorBean bean = mapper.readValue("{\"a\":\"foo\",\"b\":\"bar\"}", ContextualCtorBean.class); assertEquals("CtorA=foo", bean.a); assertEquals("CtorB=bar", bean.b); bean = mapper.readValue("{\"a\":\"1\",\"b\":\"0\"}", ContextualCtorBean.class); assertEquals("CtorA=1", bean.a); assertEquals("CtorB=0", bean.b); } public void testAnnotatedArray() throws Exception { ObjectMapper mapper = _mapperWithAnnotatedContextual(); ContextualArrayBean bean = mapper.readValue("{\"beans\":[\"x\"]}", ContextualArrayBean.class); assertEquals(1, bean.beans.length); assertEquals("array=x", bean.beans[0].value); bean = mapper.readValue("{\"beans\":[\"a\",\"b\"]}", ContextualArrayBean.class); assertEquals(2, bean.beans.length); assertEquals("array=a", bean.beans[0].value); assertEquals("array=b", bean.beans[1].value); } public void testAnnotatedList() throws Exception { ObjectMapper mapper = _mapperWithAnnotatedContextual(); ContextualListBean bean = mapper.readValue("{\"beans\":[\"x\"]}", ContextualListBean.class); assertEquals(1, bean.beans.size()); assertEquals("list=x", bean.beans.get(0).value); bean = mapper.readValue("{\"beans\":[\"x\",\"y\",\"z\"]}", ContextualListBean.class); assertEquals(3, bean.beans.size()); assertEquals("list=x", bean.beans.get(0).value); assertEquals("list=y", bean.beans.get(1).value); assertEquals("list=z", bean.beans.get(2).value); } public void testAnnotatedMap() throws Exception { ObjectMapper mapper = _mapperWithAnnotatedContextual(); ContextualMapBean bean = mapper.readValue("{\"beans\":{\"a\":\"b\"}}", ContextualMapBean.class); assertEquals(1, bean.beans.size()); Map.Entry entry = bean.beans.entrySet().iterator().next(); assertEquals("a", entry.getKey()); assertEquals("map=b", entry.getValue().value); bean = mapper.readValue("{\"beans\":{\"x\":\"y\",\"1\":\"2\"}}", ContextualMapBean.class); assertEquals(2, bean.beans.size()); Iterator> it = bean.beans.entrySet().iterator(); entry = it.next(); assertEquals("x", entry.getKey()); assertEquals("map=y", entry.getValue().value); entry = it.next(); assertEquals("1", entry.getKey()); assertEquals("map=2", entry.getValue().value); } // for [databind#165] public void testContextualType() throws Exception { GenericBean bean = new ObjectMapper().readValue(aposToQuotes("{'stuff':{'1':'b'}}"), GenericBean.class); assertNotNull(bean.stuff); assertEquals(1, bean.stuff.size()); assertEquals("String", bean.stuff.get(Integer.valueOf(1))); } /* /********************************************************** /* Helper methods /********************************************************** */ private ObjectMapper _mapperWithAnnotatedContextual() { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addDeserializer(StringValue.class, new AnnotatedContextualDeserializer()); mapper.registerModule(module); return mapper; } } TestContextualKeyTypes.java000066400000000000000000000102371325620701100402230ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/contextualpackage com.fasterxml.jackson.databind.contextual; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ContextualKeyDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Tests to ensure that we can do contextual key serializers and * deserializers as well as value ser/deser. */ public class TestContextualKeyTypes extends BaseMapTest { /* /********************************************************** /* Helper classes /********************************************************** */ static class ContextualKeySerializer extends JsonSerializer implements ContextualSerializer { protected final String _prefix; public ContextualKeySerializer() { this(""); } public ContextualKeySerializer(String p) { _prefix = p; } @Override public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException { if (_prefix != null) { value = _prefix + value; } jgen.writeFieldName(value); } @Override public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { return new ContextualKeySerializer(_prefix+":"); } } static class ContextualDeser extends KeyDeserializer implements ContextualKeyDeserializer { protected final String _prefix; protected ContextualDeser(String p) { _prefix = p; } @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException { return _prefix + ":" + key; } @Override public KeyDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { return new ContextualDeser((property == null) ? "ROOT" : property.getName()); } } static class MapBean { public Map map; } /* /********************************************************** /* Unit tests, serialization /********************************************************** */ public void testSimpleKeySer() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addKeySerializer(String.class, new ContextualKeySerializer("prefix")); mapper.registerModule(module); Map input = new HashMap(); input.put("a", Integer.valueOf(3)); String json = mapper.writerFor(TypeFactory.defaultInstance().constructMapType(HashMap.class, String.class, Object.class)) .writeValueAsString(input); assertEquals("{\"prefix:a\":3}", json); } /* /********************************************************** /* Unit tests, deserialization /********************************************************** */ public void testSimpleKeyDeser() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addKeyDeserializer(String.class, new ContextualDeser("???")); mapper.registerModule(module); MapBean result = mapper.readValue("{\"map\":{\"a\":3}}", MapBean.class); Map map = result.map; assertNotNull(map); assertEquals(1, map.size()); Map.Entry entry = map.entrySet().iterator().next(); assertEquals(Integer.valueOf(3), entry.getValue()); assertEquals("map:a", entry.getKey()); } } TestContextualSerialization.java000066400000000000000000000236301325620701100412640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/contextualpackage com.fasterxml.jackson.databind.contextual; import java.io.IOException; import java.lang.annotation.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.ResolvableSerializer; /** * Test cases to verify that it is possible to define serializers * that can use contextual information (like field/method * annotations) for configuration. */ public class TestContextualSerialization extends BaseMapTest { /* /********************************************************** /* Helper classes /********************************************************** */ /* NOTE: important; MUST be considered a 'Jackson' annotation to be seen * (or recognized otherwise via AnnotationIntrospect.isHandled()) */ @Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation public @interface Prefix { public String value(); } static class ContextualBean { protected final String _value; public ContextualBean(String s) { _value = s; } @Prefix("see:") public String getValue() { return _value; } } // For [JACKSON-569] static class AnnotatedContextualBean { @Prefix("prefix->") @JsonSerialize(using=AnnotatedContextualSerializer.class) protected final String value; public AnnotatedContextualBean(String s) { value = s; } } @Prefix("wrappedBean:") static class ContextualBeanWrapper { @Prefix("wrapped:") public ContextualBean wrapped; public ContextualBeanWrapper(String s) { wrapped = new ContextualBean(s); } } static class ContextualArrayBean { @Prefix("array->") public final String[] beans; public ContextualArrayBean(String... strings) { beans = strings; } } static class ContextualArrayElementBean { @Prefix("elem->") @JsonSerialize(contentUsing=AnnotatedContextualSerializer.class) public final String[] beans; public ContextualArrayElementBean(String... strings) { beans = strings; } } static class ContextualListBean { @Prefix("list->") public final List beans = new ArrayList(); public ContextualListBean(String... strings) { for (String string : strings) { beans.add(string); } } } static class ContextualMapBean { @Prefix("map->") public final Map beans = new HashMap(); } /** * Another bean that has class annotations that should be visible for * contextualizer, too */ @Prefix("Voila->") static class BeanWithClassConfig { public String value; public BeanWithClassConfig(String v) { value = v; } } /** * Annotation-based contextual serializer that simply prepends piece of text. */ static class AnnotatedContextualSerializer extends JsonSerializer implements ContextualSerializer { protected final String _prefix; public AnnotatedContextualSerializer() { this(""); } public AnnotatedContextualSerializer(String p) { _prefix = p; } @Override public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeString(_prefix + value); } @Override public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { String prefix = "UNKNOWN"; Prefix ann = null; if (property != null) { ann = property.getAnnotation(Prefix.class); if (ann == null) { ann = property.getContextAnnotation(Prefix.class); } } if (ann != null) { prefix = ann.value(); } return new AnnotatedContextualSerializer(prefix); } } static class ContextualAndResolvable extends JsonSerializer implements ContextualSerializer, ResolvableSerializer { protected int isContextual; protected int isResolved; public ContextualAndResolvable() { this(0, 0); } public ContextualAndResolvable(int resolved, int contextual) { isContextual = contextual; isResolved = resolved; } @Override public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeString("contextual="+isContextual+",resolved="+isResolved); } @Override public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { return new ContextualAndResolvable(isResolved, isContextual+1); } @Override public void resolve(SerializerProvider provider) { ++isResolved; } } /* /********************************************************** /* Unit tests /********************************************************** */ // Test to verify that contextual serializer can make use of property // (method, field) annotations. public void testMethodAnnotations() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addSerializer(String.class, new AnnotatedContextualSerializer()); mapper.registerModule(module); assertEquals("{\"value\":\"see:foobar\"}", mapper.writeValueAsString(new ContextualBean("foobar"))); } // Test to verify that contextual serializer can also use annotations // for enclosing class. public void testClassAnnotations() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addSerializer(String.class, new AnnotatedContextualSerializer()); mapper.registerModule(module); assertEquals("{\"value\":\"Voila->xyz\"}", mapper.writeValueAsString(new BeanWithClassConfig("xyz"))); } public void testWrappedBean() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addSerializer(String.class, new AnnotatedContextualSerializer()); mapper.registerModule(module); assertEquals("{\"wrapped\":{\"value\":\"see:xyz\"}}", mapper.writeValueAsString(new ContextualBeanWrapper("xyz"))); } // Serializer should get passed property context even if contained in an array. public void testMethodAnnotationInArray() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addSerializer(String.class, new AnnotatedContextualSerializer()); mapper.registerModule(module); ContextualArrayBean beans = new ContextualArrayBean("123"); assertEquals("{\"beans\":[\"array->123\"]}", mapper.writeValueAsString(beans)); } // Serializer should get passed property context even if contained in a Collection. public void testMethodAnnotationInList() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addSerializer(String.class, new AnnotatedContextualSerializer()); mapper.registerModule(module); ContextualListBean beans = new ContextualListBean("abc"); assertEquals("{\"beans\":[\"list->abc\"]}", mapper.writeValueAsString(beans)); } // Serializer should get passed property context even if contained in a Collection. public void testMethodAnnotationInMap() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addSerializer(String.class, new AnnotatedContextualSerializer()); mapper.registerModule(module); ContextualMapBean map = new ContextualMapBean(); map.beans.put("first", "In Map"); assertEquals("{\"beans\":{\"first\":\"map->In Map\"}}", mapper.writeValueAsString(map)); } public void testContextualViaAnnotation() throws Exception { ObjectMapper mapper = new ObjectMapper(); AnnotatedContextualBean bean = new AnnotatedContextualBean("abc"); assertEquals("{\"value\":\"prefix->abc\"}", mapper.writeValueAsString(bean)); } /* // [JACKSON-647]: is resolve() called for contextual instances? public void testResolveOnContextual() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addSerializer(String.class, new ContextualAndResolvable()); mapper.registerModule(module); assertEquals(quote("contextual=1,resolved=1"), mapper.writeValueAsString("abc")); } public void testContextualArrayElement() throws Exception { ObjectMapper mapper = new ObjectMapper(); ContextualArrayElementBean beans = new ContextualArrayElementBean("456"); assertEquals("{\"beans\":[\"elem->456\"]}", mapper.writeValueAsString(beans)); } */ } TestContextualWithAnnDeserializer.java000066400000000000000000000050721325620701100423620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/contextualpackage com.fasterxml.jackson.databind.contextual; import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.fasterxml.jackson.annotation.JacksonAnnotation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; public class TestContextualWithAnnDeserializer extends BaseMapTest { @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation public @interface Name { public String value(); } static class StringValue { protected String value; public StringValue(String v) { value = v; } } static class AnnotatedContextualClassBean { @Name("xyz") @JsonDeserialize(using=AnnotatedContextualDeserializer.class) public StringValue value; } static class AnnotatedContextualDeserializer extends JsonDeserializer implements ContextualDeserializer { protected final String _fieldName; public AnnotatedContextualDeserializer() { this(""); } public AnnotatedContextualDeserializer(String fieldName) { _fieldName = fieldName; } @Override public StringValue deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return new StringValue(""+_fieldName+"="+p.getText()); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { Name ann = property.getAnnotation(Name.class); if (ann == null) { ann = property.getContextAnnotation(Name.class); } String propertyName = (ann == null) ? "UNKNOWN" : ann.value(); return new AnnotatedContextualDeserializer(propertyName); } } // ensure that direct associations also work public void testAnnotatedContextual() throws Exception { ObjectMapper mapper = new ObjectMapper(); AnnotatedContextualClassBean bean = mapper.readValue( "{\"value\":\"a\"}", AnnotatedContextualClassBean.class); assertNotNull(bean); assertEquals("xyz=a", bean.value.value); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convert/000077500000000000000000000000001325620701100322425ustar00rootroot00000000000000ConvertingAbstractSerializer795Test.java000066400000000000000000000055071325620701100417760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.*; import com.fasterxml.jackson.databind.util.StdConverter; // for [databind#795] public class ConvertingAbstractSerializer795Test extends BaseMapTest { public static abstract class AbstractCustomType { final String value; public AbstractCustomType(String v) { this.value = v; } } public static class ConcreteCustomType extends AbstractCustomType { public ConcreteCustomType(String v) { super(v); } } public static class AbstractCustomTypeDeserializationConverter extends StdConverter{ @Override public AbstractCustomType convert(String arg) { return new ConcreteCustomType(arg); } } public static class AbstractCustomTypeUser { @JsonProperty @JsonDeserialize(converter = AbstractCustomTypeDeserializationConverter.class) private final AbstractCustomType customField; @JsonCreator AbstractCustomTypeUser(@JsonProperty("customField") AbstractCustomType cf) { this.customField = cf; } } public static class NonAbstractCustomType { final String value; public NonAbstractCustomType(String v) { this.value = v; } } public static class NonAbstractCustomTypeDeserializationConverter extends StdConverter{ @Override public NonAbstractCustomType convert(String arg) { return new NonAbstractCustomType(arg); } } public static class NonAbstractCustomTypeUser { @JsonProperty @JsonDeserialize(converter = NonAbstractCustomTypeDeserializationConverter.class) private final NonAbstractCustomType customField; @JsonCreator NonAbstractCustomTypeUser(@JsonProperty("customField") NonAbstractCustomType customField) { this.customField = customField; } } /* /********************************************************** /* Test methods /********************************************************** */ private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); public void testAbstractTypeDeserialization() throws Exception { String test="{\"customField\": \"customString\"}"; AbstractCustomTypeUser cu = JSON_MAPPER.readValue(test, AbstractCustomTypeUser.class); assertNotNull(cu); } public void testNonAbstractDeserialization() throws Exception { String test="{\"customField\": \"customString\"}"; NonAbstractCustomTypeUser cu = JSON_MAPPER.readValue(test, NonAbstractCustomTypeUser.class); assertNotNull(cu); } } NumericConversionTest.java000066400000000000000000000057451325620701100373510ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.MismatchedInputException; public class NumericConversionTest extends BaseMapTest { private final ObjectMapper MAPPER = objectMapper(); private final ObjectReader R = MAPPER.reader().without(DeserializationFeature.ACCEPT_FLOAT_AS_INT); public void testDoubleToInt() throws Exception { // by default, should be ok Integer I = MAPPER.readValue(" 1.25 ", Integer.class); assertEquals(1, I.intValue()); IntWrapper w = MAPPER.readValue("{\"i\":-2.25 }", IntWrapper.class); assertEquals(-2, w.i); int[] arr = MAPPER.readValue("[ 1.25 ]", int[].class); assertEquals(1, arr[0]); try { R.forType(Integer.class).readValue("1.5"); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot coerce a floating-point"); } try { R.forType(Integer.TYPE).readValue("1.5"); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot coerce a floating-point"); } try { R.forType(IntWrapper.class).readValue("{\"i\":-2.25 }"); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot coerce a floating-point"); } try { R.forType(int[].class).readValue("[ 2.5 ]"); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot coerce a floating-point"); } } public void testDoubleToLong() throws Exception { // by default, should be ok Long L = MAPPER.readValue(" 3.33 ", Long.class); assertEquals(3L, L.longValue()); LongWrapper w = MAPPER.readValue("{\"l\":-2.25 }", LongWrapper.class); assertEquals(-2L, w.l); long[] arr = MAPPER.readValue("[ 1.25 ]", long[].class); assertEquals(1, arr[0]); try { R.forType(Long.class).readValue("1.5"); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "Cannot coerce a floating-point"); } try { R.forType(Long.TYPE).readValue("1.5"); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "Cannot coerce a floating-point"); } try { R.forType(LongWrapper.class).readValue("{\"l\": 7.7 }"); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "Cannot coerce a floating-point"); } try { R.forType(long[].class).readValue("[ 2.5 ]"); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "Cannot coerce a floating-point"); } } } ScalarConversionTest.java000066400000000000000000000030341325620701100371410ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import com.fasterxml.jackson.databind.*; public class ScalarConversionTest extends BaseMapTest { private final ObjectMapper MAPPER = new ObjectMapper(); // [databind#1433] public void testConvertValueNullPrimitive() throws Exception { assertEquals(Byte.valueOf((byte) 0), MAPPER.convertValue(null, Byte.TYPE)); assertEquals(Short.valueOf((short) 0), MAPPER.convertValue(null, Short.TYPE)); assertEquals(Integer.valueOf(0), MAPPER.convertValue(null, Integer.TYPE)); assertEquals(Long.valueOf(0L), MAPPER.convertValue(null, Long.TYPE)); assertEquals(Float.valueOf(0f), MAPPER.convertValue(null, Float.TYPE)); assertEquals(Double.valueOf(0d), MAPPER.convertValue(null, Double.TYPE)); assertEquals(Character.valueOf('\0'), MAPPER.convertValue(null, Character.TYPE)); assertEquals(Boolean.FALSE, MAPPER.convertValue(null, Boolean.TYPE)); } // [databind#1433] public void testConvertValueNullBoxed() throws Exception { assertNull(MAPPER.convertValue(null, Byte.class)); assertNull(MAPPER.convertValue(null, Short.class)); assertNull(MAPPER.convertValue(null, Integer.class)); assertNull(MAPPER.convertValue(null, Long.class)); assertNull(MAPPER.convertValue(null, Float.class)); assertNull(MAPPER.convertValue(null, Double.class)); assertNull(MAPPER.convertValue(null, Character.class)); assertNull(MAPPER.convertValue(null, Boolean.class)); } } TestArrayConversions.java000066400000000000000000000200531325620701100371750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import java.math.*; import java.util.*; import java.lang.reflect.Array; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class TestArrayConversions extends com.fasterxml.jackson.databind.BaseMapTest { final static String OVERFLOW_MSG_BYTE = "out of range of Java byte"; final static String OVERFLOW_MSG = "overflow"; final static String OVERFLOW_MSG_INT = "out of range of int"; final static String OVERFLOW_MSG_LONG = "out of range of long"; final ObjectMapper MAPPER = new ObjectMapper(); public void testNullXform() throws Exception { /* when given null, null should be returned without conversion * (Java null has no type) */ assertNull(MAPPER.convertValue(null, Integer.class)); assertNull(MAPPER.convertValue(null, String.class)); assertNull(MAPPER.convertValue(null, byte[].class)); } /** * Tests to verify that primitive number arrays round-trip * correctly, i.e. type -> type gives equal (although * not necessarily same) output */ public void testArrayIdentityTransforms() throws Exception { // first integral types // (note: byte[] is ok, even if it goes to base64 and back) verifyByteArrayConversion(bytes(), byte[].class); verifyShortArrayConversion(shorts(), short[].class); verifyIntArrayConversion(ints(), int[].class); verifyLongArrayConversion(longs(), long[].class); // then primitive decimal types verifyFloatArrayConversion(floats(), float[].class); verifyDoubleArrayConversion(doubles(), float[].class); } public void testByteArrayFrom() throws Exception { /* Note: byte arrays are tricky, since they are considered * binary data primarily, not as array of numbers. Hence * output will be base64 encoded... */ byte[] data = _convert("c3VyZS4=", byte[].class); byte[] exp = "sure.".getBytes("Ascii"); verifyIntegralArrays(exp, data, exp.length); } public void testShortArrayToX() throws Exception { short[] data = shorts(); verifyShortArrayConversion(data, byte[].class); verifyShortArrayConversion(data, int[].class); verifyShortArrayConversion(data, long[].class); } public void testIntArrayToX() throws Exception { int[] data = ints(); verifyIntArrayConversion(data, byte[].class); verifyIntArrayConversion(data, short[].class); verifyIntArrayConversion(data, long[].class); List expNums = _numberList(data, data.length); // Alas, due to type erasure, need to use TypeRef, not just class List actNums = MAPPER.convertValue(data, new TypeReference>() {}); assertEquals(expNums, actNums); } public void testLongArrayToX() throws Exception { long[] data = longs(); verifyLongArrayConversion(data, byte[].class); verifyLongArrayConversion(data, short[].class); verifyLongArrayConversion(data, int[].class); List expNums = _numberList(data, data.length); List actNums = MAPPER.convertValue(data, new TypeReference>() {}); assertEquals(expNums, actNums); } public void testOverflows() { // Byte overflow try { MAPPER.convertValue(new int[] { 1000 }, byte[].class); } catch (IllegalArgumentException e) { verifyException(e, OVERFLOW_MSG_BYTE); } // Short overflow try { MAPPER.convertValue(new int[] { -99999 }, short[].class); } catch (IllegalArgumentException e) { verifyException(e, OVERFLOW_MSG); } // Int overflow try { MAPPER.convertValue(new long[] { Long.MAX_VALUE }, int[].class); } catch (IllegalArgumentException e) { verifyException(e, OVERFLOW_MSG_INT); } // Longs need help of BigInteger... BigInteger biggie = BigInteger.valueOf(Long.MAX_VALUE); biggie.add(BigInteger.ONE); List l = new ArrayList(); l.add(biggie); try { MAPPER.convertValue(l, long[].class); } catch (IllegalArgumentException e) { verifyException(e, OVERFLOW_MSG_LONG); } } /* /******************************************************** /* Helper methods /******************************************************** */ // note: all value need to be within byte range private byte[] bytes() { return new byte[] { 1, -1, 0, 98, 127 }; } private short[] shorts() { return new short[] { 1, -1, 0, 98, 127 }; } private int[] ints() { return new int[] { 1, -1, 0, 98, 127 }; } private long[] longs() { return new long[] { 1, -1, 0, 98, 127 }; } // note: use values that are exact in binary private double[] doubles() { return new double[] { 0.0, 0.25, -0.125, 10.5, 9875.0 }; } private float[] floats() { return new float[] { 0.0f, 0.25f, -0.125f, 10.5f, 9875.0f }; } private void verifyByteArrayConversion(byte[] data, Class arrayType) { T result = _convert(data, arrayType); verifyIntegralArrays(data, result, data.length); } private void verifyShortArrayConversion(short[] data, Class arrayType) { T result = _convert(data, arrayType); verifyIntegralArrays(data, result, data.length); } private void verifyIntArrayConversion(int[] data, Class arrayType) { T result = _convert(data, arrayType); verifyIntegralArrays(data, result, data.length); } private void verifyLongArrayConversion(long[] data, Class arrayType) { T result = _convert(data, arrayType); verifyIntegralArrays(data, result, data.length); } private void verifyFloatArrayConversion(float[] data, Class arrayType) { T result = _convert(data, arrayType); verifyDoubleArrays(data, result, data.length); } private void verifyDoubleArrayConversion(double[] data, Class arrayType) { T result = _convert(data, arrayType); verifyDoubleArrays(data, result, data.length); } private T _convert(Object input, Class outputType) { // must be a primitive array, like "int[].class" if (!outputType.isArray()) throw new IllegalArgumentException(); if (!outputType.getComponentType().isPrimitive()) throw new IllegalArgumentException(); T result = MAPPER.convertValue(input, outputType); // sanity check first: assertNotNull(result); assertEquals(outputType, result.getClass()); return result; } private List _numberList(Object numberArray, int size) { ArrayList result = new ArrayList(size); for (int i = 0; i < size; ++i) { result.add((Number) Array.get(numberArray, i)); } return result; } /** * Helper method for checking that given collections contain integral Numbers * that essentially contain same values in same order */ private void verifyIntegralArrays(Object inputArray, Object outputArray, int size) { for (int i = 0; i < size; ++i) { Number n1 = (Number) Array.get(inputArray, i); Number n2 = (Number) Array.get(outputArray, i); double value1 = n1.longValue(); double value2 = n2.longValue(); assertEquals("Entry #"+i+"/"+size+" not equal", value1, value2); } } private void verifyDoubleArrays(Object inputArray, Object outputArray, int size) { for (int i = 0; i < size; ++i) { Number n1 = (Number) Array.get(inputArray, i); Number n2 = (Number) Array.get(outputArray, i); double value1 = n1.doubleValue(); double value2 = n2.doubleValue(); assertEquals("Entry #"+i+"/"+size+" not equal", value1, value2); } } } TestBeanConversions.java000066400000000000000000000222061325620701100367660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.util.StdConverter; /** * Tests for various conversions, especially ones using * {@link ObjectMapper#convertValue(Object, Class)}. */ public class TestBeanConversions extends com.fasterxml.jackson.databind.BaseMapTest { static class PointZ { public int x, y; public int z = -13; public PointZ() { } public PointZ(int a, int b, int c) { x = a; y = b; z = c; } } static class PointStrings { public final String x, y; public PointStrings(String x, String y) { this.x = x; this.y = y; } } public static class BooleanBean { public boolean boolProp; } static class WrapperBean { public BooleanBean x; } static class ObjectWrapper { private Object data; public ObjectWrapper() { } public ObjectWrapper(Object o) { data = o; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } } static class Leaf { public int value; public Leaf() { } public Leaf(int v) { value = v; } } // [databind#288] @JsonSerialize(converter = ConvertingBeanConverter.class) static class ConvertingBean { public int x, y; public ConvertingBean(int v1, int v2) { x = v1; y = v2; } } public static class DummyBean { public final int a, b; public DummyBean(int v1, int v2) { a = v1 * 2; b = v2 * 2; } } static class ConvertingBeanConverter extends StdConverter { @Override public DummyBean convert(ConvertingBean cb) { return new DummyBean(cb.x, cb.y); } } @JsonDeserialize(using = NullBeanDeserializer.class) static class NullBean { public static final NullBean NULL_INSTANCE = new NullBean(); } static class NullBeanDeserializer extends JsonDeserializer { @Override public NullBean getNullValue(final DeserializationContext context) { return NullBean.NULL_INSTANCE; } @Override public NullBean deserialize(final JsonParser parser, final DeserializationContext context) { throw new UnsupportedOperationException(); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testBeanConvert() { // should have no problems convert between compatible beans... PointStrings input = new PointStrings("37", "-9"); PointZ point = MAPPER.convertValue(input, PointZ.class); assertEquals(37, point.x); assertEquals(-9, point.y); // z not included in input, will be whatever default constructor provides assertEquals(-13, point.z); } // For [JACKSON-371]; verify that we know property that caused issue... // (note: not optimal place for test, but will have to do for now) public void testErrorReporting() throws Exception { //String json = "{\"boolProp\":\"oops\"}"; // First: unknown property try { MAPPER.readValue("{\"unknownProp\":true}", BooleanBean.class); } catch (JsonProcessingException e) { verifyException(e, "unknownProp"); } // then bad conversion try { MAPPER.readValue("{\"boolProp\":\"foobar\"}", BooleanBean.class); } catch (JsonMappingException e) { verifyException(e, "Cannot deserialize value of type `boolean` from String"); } } public void testIssue458() throws Exception { ObjectWrapper a = new ObjectWrapper("foo"); ObjectWrapper b = new ObjectWrapper(a); ObjectWrapper b2 = MAPPER.convertValue(b, ObjectWrapper.class); ObjectWrapper a2 = MAPPER.convertValue(b2.getData(), ObjectWrapper.class); assertEquals("foo", a2.getData()); } // should work regardless of wrapping... public void testWrapping() throws Exception { ObjectMapper wrappingMapper = new ObjectMapper(); wrappingMapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); wrappingMapper.enable(SerializationFeature.WRAP_ROOT_VALUE); // conversion is ok, even if it's bogus one _convertAndVerifyPoint(wrappingMapper); // also: ok to have mismatched settings, since as per [JACKSON-710], should // not actually use wrapping internally in these cases wrappingMapper = new ObjectMapper(); wrappingMapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); wrappingMapper.disable(SerializationFeature.WRAP_ROOT_VALUE); _convertAndVerifyPoint(wrappingMapper); wrappingMapper = new ObjectMapper(); wrappingMapper.disable(DeserializationFeature.UNWRAP_ROOT_VALUE); wrappingMapper.enable(SerializationFeature.WRAP_ROOT_VALUE); _convertAndVerifyPoint(wrappingMapper); } // [Issue-11]: simple cast, for POJOs etc public void testConvertUsingCast() throws Exception { String str = new String("foo"); CharSequence seq = str; String result = MAPPER.convertValue(seq, String.class); // should just cast... assertSame(str, result); } // [Issue-11]: simple cast, for Tree public void testNodeConvert() throws Exception { ObjectNode src = (ObjectNode) MAPPER.readTree("{}"); TreeNode node = src; ObjectNode result = MAPPER.treeToValue(node, ObjectNode.class); // should just cast... assertSame(src, result); } private void _convertAndVerifyPoint(ObjectMapper m) { final PointZ input = new PointZ(1, 2, 3); PointZ output = m.convertValue(input, PointZ.class); assertEquals(1, output.x); assertEquals(2, output.y); assertEquals(3, output.z); } /** * Need to test "shortcuts" introduced by [databind#11] */ public void testIssue11() throws Exception { // First the expected use case, Node specification ObjectNode root = MAPPER.createObjectNode(); JsonNode n = root; ObjectNode ob2 = MAPPER.convertValue(n, ObjectNode.class); assertSame(root, ob2); JsonNode n2 = MAPPER.convertValue(n, JsonNode.class); assertSame(root, n2); // then some other no-op conversions String STR = "test"; CharSequence seq = MAPPER.convertValue(STR, CharSequence.class); assertSame(STR, seq); // and then something that should NOT use short-cut Leaf l = new Leaf(13); Map m = MAPPER.convertValue(l, Map.class); assertNotNull(m); assertEquals(1, m.size()); assertEquals(Integer.valueOf(13), m.get("value")); // and reverse too Leaf l2 = MAPPER.convertValue(m, Leaf.class); assertEquals(13, l2.value); // also; ok to use "untyped" (Object): Object ob = MAPPER.convertValue(l, Object.class); assertNotNull(ob); assertEquals(LinkedHashMap.class, ob.getClass()); // And one more: this time with a minor twist final Object plaino = new Object(); // first, a failed attempt: try { m = MAPPER.convertValue(plaino, Map.class); fail("Conversion should have failed"); } catch (IllegalArgumentException e) { verifyException(e, "no properties discovered"); } ObjectMapper mapper = new ObjectMapper(); mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); try { assertEquals("{}", mapper.writeValueAsString(plaino)); } catch (Exception e) { throw (Exception) e.getCause(); } // should now work, via serialization/deserialization: m = mapper.convertValue(plaino, Map.class); assertNotNull(m); assertEquals(0, m.size()); } public void testConversionIssue288() throws Exception { String json = MAPPER.writeValueAsString(new ConvertingBean(1, 2)); // must be {"a":2,"b":4} assertEquals("{\"a\":2,\"b\":4}", json); } // Test null conversions from [databind#1433] public void testConversionIssue1433() throws Exception { assertNull(MAPPER.convertValue(null, Object.class)); assertNull(MAPPER.convertValue(null, PointZ.class)); assertSame(NullBean.NULL_INSTANCE, MAPPER.convertValue(null, NullBean.class)); } } TestConvertingDeserializer.java000066400000000000000000000142731325620701100403560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import java.math.BigDecimal; import java.util.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.util.StdConverter; public class TestConvertingDeserializer extends com.fasterxml.jackson.databind.BaseMapTest { @JsonDeserialize(converter=ConvertingBeanConverter.class) static class ConvertingBean { protected int x, y; protected ConvertingBean(int x, int y) { this.x = x; this.y = y; } } static class Point { protected int x, y; public Point(int v1, int v2) { x = v1; y = v2; } } static class ConvertingBeanContainer { public List values; public ConvertingBeanContainer() { } public ConvertingBeanContainer(ConvertingBean... beans) { values = Arrays.asList(beans); } } static class ConvertingBeanConverter extends StdConverter { @Override public ConvertingBean convert(int[] values) { return new ConvertingBean(values[0], values[1]); } } private static class PointConverter extends StdConverter { @Override public Point convert(int[] value) { return new Point(value[0], value[1]); } } static class PointWrapper { @JsonDeserialize(converter=PointConverter.class) public Point value; protected PointWrapper() { } public PointWrapper(int x, int y) { value = new Point(x, y); } } static class PointListWrapperArray { @JsonDeserialize(contentConverter=PointConverter.class) public Point[] values; } static class PointListWrapperList { @JsonDeserialize(contentConverter=PointConverter.class) public List values; } static class PointListWrapperMap { @JsonDeserialize(contentConverter=PointConverter.class) public Map values; } static class LowerCaser extends StdConverter { @Override public String convert(String value) { return value.toLowerCase(); } } static class LowerCaseText { @JsonDeserialize(converter=LowerCaser.class) public String text; } static class LowerCaseTextArray { @JsonDeserialize(contentConverter=LowerCaser.class) public String[] texts; } // for [databind#795] static class ToNumberConverter extends StdConverter { @Override public Number convert(String value) { return new BigDecimal(value); } } static class Issue795Bean { @JsonDeserialize(converter=ToNumberConverter.class) public Number value; } /* /********************************************************** /* Test methods /********************************************************** */ public void testClassAnnotationSimple() throws Exception { ConvertingBean bean = objectReader(ConvertingBean.class).readValue("[1,2]"); assertNotNull(bean); assertEquals(1, bean.x); assertEquals(2, bean.y); } public void testClassAnnotationForLists() throws Exception { ConvertingBeanContainer container = objectReader(ConvertingBeanContainer.class) .readValue("{\"values\":[[1,2],[3,4]]}"); assertNotNull(container); assertNotNull(container.values); assertEquals(2, container.values.size()); assertEquals(4, container.values.get(1).y); } public void testPropertyAnnotationSimple() throws Exception { PointWrapper wrapper = objectReader(PointWrapper.class).readValue("{\"value\":[3,4]}"); assertNotNull(wrapper); assertNotNull(wrapper.value); assertEquals(3, wrapper.value.x); assertEquals(4, wrapper.value.y); } public void testPropertyAnnotationLowerCasing() throws Exception { LowerCaseText text = objectReader(LowerCaseText.class).readValue("{\"text\":\"Yay!\"}"); assertNotNull(text); assertNotNull(text.text); assertEquals("yay!", text.text); } public void testPropertyAnnotationArrayLC() throws Exception { LowerCaseTextArray texts = objectReader(LowerCaseTextArray.class).readValue("{\"texts\":[\"ABC\"]}"); assertNotNull(texts); assertNotNull(texts.texts); assertEquals(1, texts.texts.length); assertEquals("abc", texts.texts[0]); } public void testPropertyAnnotationForArrays() throws Exception { PointListWrapperArray array = objectReader(PointListWrapperArray.class) .readValue("{\"values\":[[4,5],[5,4]]}"); assertNotNull(array); assertNotNull(array.values); assertEquals(2, array.values.length); assertEquals(5, array.values[1].x); } public void testPropertyAnnotationForLists() throws Exception { PointListWrapperList array = objectReader(PointListWrapperList.class) .readValue("{\"values\":[[7,8],[8,7]]}"); assertNotNull(array); assertNotNull(array.values); assertEquals(2, array.values.size()); assertEquals(7, array.values.get(0).x); } public void testPropertyAnnotationForMaps() throws Exception { PointListWrapperMap map = objectReader(PointListWrapperMap.class) .readValue("{\"values\":{\"a\":[1,2]}}"); assertNotNull(map); assertNotNull(map.values); assertEquals(1, map.values.size()); Point p = map.values.get("a"); assertNotNull(p); assertEquals(1, p.x); assertEquals(2, p.y); } // [databind#795] public void testConvertToAbstract() throws Exception { Issue795Bean bean = objectReader(Issue795Bean.class) .readValue("{\"value\":\"1.25\"}"); assertNotNull(bean.value); assertTrue("Type not BigDecimal but "+bean.value.getClass(), bean.value instanceof BigDecimal); assertEquals(new BigDecimal("1.25"), bean.value); } } TestConvertingSerializer.java000066400000000000000000000155001325620701100400370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.util.StdConverter; public class TestConvertingSerializer extends com.fasterxml.jackson.databind.BaseMapTest { @JsonSerialize(converter=ConvertingBeanConverter.class) static class ConvertingBean { public int x, y; public ConvertingBean(int v1, int v2) { x = v1; y = v2; } } static class Point { public int x, y; public Point(int v1, int v2) { x = v1; y = v2; } } static class ConvertingBeanContainer { public List values; public ConvertingBeanContainer(ConvertingBean... beans) { values = Arrays.asList(beans); } } static class ConvertingBeanConverter extends StdConverter { @Override public int[] convert(ConvertingBean value) { return new int[] { value.x, value.y }; } } static class PointConverter extends StdConverter { @Override public int[] convert(Point value) { return new int[] { value.x, value.y }; } } static class PointWrapper { @JsonSerialize(converter=PointConverter.class) public Point value; public PointWrapper(int x, int y) { value = new Point(x, y); } } static class PointListWrapperArray { @JsonSerialize(contentConverter=PointConverter.class) public Point[] values; public PointListWrapperArray(int x, int y) { values = new Point[] { new Point(x, y), new Point(y, x) }; } } static class PointListWrapperList { @JsonSerialize(contentConverter=PointConverter.class) public List values; public PointListWrapperList(int x, int y) { values = Arrays.asList(new Point[] { new Point(x, y), new Point(y, x) }); } } static class PointListWrapperMap { @JsonSerialize(contentConverter=PointConverter.class) public Map values; public PointListWrapperMap(String key, int x, int y) { values = new HashMap(); values.put(key, new Point(x, y)); } } // [databind#357] static class Value { } static class ListWrapper { @JsonSerialize(contentConverter = ValueToStringListConverter.class) public List list = Arrays.asList(new Value()); } static class ValueToStringListConverter extends StdConverter> { @Override public List convert(Value value) { return Arrays.asList("Hello world!"); } } // [databind#359] static class Bean359 { @JsonSerialize(as = List.class, contentAs = Source.class) public List stuff = Arrays.asList(new Source()); } @JsonSerialize(using = TargetSerializer.class) static class Target { public String unexpected = "Bye."; } @JsonSerialize(converter = SourceToTargetConverter.class) static class Source { } static class SourceToTargetConverter extends StdConverter { @Override public Target convert(Source value) { return new Target(); } } static class TargetSerializer extends JsonSerializer { @Override public void serialize(Target a, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException { jsonGenerator.writeString("Target"); } } // [databind#731] public static class DummyBean { public final int a, b; public DummyBean(int v1, int v2) { a = v1 * 2; b = v2 * 2; } } @JsonSerialize(converter = UntypedConvertingBeanConverter.class) static class ConvertingBeanWithUntypedConverter { public int x, y; public ConvertingBeanWithUntypedConverter(int v1, int v2) { x = v1; y = v2; } } static class UntypedConvertingBeanConverter extends StdConverter { @Override public Object convert(ConvertingBeanWithUntypedConverter cb) { return new DummyBean(cb.x, cb.y); } } /* /********************************************************** /* Test methods /********************************************************** */ public void testClassAnnotationSimple() throws Exception { String json = objectWriter().writeValueAsString(new ConvertingBean(1, 2)); assertEquals("[1,2]", json); } public void testClassAnnotationForLists() throws Exception { String json = objectWriter().writeValueAsString(new ConvertingBeanContainer( new ConvertingBean(1, 2), new ConvertingBean(3, 4))); assertEquals("{\"values\":[[1,2],[3,4]]}", json); } public void testPropertyAnnotationSimple() throws Exception { String json = objectWriter().writeValueAsString(new PointWrapper(3, 4)); assertEquals("{\"value\":[3,4]}", json); } public void testPropertyAnnotationForArrays() throws Exception { String json = objectWriter().writeValueAsString(new PointListWrapperArray(4, 5)); assertEquals("{\"values\":[[4,5],[5,4]]}", json); } public void testPropertyAnnotationForLists() throws Exception { String json = objectWriter().writeValueAsString(new PointListWrapperList(7, 8)); assertEquals("{\"values\":[[7,8],[8,7]]}", json); } public void testPropertyAnnotationForMaps() throws Exception { String json = objectWriter().writeValueAsString(new PointListWrapperMap("a", 1, 2)); assertEquals("{\"values\":{\"a\":[1,2]}}", json); } // [databind#357] public void testConverterForList357() throws Exception { String json = objectWriter().writeValueAsString(new ListWrapper()); assertEquals("{\"list\":[[\"Hello world!\"]]}", json); } // [databind#359] public void testIssue359() throws Exception { String json = objectWriter().writeValueAsString(new Bean359()); assertEquals("{\"stuff\":[\"Target\"]}", json); } // [databind#731]: Problems converting from java.lang.Object ("unknown") public void testIssue731() throws Exception { String json = objectWriter().writeValueAsString(new ConvertingBeanWithUntypedConverter(1, 2)); // must be {"a":2,"b":4} assertEquals("{\"a\":2,\"b\":4}", json); } } TestMapConversions.java000066400000000000000000000072731325620701100366450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import java.util.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.util.StdConverter; public class TestMapConversions extends com.fasterxml.jackson.databind.BaseMapTest { final ObjectMapper MAPPER = new ObjectMapper(); enum AB { A, B; } static class Bean { public Integer A; public String B; } // [Issue#287] @JsonSerialize(converter=RequestConverter.class) static class Request { public int x() { return 1; } } static class RequestConverter extends StdConverter> { @Override public Map convert(final Request value) { final Map test = new LinkedHashMap(); final Map innerTest = new LinkedHashMap(); innerTest.put("value", value.x()); test.put("hello", innerTest); return test; } } /* /********************************************************** /* Test methods /********************************************************** */ /** * Test that verifies that we can go between couple of types of Maps... */ public void testMapToMap() { Map input = new LinkedHashMap(); input.put("A", Integer.valueOf(3)); input.put("B", Integer.valueOf(-4)); Map output = MAPPER.convertValue(input, new TypeReference>() { }); assertEquals(2, output.size()); assertEquals("3", output.get(AB.A)); assertEquals("-4", output.get(AB.B)); // Let's try the other way too... and mix up types a bit Map roundtrip = MAPPER.convertValue(input, new TypeReference>() { }); assertEquals(2, roundtrip.size()); assertEquals(Integer.valueOf(3), roundtrip.get("A")); assertEquals(Integer.valueOf(-4), roundtrip.get("B")); } public void testMapToBean() { EnumMap map = new EnumMap(AB.class); map.put(AB.A, " 17"); map.put(AB.B, " -1"); Bean bean = MAPPER.convertValue(map, Bean.class); assertEquals(Integer.valueOf(17), bean.A); assertEquals(" -1", bean.B); } public void testBeanToMap() { Bean bean = new Bean(); bean.A = 129; bean.B = "13"; EnumMap result = MAPPER.convertValue(bean, new TypeReference>() { }); assertEquals("129", result.get(AB.A)); assertEquals("13", result.get(AB.B)); } // [Issue#287]: Odd problems with `Object` type, static typing public void testIssue287() throws Exception { // use local instance to ensure no caching affects it: final ObjectMapper mapper = new ObjectMapper(); final Request request = new Request(); final String retString = mapper.writeValueAsString(request); assertEquals("{\"hello\":{\"value\":1}}",retString); } // [databind#810] public void testMapToProperties() throws Exception { Bean bean = new Bean(); bean.A = 129; bean.B = "13"; Properties props = MAPPER.convertValue(bean, Properties.class); assertEquals(2, props.size()); assertEquals("13", props.getProperty("B")); // should coercce non-Strings to Strings assertEquals("129", props.getProperty("A")); } } TestPolymorphicUpdateValue.java000066400000000000000000000023111325620701100403300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying handling of update value on polymorphic * objects. */ public class TestPolymorphicUpdateValue extends BaseMapTest { @JsonTypeInfo(include=JsonTypeInfo.As.WRAPPER_ARRAY //PROPERTY ,use=JsonTypeInfo.Id.NAME, property="type") @JsonSubTypes(value={ @JsonSubTypes.Type(value=Child.class)}) abstract static class Parent { public int x; public int y; } @JsonTypeName("child") public static class Child extends Parent { public int w; public int h; } /* /******************************************************** /* Unit tests /******************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testPolymorphicTest() throws Exception { Child c = new Child(); c.w = 10; c.h = 11; MAPPER.readerForUpdating(c).readValue("{\"x\":3,\"y\":4,\"w\":111}"); assertEquals(3, c.x); assertEquals(4, c.y); assertEquals(111, c.w); } } TestStringConversions.java000066400000000000000000000061301325620701100373650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import java.util.*; import static org.junit.Assert.*; import com.fasterxml.jackson.core.Base64Variants; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.util.StdConverter; public class TestStringConversions extends com.fasterxml.jackson.databind.BaseMapTest { static class LCConverter extends StdConverter { @Override public String convert(String value) { return value.toLowerCase(); } } static class StringWrapperWithConvert { @JsonSerialize(converter=LCConverter.class) @JsonDeserialize(converter=LCConverter.class) public String value; protected StringWrapperWithConvert() { } public StringWrapperWithConvert(String v) { value = v; } } private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimple() { assertEquals(Boolean.TRUE, MAPPER.convertValue("true", Boolean.class)); assertEquals(Integer.valueOf(-3), MAPPER.convertValue(" -3 ", Integer.class)); assertEquals(Long.valueOf(77), MAPPER.convertValue("77", Long.class)); int[] ints = { 1, 2, 3 }; List Ints = new ArrayList(); Ints.add(1); Ints.add(2); Ints.add(3); assertArrayEquals(ints, MAPPER.convertValue(Ints, int[].class)); } public void testStringsToInts() { // let's verify our "neat trick" actually works... assertArrayEquals(new int[] { 1, 2, 3, 4, -1, 0 }, MAPPER.convertValue("1 2 3 4 -1 0".split("\\s+"), int[].class)); } public void testBytesToBase64AndBack() throws Exception { byte[] input = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; String encoded = MAPPER.convertValue(input, String.class); assertNotNull(encoded); assertEquals("AQIDBAUGBw==", encoded); // plus, ensure this is consistent: assertEquals(Base64Variants.MIME.encode(input), encoded); byte[] result = MAPPER.convertValue(encoded, byte[].class); assertArrayEquals(input, result); } public void testBytestoCharArray() throws Exception { byte[] input = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; // first, do baseline encoding char[] expEncoded = MAPPER.convertValue(input, String.class).toCharArray(); // then compare char[] actEncoded = MAPPER.convertValue(input, char[].class); assertArrayEquals(expEncoded, actEncoded); } public void testLowerCasingSerializer() throws Exception { assertEquals("{\"value\":\"abc\"}", MAPPER.writeValueAsString(new StringWrapperWithConvert("ABC"))); } public void testLowerCasingDeserializer() throws Exception { StringWrapperWithConvert value = MAPPER.readValue("{\"value\":\"XyZ\"}", StringWrapperWithConvert.class); assertNotNull(value); assertEquals("xyz", value.value); } } TestUpdateViaObjectReader.java000066400000000000000000000212641325620701100400270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import static org.junit.Assert.assertArrayEquals; /** * Unit tests for verifying that "updating reader" works as * expected. */ @SuppressWarnings("serial") public class TestUpdateViaObjectReader extends BaseMapTest { static class Bean { public String a = "a"; public String b = "b"; public int[] c = new int[] { 1, 2, 3 }; public Bean child = null; } static class XYBean { public int x, y; } public class TextView {} public class NumView {} public class Updateable { @JsonView(NumView.class) public int num; @JsonView(TextView.class) public String str; } // for [databind#744] static class DataA { public int i = 1; public int j = 2; } static class DataB { public DataA da = new DataA(); public int k = 3; } static class DataADeserializer extends StdDeserializer { private static final long serialVersionUID = 1L; DataADeserializer() { super(DataA.class); } @Override public DataA deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.getCurrentToken() != JsonToken.START_OBJECT) { ctxt.reportInputMismatch(DataA.class, "Wrong current token, expected START_OBJECT, got: " +p.getCurrentToken()); // never gets here } /*JsonNode node =*/ p.readValueAsTree(); DataA da = new DataA(); da.i = 5; return da; } } // [databind#1831] @JsonTypeInfo(use = Id.NAME) @JsonSubTypes({ @JsonSubTypes.Type(value = Cat.class) }) static abstract public class AbstractAnimal { } @JsonDeserialize(using = AnimalWrapperDeserializer.class) static class AnimalWrapper { @JsonUnwrapped protected AbstractAnimal animal; public void setAnimal(AbstractAnimal animal) { this.animal = animal; } } static class Cat extends AbstractAnimal { } static class AnimalWrapperDeserializer extends StdDeserializer { public AnimalWrapperDeserializer() { super(AnimalWrapper.class); } @Override public AnimalWrapper deserialize(JsonParser json, DeserializationContext context) throws IOException { AnimalWrapper msg = new AnimalWrapper(); msg.setAnimal(json.readValueAs(AbstractAnimal.class)); return msg; } @Override public AnimalWrapper deserialize(JsonParser json, DeserializationContext context, AnimalWrapper intoValue) throws IOException { intoValue.setAnimal(json.readValueAs(AbstractAnimal.class)); return intoValue; } } /* /******************************************************** /* Test methods /******************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testBeanUpdate() throws Exception { Bean bean = new Bean(); assertEquals("b", bean.b); assertEquals(3, bean.c.length); assertNull(bean.child); Object ob = MAPPER.readerForUpdating(bean).readValue("{ \"b\":\"x\", \"c\":[4,5], \"child\":{ \"a\":\"y\"} }"); assertSame(ob, bean); assertEquals("a", bean.a); assertEquals("x", bean.b); assertArrayEquals(new int[] { 4, 5 }, bean.c); Bean child = bean.child; assertNotNull(child); assertEquals("y", child.a); assertEquals("b", child.b); assertArrayEquals(new int[] { 1, 2, 3 }, child.c); assertNull(child.child); } public void testListUpdate() throws Exception { List strs = new ArrayList(); strs.add("a"); // for lists, we will be appending entries Object ob = MAPPER.readerForUpdating(strs).readValue("[ \"b\", \"c\", \"d\" ]"); assertSame(strs, ob); assertEquals(4, strs.size()); assertEquals("a", strs.get(0)); assertEquals("b", strs.get(1)); assertEquals("c", strs.get(2)); assertEquals("d", strs.get(3)); } public void testMapUpdate() throws Exception { Map strs = new HashMap(); strs.put("a", "a"); strs.put("b", "b"); // for maps, we will be adding and/or overwriting entries Object ob = MAPPER.readerForUpdating(strs).readValue("{ \"c\" : \"c\", \"a\" : \"z\" }"); assertSame(strs, ob); assertEquals(3, strs.size()); assertEquals("z", strs.get("a")); assertEquals("b", strs.get("b")); assertEquals("c", strs.get("c")); } // Test for [JACKSON-717] -- ensure 'readValues' also does update @SuppressWarnings("resource") public void testUpdateSequence() throws Exception { XYBean toUpdate = new XYBean(); Iterator it = MAPPER.readerForUpdating(toUpdate).readValues( "{\"x\":1,\"y\":2}\n{\"x\":16}{\"y\":37}"); assertTrue(it.hasNext()); XYBean value = it.next(); assertSame(toUpdate, value); assertEquals(1, value.x); assertEquals(2, value.y); assertTrue(it.hasNext()); value = it.next(); assertSame(toUpdate, value); assertEquals(16, value.x); assertEquals(2, value.y); // unchanged assertTrue(it.hasNext()); value = it.next(); assertSame(toUpdate, value); assertEquals(16, value.x); // unchanged assertEquals(37, value.y); assertFalse(it.hasNext()); } // [JACKSON-824] public void testUpdatingWithViews() throws Exception { Updateable bean = new Updateable(); bean.num = 100; bean.str = "test"; Updateable result = MAPPER.readerForUpdating(bean) .withView(TextView.class) .readValue("{\"num\": 10, \"str\":\"foobar\"}"); assertSame(bean, result); assertEquals(100, bean.num); assertEquals("foobar", bean.str); } // [databind#744] public void testIssue744() throws IOException { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(DataA.class, new DataADeserializer()); mapper.registerModule(module); DataB db = new DataB(); db.da.i = 11; db.k = 13; String jsonBString = mapper.writeValueAsString(db); JsonNode jsonBNode = mapper.valueToTree(db); // create parent DataB dbNewViaString = mapper.readValue(jsonBString, DataB.class); assertEquals(5, dbNewViaString.da.i); assertEquals(13, dbNewViaString.k); DataB dbNewViaNode = mapper.treeToValue(jsonBNode, DataB.class); assertEquals(5, dbNewViaNode.da.i); assertEquals(13, dbNewViaNode.k); // update parent DataB dbUpdViaString = new DataB(); DataB dbUpdViaNode = new DataB(); assertEquals(1, dbUpdViaString.da.i); assertEquals(3, dbUpdViaString.k); mapper.readerForUpdating(dbUpdViaString).readValue(jsonBString); assertEquals(5, dbUpdViaString.da.i); assertEquals(13, dbUpdViaString.k); assertEquals(1, dbUpdViaNode.da.i); assertEquals(3, dbUpdViaNode.k); mapper.readerForUpdating(dbUpdViaNode).readValue(jsonBNode); assertEquals(5, dbUpdViaNode.da.i); assertEquals(13, dbUpdViaNode.k); } // [databind#1831] public void test1831UsingNode() throws IOException { String catJson = MAPPER.writeValueAsString(new Cat()); JsonNode jsonNode = MAPPER.readTree(catJson); AnimalWrapper optionalCat = new AnimalWrapper(); ObjectReader r = MAPPER.readerForUpdating(optionalCat); AnimalWrapper result = r.readValue(jsonNode); assertSame(optionalCat, result); } public void test1831UsingString() throws IOException { String catJson = MAPPER.writeValueAsString(new Cat()); AnimalWrapper optionalCat = new AnimalWrapper(); AnimalWrapper result = MAPPER.readerForUpdating(optionalCat).readValue(catJson); assertSame(optionalCat, result); } } UpdateValueTest.java000066400000000000000000000062531325620701100361130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/convertpackage com.fasterxml.jackson.databind.convert; import java.util.*; import com.fasterxml.jackson.databind.*; /** * Tests for {@link ObjectMapper#updateValue}. * * @since 2.9 */ public class UpdateValueTest extends BaseMapTest { /* /******************************************************** /* Test methods; simple containers /******************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testMapUpdate() throws Exception { Map base = new LinkedHashMap<>(); base.put("a", 345); Map overrides = new LinkedHashMap<>(); overrides.put("xyz", Boolean.TRUE); overrides.put("foo", "bar"); Map ob = MAPPER.updateValue(base, overrides); // first: should return first argument assertSame(base, ob); assertEquals(3, ob.size()); assertEquals(Integer.valueOf(345), ob.get("a")); assertEquals("bar", ob.get("foo")); assertEquals(Boolean.TRUE, ob.get("xyz")); } public void testListUpdate() throws Exception { List base = new ArrayList<>(); base.add(123456); base.add(Boolean.FALSE); Object[] overrides = new Object[] { Boolean.TRUE, "zoink!" }; List ob = MAPPER.updateValue(base, overrides); // first: should return first argument assertSame(base, ob); assertEquals(4, ob.size()); assertEquals(Integer.valueOf(123456), ob.get(0)); assertEquals(Boolean.FALSE, ob.get(1)); assertEquals(overrides[0], ob.get(2)); assertEquals(overrides[1], ob.get(3)); } public void testArrayUpdate() throws Exception { // Since Arrays are immutable, not sure what "right answer" ought to be Object[] base = new Object[] { Boolean.FALSE, Integer.valueOf(3) }; Object[] overrides = new Object[] { Boolean.TRUE, "zoink!" }; Object[] ob = MAPPER.updateValue(base, overrides); assertEquals(4, ob.length); assertEquals(base[0], ob[0]); assertEquals(base[1], ob[1]); assertEquals(overrides[0], ob[2]); assertEquals(overrides[1], ob[3]); } /* /******************************************************** /* Test methods; POJOs /******************************************************** */ public void testPOJO() throws Exception { Point base = new Point(42, 28); Map overrides = new LinkedHashMap<>(); overrides.put("y", 1234); Point result = MAPPER.updateValue(base, overrides); assertSame(base, result); assertEquals(42, result.x); assertEquals(1234, result.y); } /* /******************************************************** /* Test methods; other /******************************************************** */ public void testMisc() throws Exception { // if either is `null`, should return first arg assertNull(MAPPER.updateValue(null, "foo")); List input = new ArrayList<>(); assertSame(input, MAPPER.updateValue(input, null)); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/creators/000077500000000000000000000000001325620701100324045ustar00rootroot00000000000000DelegatingArrayCreator1804Test.java000066400000000000000000000021461325620701100407320ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/creatorspackage com.fasterxml.jackson.databind.creators; import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class DelegatingArrayCreator1804Test extends BaseMapTest { public static class MyTypeImpl extends MyType { private final List values; MyTypeImpl(List values) { this.values = values; } @Override public List getValues() { return values; } } static abstract class MyType { @JsonValue public abstract List getValues(); @JsonCreator(mode=JsonCreator.Mode.DELEGATING) public static MyType of(List values) { return new MyTypeImpl(values); } } public void testDelegatingArray1804() throws Exception { ObjectMapper mapper = new ObjectMapper(); MyType thing = mapper.readValue("[]", MyType.class); assertNotNull(thing); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/000077500000000000000000000000001325620701100316645ustar00rootroot00000000000000AnySetter349Test.java000066400000000000000000000034111325620701100354650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // test(s) for [databind#349] public class AnySetter349Test extends BaseMapTest { static class Bean349 { public String type; public int x, y; private Map props = new HashMap<>(); @JsonAnySetter public void addProperty(String key, Object value) { props.put(key, value); } @JsonAnyGetter public Map getProperties() { return props; } @JsonUnwrapped public IdentityDTO349 identity; } static class IdentityDTO349 { public int x, y; } final static String UNWRAPPED_JSON_349 = aposToQuotes( "{ 'type' : 'IST',\n" +" 'x' : 3,\n" //+" 'name' : 'BLAH-New',\n" //+" 'description' : 'namespace.name: X THIN FIR.DR-WD12-New',\n" +" 'ZoomLinks': [ 'foofoofoofoo', 'barbarbarbar' ],\n" +" 'y' : 4, 'z' : 8 }" ); public void testUnwrappedWithAny() throws Exception { final ObjectMapper mapper = objectMapper(); Bean349 value = mapper.readValue(UNWRAPPED_JSON_349, Bean349.class); assertNotNull(value); assertEquals(3, value.x); assertEquals(4, value.y); assertEquals(2, value.props.size()); } public void testUnwrappedWithAnyAsUpdate() throws Exception { final ObjectMapper mapper = objectMapper(); Bean349 bean = mapper.readerFor(Bean349.class) .withValueToUpdate(new Bean349()) .readValue(UNWRAPPED_JSON_349); assertEquals(3, bean.x); assertEquals(4, bean.y); assertEquals(2, bean.props.size()); } } AnySetterTest.java000066400000000000000000000277431325620701100352430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying that {@link JsonAnySetter} annotation * works as expected. */ public class AnySetterTest extends BaseMapTest { static class MapImitator { HashMap _map; public MapImitator() { _map = new HashMap(); } @JsonAnySetter void addEntry(String key, Object value) { _map.put(key, value); } } // for [databind#1376] static class MapImitatorDisabled extends MapImitator { @Override @JsonAnySetter(enabled=false) void addEntry(String key, Object value) { throw new RuntimeException("Should not get called"); } } /** * Let's also verify that it is possible to define different * value: not often useful, but possible. */ static class MapImitatorWithValue { HashMap _map; public MapImitatorWithValue() { _map = new HashMap(); } @JsonAnySetter void addEntry(String key, int[] value) { _map.put(key, value); } } // Bad; 2 "any setters" static class Broken { @JsonAnySetter void addEntry1(String key, Object value) { } @JsonAnySetter void addEntry2(String key, Object value) { } } @JsonIgnoreProperties("dummy") static class Ignored { HashMap map = new HashMap(); @JsonIgnore public String bogus; @JsonAnySetter void addEntry(String key, Object value) { map.put(key, value); } } static class Bean744 { protected Map additionalProperties; @JsonAnySetter public void addAdditionalProperty(String key, Object value) { if (additionalProperties == null) additionalProperties = new HashMap(); additionalProperties.put(key,value); } public void setAdditionalProperties(Map additionalProperties) { this.additionalProperties = additionalProperties; } @JsonAnyGetter public Map getAdditionalProperties() { return additionalProperties; } @JsonIgnore public String getName() { return (String) additionalProperties.get("name"); } } static class Bean797Base { @JsonAnyGetter public Map getUndefinedProperties() { throw new IllegalStateException("Should not call parent version!"); } } static class Bean797BaseImpl extends Bean797Base { @Override public Map getUndefinedProperties() { return new HashMap(); } } @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) static abstract class Base { } static class Impl extends Base { public String value; public Impl() { } public Impl(String v) { value = v; } } static class PolyAnyBean { protected Map props = new HashMap(); @JsonAnyGetter public Map props() { return props; } @JsonAnySetter public void prop(String name, Base value) { props.put(name, value); } } static class JsonAnySetterOnMap { public int id; @JsonAnySetter protected HashMap other = new HashMap(); @JsonAnyGetter public Map any() { return other; } } static class JsonAnySetterOnNullMap { public int id; @JsonAnySetter protected HashMap other; @JsonAnyGetter public Map any() { return other; } } static class MyGeneric { private String staticallyMappedProperty; private Map dynamicallyMappedProperties = new HashMap(); public String getStaticallyMappedProperty() { return staticallyMappedProperty; } @JsonAnySetter public void addDynamicallyMappedProperty(T key, int value) { dynamicallyMappedProperties.put(key, value); } public void setStaticallyMappedProperty(String staticallyMappedProperty) { this.staticallyMappedProperty = staticallyMappedProperty; } @JsonAnyGetter public Map getDynamicallyMappedProperties() { return dynamicallyMappedProperties; } } static class MyWrapper { private MyGeneric myStringGeneric; private MyGeneric myIntegerGeneric; public MyGeneric getMyStringGeneric() { return myStringGeneric; } public void setMyStringGeneric(MyGeneric myStringGeneric) { this.myStringGeneric = myStringGeneric; } public MyGeneric getMyIntegerGeneric() { return myIntegerGeneric; } public void setMyIntegerGeneric(MyGeneric myIntegerGeneric) { this.myIntegerGeneric = myIntegerGeneric; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleMapImitation() throws Exception { MapImitator mapHolder = MAPPER.readValue ("{ \"a\" : 3, \"b\" : true, \"c\":[1,2,3] }", MapImitator.class); Map result = mapHolder._map; assertEquals(3, result.size()); assertEquals(Integer.valueOf(3), result.get("a")); assertEquals(Boolean.TRUE, result.get("b")); Object ob = result.get("c"); assertTrue(ob instanceof List); List l = (List)ob; assertEquals(3, l.size()); assertEquals(Integer.valueOf(3), l.get(2)); } public void testAnySetterDisable() throws Exception { try { MAPPER.readValue(aposToQuotes("{'value':3}"), MapImitatorDisabled.class); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Unrecognized field \"value\""); } } public void testSimpleTyped() throws Exception { MapImitatorWithValue mapHolder = MAPPER.readValue ("{ \"a\" : [ 3, -1 ], \"b\" : [ ] }", MapImitatorWithValue.class); Map result = mapHolder._map; assertEquals(2, result.size()); assertEquals(new int[] { 3, -1 }, result.get("a")); assertEquals(new int[0], result.get("b")); } public void testBrokenWithDoubleAnnotations() throws Exception { try { @SuppressWarnings("unused") Broken b = MAPPER.readValue("{ \"a\" : 3 }", Broken.class); fail("Should have gotten an exception"); } catch (JsonMappingException e) { verifyException(e, "Multiple 'any-setter' methods"); } } public void testIgnored() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); _testIgnorals(mapper); } public void testIgnoredPart2() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); _testIgnorals(mapper); } public void testProblem744() throws Exception { Bean744 bean = MAPPER.readValue("{\"name\":\"Bob\"}", Bean744.class); assertNotNull(bean.additionalProperties); assertEquals(1, bean.additionalProperties.size()); assertEquals("Bob", bean.additionalProperties.get("name")); } public void testIssue797() throws Exception { String json = MAPPER.writeValueAsString(new Bean797BaseImpl()); assertEquals("{}", json); } // [Issue#337] public void testPolymorphic() throws Exception { PolyAnyBean input = new PolyAnyBean(); input.props.put("a", new Impl("xyz")); String json = MAPPER.writeValueAsString(input); // System.err.println("JSON: "+json); PolyAnyBean result = MAPPER.readValue(json, PolyAnyBean.class); assertEquals(1, result.props.size()); Base ob = result.props.get("a"); assertNotNull(ob); assertTrue(ob instanceof Impl); assertEquals("xyz", ((Impl) ob).value); } public void testJsonAnySetterOnMap() throws Exception { JsonAnySetterOnMap result = MAPPER.readValue("{\"id\":2,\"name\":\"Joe\", \"city\":\"New Jersey\"}", JsonAnySetterOnMap.class); assertEquals(2, result.id); assertEquals("Joe", result.other.get("name")); assertEquals("New Jersey", result.other.get("city")); } public void testJsonAnySetterOnNullMap() throws Exception { JsonAnySetterOnNullMap result = MAPPER.readValue("{\"id\":2,\"name\":\"Joe\", \"city\":\"New Jersey\"}", JsonAnySetterOnNullMap.class); assertEquals(2, result.id); assertNull(result.other); } // [databind#1035] public void testGenericAnySetter() throws Exception { ObjectMapper mapper = new ObjectMapper(); Map stringGenericMap = new HashMap(); stringGenericMap.put("testStringKey", 5); Map integerGenericMap = new HashMap(); integerGenericMap.put(111, 6); MyWrapper deserialized = mapper.readValue(aposToQuotes( "{'myStringGeneric':{'staticallyMappedProperty':'Test','testStringKey':5},'myIntegerGeneric':{'staticallyMappedProperty':'Test2','111':6}}" ), MyWrapper.class); MyGeneric stringGeneric = deserialized.getMyStringGeneric(); MyGeneric integerGeneric = deserialized.getMyIntegerGeneric(); assertNotNull(stringGeneric); assertEquals(stringGeneric.getStaticallyMappedProperty(), "Test"); for(Map.Entry entry : stringGeneric.getDynamicallyMappedProperties().entrySet()) { assertTrue("A key in MyGeneric is not an String.", entry.getKey() instanceof String); assertTrue("A value in MyGeneric is not an Integer.", entry.getValue() instanceof Integer); } assertEquals(stringGeneric.getDynamicallyMappedProperties(), stringGenericMap); assertNotNull(integerGeneric); assertEquals(integerGeneric.getStaticallyMappedProperty(), "Test2"); for(Map.Entry entry : integerGeneric.getDynamicallyMappedProperties().entrySet()) { Object key = entry.getKey(); assertEquals("A key in MyGeneric is not an Integer.", Integer.class, key.getClass()); Object value = entry.getValue(); assertEquals("A value in MyGeneric is not an Integer.", Integer.class, value.getClass()); } assertEquals(integerGeneric.getDynamicallyMappedProperties(), integerGenericMap); } /* /********************************************************** /* Private helper methods /********************************************************** */ private void _testIgnorals(ObjectMapper mapper) throws Exception { Ignored bean = mapper.readValue("{\"name\":\"Bob\", \"bogus\": [ 1, 2, 3], \"dummy\" : 13 }", Ignored.class); // as of 2.0, @JsonIgnoreProperties does block; @JsonIgnore not assertNull(bean.map.get("dummy")); assertEquals("[1, 2, 3]", ""+bean.map.get("bogus")); assertEquals("Bob", bean.map.get("name")); assertEquals(2, bean.map.size()); } } IgnoreWithDeserTest.java000066400000000000000000000044031325620701100363530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * This unit test suite that tests use of {@link JsonIgnore} * annotation with deserialization. */ public class IgnoreWithDeserTest extends BaseMapTest { // Class for testing {@link JsonIgnore} annotations with setters final static class SizeClassIgnore { int _x = 0; int _y = 0; public void setX(int value) { _x = value; } @JsonIgnore public void setY(int value) { _y = value; } /* Just igoring won't help a lot here; let's define a replacement * so that we won't get an exception for "unknown field" */ @JsonProperty("y") void foobar(int value) { ; // nop } } @JsonIgnoreProperties({ "z" }) final static class NoYOrZ { public int x; @JsonIgnore public int y = 1; } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testSimpleIgnore() throws Exception { SizeClassIgnore result = MAPPER.readValue("{ \"x\":1, \"y\" : 2 }", SizeClassIgnore.class); // x should be set, y not assertEquals(1, result._x); assertEquals(0, result._y); } public void testFailOnIgnore() throws Exception { ObjectReader r = MAPPER.readerFor(NoYOrZ.class); // First, fine to get "x": NoYOrZ result = r.readValue(aposToQuotes("{'x':3}")); assertEquals(3, result.x); assertEquals(1, result.y); // but not 'y' r = r.with(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES); try { result = r.readValue(aposToQuotes("{'x':3, 'y':4}")); fail("Should fail"); } catch (JsonMappingException e) { verifyException(e, "Ignored field"); } // or 'z' try { result = r.readValue(aposToQuotes("{'z':2 }")); fail("Should fail"); } catch (JsonMappingException e) { verifyException(e, "Ignored field"); } } } NullHandlingTest.java000066400000000000000000000161311325620701100356710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; public class NullHandlingTest extends BaseMapTest { static class FunnyNullDeserializer extends JsonDeserializer { @Override public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { return "text"; } @Override public String getNullValue(DeserializationContext ctxt) { return "funny"; } } static class AnySetter{ private Map any = new HashMap(); @JsonAnySetter public void setAny(String name, String value){ this.any.put(name,value); } public Map getAny(){ return this.any; } } // [databind#1601] static class RootData { public String name; public String type; @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type") @JsonSubTypes({ @Type(value = TypeA.class, name = "TypeA"), @Type(value = TypeB.class, name = "TypeB")}) public Proxy proxy; public RootData() {} public RootData(String name, String type, Proxy proxy) { this.name = name; this.type = type; this.proxy = proxy; } } static interface Proxy { } static class TypeA implements Proxy { public String aValue; public TypeA() {} public TypeA(String a) { this.aValue = a; } } static class TypeB implements Proxy { public String bValue; public TypeB() {} public TypeB(String b) { this.bValue = b; } } private final ObjectMapper MAPPER = objectMapper(); /* /********************************************************** /* Test methods /********************************************************** */ public void testNull() throws Exception { // null doesn't really have a type, fake by assuming Object Object result = MAPPER.readValue(" null", Object.class); assertNull(result); } public void testAnySetterNulls() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addDeserializer(String.class, new FunnyNullDeserializer()); mapper.registerModule(module); String fieldName = "fieldName"; String nullValue = "{\""+fieldName+"\":null}"; // should get non-default null directly: AnySetter result = mapper.readValue(nullValue, AnySetter.class); assertEquals(1, result.getAny().size()); assertNotNull(result.getAny().get(fieldName)); assertEquals("funny", result.getAny().get(fieldName)); // as well as via ObjectReader ObjectReader reader = mapper.readerFor(AnySetter.class); result = reader.readValue(nullValue); assertEquals(1, result.getAny().size()); assertNotNull(result.getAny().get(fieldName)); assertEquals("funny", result.getAny().get(fieldName)); } public void testCustomRootNulls() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addDeserializer(String.class, new FunnyNullDeserializer()); mapper.registerModule(module); // should get non-default null directly: String str = mapper.readValue("null", String.class); assertNotNull(str); assertEquals("funny", str); // as well as via ObjectReader ObjectReader reader = mapper.readerFor(String.class); str = reader.readValue("null"); assertNotNull(str); assertEquals("funny", str); } // [databind#407] public void testListOfNulls() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addDeserializer(String.class, new FunnyNullDeserializer()); mapper.registerModule(module); List list = Arrays.asList("funny"); JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, String.class); // should get non-default null directly: List deser = mapper.readValue("[null]", type); assertNotNull(deser); assertEquals(1, deser.size()); assertEquals(list.get(0), deser.get(0)); // as well as via ObjectReader ObjectReader reader = mapper.readerFor(type); deser = reader.readValue("[null]"); assertNotNull(deser); assertEquals(1, deser.size()); assertEquals(list.get(0), deser.get(0)); } // Test for [#407] public void testMapOfNulls() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addDeserializer(String.class, new FunnyNullDeserializer()); mapper.registerModule(module); JavaType type = mapper.getTypeFactory().constructMapType(Map.class, String.class, String.class); // should get non-default null directly: Map deser = mapper.readValue("{\"key\":null}", type); assertNotNull(deser); assertEquals(1, deser.size()); assertEquals("funny", deser.get("key")); // as well as via ObjectReader ObjectReader reader = mapper.readerFor(type); deser = reader.readValue("{\"key\":null}"); assertNotNull(deser); assertEquals(1, deser.size()); assertEquals("funny", deser.get("key")); } // [databind#1601] public void testPolymorphicDataNull() throws Exception { String typeA = "{\"name\":\"TypeAData\", \"type\":\"TypeA\", \"proxy\":{\"aValue\":\"This works!\"}}"; RootData typeAData = MAPPER.readValue(typeA, RootData.class); assertEquals("No value for aValue!?", "This works!", ((TypeA) typeAData.proxy).aValue); String typeB = "{\"name\":\"TypeBData\", \"type\":\"TypeB\", \"proxy\":{\"bValue\":\"This works too!\"}}"; RootData typeBData = MAPPER.readValue(typeB, RootData.class); assertEquals("No value for bValue!?", "This works too!", ((TypeB) typeBData.proxy).bValue); String typeBNull = "{\"name\":\"TypeBData\", \"type\":\"TypeB\", \"proxy\": null}"; RootData typeBNullData = MAPPER.readValue(typeBNull, RootData.class); assertNull("Proxy should be null!", typeBNullData.proxy); } } PropertyAliasTest.java000066400000000000000000000051601325620701100361100ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class PropertyAliasTest extends BaseMapTest { static class AliasBean { @JsonAlias({ "nm", "Name" }) public String name; int _xyz; int _a; @JsonCreator public AliasBean(@JsonProperty("a") @JsonAlias("A") int a) { _a = a; } @JsonAlias({ "Xyz" }) public void setXyz(int x) { _xyz = x; } } static class PolyWrapperForAlias { @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_ARRAY) @JsonSubTypes({ @JsonSubTypes.Type(value = AliasBean.class,name = "ab"), }) public Object value; protected PolyWrapperForAlias() { } public PolyWrapperForAlias(Object v) { value = v; } } private final ObjectMapper MAPPER = newObjectMapper(); // [databind#1029] public void testSimpleAliases() throws Exception { AliasBean bean; // first, one indicated by field annotation, set via field bean = MAPPER.readValue(aposToQuotes("{'Name':'Foobar','a':3,'xyz':37}"), AliasBean.class); assertEquals("Foobar", bean.name); assertEquals(3, bean._a); assertEquals(37, bean._xyz); // then method-bound one bean = MAPPER.readValue(aposToQuotes("{'name':'Foobar','a':3,'Xyz':37}"), AliasBean.class); assertEquals("Foobar", bean.name); assertEquals(3, bean._a); assertEquals(37, bean._xyz); // and finally, constructor-backed one bean = MAPPER.readValue(aposToQuotes("{'name':'Foobar','A':3,'xyz':37}"), AliasBean.class); assertEquals("Foobar", bean.name); assertEquals(3, bean._a); assertEquals(37, bean._xyz); } public void testAliasWithPolymorphic() throws Exception { PolyWrapperForAlias value = MAPPER.readValue(aposToQuotes( "{'value': ['ab', {'nm' : 'Bob', 'A' : 17} ] }" ), PolyWrapperForAlias.class); assertNotNull(value.value); AliasBean bean = (AliasBean) value.value; assertEquals("Bob", bean.name); assertEquals(17, bean._a); } } ReadOrWriteOnlyTest.java000066400000000000000000000053651325620701100363520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.beans.ConstructorProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; public class ReadOrWriteOnlyTest extends BaseMapTest { // for [databind#935], verify read/write-only cases static class ReadXWriteY { @JsonProperty(access=JsonProperty.Access.READ_ONLY) public int x = 1; @JsonProperty(access=JsonProperty.Access.WRITE_ONLY) public int y = 2; public void setX(int x) { throw new Error("Should NOT set x"); } public int getY() { throw new Error("Should NOT get y"); } } public static class Pojo935 { private String firstName = "Foo"; private String lastName = "Bar"; @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getFullName() { return firstName + " " + lastName; } public String getFirstName() { return firstName; } public void setFirstName(String n) { firstName = n; } public String getLastName() { return lastName; } public void setLastName(String n) { lastName = n; } } // for [databind#1345], emulate way Lombok embellishes classes static class Foo1345 { @JsonProperty(access=JsonProperty.Access.READ_ONLY) public String id; public String name; @ConstructorProperties({ "id", "name" }) public Foo1345(String id, String name) { this.id = id; this.name = name; } protected Foo1345() { } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); // [databind#935] public void testReadOnlyAndWriteOnly() throws Exception { String json = MAPPER.writeValueAsString(new ReadXWriteY()); assertEquals("{\"x\":1}", json); ReadXWriteY result = MAPPER.readValue("{\"x\":5, \"y\":6}", ReadXWriteY.class); assertNotNull(result); assertEquals(1, result.x); assertEquals(6, result.y); } public void testReadOnly935() throws Exception { String json = MAPPER.writeValueAsString(new Pojo935()); Pojo935 result = MAPPER.readValue(json, Pojo935.class); assertNotNull(result); } public void testReadOnly1345() throws Exception { Foo1345 result = MAPPER.readValue("{\"name\":\"test\"}", Foo1345.class); assertNotNull(result); assertEquals("test", result.name); assertNull(result.id); } } TestAnnotationUsing.java000066400000000000000000000175021325620701100364350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.*; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; /** * Unit test suite that tests "usingXxx" properties of * {@link JsonDeserialize} annotation. */ @SuppressWarnings("serial") public class TestAnnotationUsing extends BaseMapTest { /* /********************************************************************** /* Annotated Bean classes /********************************************************************** */ /** * Class for testing {@link JsonDeserializer} annotation * for class itself. */ @JsonDeserialize(using=ValueDeserializer.class) final static class ValueClass { int _a; /* we'll test it by not having default no-arg ctor, and leaving * out single-int-arg ctor (because deserializer would use that too) */ public ValueClass(int a, int b) { _a = a; } } /** * Class for testing {@link JsonDeserializer} annotation * for a method */ final static class MethodBean { int[] _ints; /* Note: could be made to work otherwise, except that * to trigger failure (in absence of annotation) Json * is of type VALUE_NUMBER_INT, not an Array: array would * work by default, but scalar not */ @JsonDeserialize(using=IntsDeserializer.class) public void setInts(int[] i) { _ints = i; } } static class ArrayBean { @JsonDeserialize(contentUsing=ValueDeserializer.class) public Object[] values; } static class ListBean { @JsonDeserialize(contentUsing=ValueDeserializer.class) public List values; } static class MapBean { @JsonDeserialize(contentUsing=ValueDeserializer.class) public Map values; } static class MapKeyBean { @JsonDeserialize(keyUsing=MapKeyDeserializer.class) public Map values; } @JsonDeserialize(keyUsing=MapKeyDeserializer.class, contentUsing=ValueDeserializer.class) static class MapKeyMap extends HashMap { } /* /********************************************************************** /* Deserializers /********************************************************************** */ static class ValueDeserializer extends StdDeserializer { public ValueDeserializer() { super(ValueClass.class); } @Override public ValueClass deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { int i = jp.getIntValue(); return new ValueClass(i, i); } } private final static class IntsDeserializer extends StdDeserializer { public IntsDeserializer() { super(int[].class); } @Override public int[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return new int[] { jp.getIntValue() }; } } private final static class MapKeyDeserializer extends KeyDeserializer { @Override public Object deserializeKey(String key, DeserializationContext ctxt) { return new String[] { key }; } } /* /********************************************************************** /* Tests: specifying deserializer of value itself /********************************************************************** */ // Unit test to verify that {@link JsonDeserialize#using} annotation works // when applied to a class public void testClassDeserializer() throws Exception { ObjectMapper m = new ObjectMapper(); ValueClass result = m.readValue(" 123 ", ValueClass.class); assertEquals(123, result._a); } // Unit test to verify that {@link JsonDeserialize#using} annotation works // when applied to a Method public void testMethodDeserializer() throws Exception { ObjectMapper m = new ObjectMapper(); // note: since it's part of method, must parse from Object struct MethodBean result = m.readValue(" { \"ints\" : 3 } ", MethodBean.class); assertNotNull(result); int[] ints = result._ints; assertNotNull(ints); assertEquals(1, ints.length); assertEquals(3, ints[0]); } /* /********************************************************************** /* Tests: specifying deserializer for keys and/or contents /********************************************************************** */ public void testArrayContentUsing() throws Exception { ObjectMapper m = new ObjectMapper(); ArrayBean result = m.readValue(" { \"values\" : [ 1, 2, 3 ] } ", ArrayBean.class); assertNotNull(result); Object[] obs = result.values; assertNotNull(obs); assertEquals(3, obs.length); assertEquals(ValueClass.class, obs[0].getClass()); assertEquals(1, ((ValueClass) obs[0])._a); assertEquals(ValueClass.class, obs[1].getClass()); assertEquals(2, ((ValueClass) obs[1])._a); assertEquals(ValueClass.class, obs[2].getClass()); assertEquals(3, ((ValueClass) obs[2])._a); } public void testListContentUsing() throws Exception { ObjectMapper m = new ObjectMapper(); ListBean result = m.readValue(" { \"values\" : [ 1, 2, 3 ] } ", ListBean.class); assertNotNull(result); List obs = result.values; assertNotNull(obs); assertEquals(3, obs.size()); assertEquals(ValueClass.class, obs.get(0).getClass()); assertEquals(1, ((ValueClass) obs.get(0))._a); assertEquals(ValueClass.class, obs.get(1).getClass()); assertEquals(2, ((ValueClass) obs.get(1))._a); assertEquals(ValueClass.class, obs.get(2).getClass()); assertEquals(3, ((ValueClass) obs.get(2))._a); } public void testMapContentUsing() throws Exception { ObjectMapper m = new ObjectMapper(); MapBean result = m.readValue(" { \"values\" : { \"a\": 1, \"b\":2 } } ", MapBean.class); assertNotNull(result); Map map = result.values; assertNotNull(map); assertEquals(2, map.size()); assertEquals(ValueClass.class, map.get("a").getClass()); assertEquals(1, ((ValueClass) map.get("a"))._a); assertEquals(ValueClass.class, map.get("b").getClass()); assertEquals(2, ((ValueClass) map.get("b"))._a); } public void testMapKeyUsing() throws Exception { ObjectMapper m = new ObjectMapper(); MapKeyBean result = m.readValue(" { \"values\" : { \"a\": true } } ", MapKeyBean.class); assertNotNull(result); Map map = result.values; assertNotNull(map); assertEquals(1, map.size()); Map.Entry en = map.entrySet().iterator().next(); assertEquals(String[].class, en.getKey().getClass()); assertEquals(Boolean.TRUE, en.getValue()); } // @since 1.8 public void testRootValueWithCustomKey() throws Exception { ObjectMapper m = new ObjectMapper(); MapKeyMap result = m.readValue(" { \"a\": 13 } ", MapKeyMap.class); assertNotNull(result); assertNotNull(result); assertEquals(1, result.size()); Map.Entry en = result.entrySet().iterator().next(); assertEquals(ValueClass.class, en.getValue().getClass()); assertEquals(13, ((ValueClass) en.getValue())._a); assertEquals(String[].class, en.getKey().getClass()); } } TestArrayDeserialization.java000066400000000000000000000440721325620701100374440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.*; import java.util.*; import static org.junit.Assert.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.module.SimpleModule; /** * This unit test suite tries to verify that the "Native" java type * mapper can properly re-construct Java array objects from Json arrays. */ public class TestArrayDeserialization extends BaseMapTest { public final static class Bean1 { int _x, _y; List _beans; // Just for deserialization: @SuppressWarnings("unused") private Bean1() { } public Bean1(int x, int y, List beans) { _x = x; _y = y; _beans = beans; } public int getX() { return _x; } public int getY() { return _y; } public List getBeans() { return _beans; } public void setX(int x) { _x = x; } public void setY(int y) { _y = y; } public void setBeans(List b) { _beans = b; } @Override public boolean equals(Object o) { if (!(o instanceof Bean1)) return false; Bean1 other = (Bean1) o; return (_x == other._x) && (_y == other._y) && _beans.equals(other._beans) ; } } /** * Simple bean that just gets serialized as a String value. * Deserialization from String value will be done via single-arg * constructor. */ public final static class Bean2 implements JsonSerializable // so we can output as simple String { final String _desc; public Bean2(String d) { _desc = d; } @Override public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { jgen.writeString(_desc); } @Override public String toString() { return _desc; } @Override public boolean equals(Object o) { if (!(o instanceof Bean2)) return false; Bean2 other = (Bean2) o; return _desc.equals(other._desc); } @Override public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) throws IOException, JsonProcessingException { } } static class ObjectWrapper { public Object wrapped; } static class ObjectArrayWrapper { public Object[] wrapped; } static class CustomNonDeserArrayDeserializer extends JsonDeserializer { @Override public NonDeserializable[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { List list = new ArrayList(); while (jp.nextToken() != JsonToken.END_ARRAY) { list.add(new NonDeserializable(jp.getText(), false)); } return list.toArray(new NonDeserializable[list.size()]); } } static class NonDeserializable { protected String value; public NonDeserializable(String v, boolean bogus) { value = v; } } static class Product { public String name; public List thelist; } static class Things { public String height; public String width; } static class HiddenBinaryBean890 { @JsonDeserialize(as=byte[].class) public Object someBytes; } /* /********************************************************** /* Tests for "untyped" arrays, Object[] /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testUntypedArray() throws Exception { // to get "untyped" default map-to-map, pass Object[].class String JSON = "[ 1, null, \"x\", true, 2.0 ]"; Object[] result = MAPPER.readValue(JSON, Object[].class); assertNotNull(result); assertEquals(5, result.length); assertEquals(Integer.valueOf(1), result[0]); assertNull(result[1]); assertEquals("x", result[2]); assertEquals(Boolean.TRUE, result[3]); assertEquals(Double.valueOf(2.0), result[4]); } public void testIntegerArray() throws Exception { final int LEN = 90000; // Let's construct array to get it big enough StringBuilder sb = new StringBuilder(); sb.append('['); for (int i = 0; i < LEN; ++i) { if (i > 0) { sb.append(','); } sb.append(i); } sb.append(']'); Integer[] result = MAPPER.readValue(sb.toString(), Integer[].class); assertNotNull(result); assertEquals(LEN, result.length); for (int i = 0; i < LEN; ++i) { assertEquals(i, result[i].intValue()); } } // [JACKSON-620]: allow "" to mean 'null' for Arrays, List and Maps public void testFromEmptyString() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); assertNull(m.readValue(quote(""), Object[].class)); assertNull( m.readValue(quote(""), String[].class)); assertNull( m.readValue(quote(""), int[].class)); } // [JACKSON-620]: allow "" to mean 'null' for Arrays, List and Maps public void testFromEmptyString2() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); m.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); Product p = m.readValue("{\"thelist\":\"\"}", Product.class); assertNotNull(p); assertNull(p.thelist); } /* /********************************************************** /* Arrays of arrays... /********************************************************** */ public void testUntypedArrayOfArrays() throws Exception { // to get "untyped" default map-to-map, pass Object[].class final String JSON = "[[[-0.027512,51.503221],[-0.008497,51.503221],[-0.008497,51.509744],[-0.027512,51.509744]]]"; Object result = MAPPER.readValue(JSON, Object.class); assertEquals(ArrayList.class, result.getClass()); assertNotNull(result); // Should be able to get it as an Object array as well Object[] array = MAPPER.readValue(JSON, Object[].class); assertNotNull(array); assertEquals(Object[].class, array.getClass()); // and as wrapped variants too ObjectWrapper w = MAPPER.readValue("{\"wrapped\":"+JSON+"}", ObjectWrapper.class); assertNotNull(w); assertNotNull(w.wrapped); assertEquals(ArrayList.class, w.wrapped.getClass()); ObjectArrayWrapper aw = MAPPER.readValue("{\"wrapped\":"+JSON+"}", ObjectArrayWrapper.class); assertNotNull(aw); assertNotNull(aw.wrapped); } /* /********************************************************** /* Tests for String arrays, char[] /********************************************************** */ public void testStringArray() throws Exception { final String[] STRS = new String[] { "a", "b", "abcd", "", "???", "\"quoted\"", "lf: \n", }; StringWriter sw = new StringWriter(); JsonGenerator jg = MAPPER.getFactory().createGenerator(sw); jg.writeStartArray(); for (String str : STRS) { jg.writeString(str); } jg.writeEndArray(); jg.close(); String[] result = MAPPER.readValue(sw.toString(), String[].class); assertNotNull(result); assertEquals(STRS.length, result.length); for (int i = 0; i < STRS.length; ++i) { assertEquals(STRS[i], result[i]); } // [#479]: null handling was busted in 2.4.0 result = MAPPER.readValue(" [ null ]", String[].class); assertNotNull(result); assertEquals(1, result.length); assertNull(result[0]); } public void testCharArray() throws Exception { final String TEST_STR = "Let's just test it? Ok!"; char[] result = MAPPER.readValue("\""+TEST_STR+"\"", char[].class); assertEquals(TEST_STR, new String(result)); // And just for [JACKSON-289], let's verify that fluffy arrays work too result = MAPPER.readValue("[\"a\",\"b\",\"c\"]", char[].class); assertEquals("abc", new String(result)); } /* /********************************************************** /* Tests for primitive arrays /********************************************************** */ public void testBooleanArray() throws Exception { boolean[] result = MAPPER.readValue("[ true, false, false ]", boolean[].class); assertNotNull(result); assertEquals(3, result.length); assertTrue(result[0]); assertFalse(result[1]); assertFalse(result[2]); } public void testByteArrayAsNumbers() throws Exception { final int LEN = 37000; StringBuilder sb = new StringBuilder(); sb.append('['); for (int i = 0; i < LEN; ++i) { int value = i - 128; sb.append((value < 256) ? value : (value & 0x7F)); sb.append(','); } sb.append("0]"); byte[] result = MAPPER.readValue(sb.toString(), byte[].class); assertNotNull(result); assertEquals(LEN+1, result.length); for (int i = 0; i < LEN; ++i) { int value = i - 128; byte exp = (byte) ((value < 256) ? value : (value & 0x7F)); if (exp != result[i]) { fail("At offset #"+i+" ("+result.length+"), expected "+exp+", got "+result[i]); } assertEquals(exp, result[i]); } assertEquals(0, result[LEN]); } public void testByteArrayAsBase64() throws Exception { /* Hmmh... let's use JsonGenerator here, to hopefully ensure we * get proper base64 encoding. Plus, not always using that * silly sample from Wikipedia. */ JsonFactory jf = new JsonFactory(); StringWriter sw = new StringWriter(); int LEN = 9000; byte[] TEST = new byte[LEN]; for (int i = 0; i < LEN; ++i) { TEST[i] = (byte) i; } JsonGenerator jg = jf.createGenerator(sw); jg.writeBinary(TEST); jg.close(); String inputData = sw.toString(); byte[] result = MAPPER.readValue(inputData, byte[].class); assertNotNull(result); assertArrayEquals(TEST, result); } /** * And then bit more challenging case; let's try decoding * multiple byte arrays from an array... */ public void testByteArraysAsBase64() throws Exception { JsonFactory jf = new JsonFactory(); StringWriter sw = new StringWriter(1000); final int entryCount = 15; JsonGenerator jg = jf.createGenerator(sw); jg.writeStartArray(); byte[][] entries = new byte[entryCount][]; for (int i = 0; i < entryCount; ++i) { byte[] b = new byte[1000 - i * 20]; for (int x = 0; x < b.length; ++x) { b[x] = (byte) (i + x); } entries[i] = b; jg.writeBinary(b); } jg.writeEndArray(); jg.close(); String inputData = sw.toString(); byte[][] result = MAPPER.readValue(inputData, byte[][].class); assertNotNull(result); assertEquals(entryCount, result.length); for (int i = 0; i < entryCount; ++i) { byte[] b = result[i]; assertArrayEquals("Comparing entry #"+i+"/"+entryCount,entries[i], b); } } // [JACKSON-763] public void testByteArraysWith763() throws Exception { String[] input = new String[] { "YQ==", "Yg==", "Yw==" }; byte[][] data = MAPPER.convertValue(input, byte[][].class); assertEquals("a", new String(data[0], "US-ASCII")); assertEquals("b", new String(data[1], "US-ASCII")); assertEquals("c", new String(data[2], "US-ASCII")); } public void testShortArray() throws Exception { final int LEN = 31001; // fits in signed 16-bit StringBuilder sb = new StringBuilder(); sb.append('['); for (int i = 0; i < LEN; ++i) { if (i > 0) { sb.append(','); } sb.append(i); } sb.append(']'); short[] result = MAPPER.readValue(sb.toString(), short[].class); assertNotNull(result); assertEquals(LEN, result.length); for (int i = 0; i < LEN; ++i) { short exp = (short) i; assertEquals(exp, result[i]); } } public void testIntArray() throws Exception { final int LEN = 70000; // Let's construct array to get it big enough StringBuilder sb = new StringBuilder(); sb.append('['); for (int i = 0; i < LEN; ++i) { if (i > 0) { sb.append(','); } sb.append(-i); } sb.append(']'); int[] result = MAPPER.readValue(sb.toString(), int[].class); assertNotNull(result); assertEquals(LEN, result.length); for (int i = 0; i < LEN; ++i) { assertEquals(-i, result[i]); } } public void testLongArray() throws Exception { final int LEN = 12300; StringBuilder sb = new StringBuilder(); sb.append('['); for (int i = 0; i < LEN; ++i) { if (i > 0) { sb.append(','); } sb.append(i); } sb.append(']'); long[] result = MAPPER.readValue(sb.toString(), long[].class); assertNotNull(result); assertEquals(LEN, result.length); for (int i = 0; i < LEN; ++i) { long exp = (long) i; assertEquals(exp, result[i]); } } public void testDoubleArray() throws Exception { final int LEN = 7000; StringBuilder sb = new StringBuilder(); sb.append('['); for (int i = 0; i < LEN; ++i) { // not ideal, but has to do... if (i > 0) { sb.append(','); } sb.append(i).append('.').append(i % 10); } sb.append(']'); double[] result = MAPPER.readValue(sb.toString(), double[].class); assertNotNull(result); assertEquals(LEN, result.length); for (int i = 0; i < LEN; ++i) { String expStr = String.valueOf(i) + "." + String.valueOf(i % 10); String actStr = String.valueOf(result[i]); if (!expStr.equals(actStr)) { fail("Entry #"+i+"/"+LEN+"; exp '"+expStr+"', got '"+actStr+"'"); } } } public void testFloatArray() throws Exception { final int LEN = 7000; StringBuilder sb = new StringBuilder(); sb.append('['); for (int i = 0; i < LEN; ++i) { if (i > 0) { sb.append(','); } // not ideal, but has to do... sb.append(i).append('.').append(i % 10); } sb.append(']'); float[] result = MAPPER.readValue(sb.toString(), float[].class); assertNotNull(result); assertEquals(LEN, result.length); for (int i = 0; i < LEN; ++i) { String expStr = String.valueOf(i) + "." + String.valueOf(i % 10); assertEquals(expStr, String.valueOf(result[i])); } } /* /********************************************************** /* Tests for Bean arrays /********************************************************** */ public void testBeanArray() throws Exception { List src = new ArrayList(); List b2 = new ArrayList(); b2.add(new Bean2("a")); b2.add(new Bean2("foobar")); src.add(new Bean1(1, 2, b2)); b2 = new ArrayList(); b2.add(null); src.add(new Bean1(4, 5, b2)); // Ok: let's assume bean serializer works ok.... StringWriter sw = new StringWriter(); MAPPER.writeValue(sw, src); // And then test de-serializer List result = MAPPER.readValue(sw.toString(), new TypeReference>() { }); assertNotNull(result); assertEquals(src, result); } /* /********************************************************** /* And special cases for byte array (base64 encoded) /********************************************************** */ // for [databind#890] public void testByteArrayTypeOverride890() throws Exception { HiddenBinaryBean890 result = MAPPER.readValue( aposToQuotes("{'someBytes':'AQIDBA=='}"), HiddenBinaryBean890.class); assertNotNull(result); assertNotNull(result.someBytes); assertEquals(byte[].class, result.someBytes.getClass()); } /* /********************************************************** /* And custom deserializers too /********************************************************** */ public void testCustomDeserializers() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule testModule = new SimpleModule("test", Version.unknownVersion()); testModule.addDeserializer(NonDeserializable[].class, new CustomNonDeserArrayDeserializer()); mapper.registerModule(testModule); NonDeserializable[] result = mapper.readValue("[\"a\"]", NonDeserializable[].class); assertNotNull(result); assertEquals(1, result.length); assertEquals("a", result[0].value); } } TestBasicAnnotations.java000066400000000000000000000152231325620701100365520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; /** * This unit test suite tests use of basic Annotations for * bean deserialization; ones that indicate (non-constructor) * method types, explicit deserializer annotations. */ @SuppressWarnings("serial") public class TestBasicAnnotations extends BaseMapTest { /// Class for testing {@link JsonProperty} annotations final static class SizeClassSetter { int _size; int _length; int _other; @JsonProperty public void size(int value) { _size = value; } @JsonProperty("length") public void foobar(int value) { _length = value; } // note: need not be public if annotated @JsonProperty protected void other(int value) { _other = value; } // finally: let's add a red herring that should be avoided... public void errorOut(int value) { throw new Error(); } } static class Issue442Bean { @JsonUnwrapped protected IntWrapper w = new IntWrapper(13); } final static class SizeClassSetter2 { int _x; @JsonProperty public void setX(int value) { _x = value; } // another red herring, which shouldn't be included public void setXandY(int x, int y) { throw new Error(); } } /** * One more, but this time checking for implied setter * using @JsonDeserialize */ final static class SizeClassSetter3 { int _x; @JsonDeserialize public void x(int value) { _x = value; } } /// Classes for testing Setter discovery with inheritance static class BaseBean { int _x = 0, _y = 0; public void setX(int value) { _x = value; } @JsonProperty("y") void foobar(int value) { _y = value; } } static class BeanSubClass extends BaseBean { int _z; public void setZ(int value) { _z = value; } } static class BeanWithDeserialize { @JsonDeserialize protected int a; } @JsonAutoDetect(setterVisibility=Visibility.NONE) final static class Dummy { } final static class EmptyDummy { } static class AnnoBean { int value = 3; @JsonProperty("y") public void setX(int v) { value = v; } } enum Alpha { A, B, C; } public static class SimpleBean { public int x, y; } /* /********************************************************** /* Other helper classes /********************************************************** */ final static class IntsDeserializer extends StdDeserializer { public IntsDeserializer() { super(int[].class); } @Override public int[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return new int[] { jp.getIntValue() }; } } /* /********************************************************** /* Test methods, basic /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleSetter() throws Exception { SizeClassSetter result = MAPPER.readValue ("{ \"other\":3, \"size\" : 2, \"length\" : -999 }", SizeClassSetter.class); assertEquals(3, result._other); assertEquals(2, result._size); assertEquals(-999, result._length); } // Test for checking [JACKSON-64] public void testSimpleSetter2() throws Exception { SizeClassSetter2 result = MAPPER.readValue("{ \"x\": -3 }", SizeClassSetter2.class); assertEquals(-3, result._x); } // Checking parts of [JACKSON-120] public void testSimpleSetter3() throws Exception { SizeClassSetter3 result = MAPPER.readValue ("{ \"x\": 128 }", SizeClassSetter3.class); assertEquals(128, result._x); } /** * Test for verifying that super-class setters are used as * expected. */ public void testSetterInheritance() throws Exception { BeanSubClass result = MAPPER.readValue ("{ \"x\":1, \"z\" : 3, \"y\" : 2 }", BeanSubClass.class); assertEquals(1, result._x); assertEquals(2, result._y); assertEquals(3, result._z); } public void testImpliedProperty() throws Exception { BeanWithDeserialize bean = MAPPER.readValue("{\"a\":3}", BeanWithDeserialize.class); assertNotNull(bean); assertEquals(3, bean.a); } // [databind#442] public void testIssue442PrivateUnwrapped() throws Exception { Issue442Bean bean = MAPPER.readValue("{\"i\":5}", Issue442Bean.class); assertEquals(5, bean.w.i); } /* /********************************************************** /* Test methods, annotations disabled /********************************************************** */ public void testAnnotationsDisabled() throws Exception { // first: verify that annotation introspection is enabled by default assertTrue(MAPPER.getDeserializationConfig().isEnabled(MapperFeature.USE_ANNOTATIONS)); // with annotations, property is renamed AnnoBean bean = MAPPER.readValue("{ \"y\" : 0 }", AnnoBean.class); assertEquals(0, bean.value); ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.USE_ANNOTATIONS, false); // without annotations, should default to default bean-based name... bean = m.readValue("{ \"x\" : 0 }", AnnoBean.class); assertEquals(0, bean.value); } public void testEnumsWhenDisabled() throws Exception { ObjectMapper m = new ObjectMapper(); assertEquals(Alpha.B, m.readValue(quote("B"), Alpha.class)); m = new ObjectMapper(); m.configure(MapperFeature.USE_ANNOTATIONS, false); // should still use the basic name handling here assertEquals(Alpha.B, m.readValue(quote("B"), Alpha.class)); } public void testNoAccessOverrides() throws Exception { ObjectMapper m = new ObjectMapper(); m.disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS); SimpleBean bean = m.readValue("{\"x\":1,\"y\":2}", SimpleBean.class); assertEquals(1, bean.x); assertEquals(2, bean.y); } } TestBeanDeserializer.java000066400000000000000000000430721325620701100365260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.type.ArrayType; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.MapType; @SuppressWarnings("serial") public class TestBeanDeserializer extends BaseMapTest { static abstract class Abstract { public int x; } static class Bean { public String b = "b"; public String a = "a"; public Bean() { } public Bean(String a, String b) { this.a = a; this.b = b; } } static class ModuleImpl extends SimpleModule { protected BeanDeserializerModifier modifier; public ModuleImpl(BeanDeserializerModifier modifier) { super("test", Version.unknownVersion()); this.modifier = modifier; } @Override public void setupModule(SetupContext context) { super.setupModule(context); if (modifier != null) { context.addBeanDeserializerModifier(modifier); } } } static class RemovingModifier extends BeanDeserializerModifier { private final String _removedProperty; public RemovingModifier(String remove) { _removedProperty = remove; } @Override public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) { builder.addIgnorable(_removedProperty); return builder; } } static class ReplacingModifier extends BeanDeserializerModifier { private final JsonDeserializer _deserializer; public ReplacingModifier(JsonDeserializer s) { _deserializer = s; } @Override public JsonDeserializer modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer deserializer) { return _deserializer; } } static class BogusBeanDeserializer extends JsonDeserializer { private final String a, b; public BogusBeanDeserializer(String a, String b) { this.a = a; this.b = b; } @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return new Bean(a, b); } } static class Issue476Bean { public Issue476Type value1, value2; } static class Issue476Type { public String name, value; } static class Issue476Deserializer extends BeanDeserializer implements ContextualDeserializer { protected static int propCount; public Issue476Deserializer(BeanDeserializer src) { super(src); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { propCount++; return this; } } public class Issue476DeserializerModifier extends BeanDeserializerModifier { @Override public JsonDeserializer modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer deserializer) { if (Issue476Type.class == beanDesc.getBeanClass()) { return new Issue476Deserializer((BeanDeserializer)deserializer); } return super.modifyDeserializer(config, beanDesc, deserializer); } } public class Issue476Module extends SimpleModule { public Issue476Module() { super("Issue476Module", Version.unknownVersion()); } @Override public void setupModule(SetupContext context) { context.addBeanDeserializerModifier(new Issue476DeserializerModifier()); } } public static class Issue1912Bean { public Issue1912SubBean subBean; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) // This is need to populate _propertyBasedCreator on BeanDeserializerBase public Issue1912Bean(@JsonProperty("subBean") Issue1912SubBean subBean) { this.subBean = subBean; } } public static class Issue1912SubBean { public String a; public Issue1912SubBean() { } public Issue1912SubBean(String a) { this.a = a; } } public static class Issue1912CustomBeanDeserializer extends JsonDeserializer { private BeanDeserializer defaultDeserializer; public Issue1912CustomBeanDeserializer(BeanDeserializer defaultDeserializer) { this.defaultDeserializer = defaultDeserializer; } @Override public Issue1912Bean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { // this is need on some cases, this populate _propertyBasedCreator defaultDeserializer.resolve(ctxt); p.nextFieldName(); // read subBean p.nextToken(); // read start object Issue1912SubBean subBean = (Issue1912SubBean) defaultDeserializer.findProperty("subBean").deserialize(p, ctxt); return new Issue1912Bean(subBean); } } public static class Issue1912CustomPropertyDeserializer extends JsonDeserializer { @Override public Issue1912SubBean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { p.nextFieldName(); // read "a" Issue1912SubBean object = new Issue1912SubBean(p.nextTextValue() + "_custom"); p.nextToken(); return object; } } public static class Issue1912UseAddOrReplacePropertyDeserializerModifier extends BeanDeserializerModifier { @Override public JsonDeserializer modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer deserializer) { if (beanDesc.getBeanClass() == Issue1912Bean.class) { return new Issue1912CustomBeanDeserializer((BeanDeserializer) deserializer); } return super.modifyDeserializer(config, beanDesc, deserializer); } @Override public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) { if (beanDesc.getBeanClass() == Issue1912Bean.class) { Iterator props = builder.getProperties(); while (props.hasNext()) { SettableBeanProperty prop = props.next(); SettableBeanProperty propWithCustomDeserializer = prop.withValueDeserializer(new Issue1912CustomPropertyDeserializer()); builder.addOrReplaceProperty(propWithCustomDeserializer, true); } } return builder; } } public class Issue1912Module extends SimpleModule { public Issue1912Module() { super("Issue1912Module", Version.unknownVersion()); } @Override public void setupModule(SetupContext context) { context.addBeanDeserializerModifier(new Issue1912UseAddOrReplacePropertyDeserializerModifier()); } } // [Issue#121], arrays, collections, maps enum EnumABC { A, B, C; } static class ArrayDeserializerModifier extends BeanDeserializerModifier { @Override public JsonDeserializer modifyArrayDeserializer(DeserializationConfig config, ArrayType valueType, BeanDescription beanDesc, JsonDeserializer deserializer) { return (JsonDeserializer) new StdDeserializer(Object.class) { @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) { return new String[] { "foo" }; } }; } } static class CollectionDeserializerModifier extends BeanDeserializerModifier { @Override public JsonDeserializer modifyCollectionDeserializer(DeserializationConfig config, CollectionType valueType, BeanDescription beanDesc, JsonDeserializer deserializer) { return (JsonDeserializer) new StdDeserializer(Object.class) { @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) { ArrayList list = new ArrayList(); list.add("foo"); return list; } }; } } static class MapDeserializerModifier extends BeanDeserializerModifier { @Override public JsonDeserializer modifyMapDeserializer(DeserializationConfig config, MapType valueType, BeanDescription beanDesc, JsonDeserializer deserializer) { return (JsonDeserializer) new StdDeserializer(Object.class) { @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) { HashMap map = new HashMap(); map.put("a", "foo"); return map; } }; } } static class EnumDeserializerModifier extends BeanDeserializerModifier { @Override public JsonDeserializer modifyEnumDeserializer(DeserializationConfig config, JavaType valueType, BeanDescription beanDesc, JsonDeserializer deserializer) { return (JsonDeserializer) new StdDeserializer(Object.class) { @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) { return "foo"; } }; } } static class KeyDeserializerModifier extends BeanDeserializerModifier { @Override public KeyDeserializer modifyKeyDeserializer(DeserializationConfig config, JavaType valueType, KeyDeserializer kd) { return new KeyDeserializer() { @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException { return "foo"; } }; } } static class UCStringDeserializer extends StdScalarDeserializer { private final JsonDeserializer _deser; public UCStringDeserializer(JsonDeserializer orig) { super(String.class); _deser = orig; } @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Object ob = _deser.deserialize(p, ctxt); return String.valueOf(ob).toUpperCase(); } } /* /******************************************************** /* Test methods /******************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); /** * Test to verify details of how trying to deserialize into * abstract type should fail (if there is no way to determine * actual type information for the concrete type to use) */ public void testAbstractFailure() throws Exception { try { MAPPER.readValue("{ \"x\" : 3 }", Abstract.class); fail("Should fail on trying to deserialize abstract type"); } catch (JsonProcessingException e) { verifyException(e, "cannot construct"); } } public void testPropertyRemoval() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new ModuleImpl(new RemovingModifier("a"))); Bean bean = mapper.readValue("{\"b\":\"2\"}", Bean.class); assertEquals("2", bean.b); // and 'a' has its default value: assertEquals("a", bean.a); } public void testDeserializerReplacement() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new ModuleImpl(new ReplacingModifier(new BogusBeanDeserializer("foo", "bar")))); Bean bean = mapper.readValue("{\"a\":\"xyz\"}", Bean.class); // custom deserializer always produces instance like this: assertEquals("foo", bean.a); assertEquals("bar", bean.b); } public void testIssue476() throws Exception { final String JSON = "{\"value1\" : {\"name\" : \"fruit\", \"value\" : \"apple\"}, \"value2\" : {\"name\" : \"color\", \"value\" : \"red\"}}"; ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new Issue476Module()); mapper.readValue(JSON, Issue476Bean.class); // there are 2 properties assertEquals(2, Issue476Deserializer.propCount); } public void testPOJOFromEmptyString() throws Exception { // first, verify default settings which do not accept empty String: assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)); try { MAPPER.readValue(quote(""), Bean.class); fail("Should not accept Empty String for POJO"); } catch (JsonProcessingException e) { verifyException(e, "from String value"); assertValidLocation(e.getLocation()); } // should be ok to enable dynamically ObjectReader r = MAPPER.readerFor(Bean.class) .with(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); Bean result = r.readValue(quote("")); assertNull(result); } // [databind#120] public void testModifyArrayDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setDeserializerModifier(new ArrayDeserializerModifier())); Object[] result = mapper.readValue("[1,2]", Object[].class); assertEquals(1, result.length); assertEquals("foo", result[0]); } public void testModifyCollectionDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setDeserializerModifier(new CollectionDeserializerModifier()) ); List result = mapper.readValue("[1,2]", List.class); assertEquals(1, result.size()); assertEquals("foo", result.get(0)); } public void testModifyMapDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setDeserializerModifier(new MapDeserializerModifier()) ); Map result = mapper.readValue("{\"a\":1,\"b\":2}", Map.class); assertEquals(1, result.size()); assertEquals("foo", result.get("a")); } public void testModifyEnumDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setDeserializerModifier(new EnumDeserializerModifier()) ); Object result = mapper.readValue(quote("B"), EnumABC.class); assertEquals("foo", result); } public void testModifyKeyDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setDeserializerModifier(new KeyDeserializerModifier()) ); Map result = mapper.readValue("{\"a\":1}", Map.class); assertEquals(1, result.size()); assertEquals("foo", result.entrySet().iterator().next().getKey()); } /** * Test to verify that even standard deserializers will result in `modifyDeserializer` * getting appropriately called. */ public void testModifyStdScalarDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setDeserializerModifier(new BeanDeserializerModifier() { @Override public JsonDeserializer modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer deser) { if (beanDesc.getBeanClass() == String.class) { return new UCStringDeserializer(deser); } return deser; } })); Object result = mapper.readValue(quote("abcDEF"), String.class); assertEquals("ABCDEF", result); } public void testAddOrReplacePropertyIsUsedOnDeserialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new Issue1912Module()); Issue1912Bean result = mapper.readValue("{\"subBean\": {\"a\":\"foo\"}}", Issue1912Bean.class); assertEquals("foo_custom", result.subBean.a); } } TestCachingOfDeser.java000066400000000000000000000074701325620701100361240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.util.List; import java.util.Map; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; @SuppressWarnings("serial") public class TestCachingOfDeser extends BaseMapTest { // For [databind#735] public static class TestMapNoCustom { public Map map; } public static class TestMapWithCustom { @JsonDeserialize(contentUsing = CustomDeserializer735.class) public Map map; } public static class TestListWithCustom { @JsonDeserialize(contentUsing = CustomDeserializer735.class) public List list; } public static class TestListNoCustom { public List list; } public static class CustomDeserializer735 extends StdDeserializer { public CustomDeserializer735() { super(Integer.class); } @Override public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return 100 * p.getValueAsInt(); } } /* /********************************************************** /* Unit tests /********************************************************** */ final static String MAP_INPUT = "{\"map\":{\"a\":1}}"; final static String LIST_INPUT = "{\"list\":[1]}"; // Ok: first, use custom-annotated instance first, then standard public void testCustomMapCaching1() throws Exception { ObjectMapper mapper = new ObjectMapper(); TestMapWithCustom mapC = mapper.readValue(MAP_INPUT, TestMapWithCustom.class); TestMapNoCustom mapStd = mapper.readValue(MAP_INPUT, TestMapNoCustom.class); assertNotNull(mapC.map); assertNotNull(mapStd.map); assertEquals(Integer.valueOf(100), mapC.map.get("a")); assertEquals(Integer.valueOf(1), mapStd.map.get("a")); } // And then standard first, custom next public void testCustomMapCaching2() throws Exception { ObjectMapper mapper = new ObjectMapper(); TestMapNoCustom mapStd = mapper.readValue(MAP_INPUT, TestMapNoCustom.class); TestMapWithCustom mapC = mapper.readValue(MAP_INPUT, TestMapWithCustom.class); assertNotNull(mapStd.map); assertNotNull(mapC.map); assertEquals(Integer.valueOf(1), mapStd.map.get("a")); assertEquals(Integer.valueOf(100), mapC.map.get("a")); } // Ok: first, use custom-annotated instance first, then standard public void testCustomListCaching1() throws Exception { ObjectMapper mapper = new ObjectMapper(); TestListWithCustom listC = mapper.readValue(LIST_INPUT, TestListWithCustom.class); TestListNoCustom listStd = mapper.readValue(LIST_INPUT, TestListNoCustom.class); assertNotNull(listC.list); assertNotNull(listStd.list); assertEquals(Integer.valueOf(100), listC.list.get(0)); assertEquals(Integer.valueOf(1), listStd.list.get(0)); } // First custom-annotated, then standard public void testCustomListCaching2() throws Exception { ObjectMapper mapper = new ObjectMapper(); TestListNoCustom listStd = mapper.readValue(LIST_INPUT, TestListNoCustom.class); TestListWithCustom listC = mapper.readValue(LIST_INPUT, TestListWithCustom.class); assertNotNull(listC.list); assertNotNull(listStd.list); assertEquals(Integer.valueOf(100), listC.list.get(0)); assertEquals(Integer.valueOf(1), listStd.list.get(0)); } } TestConcurrency.java000066400000000000000000000055411325620701100356070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; /** * Testing for [JACKSON-237] (NPE due to race condition) */ public class TestConcurrency extends BaseMapTest { /* /********************************************** /* Helper beans /********************************************** */ @JsonDeserialize(using=BeanDeserializer.class) static class Bean { public int value = 42; } /* /********************************************** /* Helper classes /********************************************** */ /** * Dummy deserializer used for verifying that partially handled (i.e. not yet * resolved) deserializers are not allowed to be used. */ static class BeanDeserializer extends JsonDeserializer implements ResolvableDeserializer { protected volatile boolean resolved = false; @Override public Bean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { if (!resolved) { throw new IOException("Deserializer not yet completely resolved"); } Bean b = new Bean(); b.value = 13; return b; } @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException { try { Thread.sleep(100L); } catch (Exception e) { } resolved = true; } } /* /********************************************** /* Unit tests /********************************************** */ public void testDeserializerResolution() throws Exception { /* Let's repeat couple of times, just to be sure; thread timing is not * exact science; plus caching plays a role too */ final String JSON = "{\"value\":42}"; for (int i = 0; i < 5; ++i) { final ObjectMapper mapper = new ObjectMapper(); Runnable r = new Runnable() { @Override public void run() { try { /*Bean b =*/ mapper.readValue(JSON, Bean.class); } catch (Exception e) { } } }; Thread t = new Thread(r); t.start(); // then let it proceed Thread.sleep(10L); // and try the same... Bean b = mapper.readValue(JSON, Bean.class); // note: funny deserializer, mangles data.. :) assertEquals(13, b.value); t.join(); } } } TestCustomDeserializers.java000066400000000000000000000353621325620701100373210ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.*; import java.lang.annotation.*; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.*; import com.fasterxml.jackson.databind.deser.std.*; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.util.StdConverter; /** * Test to check that customizations work as expected. */ @SuppressWarnings("serial") public class TestCustomDeserializers extends BaseMapTest { /* /********************************************************** /* Helper classes /********************************************************** */ static class DummyDeserializer extends StdDeserializer { final T value; public DummyDeserializer(T v, Class cls) { super(cls); value = v; } @Override public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // need to skip, if structured... p.skipChildren(); return value; } } static class TestBeans { public List beans; } static class TestBean { public CustomBean c; public String d; } @JsonDeserialize(using=CustomBeanDeserializer.class) static class CustomBean { protected final int a, b; public CustomBean(int a, int b) { this.a = a; this.b = b; } } static class CustomBeanDeserializer extends JsonDeserializer { @Override public CustomBean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { int a = 0, b = 0; JsonToken t = p.getCurrentToken(); if (t == JsonToken.START_OBJECT) { t = p.nextToken(); } else if (t != JsonToken.FIELD_NAME) { throw new Error(); } while(t == JsonToken.FIELD_NAME) { final String fieldName = p.getCurrentName(); t = p.nextToken(); if (t != JsonToken.VALUE_NUMBER_INT) { throw new JsonParseException(p, "expecting number got "+ t); } if (fieldName.equals("a")) { a = p.getIntValue(); } else if (fieldName.equals("b")) { b = p.getIntValue(); } else { throw new Error(); } t = p.nextToken(); } return new CustomBean(a, b); } } public static class Immutable { protected int x, y; public Immutable(int x0, int y0) { x = x0; y = y0; } } public static class CustomKey { private final int id; public CustomKey(int id) {this.id = id;} public int getId() { return id; } } public static class Model { protected final Map map; @JsonCreator public Model(@JsonProperty("map") @JsonDeserialize(keyUsing = CustomKeyDeserializer.class) Map map) { this.map = new HashMap(map); } @JsonProperty @JsonSerialize(keyUsing = CustomKeySerializer.class) public Map getMap() { return map; } } static class CustomKeySerializer extends JsonSerializer { @Override public void serialize(CustomKey value, JsonGenerator g, SerializerProvider provider) throws IOException { g.writeFieldName(String.valueOf(value.getId())); } } static class CustomKeyDeserializer extends KeyDeserializer { @Override public CustomKey deserializeKey(String key, DeserializationContext ctxt) throws IOException { return new CustomKey(Integer.valueOf(key)); } } // [databind#375] @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @interface Negative { } static class Bean375Wrapper { @Negative public Bean375Outer value; } static class Bean375Outer { protected Bean375Inner inner; public Bean375Outer(Bean375Inner v) { inner = v; } } static class Bean375Inner { protected int x; public Bean375Inner(int x) { this.x = x; } } static class Bean375OuterDeserializer extends StdDeserializer implements ContextualDeserializer { protected BeanProperty prop; protected Bean375OuterDeserializer() { this(null); } protected Bean375OuterDeserializer(BeanProperty p) { super(Bean375Outer.class); prop = p; } @Override public Bean375Outer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { Object ob = ctxt.readPropertyValue(p, prop, Bean375Inner.class); return new Bean375Outer((Bean375Inner) ob); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { return new Bean375OuterDeserializer(property); } } static class Bean375InnerDeserializer extends StdDeserializer implements ContextualDeserializer { protected boolean negative; protected Bean375InnerDeserializer() { this(false); } protected Bean375InnerDeserializer(boolean n) { super(Bean375Inner.class); negative = n; } @Override public Bean375Inner deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { int x = p.getIntValue(); if (negative) { x = -x; } else { x += x; } return new Bean375Inner(x); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { if (property != null) { Negative n = property.getAnnotation(Negative.class); if (n != null) { return new Bean375InnerDeserializer(true); } } return this; } } // for [databind#631] static class Issue631Bean { @JsonDeserialize(using=ParentClassDeserializer.class) public Object prop; } static class ParentClassDeserializer extends StdScalarDeserializer { protected ParentClassDeserializer() { super(Object.class); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Object parent = p.getCurrentValue(); String desc = (parent == null) ? "NULL" : parent.getClass().getSimpleName(); return "prop/"+ desc; } } static class UCStringDeserializer extends StdDeserializer { public UCStringDeserializer() { super(String.class); } @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return p.getText().toUpperCase(); } } static class DelegatingModuleImpl extends SimpleModule { public DelegatingModuleImpl() { super("test", Version.unknownVersion()); } @Override public void setupModule(SetupContext context) { super.setupModule(context); context.addBeanDeserializerModifier(new BeanDeserializerModifier() { @Override public JsonDeserializer modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer deserializer) { if (deserializer.handledType() == String.class) { JsonDeserializer d = new MyStringDeserializer(deserializer); // just for test coverage purposes... if (d.getDelegatee() != deserializer) { throw new Error("Cannot access delegatee!"); } return d; } return deserializer; } }); } } static class MyStringDeserializer extends DelegatingDeserializer { public MyStringDeserializer(JsonDeserializer newDel) { super(newDel); } @Override protected JsonDeserializer newDelegatingInstance(JsonDeserializer newDel) { return new MyStringDeserializer(newDel); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Object ob = _delegatee.deserialize(p, ctxt); return "MY:"+ob; } } /* /********************************************************** /* Unit tests /********************************************************** */ final ObjectMapper MAPPER = objectMapper(); public void testCustomBeanDeserializer() throws Exception { String json = "{\"beans\":[{\"c\":{\"a\":10,\"b\":20},\"d\":\"hello, tatu\"}]}"; TestBeans beans = MAPPER.readValue(json, TestBeans.class); assertNotNull(beans); List results = beans.beans; assertNotNull(results); assertEquals(1, results.size()); TestBean bean = results.get(0); assertEquals("hello, tatu", bean.d); CustomBean c = bean.c; assertNotNull(c); assertEquals(10, c.a); assertEquals(20, c.b); json = "{\"beans\":[{\"c\":{\"b\":3,\"a\":-4},\"d\":\"\"}," +"{\"d\":\"abc\", \"c\":{\"b\":15}}]}"; beans = MAPPER.readValue(json, TestBeans.class); assertNotNull(beans); results = beans.beans; assertNotNull(results); assertEquals(2, results.size()); bean = results.get(0); assertEquals("", bean.d); c = bean.c; assertNotNull(c); assertEquals(-4, c.a); assertEquals(3, c.b); bean = results.get(1); assertEquals("abc", bean.d); c = bean.c; assertNotNull(c); assertEquals(0, c.a); assertEquals(15, c.b); } // [Issue#87]: delegating deserializer public void testDelegating() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addDeserializer(Immutable.class, new StdDelegatingDeserializer( new StdConverter() { @Override public Immutable convert(JsonNode value) { int x = value.path("x").asInt(); int y = value.path("y").asInt(); return new Immutable(x, y); } } )); mapper.registerModule(module); Immutable imm = mapper.readValue("{\"x\":3,\"y\":7}", Immutable.class); assertEquals(3, imm.x); assertEquals(7, imm.y); } // [databind#623] public void testJsonNodeDelegating() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addDeserializer(Immutable.class, new StdNodeBasedDeserializer(Immutable.class) { @Override public Immutable convert(JsonNode root, DeserializationContext ctxt) throws IOException { int x = root.path("x").asInt(); int y = root.path("y").asInt(); return new Immutable(x, y); } }); mapper.registerModule(module); Immutable imm = mapper.readValue("{\"x\":-10,\"y\":3}", Immutable.class); assertEquals(-10, imm.x); assertEquals(3, imm.y); } public void testIssue882() throws Exception { Model original = new Model(Collections.singletonMap(new CustomKey(123), "test")); String json = MAPPER.writeValueAsString(original); Model deserialized = MAPPER.readValue(json, Model.class); assertNotNull(deserialized); assertNotNull(deserialized.map); assertEquals(1, deserialized.map.size()); } // [#337]: convenience methods for custom deserializers to use public void testContextReadValue() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addDeserializer(Bean375Outer.class, new Bean375OuterDeserializer()); module.addDeserializer(Bean375Inner.class, new Bean375InnerDeserializer()); mapper.registerModule(module); // First, without property; doubles up value: Bean375Outer outer = mapper.readValue("13", Bean375Outer.class); assertEquals(26, outer.inner.x); // then with property; should find annotation, turn negative Bean375Wrapper w = mapper.readValue("{\"value\":13}", Bean375Wrapper.class); assertNotNull(w.value); assertNotNull(w.value.inner); assertEquals(-13, w.value.inner.x); } // [#631]: "current value" access public void testCurrentValueAccess() throws Exception { Issue631Bean bean = MAPPER.readValue(aposToQuotes("{'prop':'stuff'}"), Issue631Bean.class); assertNotNull(bean); assertEquals("prop/Issue631Bean", bean.prop); } public void testCustomStringDeser() throws Exception { ObjectMapper mapper = new ObjectMapper().registerModule( new SimpleModule().addDeserializer(String.class, new UCStringDeserializer()) ); assertEquals("FOO", mapper.readValue(quote("foo"), String.class)); StringWrapper sw = mapper.readValue("{\"str\":\"foo\"}", StringWrapper.class); assertNotNull(sw); assertEquals("FOO", sw.str); } public void testDelegatingDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper().registerModule( new DelegatingModuleImpl()); String str = mapper.readValue(quote("foo"), String.class); assertEquals("MY:foo", str); } } TestCustomFactory.java000066400000000000000000000100031325620701100361040ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.*; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; /** * Test to check that customizations work as expected. */ @SuppressWarnings("serial") public class TestCustomFactory extends BaseMapTest { /* /********************************************************** /* Helper classes /********************************************************** */ static class DummyDeserializer extends StdDeserializer { final T value; public DummyDeserializer(T v, Class cls) { super(cls); value = v; } @Override public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { // need to skip, if structured... jp.skipChildren(); return value; } } static class TestBeans { public List beans; } static class TestBean { public CustomBean c; public String d; } @JsonDeserialize(using=CustomBeanDeserializer.class) static class CustomBean { protected final int a, b; public CustomBean(int a, int b) { this.a = a; this.b = b; } } static class CustomBeanDeserializer extends JsonDeserializer { @Override public CustomBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { int a = 0, b = 0; JsonToken t = jp.getCurrentToken(); if (t == JsonToken.START_OBJECT) { t = jp.nextToken(); } else if (t != JsonToken.FIELD_NAME) { throw new Error(); } while(t == JsonToken.FIELD_NAME) { final String fieldName = jp.getCurrentName(); t = jp.nextToken(); if (t != JsonToken.VALUE_NUMBER_INT) { throw new JsonParseException(jp, "expecting number got "+ t); } if (fieldName.equals("a")) { a = jp.getIntValue(); } else if (fieldName.equals("b")) { b = jp.getIntValue(); } else { throw new Error(); } t = jp.nextToken(); } return new CustomBean(a, b); } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testCustomBeanDeserializer() throws Exception { final ObjectMapper map = new ObjectMapper(); String json = "{\"beans\":[{\"c\":{\"a\":10,\"b\":20},\"d\":\"hello, tatu\"}]}"; TestBeans beans = map.readValue(json, TestBeans.class); assertNotNull(beans); List results = beans.beans; assertNotNull(results); assertEquals(1, results.size()); TestBean bean = results.get(0); assertEquals("hello, tatu", bean.d); CustomBean c = bean.c; assertNotNull(c); assertEquals(10, c.a); assertEquals(20, c.b); json = "{\"beans\":[{\"c\":{\"b\":3,\"a\":-4},\"d\":\"\"}," +"{\"d\":\"abc\", \"c\":{\"b\":15}}]}"; beans = map.readValue(json, TestBeans.class); assertNotNull(beans); results = beans.beans; assertNotNull(results); assertEquals(2, results.size()); bean = results.get(0); assertEquals("", bean.d); c = bean.c; assertNotNull(c); assertEquals(-4, c.a); assertEquals(3, c.b); bean = results.get(1); assertEquals("abc", bean.d); c = bean.c; assertNotNull(c); assertEquals(0, c.a); assertEquals(15, c.b); } } TestCyclicTypes.java000066400000000000000000000063331325620701100355500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.*; /** * Simple unit tests to verify that it is possible to handle * potentially cyclic structures, as long as object graph itself * is not cyclic. This is the case for directed hierarchies like * trees and DAGs. */ public class TestCyclicTypes extends BaseMapTest { /* /********************************************************** /* Helper bean classes /********************************************************** */ static class Bean { Bean _next; String _name; public Bean() { } public void setNext(Bean b) { _next = b; } public void setName(String n) { _name = n; } } static class LinkA { public LinkB next; } static class LinkB { protected LinkA a; public void setA(LinkA a) { this.a = a; } public LinkA getA() { return a; } } static class GenericLink { public GenericLink next; } static class StringLink extends GenericLink { } static class Selfie405 { public int id; @JsonIgnoreProperties({ "parent" }) public Selfie405 parent; public Selfie405(int id) { this.id = id; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testLinked() throws Exception { Bean first = MAPPER.readValue ("{\"name\":\"first\", \"next\": { " +" \"name\":\"last\", \"next\" : null }}", Bean.class); assertNotNull(first); assertEquals("first", first._name); Bean last = first._next; assertNotNull(last); assertEquals("last", last._name); assertNull(last._next); } public void testLinkedGeneric() throws Exception { StringLink link = MAPPER.readValue("{\"next\":null}", StringLink.class); assertNotNull(link); assertNull(link.next); } public void testCycleWith2Classes() throws Exception { LinkA a = MAPPER.readValue("{\"next\":{\"a\":null}}", LinkA.class); assertNotNull(a.next); LinkB b = a.next; assertNull(b.a); } // [Issue#405]: Should be possible to ignore cyclic ref public void testIgnoredCycle() throws Exception { Selfie405 self1 = new Selfie405(1); self1.parent = self1; // First: exception with default settings: assertTrue(MAPPER.isEnabled(SerializationFeature.FAIL_ON_SELF_REFERENCES)); try { MAPPER.writeValueAsString(self1); fail("Should fail with direct self-ref"); } catch (JsonMappingException e) { verifyException(e, "Direct self-reference"); } ObjectWriter w = MAPPER.writer() .without(SerializationFeature.FAIL_ON_SELF_REFERENCES); String json = w.writeValueAsString(self1); assertNotNull(json); assertEquals(aposToQuotes("{'id':1,'parent':{'id':1}}"), json); } } TestFieldDeserialization.java000066400000000000000000000105061325620701100374040ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.*; /** * Unit tests for verifying that field-backed properties can also be * deserialized as well as setter-accessible properties. */ public class TestFieldDeserialization extends BaseMapTest { /* /********************************************************** /* Annotated helper classes /********************************************************** */ static class SimpleFieldBean { public int x, y; // not auto-detectable, not public int z; // ignored, not detectable either @JsonIgnore public int a; } static class SimpleFieldBean2 { @JsonDeserialize String[] values; } @JsonAutoDetect(fieldVisibility=Visibility.NONE) static class NoAutoDetectBean { // not auto-detectable any more public int z; @JsonProperty("z") public int _z; } // Let's test invalid bean too static class DupFieldBean { public int z; @JsonProperty("z") public int _z; } public static class DupFieldBean2 { @JsonProperty("foo") public int _z; @JsonDeserialize private int foo; } public static class OkDupFieldBean extends SimpleFieldBean { @JsonProperty("x") protected int myX = 10; @SuppressWarnings("hiding") public int y = 11; } abstract static class Abstract { } static class Concrete extends Abstract { String value; public Concrete(String v) { value = v; } } static class AbstractWrapper { @JsonDeserialize(as=Concrete.class) public Abstract value; } /* /********************************************************** /* Main tests /********************************************************** */ public void testSimpleAutoDetect() throws Exception { ObjectMapper m = new ObjectMapper(); SimpleFieldBean result = m.readValue("{ \"x\" : -13 }", SimpleFieldBean.class); assertEquals(-13, result.x); assertEquals(0, result.y); } public void testSimpleAnnotation() throws Exception { ObjectMapper m = new ObjectMapper(); SimpleFieldBean2 bean = m.readValue("{ \"values\" : [ \"x\", \"y\" ] }", SimpleFieldBean2.class); String[] values = bean.values; assertNotNull(values); assertEquals(2, values.length); assertEquals("x", values[0]); assertEquals("y", values[1]); } public void testNoAutoDetect() throws Exception { ObjectMapper m = new ObjectMapper(); NoAutoDetectBean bean = m.readValue("{ \"z\" : 7 }", NoAutoDetectBean.class); assertEquals(7, bean._z); } public void testTypeAnnotation() throws Exception { ObjectMapper m = new ObjectMapper(); AbstractWrapper w = m.readValue("{ \"value\" : \"abc\" }", AbstractWrapper.class); Abstract bean = w.value; assertNotNull(bean); assertEquals(Concrete.class, bean.getClass()); assertEquals("abc", ((Concrete)bean).value); } public void testFailureDueToDups() throws Exception { try { writeAndMap(new ObjectMapper(), new DupFieldBean()); } catch (JsonMappingException e) { verifyException(e, "Multiple fields representing property"); } } public void testFailureDueToDups2() throws Exception { try { writeAndMap(new ObjectMapper(), new DupFieldBean2()); } catch (JsonMappingException e) { verifyException(e, "Multiple fields representing property"); } } // For [JACKSON-226], acceptable field overrides public void testOkFieldOverride() throws Exception { ObjectMapper m = new ObjectMapper(); OkDupFieldBean result = m.readValue("{ \"x\" : 1, \"y\" : 2 }", OkDupFieldBean.class); assertEquals(1, result.myX); assertEquals(2, result.y); } } TestGenericCollectionDeser.java000066400000000000000000000052751325620701100376740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @SuppressWarnings("serial") public class TestGenericCollectionDeser extends BaseMapTest { static class ListSubClass extends ArrayList { } /** * Map class that should behave like {@link ListSubClass}, but by * using annotations. */ @JsonDeserialize(contentAs=StringWrapper.class) static class AnnotatedStringList extends ArrayList { } @JsonDeserialize(contentAs=BooleanElement.class) static class AnnotatedBooleanList extends ArrayList { } protected static class BooleanElement { public Boolean b; @JsonCreator public BooleanElement(Boolean value) { b = value; } @JsonValue public Boolean value() { return b; } } /* /********************************************************** /* Tests for sub-classing /********************************************************** */ /** * Verifying that sub-classing works ok wrt generics information */ public void testListSubClass() throws Exception { ObjectMapper mapper = new ObjectMapper(); ListSubClass result = mapper.readValue("[ \"123\" ]", ListSubClass.class); assertEquals(1, result.size()); Object value = result.get(0); assertEquals(StringWrapper.class, value.getClass()); StringWrapper bw = (StringWrapper) value; assertEquals("123", bw.str); } /* /********************************************************** /* Tests for annotations /********************************************************** */ // Verifying that sub-classing works ok wrt generics information public void testAnnotatedLStringist() throws Exception { ObjectMapper mapper = new ObjectMapper(); AnnotatedStringList result = mapper.readValue("[ \"...\" ]", AnnotatedStringList.class); assertEquals(1, result.size()); Object ob = result.get(0); assertEquals(StringWrapper.class, ob.getClass()); assertEquals("...", ((StringWrapper) ob).str); } public void testAnnotatedBooleanList() throws Exception { ObjectMapper mapper = new ObjectMapper(); AnnotatedBooleanList result = mapper.readValue("[ false ]", AnnotatedBooleanList.class); assertEquals(1, result.size()); Object ob = result.get(0); assertEquals(BooleanElement.class, ob.getClass()); assertFalse(((BooleanElement) ob).b); } } TestGenericMapDeser.java000066400000000000000000000134431325620701100363120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.type.TypeFactory; @SuppressWarnings("serial") public class TestGenericMapDeser extends BaseMapTest { /* /********************************************************** /* Test classes, enums /********************************************************** */ static class BooleanWrapper { final Boolean b; @JsonCreator BooleanWrapper(Boolean value) { b = value; } } static class StringWrapper { final String str; @JsonCreator StringWrapper(String value) { str = value; } } static class MapSubClass extends HashMap { } /** * Map class that should behave like {@link MapSubClass}, but by * using annotations. */ @JsonDeserialize(keyAs=StringWrapper.class, contentAs=BooleanWrapper.class) static class AnnotatedMap extends HashMap { } interface MapWrapper extends java.io.Serializable { public abstract Map getEntries(); } static class StringMap implements MapWrapper { private Map entries = new LinkedHashMap(); public StringMap() { } @Override public Map getEntries() { return entries; } } static class StringWrapperValueMap extends HashMap { } static class StringStringWrapperMap extends StringWrapperValueMap { } static class KeyTypeCtor { protected String value; public KeyTypeCtor(String v) { value = v; } } static class KeyTypeFactory { protected String value; private KeyTypeFactory(String v, boolean foo) { value = v; } @JsonCreator public static KeyTypeFactory create(String str) { return new KeyTypeFactory(str, true); } } /* /********************************************************** /* Test methods for sub-classing /********************************************************** */ /** * Verifying that sub-classing works ok wrt generics information */ public void testMapSubClass() throws Exception { ObjectMapper mapper = new ObjectMapper(); MapSubClass result = mapper.readValue ("{\"a\":true }", MapSubClass.class); assertEquals(1, result.size()); Object value = result.get("a"); assertEquals(BooleanWrapper.class, value.getClass()); BooleanWrapper bw = (BooleanWrapper) value; assertEquals(Boolean.TRUE, bw.b); } public void testMapWrapper() throws Exception { StringMap value = new ObjectMapper().readValue ("{\"entries\":{\"a\":9} }", StringMap.class); assertNotNull(value.getEntries()); assertEquals(1, value.getEntries().size()); assertEquals(Long.valueOf(9), value.getEntries().get("a")); } public void testIntermediateTypes() throws Exception { StringStringWrapperMap result = new ObjectMapper().readValue ("{\"a\":\"b\"}", StringStringWrapperMap.class); assertEquals(1, result.size()); Object value = result.get("a"); assertNotNull(value); assertEquals(value.getClass(), StringWrapper.class); assertEquals("b", ((StringWrapper) value).str); } /* /********************************************************** /* Test methods for sub-classing for annotation handling /********************************************************** */ /** * Verifying that sub-classing works ok wrt generics information */ public void testAnnotatedMap() throws Exception { ObjectMapper mapper = new ObjectMapper(); AnnotatedMap result = mapper.readValue ("{\"a\":true }", AnnotatedMap.class); assertEquals(1, result.size()); Map.Entry en = result.entrySet().iterator().next(); assertEquals(StringWrapper.class, en.getKey().getClass()); assertEquals(BooleanWrapper.class, en.getValue().getClass()); assertEquals("a", ((StringWrapper) en.getKey()).str); assertEquals(Boolean.TRUE, ((BooleanWrapper) en.getValue()).b); } /* /********************************************************** /* Test methods for ensuring @JsonCreator works for keys /********************************************************** */ public void testKeyViaCtor() throws Exception { ObjectMapper mapper = new ObjectMapper(); Map map = mapper.readValue("{\"a\":123}", TypeFactory.defaultInstance().constructMapType(HashMap.class, KeyTypeCtor.class, Integer.class)); assertEquals(1, map.size()); Map.Entry entry = map.entrySet().iterator().next(); assertEquals(Integer.valueOf(123), entry.getValue()); Object key = entry.getKey(); assertEquals(KeyTypeCtor.class, key.getClass()); assertEquals("a", ((KeyTypeCtor) key).value); } public void testKeyViaFactory() throws Exception { ObjectMapper mapper = new ObjectMapper(); Map map = mapper.readValue("{\"a\":123}", TypeFactory.defaultInstance().constructMapType(HashMap.class, KeyTypeFactory.class, Integer.class)); assertEquals(1, map.size()); Map.Entry entry = map.entrySet().iterator().next(); assertEquals(Integer.valueOf(123), entry.getValue()); Object key = entry.getKey(); assertEquals(KeyTypeFactory.class, key.getClass()); assertEquals("a", ((KeyTypeFactory) key).value); } } TestGenerics.java000066400000000000000000000136551325620701100350610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class TestGenerics extends BaseMapTest { static abstract class BaseNumberBean { public abstract void setNumber(T value); } static class NumberBean extends BaseNumberBean { long _number; @Override public void setNumber(Long value) { _number = value.intValue(); } } /** * Very simple bean class */ static class SimpleBean { public int x; } static class Wrapper { public T value; public Wrapper() { } public Wrapper(T v) { value = v; } @Override public boolean equals(Object o) { return (o instanceof Wrapper) && (((Wrapper) o).value.equals(value)); } } /* /*************************************************** /* Test cases /*************************************************** */ public void testSimpleNumberBean() throws Exception { ObjectMapper mapper = new ObjectMapper(); NumberBean result = mapper.readValue("{\"number\":17}", NumberBean.class); assertEquals(17, result._number); } /** * Unit test for verifying fix to [JACKSON-109]. */ public void testGenericWrapper() throws Exception { ObjectMapper mapper = new ObjectMapper(); Wrapper result = mapper.readValue ("{\"value\": { \"x\" : 13 } }", new TypeReference>() { }); assertNotNull(result); assertEquals(Wrapper.class, result.getClass()); Object contents = result.value; assertNotNull(contents); assertEquals(SimpleBean.class, contents.getClass()); SimpleBean bean = (SimpleBean) contents; assertEquals(13, bean.x); } public void testGenericWrapperWithSingleElementArray() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); Wrapper result = mapper.readValue ("[{\"value\": [{ \"x\" : 13 }] }]", new TypeReference>() { }); assertNotNull(result); assertEquals(Wrapper.class, result.getClass()); Object contents = result.value; assertNotNull(contents); assertEquals(SimpleBean.class, contents.getClass()); SimpleBean bean = (SimpleBean) contents; assertEquals(13, bean.x); } /** * Unit test for verifying that we can use different * type bindings for individual generic types; * problem with [JACKSON-190] */ public void testMultipleWrappers() throws Exception { ObjectMapper mapper = new ObjectMapper(); // First, numeric wrapper Wrapper result = mapper.readValue ("{\"value\": true}", new TypeReference>() { }); assertEquals(new Wrapper(Boolean.TRUE), result); // Then string one Wrapper result2 = mapper.readValue ("{\"value\": \"abc\"}", new TypeReference>() { }); assertEquals(new Wrapper("abc"), result2); // And then number Wrapper result3 = mapper.readValue ("{\"value\": 7}", new TypeReference>() { }); assertEquals(new Wrapper(7L), result3); } //[Issue#381] public void testMultipleWrappersSingleValueArray() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); // First, numeric wrapper Wrapper result = mapper.readValue ("[{\"value\": [true]}]", new TypeReference>() { }); assertEquals(new Wrapper(Boolean.TRUE), result); // Then string one Wrapper result2 = mapper.readValue ("[{\"value\": [\"abc\"]}]", new TypeReference>() { }); assertEquals(new Wrapper("abc"), result2); // And then number Wrapper result3 = mapper.readValue ("[{\"value\": [7]}]", new TypeReference>() { }); assertEquals(new Wrapper(7L), result3); } /** * Unit test for verifying fix to [JACKSON-109]. */ public void testArrayOfGenericWrappers() throws Exception { ObjectMapper mapper = new ObjectMapper(); Wrapper[] result = mapper.readValue ("[ {\"value\": { \"x\" : 9 } } ]", new TypeReference[]>() { }); assertNotNull(result); assertEquals(Wrapper[].class, result.getClass()); assertEquals(1, result.length); Wrapper elem = result[0]; Object contents = elem.value; assertNotNull(contents); assertEquals(SimpleBean.class, contents.getClass()); SimpleBean bean = (SimpleBean) contents; assertEquals(9, bean.x); } // [Issue#381] public void testArrayOfGenericWrappersSingleValueArray() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); Wrapper[] result = mapper.readValue ("[ {\"value\": [ { \"x\" : [ 9 ] } ] } ]", new TypeReference[]>() { }); assertNotNull(result); assertEquals(Wrapper[].class, result.getClass()); assertEquals(1, result.length); Wrapper elem = result[0]; Object contents = elem.value; assertNotNull(contents); assertEquals(SimpleBean.class, contents.getClass()); SimpleBean bean = (SimpleBean) contents; assertEquals(9, bean.x); } } TestInnerClass.java000066400000000000000000000031471325620701100353560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; public class TestInnerClass extends BaseMapTest { static class Dog { public String name; public Brain brain; public Dog() { } public Dog(String n, boolean thinking) { name = n; brain = new Brain(); brain.isThinking = thinking; } // note: non-static public class Brain { @JsonProperty("brainiac") public boolean isThinking; public String parentName() { return name; } } } /* /********************************************************** /* Tests /********************************************************** */ public void testSimpleNonStaticInner() throws Exception { // Let's actually verify by first serializing, then deserializing back ObjectMapper mapper = new ObjectMapper(); Dog input = new Dog("Smurf", true); String json = mapper.writeValueAsString(input); Dog output = mapper.readValue(json, Dog.class); assertEquals("Smurf", output.name); assertNotNull(output.brain); assertTrue(output.brain.isThinking); // and verify correct binding... assertEquals("Smurf", output.brain.parentName()); output.name = "Foo"; assertEquals("Foo", output.brain.parentName()); // also, null handling input.brain = null; output = mapper.readValue(mapper.writeValueAsString(input), Dog.class); assertNull(output.brain); } } TestJacksonTypes.java000066400000000000000000000101751325620701100357310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Unit tests for those Jackson types we want to ensure can be deserialized. */ public class TestJacksonTypes extends com.fasterxml.jackson.databind.BaseMapTest { public void testJsonLocation() throws Exception { ObjectMapper m = new ObjectMapper(); // note: source reference is untyped, only String guaranteed to work JsonLocation loc = new JsonLocation("whatever", -1, -1, 100, 13); // Let's use serializer here; goal is round-tripping String ser = serializeAsString(m, loc); JsonLocation result = m.readValue(ser, JsonLocation.class); assertNotNull(result); assertEquals(loc.getSourceRef(), result.getSourceRef()); assertEquals(loc.getByteOffset(), result.getByteOffset()); assertEquals(loc.getCharOffset(), result.getCharOffset()); assertEquals(loc.getColumnNr(), result.getColumnNr()); assertEquals(loc.getLineNr(), result.getLineNr()); } // doesn't really belong here but... public void testJsonLocationProps() { JsonLocation loc = new JsonLocation(null, -1, -1, 100, 13); assertTrue(loc.equals(loc)); assertFalse(loc.equals(null)); assertFalse(loc.equals("abx")); // should we check it's not 0? loc.hashCode(); } /** * Verify that {@link TokenBuffer} can be properly deserialized * automatically, using the "standard" JSON sample document */ public void testTokenBufferWithSample() throws Exception { ObjectMapper m = new ObjectMapper(); // First, try standard sample doc: TokenBuffer result = m.readValue(SAMPLE_DOC_JSON_SPEC, TokenBuffer.class); verifyJsonSpecSampleDoc(result.asParser(), true); result.close(); } @SuppressWarnings("resource") public void testTokenBufferWithSequence() throws Exception { ObjectMapper m = new ObjectMapper(); // and then sequence of other things JsonParser jp = createParserUsingReader("[ 32, [ 1 ], \"abc\", { \"a\" : true } ]"); assertToken(JsonToken.START_ARRAY, jp.nextToken()); assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); TokenBuffer buf = m.readValue(jp, TokenBuffer.class); // check manually... JsonParser bufParser = buf.asParser(); assertToken(JsonToken.VALUE_NUMBER_INT, bufParser.nextToken()); assertEquals(32, bufParser.getIntValue()); assertNull(bufParser.nextToken()); // then bind to another buf = m.readValue(jp, TokenBuffer.class); bufParser = buf.asParser(); assertToken(JsonToken.START_ARRAY, bufParser.nextToken()); assertToken(JsonToken.VALUE_NUMBER_INT, bufParser.nextToken()); assertEquals(1, bufParser.getIntValue()); assertToken(JsonToken.END_ARRAY, bufParser.nextToken()); assertNull(bufParser.nextToken()); // third one, with automatic binding buf = m.readValue(jp, TokenBuffer.class); String str = m.readValue(buf.asParser(), String.class); assertEquals("abc", str); // and ditto for last one buf = m.readValue(jp, TokenBuffer.class); Map map = m.readValue(buf.asParser(), Map.class); assertEquals(1, map.size()); assertEquals(Boolean.TRUE, map.get("a")); assertEquals(JsonToken.END_ARRAY, jp.nextToken()); assertNull(jp.nextToken()); } public void testJavaType() throws Exception { ObjectMapper mapper = new ObjectMapper(); TypeFactory tf = TypeFactory.defaultInstance(); // first simple type: String json = mapper.writeValueAsString(tf.constructType(String.class)); assertEquals(quote(java.lang.String.class.getName()), json); // and back JavaType t = mapper.readValue(json, JavaType.class); assertNotNull(t); assertEquals(String.class, t.getRawClass()); } } TestObjectOrArrayDeserialization.java000066400000000000000000000037021325620701100410670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class TestObjectOrArrayDeserialization extends BaseMapTest { public static class SomeObject { public String someField; } public static class ArrayOrObject { private final List objects; private final SomeObject object; @JsonCreator public ArrayOrObject(List objects) { this.objects = objects; this.object = null; } @JsonCreator public ArrayOrObject(SomeObject object) { this.objects = null; this.object = object; } } public void testObjectCase() throws Exception { ArrayOrObject arrayOrObject = new ObjectMapper().readValue("{}", ArrayOrObject.class); assertNull("expected objects field to be null", arrayOrObject.objects); assertNotNull("expected object field not to be null", arrayOrObject.object); } public void testEmptyArrayCase() throws Exception { ArrayOrObject arrayOrObject = new ObjectMapper().readValue("[]", ArrayOrObject.class); assertNotNull("expected objects field not to be null", arrayOrObject.objects); assertTrue("expected objects field to be an empty list", arrayOrObject.objects.isEmpty()); assertNull("expected object field to be null", arrayOrObject.object); } public void testNotEmptyArrayCase() throws Exception { ArrayOrObject arrayOrObject = new ObjectMapper().readValue("[{}, {}]", ArrayOrObject.class); assertNotNull("expected objects field not to be null", arrayOrObject.objects); assertEquals("expected objects field to have size 2", 2, arrayOrObject.objects.size()); assertNull("expected object field to be null", arrayOrObject.object); } } TestOverloaded.java000066400000000000000000000102251325620701100353740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; /** * Unit tests related to handling of overloaded methods. * and specifically addressing problems [JACKSON-189] * and [JACKSON-739] */ public class TestOverloaded extends BaseMapTest { static class BaseListBean { List list; BaseListBean() { } public void setList(List l) { list = l; } } static class ArrayListBean extends BaseListBean { ArrayListBean() { } public void setList(ArrayList l) { super.setList(l); } } // 27-Feb-2010, tatus: Won't fix immediately, need to comment out /* static class OverloadBean { String a; public OverloadBean() { } public void setA(int value) { a = String.valueOf(value); } public void setA(String value) { a = value; } } */ static class NumberBean { protected Object value; public void setValue(Number n) { value = n; } } static class WasNumberBean extends NumberBean { public void setValue(String str) { value = str; } } // [JACKSON-739] static class Overloaded739 { protected Object _value; @JsonProperty public void setValue(String str) { _value = str; } // no annotation, should not be chosen: public void setValue(Object o) { throw new UnsupportedOperationException(); } } /** * And then a Bean that is conflicting and should not work */ static class ConflictBean { public void setA(ArrayList a) { } public void setA(LinkedList a) { } } /* /************************************************************ /* Unit tests, valid /************************************************************ */ private final ObjectMapper MAPPER = new ObjectMapper(); /** * Unit test related to [JACKSON-189] */ // 27-Feb-2010, tatus: Won't fix immediately, need to comment out /* public void testSimpleOverload() throws Exception { OverloadBean bean; try { bean = new ObjectMapper().readValue("{ \"a\" : 13 }", OverloadBean.class); } catch (JsonMappingException e) { fail("Did not expect an exception, got: "+e.getMessage()); return; } assertEquals("13", bean.a); } */ /** * It should be ok to overload with specialized * version; more specific method should be used. */ public void testSpecialization() throws Exception { ArrayListBean bean = MAPPER.readValue ("{\"list\":[\"a\",\"b\",\"c\"]}", ArrayListBean.class); assertNotNull(bean.list); assertEquals(3, bean.list.size()); assertEquals(ArrayList.class, bean.list.getClass()); assertEquals("a", bean.list.get(0)); assertEquals("b", bean.list.get(1)); assertEquals("c", bean.list.get(2)); } /** * As per [JACKSON-255], should also allow more general overriding, * as long as there are no in-class conflicts. */ public void testOverride() throws Exception { WasNumberBean bean = MAPPER.readValue ("{\"value\" : \"abc\"}", WasNumberBean.class); assertNotNull(bean); assertEquals("abc", bean.value); } // for [JACKSON-739] public void testConflictResolution() throws Exception { Overloaded739 bean = MAPPER.readValue ("{\"value\":\"abc\"}", Overloaded739.class); assertNotNull(bean); assertEquals("abc", bean._value); } /* /************************************************************ /* Unit tests, failures /************************************************************ */ /** * For genuine setter conflict, an exception is to be thrown. */ public void testSetterConflict() throws Exception { try { MAPPER.readValue("{ }", ConflictBean.class); } catch (Exception e) { verifyException(e, "Conflicting setter definitions"); } } } TestSetterlessProperties.java000066400000000000000000000075231325620701100375310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying that feature requested * via [JACKSON-88] ("setterless collections") work as * expected, similar to how Collections and Maps work * with JAXB. */ public class TestSetterlessProperties extends BaseMapTest { static class CollectionBean { List _values = new ArrayList(); public List getValues() { return _values; } } static class MapBean { Map _values = new HashMap(); public Map getValues() { return _values; } } // testing to verify that field has precedence over getter, for lists static class Dual { @JsonProperty("list") protected List values = new ArrayList(); public Dual() { } public List getList() { throw new IllegalStateException("Should not get called"); } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testSimpleSetterlessCollectionOk() throws Exception { CollectionBean result = new ObjectMapper().readValue ("{\"values\":[ \"abc\", \"def\" ]}", CollectionBean.class); List l = result._values; assertEquals(2, l.size()); assertEquals("abc", l.get(0)); assertEquals("def", l.get(1)); } /** * Let's also verify that disabling the feature makes * deserialization fail for setterless bean */ public void testSimpleSetterlessCollectionFailure() throws Exception { ObjectMapper m = new ObjectMapper(); // by default, it should be enabled assertTrue(m.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS)); m.configure(MapperFeature.USE_GETTERS_AS_SETTERS, false); assertFalse(m.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS)); // and now this should fail try { m.readValue ("{\"values\":[ \"abc\", \"def\" ]}", CollectionBean.class); fail("Expected an exception"); } catch (JsonMappingException e) { /* Not a good exception, ideally could suggest a need for * a setter...? */ verifyException(e, "Unrecognized field"); } } public void testSimpleSetterlessMapOk() throws Exception { MapBean result = new ObjectMapper().readValue ("{\"values\":{ \"a\": 15, \"b\" : -3 }}", MapBean.class); Map m = result._values; assertEquals(2, m.size()); assertEquals(Integer.valueOf(15), m.get("a")); assertEquals(Integer.valueOf(-3), m.get("b")); } public void testSimpleSetterlessMapFailure() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.USE_GETTERS_AS_SETTERS, false); // so this should fail now without a setter try { m.readValue ("{\"values\":{ \"a\":3 }}", MapBean.class); fail("Expected an exception"); } catch (JsonMappingException e) { verifyException(e, "Unrecognized field"); } } /* Test for [JACKSON-328], precedence of "getter-as-setter" (for Lists) versus * field for same property. */ public void testSetterlessPrecedence() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.USE_GETTERS_AS_SETTERS, true); Dual value = m.readValue("{\"list\":[1,2,3]}, valueType)", Dual.class); assertNotNull(value); assertEquals(3, value.values.size()); } } TestStatics.java000066400000000000000000000016421325620701100347250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Tests for checking that static methods are not recognized as accessors * for properties */ public class TestStatics extends BaseMapTest { static class Bean { int _x; public static void setX(int value) { throw new Error("Should NOT call static method"); } @JsonProperty("x") public void assignX(int x) { _x = x; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testSimpleIgnore() throws Exception { ObjectMapper m = new ObjectMapper(); // should not care about static setter... Bean result = m.readValue("{ \"x\":3}", Bean.class); assertEquals(3, result._x); } } TestTimestampDeserialization.java000066400000000000000000000043031325620701100403220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.text.DateFormat; import java.text.SimpleDateFormat; import com.fasterxml.jackson.databind.*; public class TestTimestampDeserialization extends BaseMapTest { // As for TestDateDeserialization except we don't need to test date conversion routines, so // just check we pick up timestamp class public void testTimestampUtil() throws Exception { long now = 123456789L; java.sql.Timestamp value = new java.sql.Timestamp(now); // First from long assertEquals(value, new ObjectMapper().readValue(""+now, java.sql.Timestamp.class)); String dateStr = serializeTimestampAsString(value); java.sql.Timestamp result = new ObjectMapper().readValue("\""+dateStr+"\"", java.sql.Timestamp.class); assertEquals("Date: expect "+value+" ("+value.getTime()+"), got "+result+" ("+result.getTime()+")", value.getTime(), result.getTime()); } public void testTimestampUtilSingleElementArray() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); long now = System.currentTimeMillis(); java.sql.Timestamp value = new java.sql.Timestamp(now); // First from long assertEquals(value, mapper.readValue("["+now+"]", java.sql.Timestamp.class)); String dateStr = serializeTimestampAsString(value); java.sql.Timestamp result = mapper.readValue("[\""+dateStr+"\"]", java.sql.Timestamp.class); assertEquals("Date: expect "+value+" ("+value.getTime()+"), got "+result+" ("+result.getTime()+")", value.getTime(), result.getTime()); } /* /********************************************************** /* Helper methods /********************************************************** */ private String serializeTimestampAsString(java.sql.Timestamp value) { /* Then from String. This is bit tricky, since JDK does not really * suggest a 'standard' format. So let's try using something... */ DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); return df.format(value); } } TestValueAnnotations.java000066400000000000000000000311751325620701100366110ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deserpackage com.fasterxml.jackson.databind.deser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; /** * This unit test suite tests use of "value" Annotations; * annotations that define actual type (Class) to use for * deserialization. */ public class TestValueAnnotations extends BaseMapTest { /* /********************************************************** /* Annotated root classes for @JsonDeserialize#as /********************************************************** */ @JsonDeserialize(using=RootStringDeserializer.class) interface RootString { public String contents(); } static class RootStringImpl implements RootString { final String _contents; public RootStringImpl(String x) { _contents = x; } @Override public String contents() { return _contents; } public String contents2() { return _contents; } } @JsonDeserialize(as=RootInterfaceImpl.class) interface RootInterface { public String getA(); } static class RootInterfaceImpl implements RootInterface { public String a; public RootInterfaceImpl() { } @Override public String getA() { return a; } } @SuppressWarnings("serial") @JsonDeserialize(contentAs=RootStringImpl.class) static class RootMap extends HashMap { } @SuppressWarnings("serial") @JsonDeserialize(contentAs=RootStringImpl.class) static class RootList extends LinkedList { } @SuppressWarnings("serial") static class RootStringDeserializer extends StdDeserializer { public RootStringDeserializer() { super(RootString.class); } @Override public RootString deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_STRING)) { return new RootStringImpl(p.getText()); } return (RootString) ctxt.handleUnexpectedToken(_valueClass, p); } } /* /********************************************************** /* Annotated helper classes for @JsonDeserialize#as /********************************************************** */ /* Class for testing valid {@link JsonDeserialize} annotation * with 'as' parameter to define concrete class to deserialize to */ final static class CollectionHolder { Collection _strings; /* Default for 'Collection' would probably be ArrayList or so; * let's try to make it a TreeSet instead. */ @JsonDeserialize(as=TreeSet.class) public void setStrings(Collection s) { _strings = s; } } /* Another class for testing valid {@link JsonDeserialize} annotation * with 'as' parameter to define concrete class to deserialize to */ final static class MapHolder { // Let's also coerce numbers into Strings here Map _data; /* Default for 'Collection' would be HashMap, * let's try to make it a TreeMap instead. */ @JsonDeserialize(as=TreeMap.class) public void setStrings(Map s) { _data = s; } } /* Another class for testing valid {@link JsonDeserialize} annotation * with 'as' parameter, but with array */ final static class ArrayHolder { String[] _strings; @JsonDeserialize(as=String[].class) public void setStrings(Object[] o) { // should be passed instances of proper type, as per annotation _strings = (String[]) o; } } /* Another class for testing broken {@link JsonDeserialize} annotation * with 'as' parameter; one with incompatible type */ final static class BrokenCollectionHolder { @JsonDeserialize(as=String.class) // not assignable to Collection public void setStrings(Collection s) { } } /* /********************************************************** /* Annotated helper classes for @JsonDeserialize.keyAs /********************************************************** */ final static class StringWrapper { final String _string; public StringWrapper(String s) { _string = s; } } final static class MapKeyHolder { Map _map; @JsonDeserialize(keyAs=StringWrapper.class) public void setMap(Map m) { // type should be ok, but no need to cast here (won't matter) _map = m; } } final static class BrokenMapKeyHolder { // Invalid: Integer not a sub-class of String @JsonDeserialize(keyAs=Integer.class) public void setStrings(Map m) { } } /* /********************************************************** /* Annotated helper classes for @JsonDeserialize#contentAs /********************************************************** */ final static class ListContentHolder { List _list; @JsonDeserialize(contentAs=StringWrapper.class) public void setList(List l) { _list = l; } } final static class InvalidContentClass { /* Such annotation not allowed, since it makes no sense; * non-container classes have no contents to annotate (but * note that it is possible to first use @JsonDesiarialize.as * to mark Object as, say, a List, and THEN use * @JsonDeserialize.contentAs!) */ @JsonDeserialize(contentAs=String.class) public void setValue(Object x) { } } final static class ArrayContentHolder { Object[] _data; @JsonDeserialize(contentAs=Long.class) public void setData(Object[] o) { // should have proper type, but no need to coerce here _data = o; } } final static class MapContentHolder { Map _map; @JsonDeserialize(contentAs=Integer.class) public void setMap(Map m) { _map = m; } } /* /********************************************************** /* Test methods for @JsonDeserialize#as /********************************************************** */ public void testOverrideClassValid() throws Exception { ObjectMapper m = new ObjectMapper(); CollectionHolder result = m.readValue ("{ \"strings\" : [ \"test\" ] }", CollectionHolder.class); Collection strs = result._strings; assertEquals(1, strs.size()); assertEquals(TreeSet.class, strs.getClass()); assertEquals("test", strs.iterator().next()); } public void testOverrideMapValid() throws Exception { ObjectMapper m = new ObjectMapper(); // note: expecting conversion from number to String, as well MapHolder result = m.readValue ("{ \"strings\" : { \"a\" : 3 } }", MapHolder.class); Map strs = result._data; assertEquals(1, strs.size()); assertEquals(TreeMap.class, strs.getClass()); String value = strs.get("a"); assertEquals("3", value); } public void testOverrideArrayClass() throws Exception { ObjectMapper m = new ObjectMapper(); ArrayHolder result = m.readValue ("{ \"strings\" : [ \"test\" ] }", ArrayHolder.class); String[] strs = result._strings; assertEquals(1, strs.length); assertEquals(String[].class, strs.getClass()); assertEquals("test", strs[0]); } public void testOverrideClassInvalid() throws Exception { // should fail due to incompatible Annotation try { BrokenCollectionHolder result = new ObjectMapper().readValue ("{ \"strings\" : [ ] }", BrokenCollectionHolder.class); fail("Expected a failure, but got results: "+result); } catch (JsonMappingException jme) { verifyException(jme, "not subtype of"); } } /* /********************************************************** /* Test methods for @JsonDeserialize#as used for root values /********************************************************** */ public void testRootInterfaceAs() throws Exception { RootInterface value = new ObjectMapper().readValue("{\"a\":\"abc\" }", RootInterface.class); assertTrue(value instanceof RootInterfaceImpl); assertEquals("abc", value.getA()); } public void testRootInterfaceUsing() throws Exception { RootString value = new ObjectMapper().readValue("\"xxx\"", RootString.class); assertTrue(value instanceof RootString); assertEquals("xxx", value.contents()); } public void testRootListAs() throws Exception { RootMap value = new ObjectMapper().readValue("{\"a\":\"b\"}", RootMap.class); assertEquals(1, value.size()); Object v2 = value.get("a"); assertEquals(RootStringImpl.class, v2.getClass()); assertEquals("b", ((RootString) v2).contents()); } public void testRootMapAs() throws Exception { RootList value = new ObjectMapper().readValue("[ \"c\" ]", RootList.class); assertEquals(1, value.size()); Object v2 = value.get(0); assertEquals(RootStringImpl.class, v2.getClass()); assertEquals("c", ((RootString) v2).contents()); } /* /********************************************************** /* Test methods for @JsonDeserialize#keyAs /********************************************************** */ @SuppressWarnings("unchecked") public void testOverrideKeyClassValid() throws Exception { ObjectMapper m = new ObjectMapper(); MapKeyHolder result = m.readValue("{ \"map\" : { \"xxx\" : \"yyy\" } }", MapKeyHolder.class); Map map = (Map)(Map)result._map; assertEquals(1, map.size()); Map.Entry en = map.entrySet().iterator().next(); StringWrapper key = en.getKey(); assertEquals(StringWrapper.class, key.getClass()); assertEquals("xxx", key._string); assertEquals("yyy", en.getValue()); } public void testOverrideKeyClassInvalid() throws Exception { // should fail due to incompatible Annotation try { BrokenMapKeyHolder result = new ObjectMapper().readValue ("{ \"123\" : \"xxx\" }", BrokenMapKeyHolder.class); fail("Expected a failure, but got results: "+result); } catch (JsonMappingException jme) { verifyException(jme, "not subtype of"); } } /* /********************************************************** /* Test methods for @JsonDeserialize#contentAs /********************************************************** */ @SuppressWarnings("unchecked") public void testOverrideContentClassValid() throws Exception { ObjectMapper m = new ObjectMapper(); ListContentHolder result = m.readValue("{ \"list\" : [ \"abc\" ] }", ListContentHolder.class); List list = (List)result._list; assertEquals(1, list.size()); Object value = list.get(0); assertEquals(StringWrapper.class, value.getClass()); assertEquals("abc", ((StringWrapper) value)._string); } public void testOverrideArrayContents() throws Exception { ObjectMapper m = new ObjectMapper(); ArrayContentHolder result = m.readValue("{ \"data\" : [ 1, 2, 3 ] }", ArrayContentHolder.class); Object[] data = result._data; assertEquals(3, data.length); assertEquals(Long[].class, data.getClass()); assertEquals(1L, data[0]); assertEquals(2L, data[1]); assertEquals(3L, data[2]); } public void testOverrideMapContents() throws Exception { ObjectMapper m = new ObjectMapper(); MapContentHolder result = m.readValue("{ \"map\" : { \"a\" : 9 } }", MapContentHolder.class); Map map = result._map; assertEquals(1, map.size()); Object ob = map.values().iterator().next(); assertEquals(Integer.class, ob.getClass()); assertEquals(Integer.valueOf(9), ob); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/builder/000077500000000000000000000000001325620701100333125ustar00rootroot00000000000000BuilderAdvancedTest.java000066400000000000000000000032111325620701100377470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/builderpackage com.fasterxml.jackson.databind.deser.builder; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class BuilderAdvancedTest extends BaseMapTest { @JsonDeserialize(builder=InjectableBuilderXY.class) static class InjectableXY { final int _x, _y; final String _stuff; protected InjectableXY(int x, int y, String stuff) { _x = x+1; _y = y+1; _stuff = stuff; } } static class InjectableBuilderXY { public int x, y; @JacksonInject protected String stuff; public InjectableBuilderXY withX(int x0) { this.x = x0; return this; } public InjectableBuilderXY withY(int y0) { this.y = y0; return this; } public InjectableXY build() { return new InjectableXY(x, y, stuff); } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testWithInjectable() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setInjectableValues(new InjectableValues.Std() .addValue(String.class, "stuffValue") ); InjectableXY bean = mapper.readValue(aposToQuotes("{'y':3,'x':7}"), InjectableXY.class); assertEquals(8, bean._x); assertEquals(4, bean._y); assertEquals("stuffValue", bean._stuff); } } BuilderErrorHandling.java000066400000000000000000000035711325620701100401510ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/builderpackage com.fasterxml.jackson.databind.deser.builder; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.exc.MismatchedInputException; public class BuilderErrorHandling extends BaseMapTest { @JsonDeserialize(builder=SimpleBuilderXY.class) static class ValueClassXY { final int _x, _y; protected ValueClassXY(int x, int y) { _x = x+1; _y = y+1; } } static class SimpleBuilderXY { int x, y; public SimpleBuilderXY withX(int x0) { this.x = x0; return this; } public SimpleBuilderXY withY(int y0) { this.y = y0; return this; } public ValueClassXY build() { return new ValueClassXY(x, y); } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testUnknownProperty() throws Exception { // first, default failure String json = aposToQuotes("{'x':1,'z':2,'y':4}"); try { MAPPER.readValue(json, ValueClassXY.class); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "unrecognized field"); } // but pass if ok to ignore ValueClassXY result = MAPPER.readerFor(ValueClassXY.class) .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .readValue(json); assertEquals(2, result._x); assertEquals(5, result._y); } } BuilderFailTest.java000066400000000000000000000045531325620701100371270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/builderpackage com.fasterxml.jackson.databind.deser.builder; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; public class BuilderFailTest extends BaseMapTest { @JsonDeserialize(builder=SimpleBuilderXY.class) static class ValueClassXY { final int _x, _y; protected ValueClassXY(int x, int y) { _x = x+1; _y = y+1; } } static class SimpleBuilderXY { public int x, y; public SimpleBuilderXY withX(int x0) { this.x = x0; return this; } public SimpleBuilderXY withY(int y0) { this.y = y0; return this; } public ValueClassXY build() { return new ValueClassXY(x, y); } } // for [databind#761] @JsonDeserialize(builder = ValueBuilderWrongBuildType.class) static class ValueClassWrongBuildType { } static class ValueBuilderWrongBuildType { public int x; public ValueBuilderWrongBuildType withX(int x0) { this.x = x0; return this; } public ValueClassXY build() { return null; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testBuilderMethodReturnInvalidType() throws Exception { final String json = "{\"x\":1}"; try { MAPPER.readValue(json, ValueClassWrongBuildType.class); fail("Missing expected JsonProcessingException exception"); } catch (InvalidDefinitionException e) { verifyException(e, "Build method"); verifyException(e, "has wrong return type"); } } public void testExtraFields() throws Exception { final String json = aposToQuotes("{'x':1,'y':2,'z':3}"); try { MAPPER.readValue(json, ValueClassXY.class); fail("should not pass"); } catch (UnrecognizedPropertyException e) { verifyException(e, "Unrecognized field \"z\""); } } } BuilderInfiniteLoop1978Test.java000066400000000000000000000044131325620701100411770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/builderpackage com.fasterxml.jackson.databind.deser.builder; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class BuilderInfiniteLoop1978Test extends BaseMapTest { static class Builder { private SubBean temp; private int id; Builder(@JsonProperty("beanId") int beanId) { this.id = beanId; } @JsonUnwrapped(prefix="sub.") public Builder withThing(SubBean thing) { this.temp = thing; return this; } public Bean build() { Bean bean = new Bean(id); bean.setThing( temp ); return bean; } } @JsonDeserialize(builder = Builder.class) static class Bean { int id; SubBean thing; public Bean(int id) { this.id = id; } public SubBean getThing() { return thing; } public void setThing( SubBean thing ) { this.thing = thing; } } static class SubBuilder { private int element1; private String element2; @JsonProperty("el1") public SubBuilder withElement1(int e1) { this.element1 = e1; return this; } public SubBean build() { SubBean bean = new SubBean(); bean.element1 = element1; bean.element2 = element2; return bean; } } @JsonDeserialize(builder = SubBuilder.class) static class SubBean { public int element1; public String element2; } /* /********************************************************************** /* Test methods /********************************************************************** */ // for [databind#1978] public void testInfiniteLoop1978() throws Exception { String json = "{\"sub.el1\":34,\"sub.el2\":\"some text\"}"; ObjectMapper mapper = new ObjectMapper(); Bean bean = mapper.readValue( json, Bean.class ); assertNotNull(bean); } } BuilderSimpleTest.java000066400000000000000000000256051325620701100375060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/builderpackage com.fasterxml.jackson.databind.deser.builder; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector; public class BuilderSimpleTest extends BaseMapTest { // // Simple 2-property value class, builder with standard naming @JsonDeserialize(builder=SimpleBuilderXY.class) static class ValueClassXY { final int _x, _y; protected ValueClassXY(int x, int y) { _x = x+1; _y = y+1; } } static class SimpleBuilderXY { public int x, y; public SimpleBuilderXY withX(int x0) { this.x = x0; return this; } public SimpleBuilderXY withY(int y0) { this.y = y0; return this; } public ValueClassXY build() { return new ValueClassXY(x, y); } } // // 3-property value, with more varied builder @JsonDeserialize(builder=BuildABC.class) static class ValueClassABC { final int a, b, c; protected ValueClassABC(int a, int b, int c) { this.a = a; this.b = b; this.c = c; } } @JsonIgnoreProperties({ "d" }) static class BuildABC { public int a; // to be used as is private int b, c; @JsonProperty("b") public BuildABC assignB(int b0) { this.b = b0; return this; } // Also ok NOT to return 'this' @JsonSetter("c") public void c(int c0) { this.c = c0; } public ValueClassABC build() { return new ValueClassABC(a, b, c); } } // // Then Builder that is itself immutable @JsonDeserialize(builder=BuildImmutable.class) static class ValueImmutable { final int value; protected ValueImmutable(int v) { value = v; } } static class BuildImmutable { private final int value; private BuildImmutable() { this(0); } private BuildImmutable(int v) { value = v; } public BuildImmutable withValue(int v) { return new BuildImmutable(v); } public ValueImmutable build() { return new ValueImmutable(value); } } // And then with custom naming: @JsonDeserialize(builder=BuildFoo.class) static class ValueFoo { final int value; protected ValueFoo(int v) { value = v; } } @JsonPOJOBuilder(withPrefix="foo", buildMethodName="construct") static class BuildFoo { private int value; public BuildFoo fooValue(int v) { value = v; return this; } public ValueFoo construct() { return new ValueFoo(value); } } // for [databind#761] @JsonDeserialize(builder=ValueInterfaceBuilder.class) interface ValueInterface { int getX(); } @JsonDeserialize(builder=ValueInterface2Builder.class) interface ValueInterface2 { int getX(); } static class ValueInterfaceImpl implements ValueInterface { final int _x; protected ValueInterfaceImpl(int x) { _x = x+1; } @Override public int getX() { return _x; } } static class ValueInterface2Impl implements ValueInterface2 { final int _x; protected ValueInterface2Impl(int x) { _x = x+1; } @Override public int getX() { return _x; } } static class ValueInterfaceBuilder { public int x; public ValueInterfaceBuilder withX(int x0) { this.x = x0; return this; } public ValueInterface build() { return new ValueInterfaceImpl(x); } } static class ValueInterface2Builder { public int x; public ValueInterface2Builder withX(int x0) { this.x = x0; return this; } // should also be ok: more specific type public ValueInterface2Impl build() { return new ValueInterface2Impl(x); } } // [databind#777] @JsonDeserialize(builder = SelfBuilder777.class) @JsonPOJOBuilder(buildMethodName = "", withPrefix = "with") static class SelfBuilder777 { public int x; public SelfBuilder777 withX(int value) { x = value; return this; } } // [databind#822] @JsonPOJOBuilder(buildMethodName = "build", withPrefix = "with") static class ValueBuilder822 { public int x; private Map stuff = new HashMap(); public ValueBuilder822 withX(int x0) { this.x = x0; return this; } @JsonAnySetter public void addStuff(String key, Object value) { stuff.put(key, value); } public ValueClass822 build() { return new ValueClass822(x, stuff); } } @JsonDeserialize(builder = ValueBuilder822.class) static class ValueClass822 { public int x; public Map stuff; public ValueClass822(int x, Map stuff) { this.x = x; this.stuff = stuff; } } protected static class NopModule1557 extends com.fasterxml.jackson.databind.Module { @Override public String getModuleName() { return "NopModule"; } @Override public Version version() { return Version.unknownVersion(); } @Override public void setupModule(SetupContext setupContext) { // This annotation introspector has no opinion about builders, make sure it doesn't interfere setupContext.insertAnnotationIntrospector(new NopAnnotationIntrospector() { private static final long serialVersionUID = 1L; @Override public Version version() { return Version.unknownVersion(); } }); } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimple() throws Exception { String json = aposToQuotes("{'x':1,'y':2}"); Object o = MAPPER.readValue(json, ValueClassXY.class); assertNotNull(o); assertSame(ValueClassXY.class, o.getClass()); ValueClassXY value = (ValueClassXY) o; // note: ctor adds one to both values assertEquals(value._x, 2); assertEquals(value._y, 3); } // related to [databind#1214] public void testSimpleWithIgnores() throws Exception { // 'z' is unknown, and would fail by default: final String json = aposToQuotes("{'x':1,'y':2,'z':4}"); Object o = null; try { o = MAPPER.readValue(json, ValueClassXY.class); fail("Should not pass"); } catch (UnrecognizedPropertyException e) { assertEquals("z", e.getPropertyName()); verifyException(e, "Unrecognized field \"z\""); } // but with config overrides should pass ObjectMapper ignorantMapper = new ObjectMapper(); ignorantMapper.configOverride(SimpleBuilderXY.class) .setIgnorals(JsonIgnoreProperties.Value.forIgnoreUnknown(true)); o = ignorantMapper.readValue(json, ValueClassXY.class); assertNotNull(o); assertSame(ValueClassXY.class, o.getClass()); ValueClassXY value = (ValueClassXY) o; // note: ctor adds one to both values assertEquals(value._x, 2); assertEquals(value._y, 3); } public void testMultiAccess() throws Exception { String json = aposToQuotes("{'c':3,'a':2,'b':-9}"); ValueClassABC value = MAPPER.readValue(json, ValueClassABC.class); assertNotNull(value); assertEquals(2, value.a); assertEquals(-9, value.b); assertEquals(3, value.c); // also, since we can ignore some properties: value = MAPPER.readValue(aposToQuotes("{'c':3,'d':5,'b':-9}"), ValueClassABC.class); assertNotNull(value); assertEquals(0, value.a); assertEquals(-9, value.b); assertEquals(3, value.c); } // test for Immutable builder, to ensure return value is used public void testImmutable() throws Exception { final String json = "{\"value\":13}"; ValueImmutable value = MAPPER.readValue(json, ValueImmutable.class); assertEquals(13, value.value); } // test with custom 'with-prefix' public void testCustomWith() throws Exception { final String json = "{\"value\":1}"; ValueFoo value = MAPPER.readValue(json, ValueFoo.class); assertEquals(1, value.value); } // for [databind#761] public void testBuilderMethodReturnMoreGeneral() throws Exception { final String json = "{\"x\":1}"; ValueInterface value = MAPPER.readValue(json, ValueInterface.class); assertEquals(2, value.getX()); } public void testBuilderMethodReturnMoreSpecific() throws Exception { final String json = "{\"x\":1}"; ValueInterface2 value = MAPPER.readValue(json, ValueInterface2.class); assertEquals(2, value.getX()); } public void testSelfBuilder777() throws Exception { SelfBuilder777 result = MAPPER.readValue(aposToQuotes("{'x':3}'"), SelfBuilder777.class); assertNotNull(result); assertEquals(3, result.x); } public void testWithAnySetter822() throws Exception { final String json = "{\"extra\":3,\"foobar\":[ ],\"x\":1,\"name\":\"bob\"}"; ValueClass822 value = MAPPER.readValue(json, ValueClass822.class); assertEquals(1, value.x); assertNotNull(value.stuff); assertEquals(3, value.stuff.size()); assertEquals(Integer.valueOf(3), value.stuff.get("extra")); assertEquals("bob", value.stuff.get("name")); Object ob = value.stuff.get("foobar"); assertNotNull(ob); assertTrue(ob instanceof List); assertTrue(((List) ob).isEmpty()); } public void testPOJOConfigResolution1557() throws Exception { final String json = "{\"value\":1}"; MAPPER.registerModule(new NopModule1557()); ValueFoo value = MAPPER.readValue(json, ValueFoo.class); assertEquals(1, value.value); } } BuilderViaUpdateTest.java000066400000000000000000000053711325620701100401350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/builderpackage com.fasterxml.jackson.databind.deser.builder; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; /** * Tests to ensure that use of "updateValue()" will fail with builder-based deserializers. * * @since 2.9 */ public class BuilderViaUpdateTest extends BaseMapTest { @JsonDeserialize(builder=SimpleBuilderXY.class) static class ValueClassXY { protected int x, y; protected ValueClassXY(int x, int y) { x = x+1; y = y+1; } } static class SimpleBuilderXY { public int x, y; public SimpleBuilderXY withX(int x0) { this.x = x0; return this; } public SimpleBuilderXY withY(int y0) { this.y = y0; return this; } public ValueClassXY build() { return new ValueClassXY(x, y); } } /* /***************************************************** /* Basic tests, potential (but not current) success cases /***************************************************** */ private final static ObjectMapper MAPPER = new ObjectMapper(); // Tests where result value is passed as thing to update public void testBuilderUpdateWithValue() throws Exception { try { /*ValueClassXY value =*/ MAPPER.readerFor(ValueClassXY.class) .withValueToUpdate(new ValueClassXY(6, 7)) .readValue(aposToQuotes("{'x':1,'y:'2'}")); fail("Should not have passed"); } catch (InvalidDefinitionException e) { verifyException(e, "Deserialization of"); verifyException(e, "by passing existing instance"); verifyException(e, "ValueClassXY"); } } /* /***************************************************** /* Failing test cases /***************************************************** */ // and then test to ensure error handling works as expected if attempts // is made to pass builder (API requires value, not builder) public void testBuilderWithWrongType() throws Exception { try { /* Object result =*/ MAPPER.readerFor(ValueClassXY.class) .withValueToUpdate(new SimpleBuilderXY()) .readValue(aposToQuotes("{'x':1,'y:'2'}")); fail("Should not have passed"); } catch (InvalidDefinitionException e) { verifyException(e, "Deserialization of"); verifyException(e, "by passing existing Builder"); verifyException(e, "SimpleBuilderXY"); } } } BuilderWithCreatorTest.java000066400000000000000000000106721325620701100405060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/builderpackage com.fasterxml.jackson.databind.deser.builder; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class BuilderWithCreatorTest extends BaseMapTest { @JsonDeserialize(builder=PropertyCreatorBuilder.class) static class PropertyCreatorValue { final int a, b, c; protected PropertyCreatorValue(int a, int b, int c) { this.a = a; this.b = b; this.c = c; } } static class PropertyCreatorBuilder { private final int a, b; private int c; @JsonCreator public PropertyCreatorBuilder(@JsonProperty("a") int a, @JsonProperty("b") int b) { this.a = a; this.b = b; } public PropertyCreatorBuilder withC(int v) { c = v; return this; } public PropertyCreatorValue build() { return new PropertyCreatorValue(a, b, c); } } // With String @JsonDeserialize(builder=StringCreatorBuilder.class) static class StringCreatorValue { final String str; protected StringCreatorValue(String s) { str = s; } } static class StringCreatorBuilder { private final String v; @JsonCreator public StringCreatorBuilder(String str) { v = str; } public StringCreatorValue build() { return new StringCreatorValue(v); } } // With boolean @JsonDeserialize(builder=BooleanCreatorBuilder.class) static class BooleanCreatorValue { final boolean value; protected BooleanCreatorValue(boolean v) { value = v; } } static class BooleanCreatorBuilder { private final boolean value; @JsonCreator public BooleanCreatorBuilder(boolean v) { value = v; } public BooleanCreatorValue build() { return new BooleanCreatorValue(value); } } // With Int @JsonDeserialize(builder=IntCreatorBuilder.class) static class IntCreatorValue { final int value; protected IntCreatorValue(int v) { value = v; } } static class IntCreatorBuilder { private final int value; @JsonCreator public IntCreatorBuilder(int v) { value = v; } public IntCreatorValue build() { return new IntCreatorValue(value); } } // With Double @JsonDeserialize(builder=DoubleCreatorBuilder.class) static class DoubleCreatorValue { final double value; protected DoubleCreatorValue(double v) { value = v; } } static class DoubleCreatorBuilder { private final double value; @JsonCreator public DoubleCreatorBuilder(double v) { value = v; } public DoubleCreatorValue build() { return new DoubleCreatorValue(value); } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testWithPropertiesCreator() throws Exception { final String json = aposToQuotes("{'a':1,'c':3,'b':2}"); PropertyCreatorValue value = MAPPER.readValue(json, PropertyCreatorValue.class); assertEquals(1, value.a); assertEquals(2, value.b); assertEquals(3, value.c); } public void testWithDelegatingStringCreator() throws Exception { final int EXP = 139; IntCreatorValue value = MAPPER.readValue(String.valueOf(EXP), IntCreatorValue.class); assertEquals(EXP, value.value); } public void testWithDelegatingIntCreator() throws Exception { final double EXP = -3.75; DoubleCreatorValue value = MAPPER.readValue(String.valueOf(EXP), DoubleCreatorValue.class); assertEquals(EXP, value.value); } public void testWithDelegatingBooleanCreator() throws Exception { final boolean EXP = true; BooleanCreatorValue value = MAPPER.readValue(String.valueOf(EXP), BooleanCreatorValue.class); assertEquals(EXP, value.value); } } BuilderWithUnwrappedTest.java000066400000000000000000000172051325620701100410530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/builderpackage com.fasterxml.jackson.databind.deser.builder; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; public class BuilderWithUnwrappedTest extends BaseMapTest { final static class Name { private final String first; private final String last; @JsonCreator Name( @JsonProperty("first_name") String first, @JsonProperty("last_name") String last ) { this.first = first; this.last = last; } String getFirst() { return first; } String getLast() { return last; } } @JsonDeserialize(builder = Person.Builder.class) final static class Person { private final long id; private final Name name; private final int age; private final boolean alive; private Person(Builder builder) { id = builder.id; name = builder.name; age = builder.age; alive = builder.alive; } long getId() { return id; } Name getName() { return name; } int getAge() { return age; } boolean isAlive() { return alive; } @JsonPOJOBuilder(withPrefix = "set") final static class Builder { private final long id; private Name name; private int age; private boolean alive; Builder(@JsonProperty("person_id") long id) { this.id = id; } @JsonUnwrapped void setName(Name name) { this.name = name; } @JsonProperty("years_old") void setAge(int age) { this.age = age; } @JsonProperty("living") void setAlive(boolean alive) { this.alive = alive; } Person build() { return new Person(this); } } } @JsonDeserialize(builder = Animal.Builder.class) final static class Animal { private final long id; private final Name name; private final int age; private final boolean alive; private Animal(Builder builder) { id = builder.id; name = builder.name; age = builder.age; alive = builder.alive; } long getId() { return id; } Name getName() { return name; } int getAge() { return age; } boolean isAlive() { return alive; } @JsonPOJOBuilder(withPrefix = "set") final static class Builder { private final long id; private Name name; private int age; private final boolean alive; Builder( @JsonProperty("animal_id") long id, @JsonProperty("living") boolean alive ) { this.id = id; this.alive = alive; } @JsonUnwrapped void setName(Name name) { this.name = name; } @JsonProperty("years_old") void setAge(int age) { this.age = age; } Animal build() { return new Animal(this); } } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testWithUnwrappedAndCreatorSingleParameterAtBeginning() throws Exception { final String json = aposToQuotes("{'person_id':1234,'first_name':'John','last_name':'Doe','years_old':30,'living':true}"); final ObjectMapper mapper = new ObjectMapper(); Person person = mapper.readValue(json, Person.class); assertEquals(1234, person.getId()); assertNotNull(person.getName()); assertEquals("John", person.getName().getFirst()); assertEquals("Doe", person.getName().getLast()); assertEquals(30, person.getAge()); assertEquals(true, person.isAlive()); } public void testWithUnwrappedAndCreatorSingleParameterInMiddle() throws Exception { final String json = aposToQuotes("{'first_name':'John','last_name':'Doe','person_id':1234,'years_old':30,'living':true}"); final ObjectMapper mapper = new ObjectMapper(); Person person = mapper.readValue(json, Person.class); assertEquals(1234, person.getId()); assertNotNull(person.getName()); assertEquals("John", person.getName().getFirst()); assertEquals("Doe", person.getName().getLast()); assertEquals(30, person.getAge()); assertEquals(true, person.isAlive()); } public void testWithUnwrappedAndCreatorSingleParameterAtEnd() throws Exception { final String json = aposToQuotes("{'first_name':'John','last_name':'Doe','years_old':30,'living':true,'person_id':1234}"); final ObjectMapper mapper = new ObjectMapper(); Person person = mapper.readValue(json, Person.class); assertEquals(1234, person.getId()); assertNotNull(person.getName()); assertEquals("John", person.getName().getFirst()); assertEquals("Doe", person.getName().getLast()); assertEquals(30, person.getAge()); assertEquals(true, person.isAlive()); } public void testWithUnwrappedAndCreatorMultipleParametersAtBeginning() throws Exception { final String json = aposToQuotes("{'animal_id':1234,'living':true,'first_name':'John','last_name':'Doe','years_old':30}"); final ObjectMapper mapper = new ObjectMapper(); Animal animal = mapper.readValue(json, Animal.class); assertEquals(1234, animal.getId()); assertNotNull(animal.getName()); assertEquals("John", animal.getName().getFirst()); assertEquals("Doe", animal.getName().getLast()); assertEquals(30, animal.getAge()); assertEquals(true, animal.isAlive()); } public void testWithUnwrappedAndCreatorMultipleParametersInMiddle() throws Exception { final String json = aposToQuotes("{'first_name':'John','animal_id':1234,'last_name':'Doe','living':true,'years_old':30}"); final ObjectMapper mapper = new ObjectMapper(); Animal animal = mapper.readValue(json, Animal.class); assertEquals(1234, animal.getId()); assertNotNull(animal.getName()); assertEquals("John", animal.getName().getFirst()); assertEquals("Doe", animal.getName().getLast()); assertEquals(30, animal.getAge()); assertEquals(true, animal.isAlive()); } public void testWithUnwrappedAndCreatorMultipleParametersAtEnd() throws Exception { final String json = aposToQuotes("{'first_name':'John','last_name':'Doe','years_old':30,'living':true,'animal_id':1234}"); final ObjectMapper mapper = new ObjectMapper(); Animal animal = mapper.readValue(json, Animal.class); assertEquals(1234, animal.getId()); assertNotNull(animal.getName()); assertEquals("John", animal.getName().getFirst()); assertEquals("Doe", animal.getName().getLast()); assertEquals(30, animal.getAge()); assertEquals(true, animal.isAlive()); } } BuilderWithViewTest.java000066400000000000000000000060111325620701100400110ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/builderpackage com.fasterxml.jackson.databind.deser.builder; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class BuilderWithViewTest extends BaseMapTest { static class ViewX { } static class ViewY { } @JsonDeserialize(builder=SimpleBuilderXY.class) static class ValueClassXY { final int _x, _y; protected ValueClassXY(int x, int y) { _x = x+1; _y = y+1; } } static class SimpleBuilderXY { public int x, y; @JsonView(ViewX.class) public SimpleBuilderXY withX(int x0) { this.x = x0; return this; } @JsonView(ViewY.class) public SimpleBuilderXY withY(int y0) { this.y = y0; return this; } public ValueClassXY build() { return new ValueClassXY(x, y); } } @JsonDeserialize(builder=CreatorBuilderXY.class) static class CreatorValueXY { final int _x, _y; protected CreatorValueXY(int x, int y) { _x = x; _y = y; } } @JsonIgnoreProperties({ "bogus" }) static class CreatorBuilderXY { public int x, y; @JsonCreator public CreatorBuilderXY(@JsonProperty("x") @JsonView(ViewX.class) int x, @JsonProperty("y") @JsonView(ViewY.class) int y) { this.x = x; this.y = y; } public CreatorValueXY build() { return new CreatorValueXY(x, y); } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleViews() throws Exception { final String json = aposToQuotes("{'x':5,'y':10}"); ValueClassXY resultX = MAPPER.readerFor(ValueClassXY.class) .withView(ViewX.class) .readValue(json); assertEquals(6, resultX._x); assertEquals(1, resultX._y); ValueClassXY resultY = MAPPER.readerFor(ValueClassXY.class) .withView(ViewY.class) .readValue(json); assertEquals(1, resultY._x); assertEquals(11, resultY._y); } public void testCreatorViews() throws Exception { final String json = aposToQuotes("{'x':5,'y':10,'bogus':false}"); CreatorValueXY resultX = MAPPER.readerFor(CreatorValueXY.class) .withView(ViewX.class) .readValue(json); assertEquals(5, resultX._x); assertEquals(0, resultX._y); CreatorValueXY resultY = MAPPER.readerFor(CreatorValueXY.class) .withView(ViewY.class) .readValue(json); assertEquals(0, resultY._x); assertEquals(10, resultY._y); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creators/000077500000000000000000000000001325620701100335065ustar00rootroot00000000000000ArrayDelegatorCreatorForCollectionTest.java000066400000000000000000000021551325620701100440450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.util.Collections; import java.util.Set; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // for [databind#1392] (regression in 2.7 due to separation of array-delegating creator) public class ArrayDelegatorCreatorForCollectionTest extends BaseMapTest { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) abstract static class UnmodifiableSetMixin { @JsonCreator public UnmodifiableSetMixin(Set s) {} } public void testUnmodifiable() throws Exception { ObjectMapper mapper = new ObjectMapper(); Class unmodSetType = Collections.unmodifiableSet(Collections.emptySet()).getClass(); mapper.addMixIn(unmodSetType, UnmodifiableSetMixin.class); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); final String EXPECTED_JSON = "[\""+unmodSetType.getName()+"\",[]]"; Set foo = mapper.readValue(EXPECTED_JSON, Set.class); assertTrue(foo.isEmpty()); } } BigCreatorTest.java000066400000000000000000000056451325620701100371650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // Test(s) for "big" creators; ones with at least 32 arguments (sic!). // Needed because codepaths diverge wrt handling of bitset public class BigCreatorTest extends BaseMapTest { static class Biggie { final int[] stuff; @JsonCreator public Biggie( @JsonProperty("v1") int v1, @JsonProperty("v2") int v2, @JsonProperty("v3") int v3, @JsonProperty("v4") int v4, @JsonProperty("v5") int v5, @JsonProperty("v6") int v6, @JsonProperty("v7") int v7, @JsonProperty("v8") int v8, @JsonProperty("v9") int v9, @JsonProperty("v10") int v10, @JsonProperty("v11") int v11, @JsonProperty("v12") int v12, @JsonProperty("v13") int v13, @JsonProperty("v14") int v14, @JsonProperty("v15") int v15, @JsonProperty("v16") int v16, @JsonProperty("v17") int v17, @JsonProperty("v18") int v18, @JsonProperty("v19") int v19, @JsonProperty("v20") int v20, @JsonProperty("v21") int v21, @JsonProperty("v22") int v22, @JsonProperty("v23") int v23, @JsonProperty("v24") int v24, @JsonProperty("v25") int v25, @JsonProperty("v26") int v26, @JsonProperty("v27") int v27, @JsonProperty("v28") int v28, @JsonProperty("v29") int v29, @JsonProperty("v30") int v30, @JsonProperty("v31") int v31, @JsonProperty("v32") int v32, @JsonProperty("v33") int v33, @JsonProperty("v34") int v34, @JsonProperty("v35") int v35, @JsonProperty("v36") int v36, @JsonProperty("v37") int v37, @JsonProperty("v38") int v38, @JsonProperty("v39") int v39, @JsonProperty("v40") int v40 ) { stuff = new int[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, }; } } private final ObjectReader BIGGIE_READER = objectReader(Biggie.class); public void testBigPartial() throws Exception { Biggie value = BIGGIE_READER.readValue(aposToQuotes( "{'v7':7, 'v8':8,'v29':29, 'v35':35}" )); int[] stuff = value.stuff; for (int i = 0; i < stuff.length; ++i) { int exp; switch (i) { case 6: // These are off-by-one... case 7: case 28: case 34: exp = i+1; break; default: exp = 0; } assertEquals("Entry #"+i, exp, stuff[i]); } } } CreatorPropertiesTest.java000066400000000000000000000064231325620701100406130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.beans.ConstructorProperties; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class CreatorPropertiesTest extends BaseMapTest { static class Issue905Bean { // 08-Nov-2015, tatu: Note that in real code we would most likely use same // names for properties; but here we use different name on purpose to // ensure that Jackson has no way of binding JSON properties "x" and "y" // using any other mechanism than via `@ConstructorProperties` annotation public int _x, _y; @ConstructorProperties({"x", "y"}) // Same as above; use differing local parameter names so that parameter name // introspection cannot be used as the source of property names. public Issue905Bean(int a, int b) { _x = a; _y = b; } } // for [databind#1122] static class Ambiguity { @JsonProperty("bar") private int foo; protected Ambiguity() {} @ConstructorProperties({ "foo" }) public Ambiguity(int foo) { this.foo = foo; } public int getFoo() { return foo; } @Override public String toString() { return "Ambiguity [foo=" + foo + "]"; } } // for [databind#1371] static class Lombok1371Bean { public int x, y; protected Lombok1371Bean() { } @ConstructorProperties({ "x", "y" }) public Lombok1371Bean(int _x, int _y) { x = _x + 1; y = _y + 1; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); // [databind#905] public void testCreatorPropertiesAnnotation() throws Exception { Issue905Bean b = MAPPER.readValue(aposToQuotes("{'y':3,'x':2}"), Issue905Bean.class); assertEquals(2, b._x); assertEquals(3, b._y); } // [databind#1122] public void testPossibleNamingConflict() throws Exception { String json = "{\"bar\":3}"; Ambiguity amb = MAPPER.readValue(json, Ambiguity.class); assertNotNull(amb); assertEquals(3, amb.getFoo()); } // [databind#1371]: MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES public void testConstructorPropertiesInference() throws Exception { final String JSON = aposToQuotes("{'x':3,'y':5}"); // by default, should detect and use arguments-taking constructor as creator assertTrue(MAPPER.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)); Lombok1371Bean result = MAPPER.readValue(JSON, Lombok1371Bean.class); assertEquals(4, result.x); assertEquals(6, result.y); // but change if configuration changed ObjectMapper mapper = new ObjectMapper(); mapper.disable(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES); // in which case fields are set directly: result = mapper.readValue(JSON, Lombok1371Bean.class); assertEquals(3, result.x); assertEquals(5, result.y); } } CreatorWithObjectIdTest.java000066400000000000000000000024651325620701100410000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.beans.ConstructorProperties; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.*; // for [databind#1367] public class CreatorWithObjectIdTest extends BaseMapTest { @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") // resolver = SimpleObjectIdResolver.class) public static class A { String id; String name; public A() { } @ConstructorProperties({"id", "name"}) public A(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public void testObjectIdWithCreator() throws Exception { A a = new A("123", "A"); ObjectMapper om = new ObjectMapper(); String json = om.writeValueAsString(a); A deser = om.readValue(json, A.class); assertEquals(a.name, deser.name); } } DelegatingCreatorImplicitNames1001Test.java000066400000000000000000000057551325620701100435120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class DelegatingCreatorImplicitNames1001Test extends BaseMapTest { static class D { private String raw1 = ""; private String raw2 = ""; private D(String raw1, String raw2) { this.raw1 = raw1; this.raw2 = raw2; } // not needed strictly speaking, but added for good measure @JsonCreator public static D make(String value) { String[] split = value.split(":"); return new D(split[0], split[1]); } @JsonValue public String getMyValue() { return raw1 + ":" + raw2; } @Override public String toString() { return getMyValue(); } @Override public boolean equals(Object o) { D other = (D) o; return other.raw1.equals(raw1) && other.raw2.equals(raw2); } } // To test equivalent of parameter-names, let's use this one protected static class CreatorNameIntrospector extends JacksonAnnotationIntrospector { private static final long serialVersionUID = 1L; @Override public String findImplicitPropertyName(AnnotatedMember member) { if (member instanceof AnnotatedParameter) { AnnotatedParameter p = (AnnotatedParameter) member; AnnotatedWithParams owner = p.getOwner(); if (owner instanceof AnnotatedMethod) { if (p.getIndex() == 0) { return "value"; } } } return super.findImplicitPropertyName(member); } } // Baseline test to show how things should work public void testWithoutNamedParameters() throws Exception { ObjectMapper sut = new ObjectMapper(); D d = D.make("abc:def"); String actualJson = sut.writeValueAsString(d); D actualD = sut.readValue(actualJson, D.class); assertEquals("\"abc:def\"", actualJson); assertEquals(d, actualD); } // And then case that fails with [databind#1001] public void testWithNamedParameters() throws Exception { ObjectMapper sut = new ObjectMapper() .setAnnotationIntrospector(new CreatorNameIntrospector()); D d = D.make("abc:def"); String actualJson = sut.writeValueAsString(d); D actualD = sut.readValue(actualJson, D.class); assertEquals("\"abc:def\"", actualJson); assertEquals(d, actualD); } } DelegatingExternalProperty1003Test.java000066400000000000000000000027121325620701100427530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class DelegatingExternalProperty1003Test extends BaseMapTest { static class HeroBattle { private final Hero hero; private HeroBattle(Hero hero) { if (hero == null) throw new Error(); this.hero = hero; } @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "heroType") public Hero getHero() { return hero; } @JsonCreator static HeroBattle fromJson(Delegate json) { return new HeroBattle(json.hero); } } static class Delegate { @JsonProperty @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "heroType") public Hero hero; } public interface Hero { } static class Superman implements Hero { String name = "superman"; public String getName() { return name; } } public void testExtrnalPropertyDelegatingCreator() throws Exception { ObjectMapper mapper = new ObjectMapper(); final String json = mapper.writeValueAsString(new HeroBattle(new Superman())); final HeroBattle battle = mapper.readValue(json, HeroBattle.class); assertTrue(battle.getHero() instanceof Superman); } } DisablingCreatorsTest.java000066400000000000000000000037071325620701100405400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; /** * Tests to ensure one can disable {@link JsonCreator} annotations. */ public class DisablingCreatorsTest extends BaseMapTest { static class ConflictingCreators { @JsonCreator(mode=JsonCreator.Mode.PROPERTIES) public ConflictingCreators(@JsonProperty("foo") String foo) { } @JsonCreator(mode=JsonCreator.Mode.PROPERTIES) public ConflictingCreators(@JsonProperty("foo") String foo, @JsonProperty("value") int value) { } } static class NonConflictingCreators { public String _value; @JsonCreator(mode=JsonCreator.Mode.DELEGATING) public NonConflictingCreators(String foo) { _value = foo; } @JsonCreator(mode=JsonCreator.Mode.DISABLED) public NonConflictingCreators(String foo, int value) { } } /* /********************************************************** /* Helper methods /********************************************************** */ public void testDisabling() throws Exception { final ObjectMapper mapper = objectMapper(); // first, non-problematic case NonConflictingCreators value = mapper.readValue(quote("abc"), NonConflictingCreators.class); assertNotNull(value); assertEquals("abc", value._value); // then something that ought to fail try { /*ConflictingCreators value =*/ mapper.readValue(quote("abc"), ConflictingCreators.class); fail("Should have failed with JsonCreator conflict"); } catch (JsonProcessingException e) { verifyException(e, "Conflicting property-based creators"); } } } EnumCreatorTest.java000066400000000000000000000241431325620701100373620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.math.BigDecimal; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.Deserializers; import com.fasterxml.jackson.databind.deser.std.EnumDeserializer; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.module.SimpleModule; public class EnumCreatorTest extends BaseMapTest { protected enum EnumWithCreator { A, B; @JsonCreator public static EnumWithCreator fromEnum(String str) { if ("enumA".equals(str)) return A; if ("enumB".equals(str)) return B; return null; } } protected enum EnumWithBDCreator { E5, E8; @JsonCreator public static EnumWithBDCreator create(BigDecimal bd) { if (bd.longValue() == 5L) return E5; if (bd.longValue() == 8L) return E8; return null; } } protected enum TestEnumFromInt { ENUM_A(1), ENUM_B(2), ENUM_C(3); private final int id; private TestEnumFromInt(int id) { this.id = id; } @JsonCreator public static TestEnumFromInt fromId(int id) { for (TestEnumFromInt e: values()) { if (e.id == id) return e; } return null; } } static enum EnumWithPropertiesModeJsonCreator { TEST1, TEST2, TEST3; @JsonGetter("name") public String getName() { return name(); } @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) public static EnumWithPropertiesModeJsonCreator create(@JsonProperty("name") String name) { return EnumWithPropertiesModeJsonCreator.valueOf(name); } } static enum EnumWithDelegateModeJsonCreator { TEST1, TEST2, TEST3; @JsonGetter("name") public String getName() { return name(); } @JsonCreator(mode = JsonCreator.Mode.DELEGATING) public static EnumWithDelegateModeJsonCreator create(JsonNode json) { return EnumWithDelegateModeJsonCreator.valueOf(json.get("name").asText()); } } // [databind#324]: exception from creator method protected enum TestEnum324 { A, B; @JsonCreator public static TestEnum324 creator(String arg) { throw new RuntimeException("Foobar!"); } } // [databind#745] static class DelegatingDeserializers extends Deserializers.Base { @Override public JsonDeserializer findEnumDeserializer(final Class type, final DeserializationConfig config, final BeanDescription beanDesc) throws JsonMappingException { final Collection factoryMethods = beanDesc.getFactoryMethods(); if (factoryMethods != null) { for (AnnotatedMethod am : factoryMethods) { final JsonCreator creator = am.getAnnotation(JsonCreator.class); if (creator != null) { return EnumDeserializer.deserializerForCreator(config, type, am, null, null); } } } return null; } } // [databind#745] static class DelegatingDeserializersModule extends SimpleModule { private static final long serialVersionUID = 1L; @Override public void setupModule(final SetupContext context) { context.addDeserializers(new DelegatingDeserializers()); } } // [databind#929]: support multi-arg enum creator static enum Enum929 { A, B, C; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) static Enum929 forValues(@JsonProperty("id") int intProp, @JsonProperty("name") String name) { return Enum929.valueOf(name); } } static enum MyEnum960 { VALUE, BOGUS; @JsonCreator public static MyEnum960 getInstance() { return VALUE; } } static class MyEnum960Wrapper { public MyEnum960 value; } static enum Enum1291 { V1("val1"), V2("val2"), V3("val3"), V4("val4"), V5("val5"), V6("val6"); private final String name; Enum1291(String name) { this.name = name; } public static Enum1291 fromString(String name) { for (Enum1291 type : Enum1291.values()) { if (type.name.equals(name)) { return type; } } return Enum1291.valueOf(name.toUpperCase()); } @Override public String toString() { return name; } } /* /********************************************************** /* Test methods /********************************************************** */ protected final ObjectMapper MAPPER = new ObjectMapper(); public void testCreatorEnums() throws Exception { EnumWithCreator value = MAPPER.readValue("\"enumA\"", EnumWithCreator.class); assertEquals(EnumWithCreator.A, value); } public void testCreatorEnumsFromBigDecimal() throws Exception { EnumWithBDCreator value = MAPPER.readValue("\"8.0\"", EnumWithBDCreator.class); assertEquals(EnumWithBDCreator.E8, value); } public void testEnumWithCreatorEnumMaps() throws Exception { EnumMap value = MAPPER.readValue("{\"enumA\":\"value\"}", new TypeReference>() {}); assertEquals("value", value.get(EnumWithCreator.A)); } public void testEnumWithCreatorMaps() throws Exception { HashMap value = MAPPER.readValue("{\"enumA\":\"value\"}", new TypeReference>() {}); assertEquals("value", value.get(EnumWithCreator.A)); } public void testEnumWithCreatorEnumSets() throws Exception { EnumSet value = MAPPER.readValue("[\"enumA\"]", new TypeReference>() {}); assertTrue(value.contains(EnumWithCreator.A)); } public void testJsonCreatorPropertiesWithEnum() throws Exception { EnumWithPropertiesModeJsonCreator type1 = MAPPER.readValue("{\"name\":\"TEST1\", \"description\":\"TEST\"}", EnumWithPropertiesModeJsonCreator.class); assertSame(EnumWithPropertiesModeJsonCreator.TEST1, type1); EnumWithPropertiesModeJsonCreator type2 = MAPPER.readValue("{\"name\":\"TEST3\", \"description\":\"TEST\"}", EnumWithPropertiesModeJsonCreator.class); assertSame(EnumWithPropertiesModeJsonCreator.TEST3, type2); } public void testJsonCreatorDelagateWithEnum() throws Exception { final ObjectMapper mapper = new ObjectMapper(); EnumWithDelegateModeJsonCreator type1 = mapper.readValue("{\"name\":\"TEST1\", \"description\":\"TEST\"}", EnumWithDelegateModeJsonCreator.class); assertSame(EnumWithDelegateModeJsonCreator.TEST1, type1); EnumWithDelegateModeJsonCreator type2 = mapper.readValue("{\"name\":\"TEST3\", \"description\":\"TEST\"}", EnumWithDelegateModeJsonCreator.class); assertSame(EnumWithDelegateModeJsonCreator.TEST3, type2); } public void testEnumsFromInts() throws Exception { Object ob = MAPPER.readValue("1 ", TestEnumFromInt.class); assertEquals(TestEnumFromInt.class, ob.getClass()); assertSame(TestEnumFromInt.ENUM_A, ob); } // [databind#324] public void testExceptionFromCreator() throws Exception { try { /*TestEnum324 e =*/ MAPPER.readValue(quote("xyz"), TestEnum324.class); fail("Should throw exception"); } catch (JsonMappingException e) { verifyException(e, "foobar"); } } // [databind#745] public void testDeserializerForCreatorWithEnumMaps() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new DelegatingDeserializersModule()); EnumMap value = mapper.readValue("{\"enumA\":\"value\"}", new TypeReference>() {}); assertEquals("value", value.get(EnumWithCreator.A)); } // for [databind#929] public void testMultiArgEnumCreator() throws Exception { Enum929 v = MAPPER.readValue("{\"id\":3,\"name\":\"B\"}", Enum929.class); assertEquals(Enum929.B, v); } // for [databind#960] public void testNoArgEnumCreator() throws Exception { MyEnum960 v = MAPPER.readValue("{\"value\":\"bogus\"}", MyEnum960.class); assertEquals(MyEnum960.VALUE, v); } // for [databind#1291] public void testEnumCreators1291() throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(Enum1291.V2); Enum1291 result = mapper.readValue(json, Enum1291.class); assertSame(Enum1291.V2, result); } // for [databind#1389] public void testMultiArgEnumInCollections() throws Exception { EnumSet valueEnumSet = MAPPER.readValue("[{\"id\":3,\"name\":\"B\"}, {\"id\":3,\"name\":\"A\"}]", new TypeReference>() {}); assertEquals(2, valueEnumSet.size()); assertTrue(valueEnumSet.contains(Enum929.A)); assertTrue(valueEnumSet.contains(Enum929.B)); List valueList = MAPPER.readValue("[{\"id\":3,\"name\":\"B\"}, {\"id\":3,\"name\":\"A\"}, {\"id\":3,\"name\":\"B\"}]", new TypeReference>() {}); assertEquals(3, valueList.size()); assertEquals(Enum929.B, valueList.get(2)); } } FailOnNullCreatorTest.java000066400000000000000000000040501325620701100404540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; /** * Tests to ensure that deserialization fails when a bean property has a null value * Relates to issue #988 */ public class FailOnNullCreatorTest extends BaseMapTest { static class Person { String name; Integer age; @JsonCreator public Person(@JsonProperty(value="name") String name, @JsonProperty(value="age") int age) { this.name = name; this.age = age; } } private final ObjectReader POINT_READER = objectMapper().readerFor(Person.class); public void testRequiredNonNullParam() throws Exception { Person p; // First: fine if feature is not enabled p = POINT_READER.readValue(aposToQuotes("{}")); assertEquals(null, p.name); assertEquals(Integer.valueOf(0), p.age); // Second: fine if feature is enabled but default value is not null ObjectReader r = POINT_READER.with(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES); p = POINT_READER.readValue(aposToQuotes("{'name':'John', 'age': null}")); assertEquals("John", p.name); assertEquals(Integer.valueOf(0), p.age); // Third: throws exception if property is missing try { r.readValue(aposToQuotes("{}")); fail("Should not pass third test"); } catch (JsonMappingException e) { verifyException(e, "Null value for creator property 'name'"); } // Fourth: throws exception if property is set to null explicitly try { r.readValue(aposToQuotes("{'age': 5, 'name': null}")); fail("Should not pass fourth test"); } catch (JsonMappingException e) { verifyException(e, "Null value for creator property 'name'"); } } } ImplicitNameMatch792Test.java000066400000000000000000000075021325620701100407300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class ImplicitNameMatch792Test extends BaseMapTest { // Simple introspector that gives generated "ctorN" names for constructor // parameters static class ConstructorNameAI extends JacksonAnnotationIntrospector { private static final long serialVersionUID = 1L; @Override public String findImplicitPropertyName(AnnotatedMember member) { if (member instanceof AnnotatedParameter) { return String.format("ctor%d", ((AnnotatedParameter) member).getIndex()); } return super.findImplicitPropertyName(member); } } @JsonPropertyOrder({ "first" ,"second", "other" }) static class Issue792Bean { String value; public Issue792Bean(@JsonProperty("first") String a, @JsonProperty("second") String b) { value = a; // ignore second arg } public String getCtor0() { return value; } public int getOther() { return 3; } } static class Bean2 { int x = 3; @JsonProperty("stuff") private void setValue(int i) { x = i; } public int getValue() { return x; } } static class ReadWriteBean { private int value; private ReadWriteBean(@JsonProperty(value="value", access=JsonProperty.Access.READ_WRITE) int v) { value = v; } public int testValue() { return value; } // Let's also add setter to ensure conflict resolution works public void setValue(int v) { throw new RuntimeException("Should have used constructor for 'value' not setter"); } } // Bean that should only serialize 'value', but deserialize both static class PasswordBean { @JsonProperty(access=JsonProperty.Access.WRITE_ONLY) private String password; private int value; public int getValue() { return value; } public String getPassword() { return password; } public String asString() { return String.format("[password='%s',value=%d]", password, value); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testBindingOfImplicitCreatorNames() throws Exception { ObjectMapper m = new ObjectMapper(); m.setAnnotationIntrospector(new ConstructorNameAI()); String json = m.writeValueAsString(new Issue792Bean("a", "b")); assertEquals(aposToQuotes("{'first':'a','other':3}"), json); } public void testImplicitWithSetterGetter() throws Exception { String json = MAPPER.writeValueAsString(new Bean2()); assertEquals(aposToQuotes("{'stuff':3}"), json); } public void testReadWriteWithPrivateField() throws Exception { String json = MAPPER.writeValueAsString(new ReadWriteBean(3)); assertEquals("{\"value\":3}", json); } public void testWriteOnly() throws Exception { PasswordBean bean = MAPPER.readValue(aposToQuotes("{'value':7,'password':'foo'}"), PasswordBean.class); assertEquals("[password='foo',value=7]", bean.asString()); String json = MAPPER.writeValueAsString(bean); assertEquals("{\"value\":7}", json); } } ImplicitParamsForCreatorTest.java000066400000000000000000000032341325620701100420410ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class ImplicitParamsForCreatorTest extends BaseMapTest { @SuppressWarnings("serial") static class MyParamIntrospector extends JacksonAnnotationIntrospector { @Override public String findImplicitPropertyName(AnnotatedMember param) { if (param instanceof AnnotatedParameter) { AnnotatedParameter ap = (AnnotatedParameter) param; return "paramName"+ap.getIndex(); } return super.findImplicitPropertyName(param); } } static class XY { protected int x, y; // annotation should NOT be needed with 2.6 any more (except for single-arg case) //@com.fasterxml.jackson.annotation.JsonCreator public XY(int x, int y) { this.x = x; this.y = y; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testNonSingleArgCreator() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new MyParamIntrospector()); XY value = mapper.readValue(aposToQuotes("{'paramName0':1,'paramName1':2}"), XY.class); assertNotNull(value); assertEquals(1, value.x); assertEquals(2, value.y); } } InnerClassCreatorTest.java000066400000000000000000000057421325620701100405230ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; // For [databind#1501], [databind#1502], [databind#1503]; mostly to // test that for non-static inner classes constructors are ignored // and no Creators should be processed (since they cannot be made // to work in standard way anyway). public class InnerClassCreatorTest extends BaseMapTest { static class Something1501 { public InnerSomething1501 a; // important: must name the parameter (param names module, or explicit) @JsonCreator public Something1501(@JsonProperty("a") InnerSomething1501 a) { this.a = a; } public Something1501(boolean bogus) { a = new InnerSomething1501(); } class InnerSomething1501 { @JsonCreator public InnerSomething1501() { } } } static class Something1502 { @JsonProperty public InnerSomething1502 a; @JsonCreator public Something1502(InnerSomething1502 a) {} class InnerSomething1502 { @JsonCreator public InnerSomething1502() {} } } static class Outer1503 { public InnerClass1503 innerClass; class InnerClass1503 { public Generic generic; public InnerClass1503(@JsonProperty("generic") Generic generic) {} } static class Generic { public int ignored; } } private final ObjectMapper MAPPER = new ObjectMapper(); { MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); } // Used to trigger `ArrayIndexOutOfBoundsException` for missing creator property index public void testIssue1501() throws Exception { String ser = MAPPER.writeValueAsString(new Something1501(false)); try { MAPPER.readValue(ser, Something1501.class); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot construct instance"); verifyException(e, "InnerSomething1501"); verifyException(e, "can only instantiate non-static inner class by using default"); } } public void testIssue1502() throws Exception { String ser = MAPPER.writeValueAsString(new Something1502(null)); try { MAPPER.readValue(ser, Something1502.class); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot construct instance"); verifyException(e, "InnerSomething1502"); verifyException(e, "can only instantiate non-static inner class by using default"); } } public void testIssue1503() throws Exception { String ser = MAPPER.writeValueAsString(new Outer1503()); Outer1503 result = MAPPER.readValue(ser, Outer1503.class); assertNotNull(result); } } MultiArgConstructorTest.java000066400000000000000000000073161325620701100411330ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class MultiArgConstructorTest extends BaseMapTest { static class MultiArgCtorBean { protected int _a, _b; public int c; public MultiArgCtorBean(int a, int b) { _a = a; _b = b; } } static class MultiArgCtorBeanWithAnnotations { protected int _a, _b; public int c; public MultiArgCtorBeanWithAnnotations(int a, @JsonProperty("b2") int b) { _a = a; _b = b; } } /* Before JDK8, we won't have parameter names available, so let's * fake it before that... */ @SuppressWarnings("serial") static class MyParamIntrospector extends JacksonAnnotationIntrospector { @Override public String findImplicitPropertyName(AnnotatedMember param) { if (param instanceof AnnotatedParameter) { AnnotatedParameter ap = (AnnotatedParameter) param; switch (ap.getIndex()) { case 0: return "a"; case 1: return "b"; default: return "param"+ap.getIndex(); } } return super.findImplicitPropertyName(param); } } /* /********************************************************************** /* Test methods /********************************************************************** */ public void testMultiArgVisible() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new MyParamIntrospector()); MultiArgCtorBean bean = mapper.readValue(aposToQuotes("{'b':13, 'c':2, 'a':-99}"), MultiArgCtorBean.class); assertNotNull(bean); assertEquals(13, bean._b); assertEquals(-99, bean._a); assertEquals(2, bean.c); } // But besides visibility, also allow overrides public void testMultiArgWithPartialOverride() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new MyParamIntrospector()); MultiArgCtorBeanWithAnnotations bean = mapper.readValue(aposToQuotes("{'b2':7, 'c':222, 'a':-99}"), MultiArgCtorBeanWithAnnotations.class); assertNotNull(bean); assertEquals(7, bean._b); assertEquals(-99, bean._a); assertEquals(222, bean.c); } // but let's also ensure that it is possible to prevent use of that constructor // with different visibility public void testMultiArgNotVisible() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new MyParamIntrospector()); mapper.setDefaultVisibility( JsonAutoDetect.Value.noOverrides() .withCreatorVisibility(Visibility.NONE)); try { /*MultiArgCtorBean bean =*/ mapper.readValue(aposToQuotes("{'b':13, 'a':-99}"), MultiArgCtorBean.class); fail("Should not have passed"); } catch (InvalidDefinitionException e) { verifyException(e, "no Creators"); } } } RequiredCreatorTest.java000066400000000000000000000040471325620701100402370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class RequiredCreatorTest extends BaseMapTest { static class FascistPoint { int x, y; @JsonCreator public FascistPoint(@JsonProperty(value="x", required=true) int x, @JsonProperty(value="y", required=false) int y) { this.x = x; this.y = y; } } private final ObjectReader POINT_READER = objectMapper().readerFor(FascistPoint.class); public void testRequiredAnnotatedParam() throws Exception { FascistPoint p; // First: fine if both params passed p = POINT_READER.readValue(aposToQuotes("{'y':2,'x':1}")); assertEquals(1, p.x); assertEquals(2, p.y); p = POINT_READER.readValue(aposToQuotes("{'x':3,'y':4}")); assertEquals(3, p.x); assertEquals(4, p.y); // also fine if 'y' is MIA p = POINT_READER.readValue(aposToQuotes("{'x':3}")); assertEquals(3, p.x); assertEquals(0, p.y); // but not so good if 'x' missing try { POINT_READER.readValue(aposToQuotes("{'y':3}")); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Missing required creator property 'x' (index 0)"); } } public void testRequiredGloballyParam() throws Exception { FascistPoint p; // as per above, ok to miss 'y' with default settings: p = POINT_READER.readValue(aposToQuotes("{'x':2}")); assertEquals(2, p.x); assertEquals(0, p.y); // but not if global checks desired ObjectReader r = POINT_READER.with(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES); try { r.readValue(aposToQuotes("{'x':6}")); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Missing creator property 'y' (index 1)"); } } } SingleArgCreatorTest.java000066400000000000000000000142331325620701100403300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class SingleArgCreatorTest extends BaseMapTest { // [databind#430]: single arg BUT named; should not delegate static class SingleNamedStringBean { final String _ss; @JsonCreator public SingleNamedStringBean(@JsonProperty("") String ss){ this._ss = ss; } public String getSs() { return _ss; } } // For [databind#614] static class SingleNamedButStillDelegating { protected final String value; @JsonCreator(mode=JsonCreator.Mode.DELEGATING) public SingleNamedButStillDelegating(@JsonProperty("foobar") String v){ value = v; } public String getFoobar() { return "x"; } } // [databind#557] static class StringyBean { public final String value; private StringyBean(String value) { this.value = value; } public String getValue() { return value; } } static class StringyBeanWithProps { public final String value; @JsonCreator private StringyBeanWithProps(String v) { value = v; } public String getValue() { return value; } } @SuppressWarnings("serial") static class MyParamIntrospector extends JacksonAnnotationIntrospector { private final String name; public MyParamIntrospector(String n) { name = n; } @Override public String findImplicitPropertyName(AnnotatedMember param) { if (param instanceof AnnotatedParameter) { AnnotatedParameter ap = (AnnotatedParameter) param; switch (ap.getIndex()) { case 0: return name; } return "param"+ap.getIndex(); } return super.findImplicitPropertyName(param); } } // [databind#660] static class ExplicitFactoryBeanA { private String value; private ExplicitFactoryBeanA(String str) { throw new IllegalStateException("Should not get called!"); } private ExplicitFactoryBeanA(String str, boolean b) { value = str; } @JsonCreator public static ExplicitFactoryBeanA create(String str) { ExplicitFactoryBeanA bean = new ExplicitFactoryBeanA(str, false); bean.value = str; return bean; } public String value() { return value; } } // [databind#660] static class ExplicitFactoryBeanB { private String value; @JsonCreator private ExplicitFactoryBeanB(String str) { value = str; } public static ExplicitFactoryBeanB valueOf(String str) { return new ExplicitFactoryBeanB(null); } public String value() { return value; } } static class XY { public int x, y; } // [databind#1383] static class SingleArgWithImplicit { protected XY _value; private SingleArgWithImplicit() { throw new Error("Should not get called"); } private SingleArgWithImplicit(XY v, boolean bogus) { _value = v; } @JsonCreator public static SingleArgWithImplicit from(XY v) { return new SingleArgWithImplicit(v, true); } public XY getFoobar() { return _value; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testNamedSingleArg() throws Exception { SingleNamedStringBean bean = MAPPER.readValue(quote("foobar"), SingleNamedStringBean.class); assertEquals("foobar", bean._ss); } public void testSingleStringArgWithImplicitName() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new MyParamIntrospector("value")); StringyBean bean = mapper.readValue(quote("foobar"), StringyBean.class); assertEquals("foobar", bean.getValue()); } // [databind#714] public void testSingleImplicitlyNamedNotDelegating() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new MyParamIntrospector("value")); StringyBeanWithProps bean = mapper.readValue("{\"value\":\"x\"}", StringyBeanWithProps.class); assertEquals("x", bean.getValue()); } // [databind#714] public void testSingleExplicitlyNamedButDelegating() throws Exception { SingleNamedButStillDelegating bean = MAPPER.readValue(quote("xyz"), SingleNamedButStillDelegating.class); assertEquals("xyz", bean.value); } public void testExplicitFactory660a() throws Exception { // First, explicit override for factory ExplicitFactoryBeanA bean = MAPPER.readValue(quote("abc"), ExplicitFactoryBeanA.class); assertNotNull(bean); assertEquals("abc", bean.value()); } public void testExplicitFactory660b() throws Exception { // and then one for private constructor ExplicitFactoryBeanB bean2 = MAPPER.readValue(quote("def"), ExplicitFactoryBeanB.class); assertNotNull(bean2); assertEquals("def", bean2.value()); } // [databind#1383] public void testSingleImplicitDelegating() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new MyParamIntrospector("value")); SingleArgWithImplicit bean = mapper.readValue(aposToQuotes("{'x':1,'y':2}"), SingleArgWithImplicit.class); XY v = bean.getFoobar(); assertNotNull(v); assertEquals(1, v.x); assertEquals(2, v.y); } } TestConstructFromMap.java000066400000000000000000000050061325620701100404010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.math.BigDecimal; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * This unit test suite that tests use of {@link JsonCreator} * with "delegate" constructors and factory methods: ones that * take a deserializable type that is bound from JSON content. * This is usually done to get two-phase data binding, often using * {@link java.util.Map} as the intermediate form. */ public class TestConstructFromMap extends BaseMapTest { static class ConstructorFromMap { int _x; String _y; @JsonCreator ConstructorFromMap(Map arg) { _x = ((Number) arg.get("x")).intValue(); _y = (String) arg.get("y"); } } static class FactoryFromPoint { int _x, _y; private FactoryFromPoint(Point p) { _x = p.x; _y = p.y; } @JsonCreator static FactoryFromPoint createIt(Point p) { return new FactoryFromPoint(p); } } // Also: let's test BigDecimal-from-JSON-String factory static class FactoryFromDecimalString { int _value; private FactoryFromDecimalString(BigDecimal d) { _value = d.intValue(); } @JsonCreator static FactoryFromDecimalString whateverNameWontMatter(BigDecimal d) { return new FactoryFromDecimalString(d); } } /* /********************************************************** /* Test methods /********************************************************** */ public void testViaConstructor() throws Exception { ObjectMapper m = new ObjectMapper(); ConstructorFromMap result = m.readValue ("{ \"x\":1, \"y\" : \"abc\" }", ConstructorFromMap.class); assertEquals(1, result._x); assertEquals("abc", result._y); } public void testViaFactory() throws Exception { ObjectMapper m = new ObjectMapper(); FactoryFromPoint result = m.readValue("{ \"x\" : 3, \"y\" : 4 }", FactoryFromPoint.class); assertEquals(3, result._x); assertEquals(4, result._y); } public void testViaFactoryUsingString() throws Exception { ObjectMapper m = new ObjectMapper(); FactoryFromDecimalString result = m.readValue("\"12.57\"", FactoryFromDecimalString.class); assertNotNull(result); assertEquals(12, result._value); } } TestCreatorNullValue.java000066400000000000000000000071401325620701100403630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.io.IOException; import java.util.UUID; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.*; public class TestCreatorNullValue extends BaseMapTest { protected static class Container { Contained contained; @JsonCreator public Container(@JsonProperty("contained") Contained contained) { this.contained = contained; } } protected static interface Contained {} protected static class NullContained implements Contained {} protected static final NullContained NULL_CONTAINED = new NullContained(); protected static class ContainedDeserializer extends JsonDeserializer> { @Override public Contained deserialize(JsonParser jp, DeserializationContext ctxt) throws JsonProcessingException { return null; } @Override public Contained getNullValue(DeserializationContext ctxt) { return NULL_CONTAINED; } } protected static class ContainerDeserializerResolver extends Deserializers.Base { @Override public JsonDeserializer findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { if (!Contained.class.isAssignableFrom(type.getRawClass())) { return null; } return new ContainedDeserializer(); } } protected static class TestModule extends com.fasterxml.jackson.databind.Module { @Override public String getModuleName() { return "ContainedModule"; } @Override public Version version() { return Version.unknownVersion(); } @Override public void setupModule(SetupContext setupContext) { setupContext.addDeserializers(new ContainerDeserializerResolver()); } } // [databind#597] static class JsonEntity { protected final String type; protected final UUID id; private JsonEntity(String type, UUID id) { this.type = type; this.id = id; } @JsonCreator public static JsonEntity create(@JsonProperty("type") String type, @JsonProperty("id") UUID id) { if (type != null && !type.contains(" ") && (id != null)) { return new JsonEntity(type, id); } return null; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testUsesDeserializersNullValue() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new TestModule()); Container container = mapper.readValue("{}", Container.class); assertEquals(NULL_CONTAINED, container.contained); } // [databind#597]: ensure that a useful exception is thrown public void testCreatorReturningNull() throws IOException { ObjectMapper objectMapper = new ObjectMapper(); String json = "{ \"type\" : \" \", \"id\" : \"000c0ffb-a0d6-4d2e-a379-4aeaaf283599\" }"; try { objectMapper.readValue(json, JsonEntity.class); fail("Should not have succeeded"); } catch (JsonMappingException e) { verifyException(e, "JSON creator returned null"); } } } TestCreatorWithNamingStrategy556.java000066400000000000000000000051111325620701100425000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class TestCreatorWithNamingStrategy556 extends BaseMapTest { static class RenamingCtorBean { protected String myName; protected int myAge; @JsonCreator public RenamingCtorBean(int myAge, String myName) { this.myName = myName; this.myAge = myAge; } } // Try the same with factory, too static class RenamedFactoryBean { protected String myName; protected int myAge; private RenamedFactoryBean(int a, String n, boolean foo) { myAge = a; myName = n; } @JsonCreator public static RenamedFactoryBean create(int age, String name) { return new RenamedFactoryBean(age, name, true); } } @SuppressWarnings("serial") static class MyParamIntrospector extends JacksonAnnotationIntrospector { @Override public String findImplicitPropertyName(AnnotatedMember param) { if (param instanceof AnnotatedParameter) { AnnotatedParameter ap = (AnnotatedParameter) param; switch (ap.getIndex()) { case 0: return "myAge"; case 1: return "myName"; default: return "param"+ap.getIndex(); } } return super.findImplicitPropertyName(param); } } private final ObjectMapper MAPPER = new ObjectMapper() .setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE) ; { MAPPER.setAnnotationIntrospector(new MyParamIntrospector()); } private final static String CTOR_JSON = aposToQuotes("{ 'MyAge' : 42, 'MyName' : 'NotMyRealName' }"); public void testRenameViaCtor() throws Exception { RenamingCtorBean bean = MAPPER.readValue(CTOR_JSON, RenamingCtorBean.class); assertEquals(42, bean.myAge); assertEquals("NotMyRealName", bean.myName); } public void testRenameViaFactory() throws Exception { RenamedFactoryBean bean = MAPPER.readValue(CTOR_JSON, RenamedFactoryBean.class); assertEquals(42, bean.myAge); assertEquals("NotMyRealName", bean.myName); } }TestCreatorWithPolymorphic113.java000066400000000000000000000033351325620701100420440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Test(s) for [Issue#113], problems with polymorphic types, JsonCreator. */ public class TestCreatorWithPolymorphic113 extends BaseMapTest { @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "_class") @JsonSubTypes({ @JsonSubTypes.Type(Dog.class) }) public static abstract class Animal { public final static String ID = "id"; private String id; @JsonCreator public Animal(@JsonProperty(ID) String id) { this.id = id; } @JsonProperty(ID) public String getId() { return id; } } @JsonIgnoreProperties(ignoreUnknown = true) public static class Dog extends Animal { @JsonCreator public Dog(@JsonProperty(ID) String id) { super(id); } } @JsonIgnoreProperties(ignoreUnknown = true) public static class AnimalWrapper { private Animal animal; @JsonCreator public AnimalWrapper(@JsonProperty("animal") Animal animal) { this.animal = animal; } public Animal getAnimal() { return animal; } } public void testSubtypes() throws Exception { ObjectMapper mapper = new ObjectMapper(); String id = "nice dogy"; String json = mapper.writeValueAsString(new AnimalWrapper(new Dog(id))); //System.err.println("JSON = "+json); AnimalWrapper wrapper = mapper.readValue(json, AnimalWrapper.class); assertEquals(id, wrapper.getAnimal().getId()); } } TestCreators.java000066400000000000000000000355671325620701100367340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; /** * Unit tests for verifying that it is possible to annotate * various kinds of things with {@link JsonCreator} annotation. */ public class TestCreators extends BaseMapTest { /* /********************************************************** /* Annotated helper classes, simple /********************************************************** */ /** * Simple(st) possible demonstration of using annotated * constructors */ static class ConstructorBean { int x; @JsonCreator protected ConstructorBean(@JsonProperty("x") int x) { this.x = x; } } /** * Another simple constructor, but with bit more unusual argument * type */ static class BooleanConstructorBean { Boolean b; protected BooleanConstructorBean(Boolean b) { this.b = b; } } static class BooleanConstructorBean2 { boolean b; protected BooleanConstructorBean2(boolean b) { this.b = b; } } static class DoubleConstructorBean { Double d; // cup? @JsonCreator protected DoubleConstructorBean(Double d) { this.d = d; } } static class FactoryBean { double d; // teehee private FactoryBean(double value, boolean dummy) { d = value; } @JsonCreator protected static FactoryBean createIt(@JsonProperty("f") double value) { return new FactoryBean(value, true); } } static class LongFactoryBean { long value; private LongFactoryBean(long v) { value = v; } @JsonCreator static protected LongFactoryBean valueOf(long v) { return new LongFactoryBean(v); } } static class StringFactoryBean { String value; private StringFactoryBean(String v, boolean dummy) { value = v; } @JsonCreator static protected StringFactoryBean valueOf(String v) { return new StringFactoryBean(v, true); } } static class FactoryBeanMixIn { // static just to be able to use static methods /** * Note: signature (name and parameter types) must match; but * only annotations will be used, not code or such. And use * is by augmentation, so we only need to add things to add * or override. */ static FactoryBean createIt(@JsonProperty("mixed") double xyz) { return null; } } /** * Simple demonstration of INVALID construtor annotation (only * defining name for first arg) */ static class BrokenBean { @JsonCreator protected BrokenBean(@JsonProperty("a") int a, int b) { } } /** * Bean that defines both creator and factory methor as * creators. Constructors have priority; but it is possible * to hide it using mix-in annotations. */ static class CreatorBean { String a; int x; @JsonCreator protected CreatorBean(@JsonProperty("a") String paramA, @JsonProperty("x") int paramX) { a = "ctor:"+paramA; x = 1+paramX; } private CreatorBean(String a, int x, boolean dummy) { this.a = a; this.x = x; } @JsonCreator public static CreatorBean buildMeUpButterCup(@JsonProperty("a") String paramA, @JsonProperty("x") int paramX) { return new CreatorBean("factory:"+paramA, paramX-1, false); } } /** * Class for sole purpose of hosting mix-in annotations. * Couple of things to note: (a) MUST be static class (non-static * get implicit pseudo-arg, 'this'; * (b) for factory methods, must have static to match (part of signature) */ abstract static class MixIn { @JsonIgnore private MixIn(String a, int x) { } } static class MultiBean { Object value; @JsonCreator public MultiBean(int v) { value = v; } @JsonCreator public MultiBean(double v) { value = v; } @JsonCreator public MultiBean(String v) { value = v; } @JsonCreator public MultiBean(boolean v) { value = v; } } // for [JACKSON-850] static class NoArgFactoryBean { public int x; public int y; public NoArgFactoryBean(int value) { x = value; } @JsonCreator public static NoArgFactoryBean create() { return new NoArgFactoryBean(123); } } // [Issue#208] static class FromStringBean { protected String value; private FromStringBean(String s, boolean x) { value = s; } // should be recognized as implicit factory method public static FromStringBean fromString(String s) { return new FromStringBean(s, false); } } /* /********************************************************** /* Annotated helper classes, mixed (creator and props) /********************************************************** */ /** * Test bean for ensuring that constructors can be mixed with setters */ static class ConstructorAndPropsBean { final int a, b; boolean c; @JsonCreator protected ConstructorAndPropsBean(@JsonProperty("a") int a, @JsonProperty("b") int b) { this.a = a; this.b = b; } public void setC(boolean value) { c = value; } } /** * Test bean for ensuring that factory methods can be mixed with setters */ static class FactoryAndPropsBean { boolean[] arg1; int arg2, arg3; @JsonCreator protected FactoryAndPropsBean(@JsonProperty("a") boolean[] arg) { arg1 = arg; } public void setB(int value) { arg2 = value; } public void setC(int value) { arg3 = value; } } static class DeferredConstructorAndPropsBean { final int[] createA; String propA = "xyz"; String propB; @JsonCreator public DeferredConstructorAndPropsBean(@JsonProperty("createA") int[] a) { createA = a; } public void setPropA(String a) { propA = a; } public void setPropB(String b) { propB = b; } } static class DeferredFactoryAndPropsBean { String prop, ctor; @JsonCreator DeferredFactoryAndPropsBean(@JsonProperty("ctor") String str) { ctor = str; } public void setProp(String str) { prop = str; } } /* /********************************************************** /* Annotated helper classes for Maps /********************************************************** */ @SuppressWarnings("serial") static class MapWithCtor extends HashMap { final int _number; String _text = "initial"; MapWithCtor() { this(-1, "default"); } @JsonCreator public MapWithCtor(@JsonProperty("number") int nr, @JsonProperty("text") String t) { _number = nr; _text = t; } } @SuppressWarnings("serial") static class MapWithFactory extends TreeMap { Boolean _b; private MapWithFactory(Boolean b) { _b = b; } @JsonCreator static MapWithFactory createIt(@JsonProperty("b") Boolean b) { return new MapWithFactory(b); } } /* /********************************************************** /* Test methods, valid cases, non-deferred, no-mixins /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleConstructor() throws Exception { ConstructorBean bean = MAPPER.readValue("{ \"x\" : 42 }", ConstructorBean.class); assertEquals(42, bean.x); } // [JACKSON-850] public void testNoArgsFactory() throws Exception { NoArgFactoryBean value = MAPPER.readValue("{\"y\":13}", NoArgFactoryBean.class); assertEquals(13, value.y); assertEquals(123, value.x); } public void testSimpleDoubleConstructor() throws Exception { Double exp = new Double("0.25"); DoubleConstructorBean bean = MAPPER.readValue(exp.toString(), DoubleConstructorBean.class); assertEquals(exp, bean.d); } public void testSimpleBooleanConstructor() throws Exception { BooleanConstructorBean bean = MAPPER.readValue(" true ", BooleanConstructorBean.class); assertEquals(Boolean.TRUE, bean.b); BooleanConstructorBean2 bean2 = MAPPER.readValue(" true ", BooleanConstructorBean2.class); assertTrue(bean2.b); } public void testSimpleFactory() throws Exception { FactoryBean bean = MAPPER.readValue("{ \"f\" : 0.25 }", FactoryBean.class); assertEquals(0.25, bean.d); } public void testLongFactory() throws Exception { long VALUE = 123456789000L; LongFactoryBean bean = MAPPER.readValue(String.valueOf(VALUE), LongFactoryBean.class); assertEquals(VALUE, bean.value); } public void testStringFactory() throws Exception { String str = "abc"; StringFactoryBean bean = MAPPER.readValue(quote(str), StringFactoryBean.class); assertEquals(str, bean.value); } public void testStringFactoryAlt() throws Exception { String str = "xyz"; FromStringBean bean = MAPPER.readValue(quote(str), FromStringBean.class); assertEquals(str, bean.value); } public void testConstructorCreator() throws Exception { CreatorBean bean = MAPPER.readValue ("{ \"a\" : \"xyz\", \"x\" : 12 }", CreatorBean.class); assertEquals(13, bean.x); assertEquals("ctor:xyz", bean.a); } public void testConstructorAndProps() throws Exception { ConstructorAndPropsBean bean = MAPPER.readValue ("{ \"a\" : \"1\", \"b\": 2, \"c\" : true }", ConstructorAndPropsBean.class); assertEquals(1, bean.a); assertEquals(2, bean.b); assertEquals(true, bean.c); } public void testFactoryAndProps() throws Exception { FactoryAndPropsBean bean = MAPPER.readValue ("{ \"a\" : [ false, true, false ], \"b\": 2, \"c\" : -1 }", FactoryAndPropsBean.class); assertEquals(2, bean.arg2); assertEquals(-1, bean.arg3); boolean[] arg1 = bean.arg1; assertNotNull(arg1); assertEquals(3, arg1.length); assertFalse(arg1[0]); assertTrue(arg1[1]); assertFalse(arg1[2]); } /** * Test to verify that multiple creators may co-exist, iff * they use different JSON type as input */ public void testMultipleCreators() throws Exception { MultiBean bean = MAPPER.readValue("123", MultiBean.class); assertEquals(Integer.valueOf(123), bean.value); bean = MAPPER.readValue(quote("abc"), MultiBean.class); assertEquals("abc", bean.value); bean = MAPPER.readValue("0.25", MultiBean.class); assertEquals(Double.valueOf(0.25), bean.value); } /* /********************************************************** /* Test methods, valid cases, deferred, no mixins /********************************************************** */ public void testDeferredConstructorAndProps() throws Exception { DeferredConstructorAndPropsBean bean = MAPPER.readValue ("{ \"propB\" : \"...\", \"createA\" : [ 1 ], \"propA\" : null }", DeferredConstructorAndPropsBean.class); assertEquals("...", bean.propB); assertNull(bean.propA); assertNotNull(bean.createA); assertEquals(1, bean.createA.length); assertEquals(1, bean.createA[0]); } public void testDeferredFactoryAndProps() throws Exception { DeferredFactoryAndPropsBean bean = MAPPER.readValue ("{ \"prop\" : \"1\", \"ctor\" : \"2\" }", DeferredFactoryAndPropsBean.class); assertEquals("1", bean.prop); assertEquals("2", bean.ctor); } /* /********************************************************** /* Test methods, valid cases, mixins /********************************************************** */ public void testFactoryCreatorWithMixin() throws Exception { ObjectMapper m = new ObjectMapper(); m.addMixIn(CreatorBean.class, MixIn.class); CreatorBean bean = m.readValue ("{ \"a\" : \"xyz\", \"x\" : 12 }", CreatorBean.class); assertEquals(11, bean.x); assertEquals("factory:xyz", bean.a); } public void testFactoryCreatorWithRenamingMixin() throws Exception { ObjectMapper m = new ObjectMapper(); m.addMixIn(FactoryBean.class, FactoryBeanMixIn.class); // override changes property name from "f" to "mixed" FactoryBean bean = m.readValue("{ \"mixed\" : 20.5 }", FactoryBean.class); assertEquals(20.5, bean.d); } /* /********************************************************** /* Test methods, valid cases, Map with creator /* (to test [JACKSON-153]) /********************************************************** */ public void testMapWithConstructor() throws Exception { MapWithCtor result = MAPPER.readValue ("{\"text\":\"abc\", \"entry\":true, \"number\":123, \"xy\":\"yx\"}", MapWithCtor.class); // regular Map entries: assertEquals(Boolean.TRUE, result.get("entry")); assertEquals("yx", result.get("xy")); assertEquals(2, result.size()); // then ones passed via constructor assertEquals("abc", result._text); assertEquals(123, result._number); } public void testMapWithFactory() throws Exception { MapWithFactory result = MAPPER.readValue ("{\"x\":\"...\",\"b\":true }", MapWithFactory.class); assertEquals("...", result.get("x")); assertEquals(1, result.size()); assertEquals(Boolean.TRUE, result._b); } /* /********************************************************** /* Test methods, invalid/broken cases /********************************************************** */ public void testBrokenConstructor() throws Exception { try { /*BrokenBean bean =*/ MAPPER.readValue("{ \"x\" : 42 }", BrokenBean.class); } catch (InvalidDefinitionException je) { verifyException(je, "has no property name"); } } } TestCreators1853.java000066400000000000000000000031351325620701100372370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // Reproduction for [databind#1853], problem with delegating creator, // but only explicit case public class TestCreators1853 extends BaseMapTest { public static class Product { String name; public Object other, errors; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) public Product(@JsonProperty("name") String name) { this.name = "PROP:" + name; } @JsonCreator(mode = JsonCreator.Mode.DELEGATING) public static Product from(String name){ return new Product(false, "DELEG:"+name); } private Product(boolean bogus, String name) { this.name = name; } @JsonValue public String getName(){ return name; } } private static final String EXAMPLE_DATA = "{\"name\":\"dummy\",\"other\":{},\"errors\":{}}"; private final ObjectMapper MAPPER = newObjectMapper(); public void testSerialization() throws Exception { assertEquals(quote("testProduct"), MAPPER.writeValueAsString(new Product(false, "testProduct"))); } public void testDeserializationFromObject() throws Exception { assertEquals("PROP:dummy", MAPPER.readValue(EXAMPLE_DATA, Product.class).getName()); } public void testDeserializationFromString() throws Exception { assertEquals("DELEG:testProduct", MAPPER.readValue(quote("testProduct"), Product.class).getName()); } } TestCreators2.java000066400000000000000000000225011325620701100367760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creators package com.fasterxml.jackson.databind.deser.creators; import java.io.IOException; import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class TestCreators2 extends BaseMapTest { static class HashTest { final byte[] bytes; final String type; @JsonCreator public HashTest(@JsonProperty("bytes") @JsonDeserialize(using = BytesDeserializer.class) final byte[] bytes, @JsonProperty("type") final String type) { this.bytes = bytes; this.type = type; } } static class BytesDeserializer extends JsonDeserializer { @Override public byte[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { String str = jp.getText(); return str.getBytes("UTF-8"); } } static class Primitives { protected int x = 3; protected double d = -0.5; protected boolean b = true; @JsonCreator public Primitives(@JsonProperty("x") int x, @JsonProperty("d") double d, @JsonProperty("b") boolean b) { this.x = x; this.d = d; this.b = b; } } protected static class Test431Container { protected final List items; @JsonCreator public Test431Container(@JsonProperty("items") final List i) { items = i; } } @JsonIgnoreProperties(ignoreUnknown = true) protected static class Item431 { protected final String id; @JsonCreator public Item431(@JsonProperty("id") String id) { this.id = id; } } // Test class for verifying that creator-call failures are reported as checked exceptions static class BeanFor438 { @JsonCreator public BeanFor438(@JsonProperty("name") String s) { throw new IllegalArgumentException("I don't like that name!"); } } // For [JACKSON-470]: should be appropriately detected, reported error about static class BrokenCreatorBean { protected String bar; @JsonCreator public BrokenCreatorBean(@JsonProperty("bar") String bar1, @JsonProperty("bar") String bar2) { bar = ""+bar1+"/"+bar2; } } // For [JACKSON-541]: should not need @JsonCreator if SerializationFeature.AUTO_DETECT_CREATORS is on. static class AutoDetectConstructorBean { protected final String foo; protected final String bar; public AutoDetectConstructorBean(@JsonProperty("bar") String bar, @JsonProperty("foo") String foo){ this.bar = bar; this.foo = foo; } } static class BustedCtor { @JsonCreator BustedCtor(@JsonProperty("a") String value) { throw new IllegalArgumentException("foobar"); } } static class IgnoredCtor { @JsonIgnore public IgnoredCtor(String arg) { throw new RuntimeException("Should never use this constructor"); } public IgnoredCtor() { } } abstract static class AbstractBase { @JsonCreator public static AbstractBase create(Map props) { return new AbstractBaseImpl(props); } } static class AbstractBaseImpl extends AbstractBase { protected Map props; public AbstractBaseImpl(Map props) { this.props = props; } } static interface Issue700Set extends java.util.Set { } static class Issue700Bean { protected Issue700Set item; @JsonCreator public Issue700Bean(@JsonProperty("item") String item) { } public String getItem() { return null; } } static final class MultiPropCreator1476 { private final int intField; private final String stringField; public MultiPropCreator1476(@JsonProperty("intField") int intField) { this(intField, "empty"); } public MultiPropCreator1476(@JsonProperty("stringField") String stringField) { this(-1, stringField); } @JsonCreator public MultiPropCreator1476(@JsonProperty("intField") int intField, @JsonProperty("stringField") String stringField) { this.intField = intField; this.stringField = stringField; } public int getIntField() { return intField; } public String getStringField() { return stringField; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testExceptionFromConstructor() throws Exception { try { MAPPER.readValue("{}", BustedCtor.class); fail("Expected exception"); } catch (JsonMappingException e) { verifyException(e, ": foobar"); // also: should have nested exception Throwable t = e.getCause(); if (t == null) { fail("Should have assigned cause for: ("+e.getClass().getSimpleName()+") "+e); } assertNotNull(t); assertEquals(IllegalArgumentException.class, t.getClass()); assertEquals("foobar", t.getMessage()); } } public void testSimpleConstructor() throws Exception { HashTest test = MAPPER.readValue("{\"type\":\"custom\",\"bytes\":\"abc\" }", HashTest.class); assertEquals("custom", test.type); assertEquals("abc", new String(test.bytes, "UTF-8")); } // Test for [JACKSON-372] public void testMissingPrimitives() throws Exception { Primitives p = MAPPER.readValue("{}", Primitives.class); assertFalse(p.b); assertEquals(0, p.x); assertEquals(0.0, p.d); } public void testJackson431() throws Exception { final Test431Container foo = MAPPER.readValue( "{\"items\":\n" +"[{\"bar\": 0,\n" +"\"id\": \"id123\",\n" +"\"foo\": 1\n" +"}]}", Test431Container.class); assertNotNull(foo); } // Catch and re-throw exceptions that Creator methods throw public void testJackson438() throws Exception { Exception e = null; try { MAPPER.readValue("{ \"name\":\"foobar\" }", BeanFor438.class); fail("Should have failed"); } catch (Exception e0) { e = e0; } if (!(e instanceof JsonMappingException)) { fail("Should have received JsonMappingException, caught "+e.getClass().getName()); } verifyException(e, "don't like that name"); // Ok: also, let's ensure root cause is directly linked, without other extra wrapping: Throwable t = e.getCause(); if (t == null) { fail("Should have assigned cause for: ("+e.getClass().getSimpleName()+") "+e); } assertEquals(IllegalArgumentException.class, t.getClass()); verifyException(e, "don't like that name"); } public void testCreatorWithDupNames() throws Exception { try { MAPPER.readValue("{\"bar\":\"x\"}", BrokenCreatorBean.class); fail("Should have caught duplicate creator parameters"); } catch (JsonMappingException e) { verifyException(e, "duplicate creator property \"bar\""); } } public void testCreatorMultipleArgumentWithoutAnnotation() throws Exception { AutoDetectConstructorBean value = MAPPER.readValue("{\"bar\":\"bar\",\"foo\":\"foo\"}", AutoDetectConstructorBean.class); assertEquals("bar", value.bar); assertEquals("foo", value.foo); } public void testIgnoredSingleArgCtor() throws Exception { try { MAPPER.readValue(quote("abc"), IgnoredCtor.class); fail("Should have caught missing constructor problem"); } catch (JsonMappingException e) { verifyException(e, "no String-argument constructor/factory method"); } } public void testAbstractFactory() throws Exception { AbstractBase bean = MAPPER.readValue("{\"a\":3}", AbstractBase.class); assertNotNull(bean); AbstractBaseImpl impl = (AbstractBaseImpl) bean; assertEquals(1, impl.props.size()); assertEquals(Integer.valueOf(3), impl.props.get("a")); } public void testCreatorProperties() throws Exception { Issue700Bean value = MAPPER.readValue("{ \"item\" : \"foo\" }", Issue700Bean.class); assertNotNull(value); } // [databind#1476] public void testConstructorChoice() throws Exception { ObjectMapper mapper = new ObjectMapper(); MultiPropCreator1476 pojo = mapper.readValue("{ \"intField\": 1, \"stringField\": \"foo\" }", MultiPropCreator1476.class); assertEquals(1, pojo.getIntField()); assertEquals("foo", pojo.getStringField()); } } TestCreators421.java000066400000000000000000000042521325620701100371460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class TestCreators421 extends BaseMapTest { static class MultiCtor { protected String _a, _b; private MultiCtor() { } private MultiCtor(String a, String b, Boolean c) { if (c == null) { throw new RuntimeException("Wrong factory!"); } _a = a; _b = b; } @JsonCreator static MultiCtor factory(@JsonProperty("a") String a, @JsonProperty("b") String b) { return new MultiCtor(a, b, Boolean.TRUE); } } @SuppressWarnings("serial") static class MyParamIntrospector extends JacksonAnnotationIntrospector { @Override public String findImplicitPropertyName(AnnotatedMember param) { if (param instanceof AnnotatedParameter) { AnnotatedParameter ap = (AnnotatedParameter) param; switch (ap.getIndex()) { case 0: return "a"; case 1: return "b"; case 2: return "c"; default: return "param"+ap.getIndex(); } } return super.findImplicitPropertyName(param); } } /* /********************************************************** /* Test methods /********************************************************** */ // [Issue#421] public void testMultiCtor421() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new MyParamIntrospector()); MultiCtor bean = mapper.readValue(aposToQuotes("{'a':'123','b':'foo'}"), MultiCtor.class); assertNotNull(bean); assertEquals("123", bean._a); assertEquals("foo", bean._b); } } TestCreators541.java000066400000000000000000000062261325620701100371540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; public class TestCreators541 extends BaseMapTest { static final class Foo { @JsonProperty("foo") protected Map foo; @JsonProperty("anumber") protected long anumber; public Foo() { anumber = 0; } public Map getFoo() { return foo; } public long getAnumber() { return anumber; } } static final class Bar { private final long p; private final List stuff; @JsonCreator public Bar(@JsonProperty("p") long p, @JsonProperty("stuff") List stuff) { this.p = p; this.stuff = stuff; } @JsonProperty("s") public List getStuff() { return stuff; } @JsonProperty("stuff") private List getStuffDeprecated() { return stuff; } public long getP() { return p; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testCreator541() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); mapper.disable( MapperFeature.AUTO_DETECT_CREATORS, MapperFeature.AUTO_DETECT_FIELDS, MapperFeature.AUTO_DETECT_GETTERS, MapperFeature.AUTO_DETECT_IS_GETTERS, MapperFeature.AUTO_DETECT_SETTERS, MapperFeature.USE_GETTERS_AS_SETTERS ); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); final String JSON = "{\n" + " \"foo\": {\n" + " \"0\": {\n" + " \"p\": 0,\n" + " \"stuff\": [\n" + " \"a\", \"b\" \n" + " ] \n" + " },\n" + " \"1\": {\n" + " \"p\": 1000,\n" + " \"stuff\": [\n" + " \"c\", \"d\" \n" + " ] \n" + " },\n" + " \"2\": {\n" + " \"p\": 2000,\n" + " \"stuff\": [\n" + " ] \n" + " }\n" + " },\n" + " \"anumber\": 25385874\n" + "}"; Foo obj = mapper.readValue(JSON, Foo.class); assertNotNull(obj); assertNotNull(obj.foo); assertEquals(3, obj.foo.size()); assertEquals(25385874L, obj.getAnumber()); } } TestCreatorsDelegating.java000066400000000000000000000130571325620701100407060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.JsonCreator; import java.util.Map; import com.fasterxml.jackson.annotation.JacksonInject; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.util.TokenBuffer; public class TestCreatorsDelegating extends BaseMapTest { static class BooleanBean { protected Boolean value; public BooleanBean(Boolean v) { value = v; } @JsonCreator protected static BooleanBean create(Boolean value) { return new BooleanBean(value); } } // for [JACKSON-711]; should allow delegate-based one(s) too static class CtorBean711 { protected String name; protected int age; @JsonCreator public CtorBean711(@JacksonInject String n, int a) { name = n; age = a; } } // for [JACKSON-711]; should allow delegate-based one(s) too static class FactoryBean711 { protected String name1; protected String name2; protected int age; private FactoryBean711(int a, String n1, String n2) { age = a; name1 = n1; name2 = n2; } @JsonCreator public static FactoryBean711 create(@JacksonInject String n1, int a, @JacksonInject String n2) { return new FactoryBean711(a, n1, n2); } } static class Value592 { protected Object stuff; protected Value592(Object ob, boolean bogus) { stuff = ob; } @JsonCreator public static Value592 from(TokenBuffer buffer) { return new Value592(buffer, false); } } static class MapBean { protected Map map; @JsonCreator public MapBean(Map map) { this.map = map; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testBooleanDelegate() throws Exception { // should obviously work with booleans... BooleanBean bb = MAPPER.readValue("true", BooleanBean.class); assertEquals(Boolean.TRUE, bb.value); // but also with value conversion from String bb = MAPPER.readValue(quote("true"), BooleanBean.class); assertEquals(Boolean.TRUE, bb.value); } // As per [JACKSON-711]: should also work with delegate model (single non-annotated arg) public void testWithCtorAndDelegate() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setInjectableValues(new InjectableValues.Std() .addValue(String.class, "Pooka") ); CtorBean711 bean = null; try { bean = mapper.readValue("38", CtorBean711.class); } catch (JsonMappingException e) { fail("Did not expect problems, got: "+e.getMessage()); } assertEquals(38, bean.age); assertEquals("Pooka", bean.name); } public void testWithFactoryAndDelegate() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setInjectableValues(new InjectableValues.Std() .addValue(String.class, "Fygar") ); FactoryBean711 bean = null; try { bean = mapper.readValue("38", FactoryBean711.class); } catch (JsonMappingException e) { fail("Did not expect problems, got: "+e.getMessage()); } assertEquals(38, bean.age); assertEquals("Fygar", bean.name1); assertEquals("Fygar", bean.name2); } // [databind#592] public void testDelegateWithTokenBuffer() throws Exception { Value592 value = MAPPER.readValue("{\"a\":1,\"b\":2}", Value592.class); assertNotNull(value); Object ob = value.stuff; assertEquals(TokenBuffer.class, ob.getClass()); JsonParser jp = ((TokenBuffer) ob).asParser(); assertToken(JsonToken.START_OBJECT, jp.nextToken()); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); assertEquals("a", jp.getCurrentName()); assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertEquals(1, jp.getIntValue()); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); assertEquals("b", jp.getCurrentName()); assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertEquals(2, jp.getIntValue()); assertToken(JsonToken.END_OBJECT, jp.nextToken()); jp.close(); } @SuppressWarnings("unchecked") public void testIssue465() throws Exception { final String JSON = "{\"A\":12}"; // first, test with regular Map, non empty Map map = MAPPER.readValue(JSON, Map.class); assertEquals(1, map.size()); assertEquals(Integer.valueOf(12), map.get("A")); MapBean bean = MAPPER.readValue(JSON, MapBean.class); assertEquals(1, bean.map.size()); assertEquals(Long.valueOf(12L), bean.map.get("A")); // and then empty ones final String EMPTY_JSON = "{}"; map = MAPPER.readValue(EMPTY_JSON, Map.class); assertEquals(0, map.size()); bean = MAPPER.readValue(EMPTY_JSON, MapBean.class); assertEquals(0, bean.map.size()); } } TestCreatorsWithIdentity.java000066400000000000000000000031661325620701100412700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class TestCreatorsWithIdentity extends BaseMapTest { @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Parent.class) public static class Parent { @JsonProperty("id") String id; @JsonProperty String parentProp; @JsonCreator public Parent(@JsonProperty("parentProp") String parentProp) { this.parentProp = parentProp; } } public static class Child { @JsonProperty Parent parent; @JsonProperty String childProp; @JsonCreator public Child(@JsonProperty("parent") Parent parent, @JsonProperty("childProp") String childProp) { this.parent = parent; this.childProp = childProp; } } private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); public void testSimple() throws IOException { String parentStr = "{\"id\" : \"1\", \"parentProp\" : \"parent\"}"; String childStr = "{\"childProp\" : \"child\", \"parent\" : " + parentStr + "}"; Parent parent = JSON_MAPPER.readValue(parentStr, Parent.class); assertNotNull(parent); Child child = JSON_MAPPER.readValue(childStr, Child.class); assertNotNull(child); assertNotNull(child.parent); } } TestCustomValueInstDefaults.java000066400000000000000000000544171325620701100417420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.io.IOException; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.deser.ValueInstantiators; import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer; import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator; import com.fasterxml.jackson.databind.module.SimpleModule; /** * Exercises a custom value instantiator with an overridden * {@link ValueInstantiator#createFromObjectWith(DeserializationContext, SettableBeanProperty[], PropertyValueBuffer)} * as well as the {@link PropertyValueBuffer#hasParameter(SettableBeanProperty)} * and {@link PropertyValueBuffer#getParameter(SettableBeanProperty)} methods. */ @SuppressWarnings("serial") public class TestCustomValueInstDefaults extends BaseTest { static class Bucket { static final int DEFAULT_A = 111; static final int DEFAULT_B = 222; static final String DEFAULT_C = "defaultC"; static final String DEFAULT_D = "defaultD"; final int a; final int b; final String c; final String d; @JsonCreator public Bucket( @JsonProperty("a") int a, @JsonProperty("b") int b, @JsonProperty("c") String c, @JsonProperty("d") String d) { this.a = a; this.b = b; this.c = c; this.d = d; } } static class BigBucket { static final int DEFAULT_I = 555; static final String DEFAULT_S = "defaultS"; final int i01, i02, i03, i04, i05, i06, i07, i08, i09, i10, i11, i12, i13, i14, i15, i16; final String s01, s02, s03, s04, s05, s06, s07, s08, s09, s10, s11, s12, s13, s14, s15, s16; @JsonCreator public BigBucket( @JsonProperty("i01") int i01, @JsonProperty("i02") int i02, @JsonProperty("i03") int i03, @JsonProperty("i04") int i04, @JsonProperty("i05") int i05, @JsonProperty("i06") int i06, @JsonProperty("i07") int i07, @JsonProperty("i08") int i08, @JsonProperty("i09") int i09, @JsonProperty("i10") int i10, @JsonProperty("i11") int i11, @JsonProperty("i12") int i12, @JsonProperty("i13") int i13, @JsonProperty("i14") int i14, @JsonProperty("i15") int i15, @JsonProperty("i16") int i16, @JsonProperty("s01") String s01, @JsonProperty("s02") String s02, @JsonProperty("s03") String s03, @JsonProperty("s04") String s04, @JsonProperty("s05") String s05, @JsonProperty("s06") String s06, @JsonProperty("s07") String s07, @JsonProperty("s08") String s08, @JsonProperty("s09") String s09, @JsonProperty("s10") String s10, @JsonProperty("s11") String s11, @JsonProperty("s12") String s12, @JsonProperty("s13") String s13, @JsonProperty("s14") String s14, @JsonProperty("s15") String s15, @JsonProperty("s16") String s16, // It is not clear why PropertyValueBuffer uses the BitSet for // exactly 32 params. The primitive int has 32 bits, so // couldn't the int be used there? We add this 33rd dummy // parameter just in case PropertyValueBuffer is refactored to // to so. @JsonProperty("dummy") boolean dummy) { this.i01 = i01; this.i02 = i02; this.i03 = i03; this.i04 = i04; this.i05 = i05; this.i06 = i06; this.i07 = i07; this.i08 = i08; this.i09 = i09; this.i10 = i10; this.i11 = i11; this.i12 = i12; this.i13 = i13; this.i14 = i14; this.i15 = i15; this.i16 = i16; this.s01 = s01; this.s02 = s02; this.s03 = s03; this.s04 = s04; this.s05 = s05; this.s06 = s06; this.s07 = s07; this.s08 = s08; this.s09 = s09; this.s10 = s10; this.s11 = s11; this.s12 = s12; this.s13 = s13; this.s14 = s14; this.s15 = s15; this.s16 = s16; } } static class BucketInstantiator extends StdValueInstantiator { BucketInstantiator(StdValueInstantiator src) { super(src); } @Override public Object createFromObjectWith( DeserializationContext ctxt, SettableBeanProperty[] props, PropertyValueBuffer buffer) throws JsonMappingException { int a = Bucket.DEFAULT_A; int b = Bucket.DEFAULT_B; String c = Bucket.DEFAULT_C; String d = Bucket.DEFAULT_D; for (SettableBeanProperty prop : props) { if (buffer.hasParameter(prop)) { if (prop.getName().equals("a")) { a = (Integer) buffer.getParameter(prop); } else if (prop.getName().equals("b")) { b = (Integer) buffer.getParameter(prop); } else if (prop.getName().equals("c")) { c = (String) buffer.getParameter(prop); } else if (prop.getName().equals("d")) { d = (String) buffer.getParameter(prop); } } } return new Bucket(a, b, c, d); } } static class BigBucketInstantiator extends StdValueInstantiator { BigBucketInstantiator(StdValueInstantiator src) { super(src); } @Override public Object createFromObjectWith( DeserializationContext ctxt, SettableBeanProperty[] props, PropertyValueBuffer buffer) throws JsonMappingException { int i01 = BigBucket.DEFAULT_I; int i02 = BigBucket.DEFAULT_I; int i03 = BigBucket.DEFAULT_I; int i04 = BigBucket.DEFAULT_I; int i05 = BigBucket.DEFAULT_I; int i06 = BigBucket.DEFAULT_I; int i07 = BigBucket.DEFAULT_I; int i08 = BigBucket.DEFAULT_I; int i09 = BigBucket.DEFAULT_I; int i10 = BigBucket.DEFAULT_I; int i11 = BigBucket.DEFAULT_I; int i12 = BigBucket.DEFAULT_I; int i13 = BigBucket.DEFAULT_I; int i14 = BigBucket.DEFAULT_I; int i15 = BigBucket.DEFAULT_I; int i16 = BigBucket.DEFAULT_I; String s01 = BigBucket.DEFAULT_S; String s02 = BigBucket.DEFAULT_S; String s03 = BigBucket.DEFAULT_S; String s04 = BigBucket.DEFAULT_S; String s05 = BigBucket.DEFAULT_S; String s06 = BigBucket.DEFAULT_S; String s07 = BigBucket.DEFAULT_S; String s08 = BigBucket.DEFAULT_S; String s09 = BigBucket.DEFAULT_S; String s10 = BigBucket.DEFAULT_S; String s11 = BigBucket.DEFAULT_S; String s12 = BigBucket.DEFAULT_S; String s13 = BigBucket.DEFAULT_S; String s14 = BigBucket.DEFAULT_S; String s15 = BigBucket.DEFAULT_S; String s16 = BigBucket.DEFAULT_S; for (SettableBeanProperty prop : props) { if (buffer.hasParameter(prop)) { String name = prop.getName(); Object value = buffer.getParameter(prop); if (name.equals("i01")) i01 = (Integer) value; else if (name.equals("i02")) i02 = (Integer) value; else if (name.equals("i03")) i03 = (Integer) value; else if (name.equals("i04")) i04 = (Integer) value; else if (name.equals("i05")) i05 = (Integer) value; else if (name.equals("i06")) i06 = (Integer) value; else if (name.equals("i07")) i07 = (Integer) value; else if (name.equals("i08")) i08 = (Integer) value; else if (name.equals("i09")) i09 = (Integer) value; else if (name.equals("i10")) i10 = (Integer) value; else if (name.equals("i11")) i11 = (Integer) value; else if (name.equals("i12")) i12 = (Integer) value; else if (name.equals("i13")) i13 = (Integer) value; else if (name.equals("i14")) i14 = (Integer) value; else if (name.equals("i15")) i15 = (Integer) value; else if (name.equals("i16")) i16 = (Integer) value; else if (name.equals("s01")) s01 = (String) value; else if (name.equals("s02")) s02 = (String) value; else if (name.equals("s03")) s03 = (String) value; else if (name.equals("s04")) s04 = (String) value; else if (name.equals("s05")) s05 = (String) value; else if (name.equals("s06")) s06 = (String) value; else if (name.equals("s07")) s07 = (String) value; else if (name.equals("s08")) s08 = (String) value; else if (name.equals("s09")) s09 = (String) value; else if (name.equals("s10")) s10 = (String) value; else if (name.equals("s11")) s11 = (String) value; else if (name.equals("s12")) s12 = (String) value; else if (name.equals("s13")) s13 = (String) value; else if (name.equals("s14")) s14 = (String) value; else if (name.equals("s15")) s15 = (String) value; else if (name.equals("s16")) s16 = (String) value; } } return new BigBucket( i01, i02, i03, i04, i05, i06, i07, i08, i09, i10, i11, i12, i13, i14, i15, i16, s01, s02, s03, s04, s05, s06, s07, s08, s09, s10, s11, s12, s13, s14, s15, s16, false); } } static class BucketInstantiators implements ValueInstantiators { @Override public ValueInstantiator findValueInstantiator( DeserializationConfig config, BeanDescription beanDesc, ValueInstantiator defaultInstantiator) { if (defaultInstantiator instanceof StdValueInstantiator) { if (beanDesc.getBeanClass() == Bucket.class) { return new BucketInstantiator( (StdValueInstantiator) defaultInstantiator); } if (beanDesc.getBeanClass() == BigBucket.class) { return new BigBucketInstantiator( (StdValueInstantiator) defaultInstantiator); } } return defaultInstantiator; } } static class BucketModule extends SimpleModule { @Override public void setupModule(SetupContext context) { context.addValueInstantiators(new BucketInstantiators()); } } static class ClassWith32Props { @JsonCreator public ClassWith32Props(@JsonProperty("p1") String p1, @JsonProperty("p2") String p2, @JsonProperty("p3") String p3, @JsonProperty("p4") String p4, @JsonProperty("p5") String p5, @JsonProperty("p6") String p6, @JsonProperty("p7") String p7, @JsonProperty("p8") String p8, @JsonProperty("p9") String p9, @JsonProperty("p10") String p10, @JsonProperty("p11") String p11, @JsonProperty("p12") String p12, @JsonProperty("p13") String p13, @JsonProperty("p14") String p14, @JsonProperty("p15") String p15, @JsonProperty("p16") String p16, @JsonProperty("p17") String p17, @JsonProperty("p18") String p18, @JsonProperty("p19") String p19, @JsonProperty("p20") String p20, @JsonProperty("p21") String p21, @JsonProperty("p22") String p22, @JsonProperty("p23") String p23, @JsonProperty("p24") String p24, @JsonProperty("p25") String p25, @JsonProperty("p26") String p26, @JsonProperty("p27") String p27, @JsonProperty("p28") String p28, @JsonProperty("p29") String p29, @JsonProperty("p30") String p30, @JsonProperty("p31") String p31, @JsonProperty("p32") String p32) { this.p1 = p1; this.p2 = p2; this.p3 = p3; this.p4 = p4; this.p5 = p5; this.p6 = p6; this.p7 = p7; this.p8 = p8; this.p9 = p9; this.p10 = p10; this.p11 = p11; this.p12 = p12; this.p13 = p13; this.p14 = p14; this.p15 = p15; this.p16 = p16; this.p17 = p17; this.p18 = p18; this.p19 = p19; this.p20 = p20; this.p21 = p21; this.p22 = p22; this.p23 = p23; this.p24 = p24; this.p25 = p25; this.p26 = p26; this.p27 = p27; this.p28 = p28; this.p29 = p29; this.p30 = p30; this.p31 = p31; this.p32 = p32; } public final String p1, p2, p3, p4; public final String p5, p6, p7, p8; public final String p9, p10, p11, p12; public final String p13, p14, p15, p16; public final String p17, p18, p19, p20; public final String p21, p22, p23, p24; public final String p25, p26, p27, p28; public final String p29, p30, p31, p32; } static class VerifyingValueInstantiator extends StdValueInstantiator { protected VerifyingValueInstantiator(StdValueInstantiator src) { super(src); } @Override public Object createFromObjectWith(DeserializationContext ctxt, SettableBeanProperty[] props, PropertyValueBuffer buffer) throws IOException { for (SettableBeanProperty prop : props) { assertTrue("prop " + prop.getName() + " was expected to have buffer.hasParameter(prop) be true but was false", buffer.hasParameter(prop)); } return super.createFromObjectWith(ctxt, props, buffer); } } // [databind#1432] public static class ClassWith32Module extends SimpleModule { public ClassWith32Module() { super("test", Version.unknownVersion()); } @Override public void setupModule(SetupContext context) { context.addValueInstantiators(new ValueInstantiators.Base() { @Override public ValueInstantiator findValueInstantiator(DeserializationConfig config, BeanDescription beanDesc, ValueInstantiator defaultInstantiator) { if (beanDesc.getBeanClass() == ClassWith32Props.class) { return new VerifyingValueInstantiator((StdValueInstantiator) defaultInstantiator); } return defaultInstantiator; } }); } } /* /********************************************************** /* Test methods /********************************************************** */ // When all values are in the source, no defaults should be used. public void testAllPresent() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new BucketModule()); Bucket allPresent = mapper.readValue( "{\"a\":8,\"b\":9,\"c\":\"y\",\"d\":\"z\"}", Bucket.class); assertEquals(8, allPresent.a); assertEquals(9, allPresent.b); assertEquals("y", allPresent.c); assertEquals("z", allPresent.d); } // When no values are in the source, all defaults should be used. public void testAllAbsent() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new BucketModule()); Bucket allAbsent = mapper.readValue( "{}", Bucket.class); assertEquals(Bucket.DEFAULT_A, allAbsent.a); assertEquals(Bucket.DEFAULT_B, allAbsent.b); assertEquals(Bucket.DEFAULT_C, allAbsent.c); assertEquals(Bucket.DEFAULT_D, allAbsent.d); } // When some values are in the source and some are not, defaults should only // be used for the missing values. public void testMixedPresentAndAbsent() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new BucketModule()); Bucket aAbsent = mapper.readValue( "{\"b\":9,\"c\":\"y\",\"d\":\"z\"}", Bucket.class); assertEquals(Bucket.DEFAULT_A, aAbsent.a); assertEquals(9, aAbsent.b); assertEquals("y", aAbsent.c); assertEquals("z", aAbsent.d); Bucket bAbsent = mapper.readValue( "{\"a\":8,\"c\":\"y\",\"d\":\"z\"}", Bucket.class); assertEquals(8, bAbsent.a); assertEquals(Bucket.DEFAULT_B, bAbsent.b); assertEquals("y", bAbsent.c); assertEquals("z", bAbsent.d); Bucket cAbsent = mapper.readValue( "{\"a\":8,\"b\":9,\"d\":\"z\"}", Bucket.class); assertEquals(8, cAbsent.a); assertEquals(9, cAbsent.b); assertEquals(Bucket.DEFAULT_C, cAbsent.c); assertEquals("z", cAbsent.d); Bucket dAbsent = mapper.readValue( "{\"a\":8,\"b\":9,\"c\":\"y\"}", Bucket.class); assertEquals(8, dAbsent.a); assertEquals(9, dAbsent.b); assertEquals("y", dAbsent.c); assertEquals(Bucket.DEFAULT_D, dAbsent.d); } // Ensure that 0 is not mistaken for a missing int value. public void testPresentZeroPrimitive() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new BucketModule()); Bucket aZeroRestAbsent = mapper.readValue( "{\"a\":0}", Bucket.class); assertEquals(0, aZeroRestAbsent.a); assertEquals(Bucket.DEFAULT_B, aZeroRestAbsent.b); assertEquals(Bucket.DEFAULT_C, aZeroRestAbsent.c); assertEquals(Bucket.DEFAULT_D, aZeroRestAbsent.d); } // Ensure that null is not mistaken for a missing String value. public void testPresentNullReference() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new BucketModule()); Bucket cNullRestAbsent = mapper.readValue( "{\"c\":null}", Bucket.class); assertEquals(Bucket.DEFAULT_A, cNullRestAbsent.a); assertEquals(Bucket.DEFAULT_B, cNullRestAbsent.b); assertEquals(null, cNullRestAbsent.c); assertEquals(Bucket.DEFAULT_D, cNullRestAbsent.d); } // When we have more than 32 creator parameters, the buffer will use a // BitSet instead of a primitive int to keep track of which parameters it // has seen. Ensure that nothing breaks in that case. public void testMoreThan32CreatorParams() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new BucketModule()); BigBucket big = mapper.readValue( "{\"i03\":0,\"i11\":1,\"s05\":null,\"s08\":\"x\"}", BigBucket.class); assertEquals(BigBucket.DEFAULT_I, big.i01); assertEquals(BigBucket.DEFAULT_I, big.i02); assertEquals(0, big.i03); assertEquals(BigBucket.DEFAULT_I, big.i04); assertEquals(BigBucket.DEFAULT_I, big.i05); assertEquals(BigBucket.DEFAULT_I, big.i06); assertEquals(BigBucket.DEFAULT_I, big.i07); assertEquals(BigBucket.DEFAULT_I, big.i08); assertEquals(BigBucket.DEFAULT_I, big.i09); assertEquals(BigBucket.DEFAULT_I, big.i10); assertEquals(1, big.i11); assertEquals(BigBucket.DEFAULT_I, big.i12); assertEquals(BigBucket.DEFAULT_I, big.i13); assertEquals(BigBucket.DEFAULT_I, big.i14); assertEquals(BigBucket.DEFAULT_I, big.i15); assertEquals(BigBucket.DEFAULT_I, big.i16); assertEquals(BigBucket.DEFAULT_S, big.s01); assertEquals(BigBucket.DEFAULT_S, big.s02); assertEquals(BigBucket.DEFAULT_S, big.s03); assertEquals(BigBucket.DEFAULT_S, big.s04); assertEquals(null, big.s05); assertEquals(BigBucket.DEFAULT_S, big.s06); assertEquals(BigBucket.DEFAULT_S, big.s07); assertEquals("x", big.s08); assertEquals(BigBucket.DEFAULT_S, big.s09); assertEquals(BigBucket.DEFAULT_S, big.s10); assertEquals(BigBucket.DEFAULT_S, big.s11); assertEquals(BigBucket.DEFAULT_S, big.s12); assertEquals(BigBucket.DEFAULT_S, big.s13); assertEquals(BigBucket.DEFAULT_S, big.s14); assertEquals(BigBucket.DEFAULT_S, big.s15); assertEquals(BigBucket.DEFAULT_S, big.s16); } // [databind#1432] public void testClassWith32CreatorParams() throws Exception { StringBuilder sb = new StringBuilder() .append("{\n"); for (int i = 1; i <= 32; ++i) { sb.append("\"p").append(i).append("\" : \"NotNull") .append(i).append("\""); if (i < 32) { sb.append(",\n"); } } sb.append("\n}\n"); String json = sb.toString(); ObjectMapper mapper = new ObjectMapper() .registerModule(new ClassWith32Module()); ClassWith32Props result = mapper.readValue(json, ClassWith32Props.class); // let's assume couple of first, last ones suffice assertEquals("NotNull1", result.p1); assertEquals("NotNull2", result.p2); assertEquals("NotNull31", result.p31); assertEquals("NotNull32", result.p32); } } TestPolymorphicCreators.java000066400000000000000000000106441325620701100411470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying that it is possible to annotate * various kinds of things with {@link JsonCreator} annotation. */ public class TestPolymorphicCreators extends BaseMapTest { static class Animal { // All animals have names, for our demo purposes... public String name; protected Animal() { } /** * Creator method that can instantiate instances of * appropriate polymoprphic type */ @JsonCreator public static Animal create(@JsonProperty("type") String type) { if ("dog".equals(type)) { return new Dog(); } if ("cat".equals(type)) { return new Cat(); } throw new IllegalArgumentException("No such animal type ('"+type+"')"); } } static class Dog extends Animal { double barkVolume; // in decibels public Dog() { } public void setBarkVolume(double v) { barkVolume = v; } } static class Cat extends Animal { boolean likesCream; public int lives; public Cat() { } public void setLikesCream(boolean likesCreamSurely) { likesCream = likesCreamSurely; } } abstract static class AbstractRoot { protected final String opt; protected AbstractRoot(String opt) { this.opt = opt; } @JsonCreator public static final AbstractRoot make(@JsonProperty("which") int which, @JsonProperty("opt") String opt) { if (1 == which) { return new One(opt); } throw new RuntimeException("cannot instantiate " + which); } abstract public int getWhich(); public final String getOpt() { return opt; } } static final class One extends AbstractRoot { protected One(String opt) { super(opt); } @Override public int getWhich() { return 1; } } /* /********************************************************** /* Actual tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); /** * Simple test to verify that it is possible to implement polymorphic * deserialization manually. */ public void testManualPolymorphicDog() throws Exception { // first, a dog, start with type Animal animal = MAPPER.readValue("{ \"type\":\"dog\", \"name\":\"Fido\", \"barkVolume\" : 95.0 }", Animal.class); assertEquals(Dog.class, animal.getClass()); assertEquals("Fido", animal.name); assertEquals(95.0, ((Dog) animal).barkVolume); } public void testManualPolymorphicCatBasic() throws Exception { // and finally, lactose-intolerant, but otherwise robust super-cat: Animal animal = MAPPER.readValue("{ \"name\" : \"Macavity\", \"type\":\"cat\", \"lives\":18, \"likesCream\":false }", Animal.class); assertEquals(Cat.class, animal.getClass()); assertEquals("Macavity", animal.name); // ... there's no one like Macavity! Cat cat = (Cat) animal; assertEquals(18, cat.lives); // ok, he can't drink dairy products. Let's verify: assertEquals(false, cat.likesCream); } public void testManualPolymorphicCatWithReorder() throws Exception { // Then cat; shuffle order to mandate buffering Animal animal = MAPPER.readValue("{ \"likesCream\":true, \"name\" : \"Venla\", \"type\":\"cat\" }", Animal.class); assertEquals(Cat.class, animal.getClass()); assertEquals("Venla", animal.name); // bah, of course cats like cream. But let's ensure Jackson won't mess with laws of nature! assertTrue(((Cat) animal).likesCream); } public void testManualPolymorphicWithNumbered() throws Exception { final ObjectWriter w = MAPPER.writerFor(AbstractRoot.class); final ObjectReader r = MAPPER.readerFor(AbstractRoot.class); AbstractRoot input = AbstractRoot.make(1, "oh hai!"); String json = w.writeValueAsString(input); AbstractRoot result = r.readValue(json); assertNotNull(result); assertEquals("oh hai!", result.getOpt()); } } TestPolymorphicDelegating.java000066400000000000000000000025631325620701100414310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestPolymorphicDelegating extends BaseMapTest { // For [databind#580] @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) static abstract class Issue580Base { } static class Issue580Impl extends Issue580Base { public int id = 3; public Issue580Impl() { } public Issue580Impl(int id) { this.id = id; } } static class Issue580Bean { public Issue580Base value; @JsonCreator public Issue580Bean(Issue580Base v) { value = v; } @JsonValue public Issue580Base value() { return value; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testAbstractDelegateWithCreator() throws Exception { Issue580Bean input = new Issue580Bean(new Issue580Impl(13)); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(input); Issue580Bean result = mapper.readValue(json, Issue580Bean.class); assertNotNull(result); assertNotNull(result.value); assertEquals(13, ((Issue580Impl) result.value).id); } } TestValueInstantiator.java000066400000000000000000000501231325620701100406070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/creatorspackage com.fasterxml.jackson.databind.deser.creators; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonValueInstantiator; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Test custom instantiators. */ public class TestValueInstantiator extends BaseMapTest { static class MyBean { String _secret; public MyBean(String s, boolean bogus) { _secret = s; } } static class MysteryBean { Object value; public MysteryBean(Object v) { value = v; } } static class CreatorBean { String _secret; public String value; protected CreatorBean(String s) { _secret = s; } } static abstract class InstantiatorBase extends ValueInstantiator.Base { public InstantiatorBase() { super(Object.class); } @Override public String getValueTypeDesc() { return "UNKNOWN"; } @Override public boolean canCreateUsingDelegate() { return false; } } static abstract class PolymorphicBeanBase { } static class PolymorphicBean extends PolymorphicBeanBase { public String name; } @SuppressWarnings("serial") static class MyList extends ArrayList { public MyList(boolean b) { super(); } } @SuppressWarnings("serial") static class MyMap extends HashMap { public MyMap(boolean b) { super(); } public MyMap(String name) { super(); put(name, name); } } static class MyBeanInstantiator extends InstantiatorBase { @Override public String getValueTypeDesc() { return MyBean.class.getName(); } @Override public boolean canCreateUsingDefault() { return true; } @Override public MyBean createUsingDefault(DeserializationContext ctxt) { return new MyBean("secret!", true); } } /** * Something more ambitious: semi-automated approach to polymorphic * deserialization, using ValueInstantiator; from Object to any * type... */ static class PolymorphicBeanInstantiator extends InstantiatorBase { @Override public String getValueTypeDesc() { return Object.class.getName(); } @Override public boolean canCreateFromObjectWith() { return true; } @Override public CreatorProperty[] getFromObjectArguments(DeserializationConfig config) { return new CreatorProperty[] { new CreatorProperty(new PropertyName("type"), config.constructType(Class.class), null, null, null, null, 0, null, PropertyMetadata.STD_REQUIRED) }; } @Override public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) { try { Class cls = (Class) args[0]; return cls.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } } static class CreatorMapInstantiator extends InstantiatorBase { @Override public String getValueTypeDesc() { return MyMap.class.getName(); } @Override public boolean canCreateFromObjectWith() { return true; } @Override public CreatorProperty[] getFromObjectArguments(DeserializationConfig config) { return new CreatorProperty[] { new CreatorProperty(new PropertyName("name"), config.constructType(String.class), null, null, null, null, 0, null, PropertyMetadata.STD_REQUIRED) }; } @Override public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) { return new MyMap((String) args[0]); } } static class MyDelegateBeanInstantiator extends ValueInstantiator.Base { public MyDelegateBeanInstantiator() { super(Object.class); } @Override public String getValueTypeDesc() { return "xxx"; } @Override public boolean canCreateUsingDelegate() { return true; } @Override public JavaType getDelegateType(DeserializationConfig config) { return config.constructType(Object.class); } @Override public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) { return new MyBean(""+delegate, true); } } static class MyListInstantiator extends InstantiatorBase { @Override public String getValueTypeDesc() { return MyList.class.getName(); } @Override public boolean canCreateUsingDefault() { return true; } @Override public MyList createUsingDefault(DeserializationContext ctxt) { return new MyList(true); } } static class MyDelegateListInstantiator extends ValueInstantiator.Base { public MyDelegateListInstantiator() { super(Object.class); } @Override public String getValueTypeDesc() { return "xxx"; } @Override public boolean canCreateUsingDelegate() { return true; } @Override public JavaType getDelegateType(DeserializationConfig config) { return config.constructType(Object.class); } @Override public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) { MyList list = new MyList(true); list.add(delegate); return list; } } static class MyMapInstantiator extends InstantiatorBase { @Override public String getValueTypeDesc() { return MyMap.class.getName(); } @Override public boolean canCreateUsingDefault() { return true; } @Override public MyMap createUsingDefault(DeserializationContext ctxt) { return new MyMap(true); } } static class MyDelegateMapInstantiator extends ValueInstantiator.Base { public MyDelegateMapInstantiator() { super(Object.class); } @Override public String getValueTypeDesc() { return "xxx"; } @Override public boolean canCreateUsingDelegate() { return true; } @Override public JavaType getDelegateType(DeserializationConfig config) { return TypeFactory.defaultInstance().constructType(Object.class); } @Override public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) { MyMap map = new MyMap(true); map.put("value", delegate); return map; } } @JsonValueInstantiator(AnnotatedBeanInstantiator.class) static class AnnotatedBean { protected final String a; protected final int b; public AnnotatedBean(String a, int b) { this.a = a; this.b = b; } } static class AnnotatedBeanInstantiator extends InstantiatorBase { @Override public String getValueTypeDesc() { return AnnotatedBean.class.getName(); } @Override public boolean canCreateUsingDefault() { return true; } @Override public AnnotatedBean createUsingDefault(DeserializationContext ctxt) { return new AnnotatedBean("foo", 3); } } @SuppressWarnings("serial") static class MyModule extends SimpleModule { public MyModule(Class cls, ValueInstantiator inst) { super("Test", Version.unknownVersion()); this.addValueInstantiator(cls, inst); } } @JsonValueInstantiator(AnnotatedBeanDelegatingInstantiator.class) static class AnnotatedBeanDelegating { protected final Object value; public AnnotatedBeanDelegating(Object v, boolean bogus) { value = v; } } static class AnnotatedBeanDelegatingInstantiator extends InstantiatorBase { @Override public String getValueTypeDesc() { return AnnotatedBeanDelegating.class.getName(); } @Override public boolean canCreateUsingDelegate() { return true; } @Override public JavaType getDelegateType(DeserializationConfig config) { return config.constructType(Map.class); } @Override public AnnotatedWithParams getDelegateCreator() { return null; } @Override public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) throws IOException { return new AnnotatedBeanDelegating(delegate, false); } } /* /********************************************************** /* Unit tests for default creators /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testCustomBeanInstantiator() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MyBean.class, new MyBeanInstantiator())); MyBean bean = mapper.readValue("{}", MyBean.class); assertNotNull(bean); assertEquals("secret!", bean._secret); } public void testCustomListInstantiator() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MyList.class, new MyListInstantiator())); MyList result = mapper.readValue("[]", MyList.class); assertNotNull(result); assertEquals(MyList.class, result.getClass()); assertEquals(0, result.size()); } public void testCustomMapInstantiator() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MyMap.class, new MyMapInstantiator())); MyMap result = mapper.readValue("{ \"a\":\"b\" }", MyMap.class); assertNotNull(result); assertEquals(MyMap.class, result.getClass()); assertEquals(1, result.size()); } /* /********************************************************** /* Unit tests for delegate creators /********************************************************** */ public void testDelegateBeanInstantiator() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MyBean.class, new MyDelegateBeanInstantiator())); MyBean bean = mapper.readValue("123", MyBean.class); assertNotNull(bean); assertEquals("123", bean._secret); } public void testDelegateListInstantiator() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MyList.class, new MyDelegateListInstantiator())); MyList result = mapper.readValue("123", MyList.class); assertNotNull(result); assertEquals(1, result.size()); assertEquals(Integer.valueOf(123), result.get(0)); } public void testDelegateMapInstantiator() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MyMap.class, new MyDelegateMapInstantiator())); MyMap result = mapper.readValue("123", MyMap.class); assertNotNull(result); assertEquals(1, result.size()); assertEquals(Integer.valueOf(123), result.values().iterator().next()); } public void testCustomDelegateInstantiator() throws Exception { AnnotatedBeanDelegating value = MAPPER.readValue("{\"a\":3}", AnnotatedBeanDelegating.class); assertNotNull(value); Object ob = value.value; assertNotNull(ob); assertTrue(ob instanceof Map); } /* /********************************************************** /* Unit tests for property-based creators /********************************************************** */ public void testPropertyBasedBeanInstantiator() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(CreatorBean.class, new InstantiatorBase() { @Override public boolean canCreateFromObjectWith() { return true; } @Override public CreatorProperty[] getFromObjectArguments(DeserializationConfig config) { return new CreatorProperty[] { new CreatorProperty(new PropertyName("secret"), config.constructType(String.class), null, null, null, null, 0, null, PropertyMetadata.STD_REQUIRED) }; } @Override public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) { return new CreatorBean((String) args[0]); } })); CreatorBean bean = mapper.readValue("{\"secret\":123,\"value\":37}", CreatorBean.class); assertNotNull(bean); assertEquals("123", bean._secret); } public void testPropertyBasedMapInstantiator() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MyMap.class, new CreatorMapInstantiator())); MyMap result = mapper.readValue("{\"name\":\"bob\", \"x\":\"y\"}", MyMap.class); assertNotNull(result); assertEquals(2, result.size()); assertEquals("bob", result.get("bob")); assertEquals("y", result.get("x")); } /* /********************************************************** /* Unit tests for scalar-delegates /********************************************************** */ public void testBeanFromString() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MysteryBean.class, new InstantiatorBase() { @Override public boolean canCreateFromString() { return true; } @Override public Object createFromString(DeserializationContext ctxt, String value) { return new MysteryBean(value); } })); MysteryBean result = mapper.readValue(quote("abc"), MysteryBean.class); assertNotNull(result); assertEquals("abc", result.value); } public void testBeanFromInt() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MysteryBean.class, new InstantiatorBase() { @Override public boolean canCreateFromInt() { return true; } @Override public Object createFromInt(DeserializationContext ctxt, int value) { return new MysteryBean(value+1); } })); MysteryBean result = mapper.readValue("37", MysteryBean.class); assertNotNull(result); assertEquals(Integer.valueOf(38), result.value); } public void testBeanFromLong() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MysteryBean.class, new InstantiatorBase() { @Override public boolean canCreateFromLong() { return true; } @Override public Object createFromLong(DeserializationContext ctxt, long value) { return new MysteryBean(value+1L); } })); MysteryBean result = mapper.readValue("9876543210", MysteryBean.class); assertNotNull(result); assertEquals(Long.valueOf(9876543211L), result.value); } public void testBeanFromDouble() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MysteryBean.class, new InstantiatorBase() { @Override public boolean canCreateFromDouble() { return true; } @Override public Object createFromDouble(DeserializationContext ctxt, double value) { return new MysteryBean(2.0 * value); } })); MysteryBean result = mapper.readValue("0.25", MysteryBean.class); assertNotNull(result); assertEquals(Double.valueOf(0.5), result.value); } public void testBeanFromBoolean() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(MysteryBean.class, new InstantiatorBase() { @Override public boolean canCreateFromBoolean() { return true; } @Override public Object createFromBoolean(DeserializationContext ctxt, boolean value) { return new MysteryBean(Boolean.valueOf(value)); } })); MysteryBean result = mapper.readValue("true", MysteryBean.class); assertNotNull(result); assertEquals(Boolean.TRUE, result.value); } /* /********************************************************** /* Other tests /********************************************************** */ /** * Beyond basic features, it should be possible to even implement * polymorphic handling... */ public void testPolymorphicCreatorBean() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MyModule(PolymorphicBeanBase.class, new PolymorphicBeanInstantiator())); String JSON = "{\"type\":"+quote(PolymorphicBean.class.getName())+",\"name\":\"Axel\"}"; PolymorphicBeanBase result = mapper.readValue(JSON, PolymorphicBeanBase.class); assertNotNull(result); assertSame(PolymorphicBean.class, result.getClass()); assertEquals("Axel", ((PolymorphicBean) result).name); } public void testEmptyBean() throws Exception { AnnotatedBean bean = MAPPER.readValue("{}", AnnotatedBean.class); assertNotNull(bean); assertEquals("foo", bean.a); assertEquals(3, bean.b); } // @since 2.8 public void testErrorMessageForMissingCtor() throws Exception { // first fail, check message from JSON Object (no default ctor) try { MAPPER.readValue("{ }", MyBean.class); fail("Should not succeed"); } catch (JsonMappingException e) { verifyException(e, "Cannot construct instance of"); verifyException(e, "no Creators"); // as per [databind#1414], is definition problem assertEquals(InvalidDefinitionException.class, e.getClass()); } } // @since 2.8 public void testErrorMessageForMissingStringCtor() throws Exception { // then from JSON String try { MAPPER.readValue("\"foo\"", MyBean.class); fail("Should not succeed"); } catch (JsonMappingException e) { verifyException(e, "Cannot construct instance of"); verifyException(e, "no String-argument constructor/factory"); // as per [databind#1414], is definition problem assertEquals(InvalidDefinitionException.class, e.getClass()); } } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filter/000077500000000000000000000000001325620701100331515ustar00rootroot00000000000000IgnoreCreatorProp1317Test.java000066400000000000000000000024421325620701100405170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import java.beans.ConstructorProperties; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.*; public class IgnoreCreatorProp1317Test extends BaseMapTest { static class Testing { @JsonIgnore public String ignore; String notIgnore; public Testing() {} @ConstructorProperties({"ignore", "notIgnore"}) public Testing(String ignore, String notIgnore) { super(); this.ignore = ignore; this.notIgnore = notIgnore; } public String getIgnore() { return ignore; } public void setIgnore(String ignore) { this.ignore = ignore; } public String getNotIgnore() { return notIgnore; } public void setNotIgnore(String notIgnore) { this.notIgnore = notIgnore; } } public void testThatJsonIgnoreWorksWithConstructorProperties() throws Exception { ObjectMapper om = objectMapper(); Testing testing = new Testing("shouldBeIgnored", "notIgnore"); String json = om.writeValueAsString(testing); // System.out.println(json); assertFalse(json.contains("shouldBeIgnored")); } } IgnorePropertyOnDeserTest.java000066400000000000000000000057531325620701100410570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class IgnorePropertyOnDeserTest extends BaseMapTest { // [databind#1217] static class IgnoreObject { public int x = 1; public int y = 2; } final static class TestIgnoreObject { @JsonIgnoreProperties({ "x" }) public IgnoreObject obj; @JsonIgnoreProperties({ "y" }) public IgnoreObject obj2; } // [databind#1595] @JsonIgnoreProperties(value = {"name"}, allowSetters = true) @JsonPropertyOrder(alphabetic=true) static class Simple1595 { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } /* /**************************************************************** /* Unit tests /**************************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); // [databind#1217] public void testIgnoreOnProperty1217() throws Exception { TestIgnoreObject result = MAPPER.readValue( aposToQuotes("{'obj':{'x': 10, 'y': 20}, 'obj2':{'x': 10, 'y': 20}}"), TestIgnoreObject.class); assertEquals(20, result.obj.y); assertEquals(10, result.obj2.x); assertEquals(1, result.obj.x); assertEquals(2, result.obj2.y); TestIgnoreObject result1 = MAPPER.readValue( aposToQuotes("{'obj':{'x': 20, 'y': 30}, 'obj2':{'x': 20, 'y': 40}}"), TestIgnoreObject.class); assertEquals(1, result1.obj.x); assertEquals(30, result1.obj.y); assertEquals(20, result1.obj2.x); assertEquals(2, result1.obj2.y); } public void testIgnoreViaConfigOverride1217() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(Point.class) .setIgnorals(JsonIgnoreProperties.Value.forIgnoredProperties("y")); Point p = mapper.readValue(aposToQuotes("{'x':1,'y':2}"), Point.class); // bind 'x', but ignore 'y' assertEquals(1, p.x); assertEquals(0, p.y); } // [databind#1595] public void testIgnoreGetterNotSetter1595() throws Exception { ObjectMapper mapper = new ObjectMapper(); Simple1595 config = new Simple1595(); config.setId(123); config.setName("jack"); String json = mapper.writeValueAsString(config); assertEquals(aposToQuotes("{'id':123}"), json); Simple1595 des = mapper.readValue(aposToQuotes("{'id':123,'name':'jack'}"), Simple1595.class); assertEquals("jack", des.getName()); } } NullConversionsForContentTest.java000066400000000000000000000403541325620701100417500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import java.util.*; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidNullException; // For [databind#1402]; configurable null handling, for contents of // Collections, Maps, arrays public class NullConversionsForContentTest extends BaseMapTest { static class NullContentFail { public T nullsOk; @JsonSetter(contentNulls=Nulls.FAIL) public T noNulls; } static class NullContentAsEmpty { @JsonSetter(contentNulls=Nulls.AS_EMPTY) public T values; } static class NullContentSkip { @JsonSetter(contentNulls=Nulls.SKIP) public T values; } static class NullContentUndefined { @JsonSetter // leave with defaults public T values; } /* /********************************************************** /* Test methods, fail-on-null /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); // Tests to verify that we can set default settings for failure public void testFailOnNullFromDefaults() throws Exception { final String JSON = aposToQuotes("{'values':[null]}"); TypeReference listType = new TypeReference>>() { }; // by default fine to get nulls NullContentUndefined> result = MAPPER.readValue(JSON, listType); assertNotNull(result.values); assertEquals(1, result.values.size()); assertNull(result.values.get(0)); // but not when overridden globally: ObjectMapper mapper = newObjectMapper(); mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL)); try { mapper.readValue(JSON, listType); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"values\""); } // or configured for type: mapper = newObjectMapper(); mapper.configOverride(List.class) .setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL)); try { mapper.readValue(JSON, listType); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"values\""); } } public void testFailOnNullWithCollections() throws Exception { TypeReference typeRef = new TypeReference>>() { }; // first, ok if assigning non-null to not-nullable, null for nullable NullContentFail> result = MAPPER.readValue(aposToQuotes("{'nullsOk':[null]}"), typeRef); assertNotNull(result.nullsOk); assertEquals(1, result.nullsOk.size()); assertNull(result.nullsOk.get(0)); // and then see that nulls are not ok for non-nullable. // List final String JSON = aposToQuotes("{'noNulls':[null]}"); try { MAPPER.readValue(JSON, typeRef); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"noNulls\""); } // List try { MAPPER.readValue(JSON, new TypeReference>>() { }); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"noNulls\""); } } public void testFailOnNullWithArrays() throws Exception { final String JSON = aposToQuotes("{'noNulls':[null]}"); // Object[] try { MAPPER.readValue(JSON, new TypeReference>() { }); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"noNulls\""); } // String[] try { MAPPER.readValue(JSON, new TypeReference>() { }); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"noNulls\""); } } public void testFailOnNullWithPrimitiveArrays() throws Exception { final String JSON = aposToQuotes("{'noNulls':[null]}"); // boolean[] try { MAPPER.readValue(JSON, new TypeReference>() { }); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"noNulls\""); } // int[] try { MAPPER.readValue(JSON, new TypeReference>() { }); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"noNulls\""); } // double[] try { MAPPER.readValue(JSON, new TypeReference>() { }); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"noNulls\""); } } public void testFailOnNullWithMaps() throws Exception { // Then: Map try { final String MAP_JSON = aposToQuotes("{'noNulls':{'a':null}}"); MAPPER.readValue(MAP_JSON, new TypeReference>>() { }); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"noNulls\""); } // Then: EnumMap try { final String MAP_JSON = aposToQuotes("{'noNulls':{'A':null}}"); MAPPER.readValue(MAP_JSON, new TypeReference>>() { }); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"noNulls\""); } } /* /********************************************************** /* Test methods, null-as-empty /********************************************************** */ public void testNullsAsEmptyWithCollections() throws Exception { final String JSON = aposToQuotes("{'values':[null]}"); // List { NullContentAsEmpty> result = MAPPER.readValue(JSON, new TypeReference>>() { }); assertEquals(1, result.values.size()); assertEquals(Integer.valueOf(0), result.values.get(0)); } // List { NullContentAsEmpty> result = MAPPER.readValue(JSON, new TypeReference>>() { }); assertEquals(1, result.values.size()); assertEquals("", result.values.get(0)); } } public void testNullsAsEmptyUsingDefaults() throws Exception { final String JSON = aposToQuotes("{'values':[null]}"); TypeReference listType = new TypeReference>>() { }; // Let's see defaulting in action ObjectMapper mapper = newObjectMapper(); mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY)); NullContentUndefined> result = mapper.readValue(JSON, listType); assertEquals(1, result.values.size()); assertEquals(Integer.valueOf(0), result.values.get(0)); // or configured for type: mapper = newObjectMapper(); mapper.configOverride(List.class) .setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY)); result = mapper.readValue(JSON, listType); assertEquals(1, result.values.size()); assertEquals(Integer.valueOf(0), result.values.get(0)); } public void testNullsAsEmptyWithArrays() throws Exception { // Note: skip `Object[]`, no default empty value at this point final String JSON = aposToQuotes("{'values':[null]}"); // Then: String[] { NullContentAsEmpty result = MAPPER.readValue(JSON, new TypeReference>() { }); assertEquals(1, result.values.length); assertEquals("", result.values[0]); } } public void testNullsAsEmptyWithPrimitiveArrays() throws Exception { final String JSON = aposToQuotes("{'values':[null]}"); // int[] { NullContentAsEmpty result = MAPPER.readValue(JSON, new TypeReference>() { }); assertEquals(1, result.values.length); assertEquals(0, result.values[0]); } // long[] { NullContentAsEmpty result = MAPPER.readValue(JSON, new TypeReference>() { }); assertEquals(1, result.values.length); assertEquals(0L, result.values[0]); } // boolean[] { NullContentAsEmpty result = MAPPER.readValue(JSON, new TypeReference>() { }); assertEquals(1, result.values.length); assertEquals(false, result.values[0]); } } public void testNullsAsEmptyWithMaps() throws Exception { // Then: Map final String MAP_JSON = aposToQuotes("{'values':{'A':null}}"); { NullContentAsEmpty> result = MAPPER.readValue(MAP_JSON, new TypeReference>>() { }); assertEquals(1, result.values.size()); assertEquals("A", result.values.entrySet().iterator().next().getKey()); assertEquals("", result.values.entrySet().iterator().next().getValue()); } // Then: EnumMap { NullContentAsEmpty> result = MAPPER.readValue(MAP_JSON, new TypeReference>>() { }); assertEquals(1, result.values.size()); assertEquals(ABC.A, result.values.entrySet().iterator().next().getKey()); assertEquals("", result.values.entrySet().iterator().next().getValue()); } } /* /********************************************************** /* Test methods, skip-nulls /********************************************************** */ public void testNullsSkipUsingDefaults() throws Exception { final String JSON = aposToQuotes("{'values':[null]}"); TypeReference listType = new TypeReference>>() { }; // Let's see defaulting in action ObjectMapper mapper = newObjectMapper(); mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)); NullContentUndefined> result = mapper.readValue(JSON, listType); assertEquals(0, result.values.size()); // or configured for type: mapper = newObjectMapper(); mapper.configOverride(List.class) .setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)); result = mapper.readValue(JSON, listType); assertEquals(0, result.values.size()); } // Test to verify that per-property setting overrides defaults: public void testNullsSkipWithOverrides() throws Exception { final String JSON = aposToQuotes("{'values':[null]}"); TypeReference listType = new TypeReference>>() { }; ObjectMapper mapper = newObjectMapper(); // defaults call for fail; but POJO specifies "skip"; latter should win mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL)); NullContentSkip> result = mapper.readValue(JSON, listType); assertEquals(0, result.values.size()); // ditto for per-type defaults mapper = newObjectMapper(); mapper.configOverride(List.class) .setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL)); result = mapper.readValue(JSON, listType); assertEquals(0, result.values.size()); } public void testNullsSkipWithCollections() throws Exception { // List { final String JSON = aposToQuotes("{'values':[1,null,2]}"); NullContentSkip> result = MAPPER.readValue(JSON, new TypeReference>>() { }); assertEquals(2, result.values.size()); assertEquals(Integer.valueOf(1), result.values.get(0)); assertEquals(Integer.valueOf(2), result.values.get(1)); } // List { final String JSON = aposToQuotes("{'values':['ab',null,'xy']}"); NullContentSkip> result = MAPPER.readValue(JSON, new TypeReference>>() { }); assertEquals(2, result.values.size()); assertEquals("ab", result.values.get(0)); assertEquals("xy", result.values.get(1)); } } public void testNullsSkipWithArrays() throws Exception { final String JSON = aposToQuotes("{'values':['a',null,'xy']}"); // Object[] { NullContentSkip result = MAPPER.readValue(JSON, new TypeReference>() { }); assertEquals(2, result.values.length); assertEquals("a", result.values[0]); assertEquals("xy", result.values[1]); } // String[] { NullContentSkip result = MAPPER.readValue(JSON, new TypeReference>() { }); assertEquals(2, result.values.length); assertEquals("a", result.values[0]); assertEquals("xy", result.values[1]); } } public void testNullsSkipWithPrimitiveArrays() throws Exception { // int[] { final String JSON = aposToQuotes("{'values':[3,null,7]}"); NullContentSkip result = MAPPER.readValue(JSON, new TypeReference>() { }); assertEquals(2, result.values.length); assertEquals(3, result.values[0]); assertEquals(7, result.values[1]); } // long[] { final String JSON = aposToQuotes("{'values':[-13,null,999]}"); NullContentSkip result = MAPPER.readValue(JSON, new TypeReference>() { }); assertEquals(2, result.values.length); assertEquals(-13L, result.values[0]); assertEquals(999L, result.values[1]); } // boolean[] { final String JSON = aposToQuotes("{'values':[true,null,true]}"); NullContentSkip result = MAPPER.readValue(JSON, new TypeReference>() { }); assertEquals(2, result.values.length); assertEquals(true, result.values[0]); assertEquals(true, result.values[1]); } } public void testNullsSkipWithMaps() throws Exception { // Then: Map final String MAP_JSON = aposToQuotes("{'values':{'A':'foo','B':null,'C':'bar'}}"); { NullContentSkip> result = MAPPER.readValue(MAP_JSON, new TypeReference>>() { }); assertEquals(2, result.values.size()); assertEquals("foo", result.values.get("A")); assertEquals("bar", result.values.get("C")); } // Then: EnumMap { NullContentSkip> result = MAPPER.readValue(MAP_JSON, new TypeReference>>() { }); assertEquals(2, result.values.size()); assertEquals("foo", result.values.get(ABC.A)); assertEquals("bar", result.values.get(ABC.C)); } } } NullConversionsGenericTest.java000066400000000000000000000077361325620701100412520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; // for [databind#1402]; configurable null handling, for values themselves, // using generic types public class NullConversionsGenericTest extends BaseMapTest { static class GeneralEmpty { // 09-Feb-2017, tatu: Should only need annotation either for field OR setter, not both: // @JsonSetter(nulls=JsonSetter.Nulls.AS_EMPTY) T value; @JsonSetter(nulls=Nulls.AS_EMPTY) public void setValue(T v) { value = v; } } static class NoCtorWrapper { @JsonSetter(nulls=Nulls.AS_EMPTY) public NoCtorPOJO value; } static class NoCtorPOJO { public NoCtorPOJO(boolean b) { } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testNullsToEmptyPojo() throws Exception { GeneralEmpty result = MAPPER.readValue(aposToQuotes("{'value':null}"), new TypeReference>() { }); assertNotNull(result.value); Point p = result.value; assertEquals(0, p.x); assertEquals(0, p.y); // and then also failing case with no suitable creator: try { /* NoCtorWrapper nogo =*/ MAPPER.readValue(aposToQuotes("{'value':null}"), NoCtorWrapper.class); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot create empty instance"); } } public void testNullsToEmptyCollection() throws Exception { GeneralEmpty> result = MAPPER.readValue(aposToQuotes("{'value':null}"), new TypeReference>>() { }); assertNotNull(result.value); assertEquals(0, result.value.size()); // but also non-String type, since impls vary GeneralEmpty> result2 = MAPPER.readValue(aposToQuotes("{'value':null}"), new TypeReference>>() { }); assertNotNull(result2.value); assertEquals(0, result2.value.size()); } public void testNullsToEmptyMap() throws Exception { GeneralEmpty> result = MAPPER.readValue(aposToQuotes("{'value':null}"), new TypeReference>>() { }); assertNotNull(result.value); assertEquals(0, result.value.size()); } public void testNullsToEmptyArrays() throws Exception { final String json = aposToQuotes("{'value':null}"); GeneralEmpty result = MAPPER.readValue(json, new TypeReference>() { }); assertNotNull(result.value); assertEquals(0, result.value.length); GeneralEmpty result2 = MAPPER.readValue(json, new TypeReference>() { }); assertNotNull(result2.value); assertEquals(0, result2.value.length); GeneralEmpty result3 = MAPPER.readValue(json, new TypeReference>() { }); assertNotNull(result3.value); assertEquals(0, result3.value.length); GeneralEmpty result4 = MAPPER.readValue(json, new TypeReference>() { }); assertNotNull(result4.value); assertEquals(0, result4.value.length); GeneralEmpty result5 = MAPPER.readValue(json, new TypeReference>() { }); assertNotNull(result5.value); assertEquals(0, result5.value.length); } } NullConversionsPojoTest.java000066400000000000000000000070141325620701100405720ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidNullException; // for [databind#1402]; configurable null handling, for values themselves public class NullConversionsPojoTest extends BaseMapTest { static class NullFail { public String nullsOk = "a"; @JsonSetter(nulls=Nulls.FAIL) public String noNulls = "b"; } static class NullAsEmpty { public String nullsOk = "a"; @JsonSetter(nulls=Nulls.AS_EMPTY) public String nullAsEmpty = "b"; } static class NullsForString { /* String n = "foo"; public void setName(String name) { n = name; } */ String n = "foo"; public void setName(String n0) { n = n0; } public String getName() { return n; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testFailOnNull() throws Exception { // first, ok if assigning non-null to not-nullable, null for nullable NullFail result = MAPPER.readValue(aposToQuotes("{'noNulls':'foo', 'nullsOk':null}"), NullFail.class); assertEquals("foo", result.noNulls); assertNull(result.nullsOk); // and then see that nulls are not ok for non-nullable try { result = MAPPER.readValue(aposToQuotes("{'noNulls':null}"), NullFail.class); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"noNulls\""); } } public void testFailOnNullWithDefaults() throws Exception { // also: config overrides by type should work String json = aposToQuotes("{'name':null}"); NullsForString def = MAPPER.readValue(json, NullsForString.class); assertNull(def.getName()); ObjectMapper mapper = newObjectMapper(); mapper.configOverride(String.class) .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.FAIL)); try { mapper.readValue(json, NullsForString.class); fail("Should not pass"); } catch (InvalidNullException e) { verifyException(e, "property \"name\""); } } public void testNullsToEmptyScalar() throws Exception { NullAsEmpty result = MAPPER.readValue(aposToQuotes("{'nullAsEmpty':'foo', 'nullsOk':null}"), NullAsEmpty.class); assertEquals("foo", result.nullAsEmpty); assertNull(result.nullsOk); // and then see that nulls are not ok for non-nullable result = MAPPER.readValue(aposToQuotes("{'nullAsEmpty':null}"), NullAsEmpty.class); assertEquals("", result.nullAsEmpty); // also: config overrides by type should work String json = aposToQuotes("{'name':null}"); NullsForString def = MAPPER.readValue(json, NullsForString.class); assertNull(def.getName()); ObjectMapper mapper = newObjectMapper(); mapper.configOverride(String.class) .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); NullsForString named = mapper.readValue(json, NullsForString.class); assertEquals("", named.getName()); } } NullConversionsSkipTest.java000066400000000000000000000056311325620701100405740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.*; // for [databind#1402]; configurable null handling, specifically with SKIP public class NullConversionsSkipTest extends BaseMapTest { static class NullSkipField { public String nullsOk = "a"; @JsonSetter(nulls=Nulls.SKIP) public String noNulls = "b"; } static class NullSkipMethod { String _nullsOk = "a"; String _noNulls = "b"; public void setNullsOk(String v) { _nullsOk = v; } @JsonSetter(nulls=Nulls.SKIP) public void setNoNulls(String v) { _noNulls = v; } } static class StringValue { String value = "default"; public void setValue(String v) { value = v; } } /* /********************************************************** /* Test methods, straight annotation /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testSkipNullField() throws Exception { // first, ok if assigning non-null to not-nullable, null for nullable NullSkipField result = MAPPER.readValue(aposToQuotes("{'noNulls':'foo', 'nullsOk':null}"), NullSkipField.class); assertEquals("foo", result.noNulls); assertNull(result.nullsOk); // and then see that nulls are not ok for non-nullable result = MAPPER.readValue(aposToQuotes("{'noNulls':null}"), NullSkipField.class); assertEquals("b", result.noNulls); assertEquals("a", result.nullsOk); } public void testSkipNullMethod() throws Exception { NullSkipMethod result = MAPPER.readValue(aposToQuotes("{'noNulls':'foo', 'nullsOk':null}"), NullSkipMethod.class); assertEquals("foo", result._noNulls); assertNull(result._nullsOk); result = MAPPER.readValue(aposToQuotes("{'noNulls':null}"), NullSkipMethod.class); assertEquals("b", result._noNulls); assertEquals("a", result._nullsOk); } /* /********************************************************** /* Test methods, defaulting /********************************************************** */ public void testSkipNullWithDefaults() throws Exception { String json = aposToQuotes("{'value':null}"); StringValue result = MAPPER.readValue(json, StringValue.class); assertNull(result.value); ObjectMapper mapper = newObjectMapper(); mapper.configOverride(String.class) .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP)); result = mapper.readValue(json, StringValue.class); assertEquals("default", result.value); } } ProblemHandlerLocation1440Test.java000066400000000000000000000121341325620701100414760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; // Test(s) to verify [databind#1440] public class ProblemHandlerLocation1440Test extends BaseMapTest { static class DeserializationProblem { public List unknownProperties = new ArrayList<>(); public DeserializationProblem() { } public void addUnknownProperty(final String prop) { unknownProperties.add(prop); } public boolean foundProblems() { return !unknownProperties.isEmpty(); } @Override public String toString() { return "DeserializationProblem{" +"unknownProperties=" + unknownProperties +'}'; } } static class DeserializationProblemLogger extends DeserializationProblemHandler { public DeserializationProblem probs = new DeserializationProblem(); public List problems() { return probs.unknownProperties; } @Override public boolean handleUnknownProperty(final DeserializationContext ctxt, final JsonParser p, JsonDeserializer deserializer, Object beanOrClass, String propertyName) throws IOException { final JsonStreamContext parsingContext = p.getParsingContext(); final List pathList = new ArrayList<>(); addParent(parsingContext, pathList); Collections.reverse(pathList); final String path = _join(".", pathList) + "#" + propertyName; probs.addUnknownProperty(path); p.skipChildren(); return true; } static String _join(String sep, Collection parts) { StringBuilder sb = new StringBuilder(); for (String part : parts) { if (sb.length() > 0) { sb.append(sep); } sb.append(part); } return sb.toString(); } private void addParent(final JsonStreamContext streamContext, final List pathList) { if (streamContext != null && streamContext.getCurrentName() != null) { pathList.add(streamContext.getCurrentName()); addParent(streamContext.getParent(), pathList); } } } @JsonInclude(JsonInclude.Include.NON_NULL) static class Activity { public ActivityEntity actor; public String verb; public ActivityEntity object; public ActivityEntity target; @JsonCreator public Activity(@JsonProperty("actor") final ActivityEntity actor, @JsonProperty("object") final ActivityEntity object, @JsonProperty("target") final ActivityEntity target, @JsonProperty("verb") final String verb) { this.actor = actor; this.verb = verb; this.object = object; this.target = target; } } @JsonInclude(JsonInclude.Include.NON_NULL) static class ActivityEntity { public String id; public String type; public String status; public String context; @JsonCreator public ActivityEntity(@JsonProperty("id") final String id, @JsonProperty("type") final String type, @JsonProperty("status") final String status, @JsonProperty("context") final String context) { this.id = id; this.type = type; this.status = status; this.context = context; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testIncorrectContext() throws Exception { // need invalid to trigger problem: final String invalidInput = aposToQuotes( "{'actor': {'id': 'actor_id','type': 'actor_type'," +"'status': 'actor_status','context':'actor_context','invalid_1': 'actor_invalid_1'}," +"'verb': 'verb','object': {'id': 'object_id','type': 'object_type'," +"'invalid_2': 'object_invalid_2','status': 'object_status','context': 'object_context'}," +"'target': {'id': 'target_id','type': 'target_type','invalid_3': 'target_invalid_3'," +"'invalid_4': 'target_invalid_4','status': 'target_status','context': 'target_context'}}" ); ObjectMapper mapper = newObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); final DeserializationProblemLogger logger = new DeserializationProblemLogger(); mapper.addHandler(logger); mapper.readValue(invalidInput, Activity.class); List probs = logger.problems(); assertEquals(4, probs.size()); assertEquals("actor.invalid_1#invalid_1", probs.get(0)); assertEquals("object.invalid_2#invalid_2", probs.get(1)); assertEquals("target.invalid_3#invalid_3", probs.get(2)); assertEquals("target.invalid_4#invalid_4", probs.get(3)); } } ProblemHandlerTest.java000066400000000000000000000253031325620701100374760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import java.io.IOException; import java.util.Map; import java.util.UUID; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; import com.fasterxml.jackson.databind.exc.InvalidTypeIdException; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; /** * Tests to exercise handler methods of {@link DeserializationProblemHandler}. * * @since 2.8 */ public class ProblemHandlerTest extends BaseMapTest { /* /********************************************************** /* Test handler types /********************************************************** */ static class WeirdKeyHandler extends DeserializationProblemHandler { protected final Object key; public WeirdKeyHandler(Object key0) { key = key0; } @Override public Object handleWeirdKey(DeserializationContext ctxt, Class rawKeyType, String keyValue, String failureMsg) throws IOException { return key; } } static class WeirdNumberHandler extends DeserializationProblemHandler { protected final Object value; public WeirdNumberHandler(Object v0) { value = v0; } @Override public Object handleWeirdNumberValue(DeserializationContext ctxt, Class targetType, Number n, String failureMsg) throws IOException { return value; } } static class WeirdStringHandler extends DeserializationProblemHandler { protected final Object value; public WeirdStringHandler(Object v0) { value = v0; } @Override public Object handleWeirdStringValue(DeserializationContext ctxt, Class targetType, String v, String failureMsg) throws IOException { return value; } } static class InstantiationProblemHandler extends DeserializationProblemHandler { protected final Object value; public InstantiationProblemHandler(Object v0) { value = v0; } @Override public Object handleInstantiationProblem(DeserializationContext ctxt, Class instClass, Object argument, Throwable t) throws IOException { if (!(t instanceof InvalidDefinitionException)) { throw new IllegalArgumentException("Should have gotten `InvalidDefinitionException`, instead got: "+t); } return value; } } static class MissingInstantiationHandler extends DeserializationProblemHandler { protected final Object value; public MissingInstantiationHandler(Object v0) { value = v0; } @Override public Object handleMissingInstantiator(DeserializationContext ctxt, Class instClass, ValueInstantiator inst, JsonParser p, String msg) throws IOException { p.skipChildren(); return value; } } static class WeirdTokenHandler extends DeserializationProblemHandler { protected final Object value; public WeirdTokenHandler(Object v) { value = v; } @Override public Object handleUnexpectedToken(DeserializationContext ctxt, Class targetType, JsonToken t, JsonParser p, String failureMsg) throws IOException { return value; } } static class UnknownTypeIdHandler extends DeserializationProblemHandler { protected final Class raw; public UnknownTypeIdHandler(Class r) { raw = r; } @Override public JavaType handleUnknownTypeId(DeserializationContext ctxt, JavaType baseType, String subTypeId, TypeIdResolver idResolver, String failureMsg) throws IOException { return ctxt.constructType(raw); } } static class MissingTypeIdHandler extends DeserializationProblemHandler { protected final Class raw; public MissingTypeIdHandler(Class r) { raw = r; } @Override public JavaType handleMissingTypeId(DeserializationContext ctxt, JavaType baseType, TypeIdResolver idResolver, String failureMsg) throws IOException { return ctxt.constructType(raw); } } /* /********************************************************** /* Other helper types /********************************************************** */ static class IntKeyMapWrapper { public Map stuff; } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") static class Base { } static class BaseImpl extends Base { public int a; } static class BaseWrapper { public Base value; } @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "clazz") static class Base2 { } static class Base2Impl extends Base2 { public int a; } static class Base2Wrapper { public Base2 value; } enum SingleValuedEnum { A; } static class BustedCtor { public final static BustedCtor INST = new BustedCtor(true); public BustedCtor() { throw new RuntimeException("Fail! (to be caught by handler)"); } private BustedCtor(boolean b) { } } static class NoDefaultCtor { public int value; public NoDefaultCtor(int v) { value = v; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testWeirdKeyHandling() throws Exception { ObjectMapper mapper = newObjectMapper() .addHandler(new WeirdKeyHandler(7)); IntKeyMapWrapper w = mapper.readValue("{\"stuff\":{\"foo\":\"abc\"}}", IntKeyMapWrapper.class); Map map = w.stuff; assertEquals(1, map.size()); assertEquals("abc", map.values().iterator().next()); assertEquals(Integer.valueOf(7), map.keySet().iterator().next()); } public void testWeirdNumberHandling() throws Exception { ObjectMapper mapper = newObjectMapper() .addHandler(new WeirdNumberHandler(SingleValuedEnum.A)) ; SingleValuedEnum result = mapper.readValue("3", SingleValuedEnum.class); assertEquals(SingleValuedEnum.A, result); } public void testWeirdStringHandling() throws Exception { ObjectMapper mapper = newObjectMapper() .addHandler(new WeirdStringHandler(SingleValuedEnum.A)) ; SingleValuedEnum result = mapper.readValue("\"B\"", SingleValuedEnum.class); assertEquals(SingleValuedEnum.A, result); // also, write [databind#1629] try this mapper = new ObjectMapper() .addHandler(new WeirdStringHandler(null)); UUID result2 = mapper.readValue(quote("not a uuid!"), UUID.class); assertNull(result2); } public void testInvalidTypeId() throws Exception { ObjectMapper mapper = newObjectMapper() .addHandler(new UnknownTypeIdHandler(BaseImpl.class)); BaseWrapper w = mapper.readValue("{\"value\":{\"type\":\"foo\",\"a\":4}}", BaseWrapper.class); assertNotNull(w); assertEquals(BaseImpl.class, w.value.getClass()); } public void testInvalidClassAsId() throws Exception { ObjectMapper mapper = newObjectMapper() .addHandler(new UnknownTypeIdHandler(Base2Impl.class)); Base2Wrapper w = mapper.readValue("{\"value\":{\"clazz\":\"com.fizz\",\"a\":4}}", Base2Wrapper.class); assertNotNull(w); assertEquals(Base2Impl.class, w.value.getClass()); } // 2.9: missing type id, distinct from unknown public void testMissingTypeId() throws Exception { ObjectMapper mapper = newObjectMapper() .addHandler(new MissingTypeIdHandler(BaseImpl.class)); BaseWrapper w = mapper.readValue("{\"value\":{\"a\":4}}", BaseWrapper.class); assertNotNull(w); assertEquals(BaseImpl.class, w.value.getClass()); } public void testMissingClassAsId() throws Exception { ObjectMapper mapper = newObjectMapper() .addHandler(new MissingTypeIdHandler(Base2Impl.class)); Base2Wrapper w = mapper.readValue("{\"value\":{\"a\":4}}", Base2Wrapper.class); assertNotNull(w); assertEquals(Base2Impl.class, w.value.getClass()); } // verify that by default we get special exception type public void testInvalidTypeIdFail() throws Exception { try { MAPPER.readValue("{\"value\":{\"type\":\"foo\",\"a\":4}}", BaseWrapper.class); fail("Should not pass"); } catch (InvalidTypeIdException e) { verifyException(e, "Could not resolve type id 'foo'"); assertEquals(Base.class, e.getBaseType().getRawClass()); assertEquals("foo", e.getTypeId()); } } public void testInstantiationExceptionHandling() throws Exception { ObjectMapper mapper = newObjectMapper() .addHandler(new InstantiationProblemHandler(BustedCtor.INST)); BustedCtor w = mapper.readValue("{ }", BustedCtor.class); assertNotNull(w); } public void testMissingInstantiatorHandling() throws Exception { ObjectMapper mapper = newObjectMapper() .addHandler(new MissingInstantiationHandler(new NoDefaultCtor(13))) ; NoDefaultCtor w = mapper.readValue("{ \"x\" : true }", NoDefaultCtor.class); assertNotNull(w); assertEquals(13, w.value); } public void testUnexpectedTokenHandling() throws Exception { ObjectMapper mapper = newObjectMapper() .addHandler(new WeirdTokenHandler(Integer.valueOf(13))) ; Integer v = mapper.readValue("true", Integer.class); assertEquals(Integer.valueOf(13), v); } } ReadOnlyDeser1890Test.java000066400000000000000000000055751325620701100376330ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import java.beans.ConstructorProperties; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class ReadOnlyDeser1890Test extends BaseMapTest { public static class PersonAnnotations { public String name; @JsonProperty(access = JsonProperty.Access.READ_ONLY) private TestEnum testEnum = TestEnum.DEFAULT; PersonAnnotations() { } @ConstructorProperties({"testEnum", "name"}) public PersonAnnotations(TestEnum testEnum, String name) { this.testEnum = testEnum; this.name = name; } public TestEnum getTestEnum() { return testEnum; } public void setTestEnum(TestEnum testEnum) { this.testEnum = testEnum; } } public static class Person { public String name; @JsonProperty(access = JsonProperty.Access.READ_ONLY) private TestEnum testEnum = TestEnum.DEFAULT; Person() { } public Person(TestEnum testEnum, String name) { this.testEnum = testEnum; this.name = name; } public TestEnum getTestEnum() { return testEnum; } public void setTestEnum(TestEnum testEnum) { this.testEnum = testEnum; } } enum TestEnum{ DEFAULT, TEST; } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testDeserializeAnnotationsOneField() throws IOException { PersonAnnotations person = MAPPER.readValue("{\"testEnum\":\"\"}", PersonAnnotations.class); // can not remain as is, so becomes `null` assertEquals(null, person.getTestEnum()); assertNull(person.name); } public void testDeserializeAnnotationsTwoFields() throws IOException { PersonAnnotations person = MAPPER.readValue("{\"testEnum\":\"\",\"name\":\"changyong\"}", PersonAnnotations.class); // can not remain as is, so becomes `null` assertEquals(null, person.getTestEnum()); assertEquals("changyong", person.name); } public void testDeserializeOneField() throws IOException { Person person = MAPPER.readValue("{\"testEnum\":\"\"}", Person.class); assertEquals(TestEnum.DEFAULT, person.getTestEnum()); assertNull(person.name); } public void testDeserializeTwoFields() throws IOException { Person person = MAPPER.readValue("{\"testEnum\":\"\",\"name\":\"changyong\"}", Person.class); assertEquals(TestEnum.DEFAULT, person.getTestEnum()); assertEquals("changyong", person.name); } } ReadOnlyDeser95Test.java000066400000000000000000000015301325620701100374520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.*; /** * Failing test related to [databind#95] */ public class ReadOnlyDeser95Test extends BaseMapTest { @JsonIgnoreProperties(value={ "computed" }, allowGetters=true) static class ReadOnlyBean { public int value = 3; public int getComputed() { return 32; } } public void testReadOnlyProp() throws Exception { ObjectMapper m = new ObjectMapper(); String json = m.writeValueAsString(new ReadOnlyBean()); if (json.indexOf("computed") < 0) { fail("Should have property 'computed', didn't: "+json); } ReadOnlyBean bean = m.readValue(json, ReadOnlyBean.class); assertNotNull(bean); } } RecursiveIgnorePropertiesTest.java000066400000000000000000000025221325620701100417660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; public class RecursiveIgnorePropertiesTest extends BaseMapTest { static class Person { public String name; @JsonProperty("person_z") // renaming this to person_p works @JsonIgnoreProperties({"person_z"}) // renaming this to person_p works // public Set personZ; public Person personZ; } public void testRecursiveForDeser() throws Exception { String st = aposToQuotes("{ 'name': 'admin',\n" // + " 'person_z': [ { 'name': 'admin' } ]" + " 'person_z': { 'name': 'admin' }" + "}"); ObjectMapper mapper = newObjectMapper(); Person result = mapper.readValue(st, Person.class); assertEquals("admin", result.name); } public void testRecursiveForSer() throws Exception { ObjectMapper mapper = newObjectMapper(); Person input = new Person(); input.name = "Bob"; Person p2 = new Person(); p2.name = "Bill"; input.personZ = p2; p2.personZ = input; String json = mapper.writeValueAsString(input); assertNotNull(json); } } TestUnknownPropertyDeserialization.java000066400000000000000000000224401325620701100430520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/filterpackage com.fasterxml.jackson.databind.deser.filter; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; /** * Unit tests for checking handling of unknown properties */ public class TestUnknownPropertyDeserialization extends BaseMapTest { final static String JSON_UNKNOWN_FIELD = "{ \"a\" : 1, \"foo\" : [ 1, 2, 3], \"b\" : -1 }"; /* /********************************************************** /* Helper classes /********************************************************** */ final static class TestBean { String _unknown; int _a, _b; public TestBean() { } public void setA(int a) { _a = a; } public void setB(int b) { _b = b; } public void markUnknown(String unk) { _unknown = unk; } } /** * Simple {@link DeserializationProblemHandler} sub-class that * just marks unknown property/ies when encountered, along with * Json value of the property. */ static class MyHandler extends DeserializationProblemHandler { @Override public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser jp, JsonDeserializer deserializer, Object bean, String propertyName) throws IOException, JsonProcessingException { // very simple, just to verify that we do see correct token type ((TestBean) bean).markUnknown(propertyName+":"+jp.getCurrentToken().toString()); // Yup, we are good to go; must skip whatever value we'd have: jp.skipChildren(); return true; } } @JsonIgnoreProperties({"b", "c"}) static class IgnoreSome { public int a, b; private String c, d; public IgnoreSome() { } public String c() { return c; } public void setC(String value) { c = value; } public String d() { return d; } public void setD(String value) { d = value; } } @JsonIgnoreProperties(ignoreUnknown=true) static class IgnoreUnknown { public int a; } @SuppressWarnings("serial") @JsonIgnoreProperties({"a", "d"}) static class IgnoreMap extends HashMap { } static class ImplicitIgnores { @JsonIgnore public int a; @JsonIgnore public void setB(int b) { } public int c; } // // Ignored as per [JACKSON-787] static class XYZWrapper1 { @JsonIgnoreProperties({"x"}) public YZ value; } static class YZ { public int y, z; } static class XYZWrapper2 { @JsonIgnoreProperties({"y"}) public X value; } @JsonIgnoreProperties({"z"}) static class X { public int x; } static class MapWithoutX { @JsonIgnoreProperties("x") public Map values; } // [databind#987] static class Bean987 { public String aProperty; } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); /** * By default we should just get an exception if an unknown property * is encountered */ public void testUnknownHandlingDefault() throws Exception { try { MAPPER.readValue(new StringReader(JSON_UNKNOWN_FIELD), TestBean.class); } catch (JsonMappingException jex) { verifyException(jex, "Unrecognized field \"foo\""); } } /** * Test that verifies that it is possible to ignore unknown properties using * {@link DeserializationProblemHandler}. */ public void testUnknownHandlingIgnoreWithHandler() throws Exception { ObjectMapper mapper = newObjectMapper(); mapper.clearProblemHandlers(); mapper.addHandler(new MyHandler()); TestBean result = mapper.readValue(new StringReader(JSON_UNKNOWN_FIELD), TestBean.class); assertNotNull(result); assertEquals(1, result._a); assertEquals(-1, result._b); assertEquals("foo:START_ARRAY", result._unknown); } /** * Test that verifies that it is possible to ignore unknown properties using * {@link DeserializationProblemHandler} and an ObjectReader. */ public void testUnknownHandlingIgnoreWithHandlerAndObjectReader() throws Exception { ObjectMapper mapper = newObjectMapper(); mapper.clearProblemHandlers(); TestBean result = mapper.readerFor(TestBean.class).withHandler(new MyHandler()).readValue(new StringReader(JSON_UNKNOWN_FIELD)); assertNotNull(result); assertEquals(1, result._a); assertEquals(-1, result._b); assertEquals("foo:START_ARRAY", result._unknown); } /** * Test for checking that it is also possible to simply suppress * error reporting for unknown properties. */ public void testUnknownHandlingIgnoreWithFeature() throws Exception { ObjectMapper mapper = newObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); TestBean result = null; try { result = mapper.readValue(new StringReader(JSON_UNKNOWN_FIELD), TestBean.class); } catch (JsonMappingException jex) { fail("Did not expect a problem, got: "+jex.getMessage()); } assertNotNull(result); assertEquals(1, result._a); assertNull(result._unknown); assertEquals(-1, result._b); } public void testWithClassIgnore() throws Exception { IgnoreSome result = MAPPER.readValue("{ \"a\":1,\"b\":2,\"c\":\"x\",\"d\":\"y\"}", IgnoreSome.class); // first: should deserialize 2 of properties normally assertEquals(1, result.a); assertEquals("y", result.d()); // and not take other 2 assertEquals(0, result.b); assertNull(result.c()); } /// @since 1.4 public void testClassIgnoreWithMap() throws Exception { // Let's actually use incompatible types for "a" and "d"; should not matter when ignored IgnoreMap result = MAPPER.readValue ("{ \"a\":[ 1],\n" +"\"b\":2,\n" +"\"c\": \"x\",\n" +"\"d\":false }", IgnoreMap.class); assertEquals(2, result.size()); Object ob = result.get("b"); assertEquals(Integer.class, ob.getClass()); assertEquals(Integer.valueOf(2), ob); assertEquals("x", result.get("c")); assertFalse(result.containsKey("a")); assertFalse(result.containsKey("d")); } public void testClassWithIgnoreUnknown() throws Exception { IgnoreUnknown result = MAPPER.readValue ("{\"b\":3,\"c\":[1,2],\"x\":{ },\"a\":-3}", IgnoreUnknown.class); assertEquals(-3, result.a); } /** * Test that verifies that use of {@link JsonIgnore} will add implicit * skipping of matching properties. */ public void testClassWithUnknownAndIgnore() throws Exception { // should be ok: "a" and "b" ignored, "c" mapped: ImplicitIgnores result = MAPPER.readValue ("{\"a\":1,\"b\":2,\"c\":3 }", ImplicitIgnores.class); assertEquals(3, result.c); // but "d" is not defined, so should still error try { MAPPER.readValue("{\"a\":1,\"b\":2,\"c\":3,\"d\":4 }", ImplicitIgnores.class); } catch (JsonMappingException e) { verifyException(e, "Unrecognized field \"d\""); } } public void testPropertyIgnoral() throws Exception { XYZWrapper1 result = MAPPER.readValue("{\"value\":{\"y\":2,\"x\":1,\"z\":3}}", XYZWrapper1.class); assertEquals(2, result.value.y); assertEquals(3, result.value.z); } public void testPropertyIgnoralWithClass() throws Exception { XYZWrapper2 result = MAPPER.readValue("{\"value\":{\"y\":2,\"x\":1,\"z\":3}}", XYZWrapper2.class); assertEquals(1, result.value.x); } public void testPropertyIgnoralForMap() throws Exception { MapWithoutX result = MAPPER.readValue("{\"values\":{\"x\":1,\"y\":2}}", MapWithoutX.class); assertNotNull(result.values); assertEquals(1, result.values.size()); assertEquals(Integer.valueOf(2), result.values.get("y")); } public void testIssue987() throws Exception { ObjectMapper jsonMapper = newObjectMapper(); jsonMapper.addHandler(new DeserializationProblemHandler() { @Override public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer deserializer, Object beanOrClass, String propertyName) throws IOException, JsonProcessingException { p.skipChildren(); return true; } }); String input = "[{\"aProperty\":\"x\",\"unknown\":{\"unknown\":{}}}]"; List deserializedList = jsonMapper.readValue(input, new TypeReference>() { }); assertEquals(1, deserializedList.size()); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/inject/000077500000000000000000000000001325620701100331405ustar00rootroot00000000000000InvalidInjectionTest.java000066400000000000000000000025031325620701100400150ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/injectpackage com.fasterxml.jackson.databind.deser.inject; import com.fasterxml.jackson.annotation.JacksonInject; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; public class InvalidInjectionTest extends BaseMapTest { static class BadBean1 { @JacksonInject protected String prop1; @JacksonInject protected String prop2; } static class BadBean2 { @JacksonInject("x") protected String prop1; @JacksonInject("x") protected String prop2; } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testInvalidDup() throws Exception { try { MAPPER.readValue("{}", BadBean1.class); fail("Should not pass"); } catch (InvalidDefinitionException e) { verifyException(e, "Duplicate injectable value"); } try { MAPPER.readValue("{}", BadBean2.class); fail("Should not pass"); } catch (InvalidDefinitionException e) { verifyException(e, "Duplicate injectable value"); } } } TestInjectables.java000066400000000000000000000125101325620701100370060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/injectpackage com.fasterxml.jackson.databind.deser.inject; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestInjectables extends BaseMapTest { static class InjectedBean { @JacksonInject protected String stuff; @JacksonInject("myId") protected String otherStuff; protected long third; public int value; @JacksonInject public void injectThird(long v) { third = v; } } static class CtorBean { protected String name; protected int age; public CtorBean(@JacksonInject String n, @JsonProperty("age") int a) { name = n; age = a; } } static class CtorBean2 { protected String name; protected Integer age; public CtorBean2(@JacksonInject String n, @JacksonInject("number") Integer a) { name = n; age = a; } } // [databind#77] static class TransientBean { @JacksonInject("transient") transient Object injected; public int value; } static class Bean471 { protected final Object constructorInjected; protected final String constructorValue; @JacksonInject("field_injected") protected Object fieldInjected; @JsonProperty("field_value") protected String fieldValue; protected Object methodInjected; protected String methodValue; public int x; @JsonCreator private Bean471(@JacksonInject("constructor_injected") Object constructorInjected, @JsonProperty("constructor_value") String constructorValue) { this.constructorInjected = constructorInjected; this.constructorValue = constructorValue; } @JacksonInject("method_injected") private void setMethodInjected(Object methodInjected) { this.methodInjected = methodInjected; } @JsonProperty("method_value") public void setMethodValue(String methodValue) { this.methodValue = methodValue; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testSimple() throws Exception { ObjectMapper mapper = newObjectMapper(); mapper.setInjectableValues(new InjectableValues.Std() .addValue(String.class, "stuffValue") .addValue("myId", "xyz") .addValue(Long.TYPE, Long.valueOf(37)) ); InjectedBean bean = mapper.readValue("{\"value\":3}", InjectedBean.class); assertEquals(3, bean.value); assertEquals("stuffValue", bean.stuff); assertEquals("xyz", bean.otherStuff); assertEquals(37L, bean.third); } public void testWithCtors() throws Exception { CtorBean bean = MAPPER.readerFor(CtorBean.class) .with(new InjectableValues.Std() .addValue(String.class, "Bubba")) .readValue("{\"age\":55}"); assertEquals(55, bean.age); assertEquals("Bubba", bean.name); } public void testTwoInjectablesViaCreator() throws Exception { CtorBean2 bean = MAPPER.readerFor(CtorBean2.class) .with(new InjectableValues.Std() .addValue(String.class, "Bob") .addValue("number", Integer.valueOf(13)) ).readValue("{ }"); assertEquals(Integer.valueOf(13), bean.age); assertEquals("Bob", bean.name); } // [databind#471] public void testIssue471() throws Exception { final Object constructorInjected = "constructorInjected"; final Object methodInjected = "methodInjected"; final Object fieldInjected = "fieldInjected"; ObjectMapper mapper = newObjectMapper() .setInjectableValues(new InjectableValues.Std() .addValue("constructor_injected", constructorInjected) .addValue("method_injected", methodInjected) .addValue("field_injected", fieldInjected)); Bean471 bean = mapper.readValue(aposToQuotes( "{'x':13,'constructor_value':'constructor','method_value':'method','field_value':'field'}"), Bean471.class); /* Assert *SAME* instance */ assertSame(constructorInjected, bean.constructorInjected); assertSame(methodInjected, bean.methodInjected); assertSame(fieldInjected, bean.fieldInjected); /* Check that basic properties still work (better safe than sorry) */ assertEquals("constructor", bean.constructorValue); assertEquals("method", bean.methodValue); assertEquals("field", bean.fieldValue); assertEquals(13, bean.x); } // [databind#77] public void testTransientField() throws Exception { TransientBean bean = MAPPER.readerFor(TransientBean.class) .with(new InjectableValues.Std() .addValue("transient", "Injected!")) .readValue("{\"value\":28}"); assertEquals(28, bean.value); assertEquals("Injected!", bean.injected); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdk/000077500000000000000000000000001325620701100324345ustar00rootroot00000000000000Base64DecodingTest.java000066400000000000000000000033761325620701100365520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.nio.charset.StandardCharsets; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.MismatchedInputException; // Mostly for [databind#1425]; not in optimal place (as it also has // tree-access tests), but has to do for now public class Base64DecodingTest extends BaseMapTest { private final ObjectMapper MAPPER = objectMapper(); private final byte[] HELLO_BYTES = "hello".getBytes(StandardCharsets.UTF_8); private final String BASE64_HELLO = "aGVsbG8="; // for [databind#1425] public void testInvalidBase64() throws Exception { byte[] b = MAPPER.readValue(quote(BASE64_HELLO), byte[].class); assertEquals(HELLO_BYTES, b); _testInvalidBase64(MAPPER, BASE64_HELLO+"!"); _testInvalidBase64(MAPPER, BASE64_HELLO+"!!"); } private void _testInvalidBase64(ObjectMapper mapper, String value) throws Exception { // First, use data-binding try { MAPPER.readValue(quote(value), byte[].class); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "Failed to decode"); verifyException(e, "as base64"); verifyException(e, "Illegal character '!'"); } // and then tree model JsonNode tree = mapper.readTree(String.format("{\"foo\":\"%s\"}", value)); JsonNode nodeValue = tree.get("foo"); try { /*byte[] b =*/ nodeValue.binaryValue(); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "Cannot access contents of TextNode as binary"); verifyException(e, "Illegal character '!'"); } } } CollectionDeserTest.java000066400000000000000000000240121325620701100371350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.IOException; import java.util.*; import java.util.concurrent.ArrayBlockingQueue; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; @SuppressWarnings("serial") public class CollectionDeserTest extends BaseMapTest { enum Key { KEY1, KEY2, WHATEVER; } @JsonDeserialize(using=ListDeserializer.class) static class CustomList extends LinkedList { } static class ListDeserializer extends StdDeserializer { public ListDeserializer() { super(CustomList.class); } @Override public CustomList deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { CustomList result = new CustomList(); result.add(jp.getText()); return result; } } static class XBean { public int x; public XBean() { } public XBean(int x) { this.x = x; } } // [databind#199] static class ListAsIterable { public Iterable values; } static class ListAsIterableX { public Iterable nums; } static class KeyListBean { public List keys; } // [Issue#828] @JsonDeserialize(using=SomeObjectDeserializer.class) static class SomeObject {} static class SomeObjectDeserializer extends StdDeserializer { public SomeObjectDeserializer() { super(SomeObject.class); } @Override public SomeObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { throw new RuntimeException("I want to catch this exception"); } } /* /********************************************************** /* Test methods /********************************************************** */ private final static ObjectMapper MAPPER = new ObjectMapper(); public void testUntypedList() throws Exception { // to get "untyped" default List, pass Object.class String JSON = "[ \"text!\", true, null, 23 ]"; // Not a guaranteed cast theoretically, but will work: // (since we know that Jackson will construct an ArrayList here...) Object value = MAPPER.readValue(JSON, Object.class); assertNotNull(value); assertTrue(value instanceof ArrayList); List result = (List) value; assertEquals(4, result.size()); assertEquals("text!", result.get(0)); assertEquals(Boolean.TRUE, result.get(1)); assertNull(result.get(2)); assertEquals(Integer.valueOf(23), result.get(3)); } public void testExactStringCollection() throws Exception { // to get typing, must use type reference String JSON = "[ \"a\", \"b\" ]"; List result = MAPPER.readValue(JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(ArrayList.class, result.getClass()); assertEquals(2, result.size()); assertEquals("a", result.get(0)); assertEquals("b", result.get(1)); } public void testHashSet() throws Exception { String JSON = "[ \"KEY1\", \"KEY2\" ]"; EnumSet result = MAPPER.readValue(JSON, new TypeReference>() { }); assertNotNull(result); assertTrue(EnumSet.class.isAssignableFrom(result.getClass())); assertEquals(2, result.size()); assertTrue(result.contains(Key.KEY1)); assertTrue(result.contains(Key.KEY2)); assertFalse(result.contains(Key.WHATEVER)); } /// Test to verify that @JsonDeserialize.using works as expected public void testCustomDeserializer() throws IOException { CustomList result = MAPPER.readValue(quote("abc"), CustomList.class); assertEquals(1, result.size()); assertEquals("abc", result.get(0)); } // Testing "implicit JSON array" for single-element arrays, // mostly produced by Jettison, Badgerfish conversions (from XML) @SuppressWarnings("unchecked") public void testImplicitArrays() throws Exception { // can't share mapper, custom configs (could create ObjectWriter tho) ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); // first with simple scalar types (numbers), with collections List ints = mapper.readValue("4", List.class); assertEquals(1, ints.size()); assertEquals(Integer.valueOf(4), ints.get(0)); List strings = mapper.readValue(quote("abc"), new TypeReference>() { }); assertEquals(1, strings.size()); assertEquals("abc", strings.get(0)); // and arrays: int[] intArray = mapper.readValue("-7", int[].class); assertEquals(1, intArray.length); assertEquals(-7, intArray[0]); String[] stringArray = mapper.readValue(quote("xyz"), String[].class); assertEquals(1, stringArray.length); assertEquals("xyz", stringArray[0]); // and then with Beans: List xbeanList = mapper.readValue("{\"x\":4}", new TypeReference>() { }); assertEquals(1, xbeanList.size()); assertEquals(XBean.class, xbeanList.get(0).getClass()); Object ob = mapper.readValue("{\"x\":29}", XBean[].class); XBean[] xbeanArray = (XBean[]) ob; assertEquals(1, xbeanArray.length); assertEquals(XBean.class, xbeanArray[0].getClass()); } // [JACKSON-620]: allow "" to mean 'null' for Maps public void testFromEmptyString() throws Exception { ObjectReader r = MAPPER.reader(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); List result = r.forType(List.class).readValue(quote("")); assertNull(result); } // [databind#161] public void testArrayBlockingQueue() throws Exception { // ok to skip polymorphic type to get Object ArrayBlockingQueue q = MAPPER.readValue("[1, 2, 3]", ArrayBlockingQueue.class); assertNotNull(q); assertEquals(3, q.size()); assertEquals(Integer.valueOf(1), q.take()); assertEquals(Integer.valueOf(2), q.take()); assertEquals(Integer.valueOf(3), q.take()); } // [databind#199] public void testIterableWithStrings() throws Exception { String JSON = "{ \"values\":[\"a\",\"b\"]}"; ListAsIterable w = MAPPER.readValue(JSON, ListAsIterable.class); assertNotNull(w); assertNotNull(w.values); Iterator it = w.values.iterator(); assertTrue(it.hasNext()); assertEquals("a", it.next()); assertEquals("b", it.next()); assertFalse(it.hasNext()); } public void testIterableWithBeans() throws Exception { String JSON = "{ \"nums\":[{\"x\":1},{\"x\":2}]}"; ListAsIterableX w = MAPPER.readValue(JSON, ListAsIterableX.class); assertNotNull(w); assertNotNull(w.nums); Iterator it = w.nums.iterator(); assertTrue(it.hasNext()); XBean xb = it.next(); assertNotNull(xb); assertEquals(1, xb.x); xb = it.next(); assertEquals(2, xb.x); assertFalse(it.hasNext()); } // for [databind#506] public void testArrayIndexForExceptions() throws Exception { final String OBJECTS_JSON = "[ \"KEY2\", false ]"; try { MAPPER.readValue(OBJECTS_JSON, Key[].class); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot deserialize"); List refs = e.getPath(); assertEquals(1, refs.size()); assertEquals(1, refs.get(0).getIndex()); } try { MAPPER.readValue("[ \"xyz\", { } ]", String[].class); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot deserialize"); List refs = e.getPath(); assertEquals(1, refs.size()); assertEquals(1, refs.get(0).getIndex()); } try { MAPPER.readValue("{\"keys\":"+OBJECTS_JSON+"}", KeyListBean.class); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot deserialize"); List refs = e.getPath(); assertEquals(2, refs.size()); // Bean has no index, but has name: assertEquals(-1, refs.get(0).getIndex()); assertEquals("keys", refs.get(0).getFieldName()); // and for List, reverse: assertEquals(1, refs.get(1).getIndex()); assertNull(refs.get(1).getFieldName()); } } // for [databind#828] public void testWrapExceptions() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.WRAP_EXCEPTIONS); try { mapper.readValue("[{}]", new TypeReference>() {}); } catch (JsonMappingException exc) { assertEquals("I want to catch this exception", exc.getOriginalMessage()); } catch (RuntimeException exc) { fail("The RuntimeException should have been wrapped with a JsonMappingException."); } ObjectMapper mapperNoWrap = new ObjectMapper(); mapperNoWrap.disable(DeserializationFeature.WRAP_EXCEPTIONS); try { mapperNoWrap.readValue("[{}]", new TypeReference>() {}); } catch (JsonMappingException exc) { fail("It should not have wrapped the RuntimeException."); } catch (RuntimeException exc) { assertEquals("I want to catch this exception", exc.getMessage()); } } } DateDeserializationTZTest.java000066400000000000000000000603651325620701100402740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.math.BigInteger; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import com.fasterxml.jackson.databind.exc.MismatchedInputException; /** * Additional `java.util.Date` deserialization tests for cases where `ObjectMapper` * is configured to use timezone different from UTC. */ @SuppressWarnings("javadoc") public class DateDeserializationTZTest extends BaseMapTest { private static final String LOCAL_TZ = "GMT+2"; private static final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); static class Annot_TimeZone { @JsonFormat(timezone="GMT+4") private java.util.Date date; } static class Annot_Pattern { @JsonFormat(pattern="'*'d MMM yyyy HH:mm:ss'*'") private java.util.Date pattern; @JsonFormat(pattern="'*'d MMM yyyy HH:mm:ss'*'", locale="FR") private java.util.Date pattern_FR; @JsonFormat(pattern="'*'d MMM yyyy HH:mm:ss'*'", timezone="GMT+4") private java.util.Date pattern_GMT4; @JsonFormat(pattern="'*'d MMM yyyy HH:mm:ss'*'", locale="FR", timezone="GMT+4") private java.util.Date pattern_FR_GMT4; } static class DateAsStringBean { @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="/yyyy/MM/dd/") public Date date; } static class DateAsStringBeanGermany { @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="/yyyy/MM/dd/", locale="fr_FR") public Date date; } private ObjectMapper MAPPER; @Override protected void setUp() throws Exception { super.setUp(); // Create an ObjectMapper with its timezone set to something other than the default (UTC). // This way we can verify that serialization and deserialization actually consider the time // zone set on the mapper. ObjectMapper m = new ObjectMapper(); m.setTimeZone(TimeZone.getTimeZone(LOCAL_TZ)); MAPPER = m; FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); } /* /********************************************************** /* Test methods /********************************************************** */ /** * Test the various timezone/offset representations */ public void testDateUtilISO8601_Timezone() throws Exception { // Complete offset, with ':' between hours and minutes verify( MAPPER, "2000-01-02T03:04:05.678+01:00", judate(2000, 1, 2, 3, 4, 5, 678, "GMT+1")); // Complete offset, without ':' between hours and minutes verify( MAPPER, "2000-01-02T03:04:05.678+0100", judate(2000, 1, 2, 3, 4, 5, 678, "GMT+1")); // Hour offset (no minutes) verify( MAPPER, "2000-01-02T03:04:05.678+01", judate(2000, 1, 2, 3, 4, 5, 678, "GMT+1")); // 'zulu' offset verify( MAPPER, "2000-01-02T03:04:05.678Z", judate(2000, 1, 2, 3, 4, 5, 678, "UTC")); // --------------------------------------------------------------------------------------------- // WARNING: // According to ISO8601, hours and minutes of the offset must be expressed with 2 digits // (not more, not less), i.e. Z or +hh:mm or -hh:mm. See https://www.w3.org/TR/NOTE-datetime. // // The forms below are therefore ILLEGAL and must be refused. // --------------------------------------------------------------------------------------------- failure( MAPPER, "2000-01-02T03:04:05.678+"); failure( MAPPER, "2000-01-02T03:04:05.678+1"); failure( MAPPER, "2000-01-02T03:04:05.678+001"); failure( MAPPER, "2000-01-02T03:04:05.678+00:"); failure( MAPPER, "2000-01-02T03:04:05.678+00:001"); failure( MAPPER, "2000-01-02T03:04:05.678+001:001"); failure( MAPPER, "2000-01-02T03:04:05.678+1:"); failure( MAPPER, "2000-01-02T03:04:05.678+00:1"); } /** * Test the millis */ public void testDateUtilISO8601_DateTimeMillis() throws Exception { // WITH timezone (from 4 to 0 digits) failure(MAPPER, "2000-01-02T03:04:05.0123456789+01:00"); // at most 9 digits for the millis verify( MAPPER, "2000-01-02T03:04:05.6789+01:00", judate(2000, 1, 2, 3, 4, 5, 678, "GMT+1")); verify( MAPPER, "2000-01-02T03:04:05.678+01:00", judate(2000, 1, 2, 3, 4, 5, 678, "GMT+1")); verify( MAPPER, "2000-01-02T03:04:05.67+01:00", judate(2000, 1, 2, 3, 4, 5, 670, "GMT+1")); verify( MAPPER, "2000-01-02T03:04:05.6+01:00", judate(2000, 1, 2, 3, 4, 5, 600, "GMT+1")); verify( MAPPER, "2000-01-02T03:04:05+01:00", judate(2000, 1, 2, 3, 4, 5, 000, "GMT+1")); // WITH timezone Z (from 4 to 0 digits) failure(MAPPER, "2000-01-02T03:04:05.0123456789Z"); // at most 9 digits for the millis verify( MAPPER, "2000-01-02T03:04:05.6789Z", judate(2000, 1, 2, 3, 4, 5, 678, "UTC")); verify( MAPPER, "2000-01-02T03:04:05.678Z", judate(2000, 1, 2, 3, 4, 5, 678, "UTC")); verify( MAPPER, "2000-01-02T03:04:05.67Z", judate(2000, 1, 2, 3, 4, 5, 670, "UTC")); verify( MAPPER, "2000-01-02T03:04:05.6Z", judate(2000, 1, 2, 3, 4, 5, 600, "UTC")); verify( MAPPER, "2000-01-02T03:04:05Z", judate(2000, 1, 2, 3, 4, 5, 0, "UTC")); // WITHOUT timezone (from 4 to 0 digits) failure(MAPPER, "2000-01-02T03:04:05.0123456789"); // at most 9 digits for the millis verify( MAPPER, "2000-01-02T03:04:05.6789", judate(2000, 1, 2, 3, 4, 5, 678, LOCAL_TZ)); verify( MAPPER, "2000-01-02T03:04:05.678", judate(2000, 1, 2, 3, 4, 5, 678, LOCAL_TZ)); verify( MAPPER, "2000-01-02T03:04:05.67", judate(2000, 1, 2, 3, 4, 5, 670, LOCAL_TZ)); verify( MAPPER, "2000-01-02T03:04:05.6", judate(2000, 1, 2, 3, 4, 5, 600, LOCAL_TZ)); verify( MAPPER, "2000-01-02T03:04:05", judate(2000, 1, 2, 3, 4, 5, 000, LOCAL_TZ)); // --------------------------------------------------------------------------------------------- // WARNING: // RFC339 includes an Internet profile of the ISO 8601 standard for representation of dates // and times using the Gregorian calendar (https://tools.ietf.org/html/rfc3339). // // The RFC defines a partial time with the following BNF notation (chapter 5.6): // time-hour = 2DIGIT ; 00-23 // time-minute = 2DIGIT ; 00-59 // time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules // time-secfrac = "." 1*DIGIT // partial-time = time-hour ":" time-minute ":" time-second [time-secfrac] // // The second fraction (ie the millis) is optional and can be omitted. However, a fraction // with only a dot (.) and no digit is not allowed. // // The forms below are therefore ILLEGAL and must be refused. // --------------------------------------------------------------------------------------------- // millis part with only a dot (.) and no digits failure( MAPPER, "2000-01-02T03:04:05.+01:00"); failure( MAPPER, "2000-01-02T03:04:05."); failure( MAPPER, "2000-01-02T03:04:05.Z"); } /** * Date+Time representations * * NOTE: millis are not tested here since they are covered by another test case */ public void testDateUtilISO8601_DateTime() throws Exception { // Full representation with a timezone verify(MAPPER, "2000-01-02T03:04:05+01:00", judate(2000, 1, 2, 3, 4, 5, 0, "GMT+1")); // No timezone --> the one configured on the ObjectMapper must be used verify(MAPPER, "2000-01-02T03:04:05", judate(2000, 1, 2, 3, 4, 5, 0, LOCAL_TZ)); // Hours, minutes are mandatory but seconds are optional failure(MAPPER, "2000-01-02T"); failure(MAPPER, "2000-01-02T03"); failure(MAPPER, "2000-01-02T03:"); verify(MAPPER, "2000-01-02T03:04", judate(2000, 1, 2, 3, 4, 0, 0, LOCAL_TZ)); failure(MAPPER, "2000-01-02T03:04:"); // Hours, minutes are mandatory but seconds are optional - test with a TZ failure(MAPPER, "2000-01-02T+01:00"); failure(MAPPER, "2000-01-02T03+01:00"); failure(MAPPER, "2000-01-02T03:+01:00"); verify( MAPPER, "2000-01-02T03:04+01:00", judate(2000, 1, 2, 3, 4, 0, 0, "GMT+1")); failure(MAPPER, "2000-01-02T03:04:+01:00"); failure(MAPPER, "2000-01-02TZ"); failure(MAPPER, "2000-01-02T03Z"); failure(MAPPER, "2000-01-02T03:Z"); verify(MAPPER, "2000-01-02T03:04Z", judate(2000, 1, 2, 3, 4, 0, 0, "UTC")); failure(MAPPER, "2000-01-02T03:04:Z"); // --------------------------------------------------------------------------------------------- // WARNING: // ISO8601 (https://en.wikipedia.org/wiki/ISO_8601#Times) and its RFC339 profile // (https://tools.ietf.org/html/rfc3339, chapter 5.6) seem to require 2 DIGITS for // the hours, minutes and seconds. // // The following forms should therefore be refused but are accepted by Jackson (and // java.text.SimpleDateFormat). They are verified here to detect any changes in future // releases. // // --------------------------------------------------------------------------------------------- // FIXME As highlighted in the tests below, the behaviour is not consistent and largely // depends on wether a timezone and or millis are specified or not. // The tests assert the behavior with different number of digits for hour, min and sec. // Behavior should be the SAME whatever the timezone and/or the millis. // seconds (no TZ) failure( MAPPER, "2000-01-02T03:04:5"); failure( MAPPER, "2000-01-02T03:04:5.000"); failure(MAPPER, "2000-01-02T03:04:005"); // seconds (+01:00) failure(MAPPER, "2000-01-02T03:04:5+01:00"); failure(MAPPER, "2000-01-02T03:04:5.000+01:00"); failure(MAPPER, "2000-01-02T03:04:005+01:00"); // seconds (Z) failure(MAPPER, "2000-01-02T03:04:5Z"); failure( MAPPER, "2000-01-02T03:04:5.000Z"); failure(MAPPER, "2000-01-02T03:04:005Z"); // minutes (no TZ) failure( MAPPER, "2000-01-02T03:4:05"); failure( MAPPER, "2000-01-02T03:4:05.000"); failure(MAPPER, "2000-01-02T03:004:05"); // minutes (+01:00) failure(MAPPER, "2000-01-02T03:4:05+01:00"); failure(MAPPER, "2000-01-02T03:4:05.000+01:00"); failure(MAPPER, "2000-01-02T03:004:05+01:00"); // minutes (Z) failure( MAPPER, "2000-01-02T03:4:05Z"); failure( MAPPER, "2000-01-02T03:4:05.000Z"); failure( MAPPER, "2000-01-02T03:004:05Z"); // hour (no TZ) failure( MAPPER, "2000-01-02T3:04:05"); failure( MAPPER, "2000-01-02T3:04:05.000"); failure(MAPPER, "2000-01-02T003:04:05"); // hour (+01:00) failure(MAPPER, "2000-01-02T3:04:05+01:00"); failure(MAPPER, "2000-01-02T3:04:05.000+01:00"); failure(MAPPER, "2000-01-02T003:04:05+01:00"); // hour (Z) failure( MAPPER, "2000-01-02T3:04:05Z"); failure( MAPPER, "2000-01-02T3:04:05.000Z"); failure( MAPPER, "2000-01-02T003:04:05Z"); } /** * Date-only representations (no Time part) * * NOTE: time part is not tested here since they it is covered by another test case */ public void testDateUtilISO8601_Date() throws Exception { // Date is constructed with the timezone of the ObjectMapper. Time part is set to zero. verify(MAPPER, "2000-01-02", judate(2000, 1, 2, 0, 0, 0, 0, LOCAL_TZ)); // --------------------------------------------------------------------------------------------- // WARNING: // ISO8601 (https://en.wikipedia.org/wiki/ISO_8601#Times) and its RFC339 profile // (https://tools.ietf.org/html/rfc3339, chapter 5.6) seem to require 2 DIGITS for // the month and dayofweek but 4 DIGITS for the year. // // The following forms should therefore be refused but are accepted by Jackson (and // java.text.SimpleDateFormat). They are verified here to detect any changes in future // releases. // --------------------------------------------------------------------------------------------- // day failure( MAPPER, "2000-01-2"); failure( MAPPER, "2000-01-002"); // month failure( MAPPER, "2000-1-02"); failure( MAPPER, "2000-001-02"); // year failure( MAPPER, "20000-01-02"); failure( MAPPER, "200-01-02" ); failure( MAPPER, "20-01-02" ); failure( MAPPER, "2-01-02"); } /** * DateTime as numeric representation */ public void testDateUtil_Numeric() throws Exception { { long now = 123456789L; verify( MAPPER, now, new java.util.Date(now) ); // as a long verify( MAPPER, Long.toString(now), new java.util.Date(now) ); // as a string } { // should be ok to pass as JSON String, as long // as it is plain timestamp (all numbers, 64-bit) long now = 1321992375446L; verify( MAPPER, now, new java.util.Date(now) ); // as a long verify( MAPPER, Long.toString(now), new java.util.Date(now) ); // as a string } { // #267: should handle negative timestamps too; like 12 hours before 1.1.1970 long now = - (24 * 3600 * 1000L); verify( MAPPER, now, new java.util.Date(now) ); // as a long verify( MAPPER, Long.toString(now), new java.util.Date(now) ); // as a string } // value larger than a long (Long.MAX_VALUE+1) BigInteger tooLarge = BigInteger.valueOf(Long.MAX_VALUE).add( BigInteger.valueOf(1) ); failure(MAPPER, tooLarge, InvalidFormatException.class); failure(MAPPER, tooLarge.toString(), InvalidFormatException.class); // decimal value failure(MAPPER, 0.0, MismatchedInputException.class); failure(MAPPER, "0.0", InvalidFormatException.class); } /** * Note: may be these cases are already covered by {@link #testDateUtil_Annotation_PatternAndLocale()} */ public void testDateUtil_Annotation() throws Exception { // Build the input JSON and expected value String json = aposToQuotes("{'date':'/2005/05/25/'}"); java.util.Date expected = judate(2005, 05, 25, 0, 0, 0, 0, LOCAL_TZ); // Read it to make sure the format specified by the annotation is taken into account { DateAsStringBean result = MAPPER.readValue(json, DateAsStringBean.class); assertNotNull(result); assertEquals( expected, result.date ); } { DateAsStringBean result = MAPPER.readerFor(DateAsStringBean.class) .with(Locale.GERMANY) .readValue(json); assertNotNull(result); assertEquals( expected, result.date ); } // or, via annotations { DateAsStringBeanGermany result = MAPPER.readerFor(DateAsStringBeanGermany.class) .readValue(json); assertNotNull(result); assertEquals( expected, result.date ); } } /** * Test a POJO annotated with @JsonFormat to force an pattern. * Alternate with different combination of Locale and TimeZone. */ public void testDateUtil_Annotation_PatternAndLocale() throws Exception { // Change the default locale set on the ObjectMapper to something else than the default. // This way we know if the default is correctly taken into account ObjectMapper mapper = MAPPER.copy(); mapper.setLocale( Locale.ITALY ); // Build the JSON string. This is a mixed of ITALIAN and FRENCH (no ENGLISH because this // would be the default). String json = aposToQuotes("{ 'pattern': '*1 giu 2000 01:02:03*', 'pattern_FR': '*01 juin 2000 01:02:03*', 'pattern_GMT4': '*1 giu 2000 01:02:03*', 'pattern_FR_GMT4': '*1 juin 2000 01:02:03*'}"); Annot_Pattern result = mapper.readValue(json, Annot_Pattern.class); assertNotNull(result); assertEquals( judate(2000, 6, 1, 1, 2, 3, 0, LOCAL_TZ), result.pattern ); assertEquals( judate(2000, 6, 1, 1, 2, 3, 0, LOCAL_TZ), result.pattern_FR ); assertEquals( judate(2000, 6, 1, 1, 2, 3, 0, "GMT+4"), result.pattern_GMT4 ); assertEquals( judate(2000, 6, 1, 1, 2, 3, 0, "GMT+4"), result.pattern_FR_GMT4 ); } /** * Test a POJO annotated with @JsonFormat to force a default TimeZone * other than the one set on the ObjectMapper when the JSON doesn't contain any. */ public void testDateUtil_Annotation_TimeZone() throws Exception { // WITHOUT timezone { String json = aposToQuotes("{ 'date': '2000-01-02T03:04:05.678' }"); Annot_TimeZone result = MAPPER.readValue(json, Annot_TimeZone.class); assertNotNull(result); assertEquals( judate(2000, 1, 2, 3, 4, 5, 678, "GMT+4"), result.date); } // WITH timezone // --> the annotation acts as the "default" timezone. The timezone specified // in the JSON should be considered first. { String json = aposToQuotes("{ 'date': '2000-01-02T03:04:05.678+01:00' }"); Annot_TimeZone result = MAPPER.readValue(json, Annot_TimeZone.class); assertNotNull(result); assertEquals( judate(2000, 1, 2, 3, 4, 5, 678, "GMT+1"), result.date); } } /** * ObjectMapper configured with a custom date format that does NOT handle the TIMEZONE. * Dates must be constructed with the time zone set on the ObjectMapper. */ public void testDateUtil_customDateFormat_withoutTZ() throws Exception { // FIXME // // The general rule with the StdDateFormat is: // the TimeZone of the ObjectMapper is used if the JSON doesn't hold // any timezone/offset information. // // This rule remains valid with the @JsonFormat annotation unless it forces // an explicit timezeone, in which case the latter takes precedence. // // One would expect the same behavior when the StdDateFormat is replaced by a // custom DateFormat on the ObjectMapper. In other words, the timezone of the // DateFormat is of no importance: the ObjectMapper's default should be used // whenever it is needed. // Test first with a non default TZ on the ObjectMapper // --> OK: the mapper's default TZ is used to parse the date. { DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss"); df.setTimeZone( TimeZone.getTimeZone("GMT+4") ); // TZ different from mapper's default ObjectMapper mapper = new ObjectMapper(); mapper.setTimeZone( TimeZone.getTimeZone(LOCAL_TZ) ); mapper.setDateFormat(df); // The mapper's default TZ is used... verify(mapper, "2000-01-02X04:00:00", judate(2000, 1, 2, 4, 00, 00, 00, LOCAL_TZ)); } // Test a second time with the default TZ on the ObjectMapper // Note it is important NOT TO CALL mapper.setTimeZone(...) in this test.. // --> KO: the custom format's TZ is used instead of the mapper's default as above. // { DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss"); df.setTimeZone( TimeZone.getTimeZone("GMT+4") ); // TZ different from mapper's default ObjectMapper mapper = new ObjectMapper(); mapper.setDateFormat(df); // FIXME mapper's default TZ should have been used verify(mapper, "2000-01-02X04:00:00", judate(2000, 1, 2, 4, 00, 00, 00, "GMT+4")); } } /** * ObjectMapper configured with a custom date format that DOES handle the TIMEZONE. * Dates must be constructed from the timezone of the input, regardless of the one * of the ObjectMapper. */ public void testDateUtil_customDateFormat_withTZ() throws Exception { ObjectMapper mapper = new ObjectMapper(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ssZ"); df.setTimeZone(TimeZone.getTimeZone("GMT+4")); // use a timezone different than the ObjectMapper and the system default mapper.setDateFormat(df); verify(mapper, "2000-01-02X03:04:05+0300", judate(2000, 1, 2, 3, 4, 5, 00, "GMT+3")); } /* /********************************************************** /* Helper methods /********************************************************** */ /** * Create a {@link java.util.Date} with all the fields set to the given value. * * @param year year * @param month month (1-12) * @param day day of month (1-31) * @param hour hour (0-23) * @param minutes minutes (0-59) * @param seconds seconds (0-59) * @param millis millis * @param tz timezone id as accepted by {@link TimeZone#getTimeZone(String)} * @return a new {@link Date} instance */ private static Date judate(int year, int month, int day, int hour, int minutes, int seconds, int millis, String tz) { Calendar cal = Calendar.getInstance(); cal.setLenient(false); cal.set(year, month-1, day, hour, minutes, seconds); cal.set(Calendar.MILLISECOND, millis); cal.setTimeZone(TimeZone.getTimeZone(tz)); return cal.getTime(); } private static void verify(ObjectMapper mapper, Object input, Date expected) throws Exception { // Deserialize using the supplied ObjectMapper Date actual = read(mapper, input, java.util.Date.class); // Test against the expected if( expected==null && actual==null) { return; } if( expected==null && actual != null) { fail("Failed to deserialize "+input+", actual: '"+FORMAT.format(actual)+"', expected: '"); } if( expected != null && actual == null ) { fail("Failed to deserialize "+input+", actual: , expected: '"+FORMAT.format(expected)+"'"); } if( actual.getTime() != expected.getTime() ) { fail("Failed to deserialize "+input+", actual: '"+FORMAT.format(actual)+"', expected: '"+FORMAT.format(expected)+"'"); } } private static void failure(ObjectMapper mapper, Object input) throws Exception { failure(mapper, input, MismatchedInputException.class); } private static void failure(ObjectMapper mapper, Object input, Class exceptionType) throws Exception { try { Date date = read(mapper, input, java.util.Date.class); fail("Input "+input+" should not have been accepted but was deserialized into "+FORMAT.format(date)); } catch(Exception e) { // Is it the expected exception ? if (!exceptionType.isAssignableFrom(e.getClass()) ) { fail("Wrong exception thrown when reading "+input+", actual: "+e.getClass().getName() + "("+e.getMessage()+"), expected: "+exceptionType.getName()); } } } private static T read(ObjectMapper mapper, Object input, Class type) throws Exception { // Construct the json representation from the input String json = input.toString(); if( !(input instanceof Number) ) { json = "\""+json+"\""; } // Deserialize using the supplied ObjectMapper return (T) mapper.readValue(json, type); } } DateDeserializationTest.java000066400000000000000000000770551325620701100400220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.beans.ConstructorProperties; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.OptBoolean; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.exc.InvalidFormatException; public class DateDeserializationTest extends BaseMapTest { static class DateAsStringBean { @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="/yyyy/MM/dd/") public Date date; } static class DateAsStringBeanGermany { @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="/yyyy/MM/dd/", locale="fr_FR") public Date date; } static class CalendarAsStringBean { @JsonFormat(shape=JsonFormat.Shape.STRING, pattern=";yyyy/MM/dd;") public Calendar cal; } static class DateInCETBean { @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd,HH", timezone="CET") public Date date; } static class CalendarBean { Calendar _v; void setV(Calendar v) { _v = v; } } static class LenientCalendarBean { @JsonFormat(lenient=OptBoolean.TRUE) public Calendar value; } static class StrictCalendarBean { @JsonFormat(lenient=OptBoolean.FALSE) public Calendar value; } // [databind#1722] public static class Date1722 { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS") private Date date; @JsonIgnore private String foo; @ConstructorProperties({"date", "foo"}) public Date1722(Date date, String foo) { this.date = date; this.foo = foo; } public Date getDate() { return this.date; } public void setDate(Date date) { this.date = date; } public String getFoo() { return this.foo; } public void setFoo(String foo) { this.foo = foo; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testDateUtil() throws Exception { long now = 123456789L; java.util.Date value = new java.util.Date(now); // First from long assertEquals(value, MAPPER.readValue(""+now, java.util.Date.class)); // then from String String dateStr = dateToString(value); java.util.Date result = MAPPER.readValue("\""+dateStr+"\"", java.util.Date.class); assertEquals("Date: expect "+value+" ("+value.getTime()+"), got "+result+" ("+result.getTime()+")", value.getTime(), result.getTime()); } public void testDateUtilWithStringTimestamp() throws Exception { long now = 1321992375446L; /* Should be ok to pass as JSON String, as long * as it is plain timestamp (all numbers, 64-bit) */ String json = quote(String.valueOf(now)); java.util.Date value = MAPPER.readValue(json, java.util.Date.class); assertEquals(now, value.getTime()); // #267: should handle negative timestamps too; like 12 hours before 1.1.1970 long before = - (24 * 3600 * 1000L); json = quote(String.valueOf(before)); value = MAPPER.readValue(json, java.util.Date.class); assertEquals(before, value.getTime()); } public void testDateUtilRFC1123() throws Exception { DateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); // let's use an arbitrary value... String inputStr = "Sat, 17 Jan 2009 06:13:58 +0000"; java.util.Date inputDate = fmt.parse(inputStr); assertEquals(inputDate, MAPPER.readValue("\""+inputStr+"\"", java.util.Date.class)); } public void testDateUtilRFC1123OnNonUSLocales() throws Exception { Locale old = Locale.getDefault(); Locale.setDefault(Locale.GERMAN); DateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); // let's use an arbitrary value... String inputStr = "Sat, 17 Jan 2009 06:13:58 +0000"; java.util.Date inputDate = fmt.parse(inputStr); assertEquals(inputDate, MAPPER.readValue("\""+inputStr+"\"", java.util.Date.class)); Locale.setDefault(old); } /** * ISO8601 is supported as well */ public void testDateUtilISO8601() throws Exception { /* let's use simple baseline value, arbitrary date in GMT, * using the standard notation */ String inputStr = "1972-12-28T00:00:00.000+0000"; Date inputDate = MAPPER.readValue("\""+inputStr+"\"", java.util.Date.class); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.setTime(inputDate); assertEquals(1972, c.get(Calendar.YEAR)); assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH)); assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); // And then the same, but using 'Z' as alias for +0000 (very common) inputStr = "1972-12-28T00:00:00.000Z"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(1972, c.get(Calendar.YEAR)); assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH)); assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); // Same but using colon in timezone inputStr = "1972-12-28T00:00:00.000+00:00"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(1972, c.get(Calendar.YEAR)); assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH)); assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); // Same but only passing hour difference as timezone inputStr = "1972-12-28T00:00:00.000+00"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(1972, c.get(Calendar.YEAR)); assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH)); assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); inputStr = "1984-11-30T00:00:00.000Z"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(1984, c.get(Calendar.YEAR)); assertEquals(Calendar.NOVEMBER, c.get(Calendar.MONTH)); assertEquals(30, c.get(Calendar.DAY_OF_MONTH)); } // [Databind#570] public void testISO8601PartialMilliseconds() throws Exception { String inputStr; Date inputDate; Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); inputStr = "2014-10-03T18:00:00.6-05:00"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(2014, c.get(Calendar.YEAR)); assertEquals(Calendar.OCTOBER, c.get(Calendar.MONTH)); assertEquals(3, c.get(Calendar.DAY_OF_MONTH)); assertEquals(600, c.get(Calendar.MILLISECOND)); inputStr = "2014-10-03T18:00:00.61-05:00"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(2014, c.get(Calendar.YEAR)); assertEquals(Calendar.OCTOBER, c.get(Calendar.MONTH)); assertEquals(3, c.get(Calendar.DAY_OF_MONTH)); assertEquals(18 + 5, c.get(Calendar.HOUR_OF_DAY)); assertEquals(0, c.get(Calendar.MINUTE)); assertEquals(0, c.get(Calendar.SECOND)); assertEquals(610, c.get(Calendar.MILLISECOND)); inputStr = "1997-07-16T19:20:30.45+01:00"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(1997, c.get(Calendar.YEAR)); assertEquals(Calendar.JULY, c.get(Calendar.MONTH)); assertEquals(16, c.get(Calendar.DAY_OF_MONTH)); assertEquals(19 - 1, c.get(Calendar.HOUR_OF_DAY)); assertEquals(20, c.get(Calendar.MINUTE)); assertEquals(30, c.get(Calendar.SECOND)); assertEquals(450, c.get(Calendar.MILLISECOND)); // 14-Sep-2015, tatu: Colon for timezone offset is optional, verify inputStr = "1997-07-16T19:20:30.45+0100"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(1997, c.get(Calendar.YEAR)); assertEquals(Calendar.JULY, c.get(Calendar.MONTH)); assertEquals(16, c.get(Calendar.DAY_OF_MONTH)); assertEquals(19 - 1, c.get(Calendar.HOUR_OF_DAY)); assertEquals(20, c.get(Calendar.MINUTE)); assertEquals(30, c.get(Calendar.SECOND)); assertEquals(450, c.get(Calendar.MILLISECOND)); // plus may also just have hour part inputStr = "1997-07-16T19:20:30.45+01"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(1997, c.get(Calendar.YEAR)); assertEquals(Calendar.JULY, c.get(Calendar.MONTH)); assertEquals(16, c.get(Calendar.DAY_OF_MONTH)); assertEquals(19 - 1, c.get(Calendar.HOUR_OF_DAY)); assertEquals(20, c.get(Calendar.MINUTE)); assertEquals(30, c.get(Calendar.SECOND)); assertEquals(450, c.get(Calendar.MILLISECOND)); } // Also: minutes-part of offset need not be all zeroes: [databind#1788] public void testISO8601FractionalTimezoneOffset() throws Exception { String inputStr = "1997-07-16T19:20:30.45+01:30"; java.util.Date inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.setTime(inputDate); assertEquals(1997, c.get(Calendar.YEAR)); assertEquals(Calendar.JULY, c.get(Calendar.MONTH)); assertEquals(16, c.get(Calendar.DAY_OF_MONTH)); assertEquals(19 - 2, c.get(Calendar.HOUR_OF_DAY)); assertEquals(50, c.get(Calendar.MINUTE)); assertEquals(30, c.get(Calendar.SECOND)); assertEquals(450, c.get(Calendar.MILLISECOND)); } // [databind#1745] public void testISO8601FractSecondsLong() throws Exception { String inputStr; Date inputDate; Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); inputStr = "2014-10-03T18:00:00.3456-05:00"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(2014, c.get(Calendar.YEAR)); assertEquals(Calendar.OCTOBER, c.get(Calendar.MONTH)); assertEquals(3, c.get(Calendar.DAY_OF_MONTH)); // should truncate; not error or round assertEquals(345, c.get(Calendar.MILLISECOND)); // But! Still limit to 9 digits (nanoseconds) try { MAPPER.readValue(quote("2014-10-03T18:00:00.1234567890-05:00"), java.util.Date.class); } catch (InvalidFormatException e) { verifyException(e, "invalid fractional seconds"); verifyException(e, "can use at most 9 digits"); } } public void testISO8601MissingSeconds() throws Exception { String inputStr; Date inputDate; // 23-Jun-2017, tatu: Shouldn't this be UTC? Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); inputStr = "1997-07-16T19:20+01:00"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(1997, c.get(Calendar.YEAR)); assertEquals(Calendar.JULY, c.get(Calendar.MONTH)); assertEquals(16, c.get(Calendar.DAY_OF_MONTH)); assertEquals(19 - 1, c.get(Calendar.HOUR_OF_DAY)); assertEquals(0, c.get(Calendar.SECOND)); assertEquals(0, c.get(Calendar.MILLISECOND)); // 14-Sep-2015, tatu: Colon for timezone offset is optional, verify inputStr = "1997-07-16T19:20+0200"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(1997, c.get(Calendar.YEAR)); assertEquals(Calendar.JULY, c.get(Calendar.MONTH)); assertEquals(16, c.get(Calendar.DAY_OF_MONTH)); assertEquals(19 - 2, c.get(Calendar.HOUR_OF_DAY)); assertEquals(0, c.get(Calendar.SECOND)); assertEquals(0, c.get(Calendar.MILLISECOND)); // or just hour inputStr = "1997-07-16T19:20+04"; inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); c.setTime(inputDate); assertEquals(1997, c.get(Calendar.YEAR)); assertEquals(Calendar.JULY, c.get(Calendar.MONTH)); assertEquals(16, c.get(Calendar.DAY_OF_MONTH)); assertEquals(19 - 4, c.get(Calendar.HOUR_OF_DAY)); assertEquals(0, c.get(Calendar.SECOND)); assertEquals(0, c.get(Calendar.MILLISECOND)); } public void testDateUtilISO8601NoTimezone() throws Exception { // Timezone itself is optional as well... String inputStr = "1984-11-13T00:00:09"; Date inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.setTime(inputDate); assertEquals(1984, c.get(Calendar.YEAR)); assertEquals(Calendar.NOVEMBER, c.get(Calendar.MONTH)); assertEquals(13, c.get(Calendar.DAY_OF_MONTH)); assertEquals(0, c.get(Calendar.HOUR_OF_DAY)); assertEquals(0, c.get(Calendar.MINUTE)); assertEquals(9, c.get(Calendar.SECOND)); assertEquals(0, c.get(Calendar.MILLISECOND)); } // [databind#1657]: no timezone should use configured default public void testDateUtilISO8601NoTimezoneNonDefault() throws Exception { // In first case, no timezone -> SHOULD use configured timezone ObjectReader r = MAPPER.readerFor(Date.class); TimeZone tz = TimeZone.getTimeZone("GMT-2"); Date date1 = r.with(tz) .readValue(quote("1970-01-01T00:00:00.000")); // Second case, should use specified timezone, not configured Date date2 = r.with(TimeZone.getTimeZone("GMT+5")) .readValue(quote("1970-01-01T00:00:00.000-02:00")); assertEquals(date1, date2); // also verify actual value, in GMT Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.setTime(date1); assertEquals(1970, c.get(Calendar.YEAR)); assertEquals(Calendar.JANUARY, c.get(Calendar.MONTH)); assertEquals(1, c.get(Calendar.DAY_OF_MONTH)); assertEquals(2, c.get(Calendar.HOUR_OF_DAY)); } // [databind#1722]: combination of `@ConstructorProperties` and `@JsonIgnore` // should work fine. public void testFormatAndCtors1722() throws Exception { Date1722 input = new Date1722(new Date(0L), "bogus"); String json = MAPPER.writeValueAsString(input); Date1722 result = MAPPER.readValue(json, Date1722.class); assertNotNull(result); } // [databind#338] public void testDateUtilISO8601NoMilliseconds() throws Exception { final String INPUT_STR = "2013-10-31T17:27:00"; Date inputDate; Calendar c; inputDate = MAPPER.readValue(quote(INPUT_STR), java.util.Date.class); c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.setTime(inputDate); assertEquals(2013, c.get(Calendar.YEAR)); assertEquals(Calendar.OCTOBER, c.get(Calendar.MONTH)); assertEquals(31, c.get(Calendar.DAY_OF_MONTH)); assertEquals(17, c.get(Calendar.HOUR_OF_DAY)); assertEquals(27, c.get(Calendar.MINUTE)); assertEquals(0, c.get(Calendar.SECOND)); assertEquals(0, c.get(Calendar.MILLISECOND)); // 03-Nov-2013, tatu: This wouldn't work, and is the nominal reason // for #338 I think /* inputDate = ISO8601Utils.parse(INPUT_STR, new ParsePosition(0)); c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.setTime(inputDate); assertEquals(2013, c.get(Calendar.YEAR)); assertEquals(Calendar.OCTOBER, c.get(Calendar.MONTH)); assertEquals(31, c.get(Calendar.DAY_OF_MONTH)); assertEquals(17, c.get(Calendar.HOUR_OF_DAY)); assertEquals(27, c.get(Calendar.MINUTE)); assertEquals(0, c.get(Calendar.SECOND)); assertEquals(0, c.get(Calendar.MILLISECOND)); */ } public void testDateUtilISO8601JustDate() throws Exception { // Plain date (no time) String inputStr = "1972-12-28"; Date inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.setTime(inputDate); assertEquals(1972, c.get(Calendar.YEAR)); assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH)); assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); } @SuppressWarnings("deprecation") public void testDateSql() throws Exception { java.sql.Date value = new java.sql.Date(0L); value.setYear(99); // 1999 value.setDate(19); value.setMonth(Calendar.APRIL); long now = value.getTime(); // First from long assertEquals(value, MAPPER.readValue(String.valueOf(now), java.sql.Date.class)); // then from default java.sql.Date String serialization: java.sql.Date result = MAPPER.readValue(quote(value.toString()), java.sql.Date.class); Calendar c = gmtCalendar(result.getTime()); assertEquals(1999, c.get(Calendar.YEAR)); assertEquals(Calendar.APRIL, c.get(Calendar.MONTH)); assertEquals(19, c.get(Calendar.DAY_OF_MONTH)); /* [JACKSON-200]: looks like we better add support for regular date * formats as well */ String expStr = "1981-07-13"; result = MAPPER.readValue(quote(expStr), java.sql.Date.class); c.setTimeInMillis(result.getTime()); assertEquals(1981, c.get(Calendar.YEAR)); assertEquals(Calendar.JULY, c.get(Calendar.MONTH)); assertEquals(13, c.get(Calendar.DAY_OF_MONTH)); /* 20-Nov-2009, tatus: I'll be damned if I understand why string serialization * is off-by-one, but day-of-month does seem to be one less. My guess is * that something is funky with timezones (i.e. somewhere local TZ is * being used), but just can't resolve it. Hence, need to comment this: */ // assertEquals(expStr, result.toString()); } public void testCalendar() throws Exception { // not ideal, to use (ever-changing) current date, but... java.util.Calendar value = Calendar.getInstance(); long l = 12345678L; value.setTimeInMillis(l); // First from long Calendar result = MAPPER.readValue(""+l, Calendar.class); assertEquals(l, result.getTimeInMillis()); // Then from serialized String String dateStr = dateToString(new Date(l)); result = MAPPER.readValue(quote(dateStr), Calendar.class); // note: representation may differ (wrt timezone etc), but underlying value must remain the same: if (l != result.getTimeInMillis()) { fail(String.format("Expected timestamp %d, got %d, for '%s'", l, result.getTimeInMillis(), dateStr)); } } public void testCustom() throws Exception { final ObjectMapper mapper = new ObjectMapper(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss"); df.setTimeZone(TimeZone.getTimeZone("PST")); mapper.setDateFormat(df); String dateStr = "1972-12-28X15:45:00"; java.util.Date exp = df.parse(dateStr); java.util.Date result = mapper.readValue("\""+dateStr+"\"", java.util.Date.class); assertEquals(exp, result); } /** * Test for [JACKSON-203]: make empty Strings deserialize as nulls by default, * without need to turn on feature (which may be added in future) */ public void testDatesWithEmptyStrings() throws Exception { assertNull(MAPPER.readValue(quote(""), java.util.Date.class)); assertNull(MAPPER.readValue(quote(""), java.util.Calendar.class)); assertNull(MAPPER.readValue(quote(""), java.sql.Date.class)); } public void test8601DateTimeNoMilliSecs() throws Exception { // ok, Zebra, no milliseconds for (String inputStr : new String[] { "2010-06-28T23:34:22Z", "2010-06-28T23:34:22+0000", "2010-06-28T23:34:22+00:00", "2010-06-28T23:34:22+00", }) { Date inputDate = MAPPER.readValue(quote(inputStr), java.util.Date.class); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.setTime(inputDate); assertEquals(2010, c.get(Calendar.YEAR)); assertEquals(Calendar.JUNE, c.get(Calendar.MONTH)); assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); assertEquals(23, c.get(Calendar.HOUR_OF_DAY)); assertEquals(34, c.get(Calendar.MINUTE)); assertEquals(22, c.get(Calendar.SECOND)); assertEquals(0, c.get(Calendar.MILLISECOND)); } } public void testTimeZone() throws Exception { TimeZone result = MAPPER.readValue(quote("PST"), TimeZone.class); assertEquals("PST", result.getID()); } public void testCustomDateWithAnnotation() throws Exception { final String INPUT = "{\"date\":\"/2005/05/25/\"}"; DateAsStringBean result = MAPPER.readValue(INPUT, DateAsStringBean.class); assertNotNull(result); assertNotNull(result.date); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); long l = result.date.getTime(); if (l == 0L) { fail("Should not get null date"); } c.setTimeInMillis(l); assertEquals(2005, c.get(Calendar.YEAR)); assertEquals(Calendar.MAY, c.get(Calendar.MONTH)); assertEquals(25, c.get(Calendar.DAY_OF_MONTH)); // 27-Mar-2014, tatu: Let's verify that changing Locale won't break it; // either via context Locale result = MAPPER.readerFor(DateAsStringBean.class) .with(Locale.GERMANY) .readValue(INPUT); assertNotNull(result); assertNotNull(result.date); l = result.date.getTime(); if (l == 0L) { fail("Should not get null date"); } c.setTimeInMillis(l); assertEquals(2005, c.get(Calendar.YEAR)); assertEquals(Calendar.MAY, c.get(Calendar.MONTH)); assertEquals(25, c.get(Calendar.DAY_OF_MONTH)); // or, via annotations DateAsStringBeanGermany result2 = MAPPER.readerFor(DateAsStringBeanGermany.class).readValue(INPUT); assertNotNull(result2); assertNotNull(result2.date); l = result2.date.getTime(); if (l == 0L) { fail("Should not get null date"); } c.setTimeInMillis(l); assertEquals(2005, c.get(Calendar.YEAR)); assertEquals(Calendar.MAY, c.get(Calendar.MONTH)); assertEquals(25, c.get(Calendar.DAY_OF_MONTH)); } public void testCustomCalendarWithAnnotation() throws Exception { CalendarAsStringBean cbean = MAPPER.readValue("{\"cal\":\";2007/07/13;\"}", CalendarAsStringBean.class); assertNotNull(cbean); assertNotNull(cbean.cal); Calendar c = cbean.cal; assertEquals(2007, c.get(Calendar.YEAR)); assertEquals(Calendar.JULY, c.get(Calendar.MONTH)); assertEquals(13, c.get(Calendar.DAY_OF_MONTH)); } public void testCustomCalendarWithTimeZone() throws Exception { // And then with different TimeZone: CET is +01:00 from GMT -- read as CET DateInCETBean cet = MAPPER.readValue("{\"date\":\"2001-01-01,10\"}", DateInCETBean.class); Calendar c = Calendar.getInstance(getUTCTimeZone()); c.setTimeInMillis(cet.date.getTime()); // so, going to UTC/GMT should reduce hour by one assertEquals(2001, c.get(Calendar.YEAR)); assertEquals(Calendar.JANUARY, c.get(Calendar.MONTH)); assertEquals(1, c.get(Calendar.DAY_OF_MONTH)); assertEquals(9, c.get(Calendar.HOUR_OF_DAY)); } // [databind#1651] public void testDateEndingWithZNonDefTZ1651() throws Exception { String json = quote("1970-01-01T00:00:00.000Z"); // Standard mapper with timezone UTC: shared instance should be ok. // ... but, Travis manages to have fails, so insist on newly created ObjectMapper mapper = newObjectMapper(); Date dateUTC = mapper.readValue(json, Date.class); // 1970-01-01T00:00:00.000+00:00 // Mapper with timezone GMT-2 // note: must construct new one, not share mapper = new ObjectMapper(); mapper.setTimeZone(TimeZone.getTimeZone("GMT-2")); Date dateGMT1 = mapper.readValue(json, Date.class); // 1970-01-01T00:00:00.000-02:00 // Underlying timestamps should be the same assertEquals(dateUTC.getTime(), dateGMT1.getTime()); } /* /********************************************************** /* Context timezone use (or not) /********************************************************** */ // for [databind#204] public void testContextTimezone() throws Exception { String inputStr = "1997-07-16T19:20:30.45+0100"; final String tzId = "PST"; // this is enabled by default: assertTrue(MAPPER.isEnabled(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)); final ObjectReader r = MAPPER .readerFor(Calendar.class) .with(TimeZone.getTimeZone(tzId)); // by default use contextual timezone: Calendar cal = r.readValue(quote(inputStr)); TimeZone tz = cal.getTimeZone(); assertEquals(tzId, tz.getID()); assertEquals(1997, cal.get(Calendar.YEAR)); assertEquals(Calendar.JULY, cal.get(Calendar.MONTH)); assertEquals(16, cal.get(Calendar.DAY_OF_MONTH)); // Translated from original into PST differs: assertEquals(20, cal.get(Calendar.MINUTE)); assertEquals(30, cal.get(Calendar.SECOND)); assertEquals(11, cal.get(Calendar.HOUR_OF_DAY)); // but if disabled, should use what's been sent in: cal = r.without(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE) .readValue(quote(inputStr)); // 23-Jun-2017, tatu: Actually turns out to be hard if not impossible to do ... // problem being SimpleDateFormat does not really retain timezone offset. // But if we match fields... we perhaps could use it? // !!! TODO: would not yet pass /* System.err.println("CAL/2 == "+cal); System.err.println("tz == "+cal.getTimeZone()); */ } /* /********************************************************** /* Test(s) for array unwrapping /********************************************************** */ public void testCalendarArrayUnwrap() throws Exception { ObjectReader reader = new ObjectMapper() .readerFor(CalendarBean.class) .without(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); final String inputDate = "1972-12-28T00:00:00.000+0000"; final String input = aposToQuotes("{'v':['"+inputDate+"']}"); try { reader.readValue(input); fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled"); } catch (MismatchedInputException exp) { verifyException(exp, "Cannot deserialize"); verifyException(exp, "out of START_ARRAY"); } reader = reader.with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); CalendarBean bean = reader.readValue(input); assertNotNull(bean._v); assertEquals(1972, bean._v.get(Calendar.YEAR)); // and finally, a fail due to multiple values: try { reader.readValue(aposToQuotes("{'v':['"+inputDate+"','"+inputDate+"']}")); fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled"); } catch (JsonMappingException exp) { verifyException(exp, "Attempted to unwrap"); } } /* /********************************************************** /* Tests for leniency /********************************************************** */ public void testLenientCalendar() throws Exception { final String JSON = aposToQuotes("{'value':'2015-11-32'}"); // with lenient, can parse fine LenientCalendarBean lenBean = MAPPER.readValue(JSON, LenientCalendarBean.class); assertEquals(Calendar.DECEMBER, lenBean.value.get(Calendar.MONTH)); assertEquals(2, lenBean.value.get(Calendar.DAY_OF_MONTH)); // with strict, ought to produce exception try { MAPPER.readValue(JSON, StrictCalendarBean.class); fail("Should not pass with invalid (with strict) date value"); } catch (MismatchedInputException e) { verifyException(e, "Cannot deserialize value of type `java.util.Calendar`"); verifyException(e, "from String \"2015-11-32\""); verifyException(e, "expected format"); } // similarly with Date... ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(java.util.Date.class) .setFormat(JsonFormat.Value.forLeniency(Boolean.FALSE)); try { mapper.readValue(quote("2015-11-32"), java.util.Date.class); fail("Should not pass with invalid (with strict) date value"); } catch (MismatchedInputException e) { verifyException(e, "Cannot deserialize value of type `java.util.Date`"); verifyException(e, "from String \"2015-11-32\""); verifyException(e, "expected format"); } } /* /********************************************************** /* Tests to verify failing cases /********************************************************** */ public void testInvalidFormat() throws Exception { try { MAPPER.readValue(quote("foobar"), Date.class); fail("Should have failed with an exception"); } catch (InvalidFormatException e) { verifyException(e, "Cannot deserialize value of type `java.util.Date` from String"); assertEquals("foobar", e.getValue()); assertEquals(Date.class, e.getTargetType()); } catch (Exception e) { fail("Wrong type of exception ("+e.getClass().getName()+"), should get " +InvalidFormatException.class.getName()); } } /* /********************************************************** /* Helper methods /********************************************************** */ private String dateToString(java.util.Date value) { /* Then from String. This is bit tricky, since JDK does not really * suggest a 'standard' format. So let's try using something... */ DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); return df.format(value); } private static Calendar gmtCalendar(long time) { Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.setTimeInMillis(time); return c; } } EnumAltIdTest.java000066400000000000000000000114361325620701100357070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.IOException; import java.util.EnumSet; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.exc.InvalidFormatException; public class EnumAltIdTest extends BaseMapTest { // [databind#1313] enum TestEnum { JACKSON, RULES, OK; } protected enum LowerCaseEnum { A, B, C; private LowerCaseEnum() { } @Override public String toString() { return name().toLowerCase(); } } protected static class EnumBean { @JsonFormat(with={ JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES }) public TestEnum value; } protected static class StrictCaseBean { @JsonFormat(without={ JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES }) public TestEnum value; } /* /********************************************************** /* Test methods, basic /********************************************************** */ protected final ObjectMapper MAPPER = new ObjectMapper(); protected final ObjectMapper MAPPER_IGNORE_CASE; { MAPPER_IGNORE_CASE = new ObjectMapper(); MAPPER_IGNORE_CASE.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS); } protected final ObjectReader READER_DEFAULT = MAPPER.reader(); protected final ObjectReader READER_IGNORE_CASE = MAPPER_IGNORE_CASE.reader(); // Tests for [databind#1313], case-insensitive public void testFailWhenCaseSensitiveAndNameIsNotUpperCase() throws IOException { try { READER_DEFAULT.forType(TestEnum.class).readValue("\"Jackson\""); fail("InvalidFormatException expected"); } catch (InvalidFormatException e) { verifyException(e, "value not one of declared Enum instance names: [JACKSON, OK, RULES]"); } } public void testFailWhenCaseSensitiveAndToStringIsUpperCase() throws IOException { ObjectReader r = READER_DEFAULT.forType(LowerCaseEnum.class) .with(DeserializationFeature.READ_ENUMS_USING_TO_STRING); try { r.readValue("\"A\""); fail("InvalidFormatException expected"); } catch (InvalidFormatException e) { verifyException(e, "value not one of declared Enum instance names: [a, b, c]"); } } public void testEnumDesIgnoringCaseWithLowerCaseContent() throws IOException { assertEquals(TestEnum.JACKSON, READER_IGNORE_CASE.forType(TestEnum.class).readValue(quote("jackson"))); } public void testEnumDesIgnoringCaseWithUpperCaseToString() throws IOException { ObjectReader r = MAPPER_IGNORE_CASE.readerFor(LowerCaseEnum.class) .with(DeserializationFeature.READ_ENUMS_USING_TO_STRING); assertEquals(LowerCaseEnum.A, r.readValue("\"A\"")); } /* /********************************************************** /* Test methods, containers /********************************************************** */ public void testIgnoreCaseInEnumList() throws Exception { TestEnum[] enums = READER_IGNORE_CASE.forType(TestEnum[].class) .readValue("[\"jacksON\", \"ruLes\"]"); assertEquals(2, enums.length); assertEquals(TestEnum.JACKSON, enums[0]); assertEquals(TestEnum.RULES, enums[1]); } public void testIgnoreCaseInEnumSet() throws IOException { ObjectReader r = READER_IGNORE_CASE.forType(new TypeReference>() { }); EnumSet set = r.readValue("[\"jackson\"]"); assertEquals(1, set.size()); assertTrue(set.contains(TestEnum.JACKSON)); } /* /********************************************************** /* Test methods, property overrides /********************************************************** */ public void testIgnoreCaseViaFormat() throws Exception { final String JSON = aposToQuotes("{'value':'ok'}"); // should be able to allow on per-case basis: EnumBean pojo = READER_DEFAULT.forType(EnumBean.class) .readValue(JSON); assertEquals(TestEnum.OK, pojo.value); // including disabling acceptance try { READER_DEFAULT.forType(StrictCaseBean.class) .readValue(JSON); fail("Should not pass"); } catch (InvalidFormatException e) { verifyException(e, "value not one of declared Enum instance names: [JACKSON, OK, RULES]"); } } } EnumDefaultReadTest.java000066400000000000000000000255621325620701100370770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.IOException; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidFormatException; public class EnumDefaultReadTest extends BaseMapTest { enum SimpleEnum { ZERO, ONE; } enum SimpleEnumWithDefault { @JsonEnumDefaultValue ZERO, ONE; } enum CustomEnum { ZERO(0), ONE(1); private final int number; CustomEnum(final int number) { this.number = number; } @JsonValue int getNumber() { return this.number; } } enum CustomEnumWithDefault { @JsonEnumDefaultValue ZERO(0), ONE(1); private final int number; CustomEnumWithDefault(final int number) { this.number = number; } @JsonValue int getNumber() { return this.number; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testWithoutCustomFeatures() throws Exception { final ObjectReader r = MAPPER.reader(); _verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO); _verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE); _verifyOkDeserialization(r, "0", SimpleEnum.class, SimpleEnum.ZERO); _verifyOkDeserialization(r, "1", SimpleEnum.class, SimpleEnum.ONE); _verifyFailingDeserialization(r, "TWO", SimpleEnum.class); _verifyFailingDeserialization(r, "2", SimpleEnum.class); _verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE); _verifyFailingDeserialization(r, "TWO", SimpleEnumWithDefault.class); _verifyOkDeserialization(r, "0", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyOkDeserialization(r, "1", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE); _verifyFailingDeserialization(r, "2", SimpleEnumWithDefault.class); _verifyFailingDeserialization(r, "ZERO", CustomEnum.class); _verifyFailingDeserialization(r, "ONE", CustomEnum.class); _verifyFailingDeserialization(r, "TWO", CustomEnum.class); _verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO); _verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE); _verifyFailingDeserialization(r, "2", CustomEnum.class); _verifyFailingDeserialization(r, "ZERO", CustomEnumWithDefault.class); _verifyFailingDeserialization(r, "ONE", CustomEnumWithDefault.class); _verifyFailingDeserialization(r, "TWO", CustomEnumWithDefault.class); _verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); _verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE); _verifyFailingDeserialization(r, "2", CustomEnumWithDefault.class); } public void testWithFailOnNumbers() throws Exception { ObjectReader r = MAPPER.reader() .with(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS); _verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO); _verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE); _verifyFailingDeserialization(r, "TWO", SimpleEnum.class); _verifyFailingDeserialization(r, "0", SimpleEnum.class); _verifyFailingDeserialization(r, "1", SimpleEnum.class); _verifyFailingDeserialization(r, "2", SimpleEnum.class); _verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE); _verifyFailingDeserialization(r, "TWO", SimpleEnumWithDefault.class); _verifyFailingDeserialization(r, "0", SimpleEnumWithDefault.class); _verifyFailingDeserialization(r, "1", SimpleEnumWithDefault.class); _verifyFailingDeserialization(r, "2", SimpleEnumWithDefault.class); _verifyFailingDeserialization(r, "ZERO", CustomEnum.class); _verifyFailingDeserialization(r, "ONE", CustomEnum.class); _verifyFailingDeserialization(r, "TWO", CustomEnum.class); _verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO); _verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE); _verifyFailingDeserialization(r, "2", CustomEnum.class); _verifyFailingDeserialization(r, "ZERO", CustomEnumWithDefault.class); _verifyFailingDeserialization(r, "ONE", CustomEnumWithDefault.class); _verifyFailingDeserialization(r, "TWO", CustomEnumWithDefault.class); _verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); _verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE); _verifyFailingDeserialization(r, "2", CustomEnumWithDefault.class); } public void testWithReadUnknownAsDefault() throws Exception { ObjectReader r = MAPPER.reader() .with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); _verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO); _verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE); _verifyFailingDeserialization(r, "TWO", SimpleEnum.class); _verifyOkDeserialization(r, "0", SimpleEnum.class, SimpleEnum.ZERO); _verifyOkDeserialization(r, "1", SimpleEnum.class, SimpleEnum.ONE); _verifyFailingDeserialization(r, "2", SimpleEnum.class); _verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE); _verifyOkDeserialization(r, "TWO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyOkDeserialization(r, "0", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyOkDeserialization(r, "1", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE); _verifyOkDeserialization(r, "2", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyFailingDeserialization(r, "ZERO", CustomEnum.class); _verifyFailingDeserialization(r, "ONE", CustomEnum.class); _verifyFailingDeserialization(r, "TWO", CustomEnum.class); _verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO); _verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE); _verifyFailingDeserialization(r, "2", CustomEnum.class); _verifyOkDeserialization(r, "ZERO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); _verifyOkDeserialization(r, "ONE", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); _verifyOkDeserialization(r, "TWO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); _verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); _verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE); _verifyOkDeserialization(r, "2", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); } public void testWithFailOnNumbersAndReadUnknownAsDefault() throws Exception { ObjectReader r = MAPPER.reader() .with(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS) .with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); _verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO); _verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE); _verifyFailingDeserialization(r, "TWO", SimpleEnum.class); _verifyFailingDeserialization(r, "0", SimpleEnum.class); _verifyFailingDeserialization(r, "1", SimpleEnum.class); _verifyFailingDeserialization(r, "2", SimpleEnum.class); _verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE); _verifyOkDeserialization(r, "TWO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyFailingDeserialization(r, "ZERO", CustomEnum.class); _verifyFailingDeserialization(r, "ONE", CustomEnum.class); _verifyFailingDeserialization(r, "TWO", CustomEnum.class); _verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO); _verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE); _verifyFailingDeserialization(r, "2", CustomEnum.class); _verifyOkDeserialization(r, "ZERO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); _verifyOkDeserialization(r, "ONE", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); _verifyOkDeserialization(r, "TWO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); _verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); _verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE); // // The three tests below fail; Jackson throws an exception on the basis that // "FAIL_ON_NUMBERS_FOR_ENUMS" is enabled. I claim the default value should be returned instead. _verifyOkDeserialization(r, "0", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyOkDeserialization(r, "1", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); _verifyOkDeserialization(r, "2", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO); // Fails. Jackson throws an exception on the basis that "FAIL_ON_NUMBERS_FOR_ENUMS" // is enabled, but the default value should have been returned instead. _verifyOkDeserialization(r, "2", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO); } private void _verifyOkDeserialization(ObjectReader reader, String fromValue, Class toValueType, T expValue) throws IOException { assertEquals(expValue, reader.forType(toValueType).readValue(quote(fromValue))); } private void _verifyFailingDeserialization(final ObjectReader reader, final String fromValue, final Class toValueType) throws IOException { try { reader.forType(toValueType).readValue(quote(fromValue)); fail("Deserialization should have failed"); } catch (InvalidFormatException e) { verifyException(e, "Cannot deserialize value of type"); /* Expected. */ } } } EnumDeserializationTest.java000066400000000000000000000467061325620701100400500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.module.SimpleModule; @SuppressWarnings("serial") public class EnumDeserializationTest extends BaseMapTest { enum TestEnum { JACKSON, RULES, OK; } /** * Alternative version that annotates which deserializer to use */ @JsonDeserialize(using=DummyDeserializer.class) enum AnnotatedTestEnum { JACKSON, RULES, OK; } public static class DummyDeserializer extends StdDeserializer { public DummyDeserializer() { super(Object.class); } @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) { return AnnotatedTestEnum.OK; } } public static class LcEnumDeserializer extends StdDeserializer { public LcEnumDeserializer() { super(TestEnum.class); } @Override public TestEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { return TestEnum.valueOf(jp.getText().toUpperCase()); } } protected enum LowerCaseEnum { A, B, C; private LowerCaseEnum() { } @Override public String toString() { return name().toLowerCase(); } } protected enum EnumWithJsonValue { A("foo"), B("bar"); private final String name; private EnumWithJsonValue(String n) { name = n; } @JsonValue @Override public String toString() { return name; } } static class ClassWithEnumMapKey { @JsonProperty Map map; } // [databind#677] static enum EnumWithPropertyAnno { @JsonProperty("a") A, // For this value, force use of anonymous sub-class, to ensure things still work @JsonProperty("b") B { @Override public String toString() { return "bb"; } } ; } // [databind#1161] enum Enum1161 { A, B, C; @Override public String toString() { return name().toLowerCase(); }; } static enum EnumWithDefaultAnno { A, B, @JsonEnumDefaultValue OTHER; } static enum EnumWithDefaultAnnoAndConstructor { A, B, @JsonEnumDefaultValue OTHER; @JsonCreator public static EnumWithDefaultAnnoAndConstructor fromId(String value) { for (EnumWithDefaultAnnoAndConstructor e: values()) { if (e.name().toLowerCase().equals(value)) return e; } return null; } } static enum StrictEnumCreator { A, B; @JsonCreator public static StrictEnumCreator fromId(String value) { for (StrictEnumCreator e: values()) { if (e.name().toLowerCase().equals(value)) return e; } throw new IllegalArgumentException(value); } } // // public enum AnEnum { ZERO, ONE } public static class AnEnumDeserializer extends FromStringDeserializer { public AnEnumDeserializer() { super(AnEnum.class); } @Override protected AnEnum _deserialize(String value, DeserializationContext ctxt) throws IOException { try { return AnEnum.valueOf(value); } catch (IllegalArgumentException e) { return (AnEnum) ctxt.handleWeirdStringValue(AnEnum.class, value, "Undefined AnEnum code"); } } } public static class AnEnumKeyDeserializer extends KeyDeserializer { @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { try { return AnEnum.valueOf(key); } catch (IllegalArgumentException e) { return ctxt.handleWeirdKey(AnEnum.class, key, "Undefined AnEnum code"); } } } @JsonDeserialize(using = AnEnumDeserializer.class, keyUsing = AnEnumKeyDeserializer.class) public enum LanguageCodeMixin { } public static class EnumModule extends SimpleModule { @Override public void setupModule(SetupContext context) { context.setMixInAnnotations(AnEnum.class, LanguageCodeMixin.class); } public static ObjectMapper setupObjectMapper(ObjectMapper mapper) { final EnumModule module = new EnumModule(); mapper.registerModule(module); return mapper; } } /* /********************************************************** /* Test methods /********************************************************** */ protected final ObjectMapper MAPPER = new ObjectMapper(); public void testSimple() throws Exception { // First "good" case with Strings String JSON = "\"OK\" \"RULES\" null"; // multiple main-level mappings, need explicit parser: JsonParser jp = MAPPER.getFactory().createParser(JSON); assertEquals(TestEnum.OK, MAPPER.readValue(jp, TestEnum.class)); assertEquals(TestEnum.RULES, MAPPER.readValue(jp, TestEnum.class)); // should be ok; nulls are typeless; handled by mapper, not by deserializer assertNull(MAPPER.readValue(jp, TestEnum.class)); // and no more content beyond that... assertFalse(jp.hasCurrentToken()); // Then alternative with index (0 means first entry) assertEquals(TestEnum.JACKSON, MAPPER.readValue(" 0 ", TestEnum.class)); // Then error case: unrecognized value try { /*Object result =*/ MAPPER.readValue("\"NO-SUCH-VALUE\"", TestEnum.class); fail("Expected an exception for bogus enum value..."); } catch (MismatchedInputException jex) { verifyException(jex, "value not one of declared"); } jp.close(); } /** * Enums are considered complex if they have code (and hence sub-classes)... an * example is TimeUnit */ public void testComplexEnum() throws Exception { String json = MAPPER.writeValueAsString(TimeUnit.SECONDS); assertEquals(quote("SECONDS"), json); TimeUnit result = MAPPER.readValue(json, TimeUnit.class); assertSame(TimeUnit.SECONDS, result); } /** * Testing to see that annotation override works */ public void testAnnotated() throws Exception { AnnotatedTestEnum e = MAPPER.readValue("\"JACKSON\"", AnnotatedTestEnum.class); /* dummy deser always returns value OK, independent of input; * only works if annotation is used */ assertEquals(AnnotatedTestEnum.OK, e); } public void testSubclassedEnums() throws Exception { EnumWithSubClass value = MAPPER.readValue("\"A\"", EnumWithSubClass.class); assertEquals(EnumWithSubClass.A, value); } public void testToStringEnums() throws Exception { // can't reuse global one due to reconfig ObjectMapper m = new ObjectMapper(); m.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true); LowerCaseEnum value = m.readValue("\"c\"", LowerCaseEnum.class); assertEquals(LowerCaseEnum.C, value); } public void testNumbersToEnums() throws Exception { // by default numbers are fine: assertFalse(MAPPER.getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)); TestEnum value = MAPPER.readValue("1", TestEnum.class); assertSame(TestEnum.RULES, value); // but can also be changed to errors: ObjectReader r = MAPPER.readerFor(TestEnum.class) .with(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS); try { value = r.readValue("1"); fail("Expected an error"); } catch (MismatchedInputException e) { verifyException(e, "Cannot deserialize"); verifyException(e, "not allowed to deserialize Enum value out of number: disable"); } // and [databind#684] try { value = r.readValue(quote("1")); fail("Expected an error"); } catch (MismatchedInputException e) { verifyException(e, "Cannot deserialize"); // 26-Jan-2017, tatu: as per [databind#1505], should fail bit differently verifyException(e, "value not one of declared Enum"); } } public void testEnumsWithIndex() throws Exception { ObjectMapper m = new ObjectMapper(); m.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX); String json = m.writeValueAsString(TestEnum.RULES); assertEquals(String.valueOf(TestEnum.RULES.ordinal()), json); TestEnum result = m.readValue(json, TestEnum.class); assertSame(TestEnum.RULES, result); } public void testEnumsWithJsonValue() throws Exception { // first, enum as is EnumWithJsonValue e = MAPPER.readValue(quote("foo"), EnumWithJsonValue.class); assertSame(EnumWithJsonValue.A, e); e = MAPPER.readValue(quote("bar"), EnumWithJsonValue.class); assertSame(EnumWithJsonValue.B, e); // then in EnumSet EnumSet set = MAPPER.readValue("[\"bar\"]", new TypeReference>() { }); assertNotNull(set); assertEquals(1, set.size()); assertTrue(set.contains(EnumWithJsonValue.B)); assertFalse(set.contains(EnumWithJsonValue.A)); // and finally EnumMap EnumMap map = MAPPER.readValue("{\"foo\":13}", new TypeReference>() { }); assertNotNull(map); assertEquals(1, map.size()); assertEquals(Integer.valueOf(13), map.get(EnumWithJsonValue.A)); } // Ability to ignore unknown Enum values: public void testAllowUnknownEnumValuesReadAsNull() throws Exception { // cannot use shared mapper when changing configs... ObjectReader reader = MAPPER.reader(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); assertNull(reader.forType(TestEnum.class).readValue("\"NO-SUCH-VALUE\"")); assertNull(reader.forType(TestEnum.class).readValue(" 4343 ")); } // Ability to ignore unknown Enum values: // [databind#1642] public void testAllowUnknownEnumValuesReadAsNullWithCreatorMethod() throws Exception { // cannot use shared mapper when changing configs... ObjectReader reader = MAPPER.reader(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); assertNull(reader.forType(StrictEnumCreator.class).readValue("\"NO-SUCH-VALUE\"")); assertNull(reader.forType(StrictEnumCreator.class).readValue(" 4343 ")); } public void testAllowUnknownEnumValuesForEnumSets() throws Exception { ObjectReader reader = MAPPER.reader(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); EnumSet result = reader.forType(new TypeReference>() { }) .readValue("[\"NO-SUCH-VALUE\"]"); assertEquals(0, result.size()); } public void testAllowUnknownEnumValuesAsMapKeysReadAsNull() throws Exception { ObjectReader reader = MAPPER.reader(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); ClassWithEnumMapKey result = reader.forType(ClassWithEnumMapKey.class) .readValue("{\"map\":{\"NO-SUCH-VALUE\":\"val\"}}"); assertTrue(result.map.containsKey(null)); } public void testDoNotAllowUnknownEnumValuesAsMapKeysWhenReadAsNullDisabled() throws Exception { assertFalse(MAPPER.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)); try { MAPPER.readValue("{\"map\":{\"NO-SUCH-VALUE\":\"val\"}}", ClassWithEnumMapKey.class); fail("Expected an exception for bogus enum value..."); } catch (InvalidFormatException jex) { verifyException(jex, "Cannot deserialize Map key of type `com.fasterxml.jackson.databind.deser.jdk.EnumDeserializationTest$TestEnum`"); } } // [databind#141]: allow mapping of empty String into null public void testEnumsWithEmpty() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); TestEnum result = mapper.readValue("\"\"", TestEnum.class); assertNull(result); } public void testGenericEnumDeserialization() throws Exception { final ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("foobar"); module.addDeserializer(Enum.class, new LcEnumDeserializer()); mapper.registerModule(module); // not sure this is totally safe but... assertEquals(TestEnum.JACKSON, mapper.readValue(quote("jackson"), TestEnum.class)); } // [databind#381] public void testUnwrappedEnum() throws Exception { final ObjectMapper mapper = newObjectMapper(); mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); assertEquals(TestEnum.JACKSON, mapper.readValue("[" + quote("JACKSON") + "]", TestEnum.class)); } public void testUnwrappedEnumException() throws Exception { final ObjectMapper mapper = newObjectMapper(); mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); try { Object v = mapper.readValue("[" + quote("JACKSON") + "]", TestEnum.class); fail("Exception was not thrown on deserializing a single array element of type enum; instead got: "+v); } catch (MismatchedInputException exp) { //exception as thrown correctly verifyException(exp, "Cannot deserialize"); } } // [databind#149]: 'stringified' indexes for enums public void testIndexAsString() throws Exception { // first, regular index ought to work fine TestEnum en = MAPPER.readValue("2", TestEnum.class); assertSame(TestEnum.values()[2], en); // but also with quoted Strings en = MAPPER.readValue(quote("1"), TestEnum.class); assertSame(TestEnum.values()[1], en); // [databind#1690]: unless prevented final ObjectMapper mapper = newObjectMapper(); mapper.disable(MapperFeature.ALLOW_COERCION_OF_SCALARS); try { en = mapper.readValue(quote("1"), TestEnum.class); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "Cannot deserialize value of type"); verifyException(e, "EnumDeserializationTest$TestEnum"); verifyException(e, "value looks like quoted Enum index"); } } public void testEnumWithJsonPropertyRename() throws Exception { String json = MAPPER.writeValueAsString(new EnumWithPropertyAnno[] { EnumWithPropertyAnno.B, EnumWithPropertyAnno.A }); assertEquals("[\"b\",\"a\"]", json); // and while not really proper place, let's also verify deser while we're at it EnumWithPropertyAnno[] result = MAPPER.readValue(json, EnumWithPropertyAnno[].class); assertNotNull(result); assertEquals(2, result.length); assertSame(EnumWithPropertyAnno.B, result[0]); assertSame(EnumWithPropertyAnno.A, result[1]); } // [databind#1161], unable to switch READ_ENUMS_USING_TO_STRING public void testDeserWithToString1161() throws Exception { Enum1161 result = MAPPER.readerFor(Enum1161.class) .readValue(quote("A")); assertSame(Enum1161.A, result); result = MAPPER.readerFor(Enum1161.class) .with(DeserializationFeature.READ_ENUMS_USING_TO_STRING) .readValue(quote("a")); assertSame(Enum1161.A, result); // and once again, going back to defaults result = MAPPER.readerFor(Enum1161.class) .without(DeserializationFeature.READ_ENUMS_USING_TO_STRING) .readValue(quote("A")); assertSame(Enum1161.A, result); } public void testEnumWithDefaultAnnotation() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); EnumWithDefaultAnno myEnum = mapper.readValue("\"foo\"", EnumWithDefaultAnno.class); assertSame(EnumWithDefaultAnno.OTHER, myEnum); } public void testEnumWithDefaultAnnotationUsingIndexInBound1() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); EnumWithDefaultAnno myEnum = mapper.readValue("1", EnumWithDefaultAnno.class); assertSame(EnumWithDefaultAnno.B, myEnum); } public void testEnumWithDefaultAnnotationUsingIndexInBound2() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); EnumWithDefaultAnno myEnum = mapper.readValue("2", EnumWithDefaultAnno.class); assertSame(EnumWithDefaultAnno.OTHER, myEnum); } public void testEnumWithDefaultAnnotationUsingIndexSameAsLength() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); EnumWithDefaultAnno myEnum = mapper.readValue("3", EnumWithDefaultAnno.class); assertSame(EnumWithDefaultAnno.OTHER, myEnum); } public void testEnumWithDefaultAnnotationUsingIndexOutOfBound() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); EnumWithDefaultAnno myEnum = mapper.readValue("4", EnumWithDefaultAnno.class); assertSame(EnumWithDefaultAnno.OTHER, myEnum); } public void testEnumWithDefaultAnnotationWithConstructor() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); EnumWithDefaultAnnoAndConstructor myEnum = mapper.readValue("\"foo\"", EnumWithDefaultAnnoAndConstructor.class); assertNull("When using a constructor, the default value annotation shouldn't be used.", myEnum); } public void testExceptionFromCustomEnumKeyDeserializer() throws Exception { ObjectMapper mapper = newObjectMapper() .registerModule(new EnumModule()); try { mapper.readValue("{\"TWO\": \"dumpling\"}", new TypeReference>() {}); fail("No exception"); } catch (MismatchedInputException e) { assertTrue(e.getMessage().contains("Undefined AnEnum")); } } } EnumMapDeserializationTest.java000066400000000000000000000171261325620701100405000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.util.EnumMap; import java.util.Map; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; @SuppressWarnings("serial") public class EnumMapDeserializationTest extends BaseMapTest { enum TestEnum { JACKSON, RULES, OK; } enum TestEnumWithDefault { JACKSON, RULES, @JsonEnumDefaultValue OK; } protected enum LowerCaseEnum { A, B, C; private LowerCaseEnum() { } @Override public String toString() { return name().toLowerCase(); } } static class MySimpleEnumMap extends EnumMap { public MySimpleEnumMap() { super(TestEnum.class); } } static class FromStringEnumMap extends EnumMap { @JsonCreator public FromStringEnumMap(String value) { super(TestEnum.class); put(TestEnum.JACKSON, value); } } static class FromDelegateEnumMap extends EnumMap { @JsonCreator public FromDelegateEnumMap(Map stuff) { super(TestEnum.class); put(TestEnum.OK, String.valueOf(stuff)); } } static class FromPropertiesEnumMap extends EnumMap { int a0, b0; @JsonCreator public FromPropertiesEnumMap(@JsonProperty("a") int a, @JsonProperty("b") int b) { super(TestEnum.class); a0 = a; b0 = b; } } // [databind#1859] public enum Enum1859 { A, B, C; } static class Pojo1859 { public EnumMap values; public Pojo1859() { } public Pojo1859(EnumMap v) { values = v; } } /* /********************************************************** /* Test methods, basic /********************************************************** */ protected final ObjectMapper MAPPER = new ObjectMapper(); public void testEnumMaps() throws Exception { EnumMap value = MAPPER.readValue("{\"OK\":\"value\"}", new TypeReference>() { }); assertEquals("value", value.get(TestEnum.OK)); } public void testToStringEnumMaps() throws Exception { // can't reuse global one due to reconfig ObjectReader r = MAPPER.reader() .with(DeserializationFeature.READ_ENUMS_USING_TO_STRING); EnumMap value = r.forType( new TypeReference>() { }) .readValue("{\"a\":\"value\"}"); assertEquals("value", value.get(LowerCaseEnum.A)); } /* /********************************************************** /* Test methods: custom enum maps /********************************************************** */ public void testCustomEnumMapWithDefaultCtor() throws Exception { MySimpleEnumMap map = MAPPER.readValue(aposToQuotes("{'RULES':'waves'}"), MySimpleEnumMap.class); assertEquals(1, map.size()); assertEquals("waves", map.get(TestEnum.RULES)); } public void testCustomEnumMapFromString() throws Exception { FromStringEnumMap map = MAPPER.readValue(quote("kewl"), FromStringEnumMap.class); assertEquals(1, map.size()); assertEquals("kewl", map.get(TestEnum.JACKSON)); } public void testCustomEnumMapWithDelegate() throws Exception { FromDelegateEnumMap map = MAPPER.readValue(aposToQuotes("{'foo':'bar'}"), FromDelegateEnumMap.class); assertEquals(1, map.size()); assertEquals("{foo=bar}", map.get(TestEnum.OK)); } public void testCustomEnumMapFromProps() throws Exception { FromPropertiesEnumMap map = MAPPER.readValue(aposToQuotes( "{'a':13,'RULES':'jackson','b':-731,'OK':'yes'}"), FromPropertiesEnumMap.class); assertEquals(13, map.a0); assertEquals(-731, map.b0); assertEquals("jackson", map.get(TestEnum.RULES)); assertEquals("yes", map.get(TestEnum.OK)); assertEquals(2, map.size()); } /* /********************************************************** /* Test methods: polymorphic /********************************************************** */ // [databind#1859] public void testEnumMapAsPolymorphic() throws Exception { EnumMap enumMap = new EnumMap<>(Enum1859.class); enumMap.put(Enum1859.A, "Test"); enumMap.put(Enum1859.B, "stuff"); Pojo1859 input = new Pojo1859(enumMap); ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, "@type"); // 05-Mar-2018, tatu: Original issue had this; should not make difference: /* TypeResolverBuilder mapTyperAsPropertyType = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL); mapTyperAsPropertyType.init(JsonTypeInfo.Id.CLASS, null); mapTyperAsPropertyType.inclusion(JsonTypeInfo.As.PROPERTY); mapper.setDefaultTyping(mapTyperAsPropertyType); */ String json = mapper.writeValueAsString(input); Pojo1859 result = mapper.readValue(json, Pojo1859.class); assertNotNull(result); assertNotNull(result.values); assertEquals(2, result.values.size()); } /* /********************************************************** /* Test methods: handling of invalid values /********************************************************** */ // [databind#1859] public void testUnknownKeyAsDefault() throws Exception { // first, via EnumMap EnumMap value = MAPPER .readerFor(new TypeReference>() { }) .with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE) .readValue("{\"unknown\":\"value\"}"); assertEquals(1, value.size()); assertEquals("value", value.get(TestEnumWithDefault.OK)); Map value2 = MAPPER .readerFor(new TypeReference>() { }) .with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE) .readValue("{\"unknown\":\"value\"}"); assertEquals(1, value2.size()); assertEquals("value", value2.get(TestEnumWithDefault.OK)); } // [databind#1859] public void testUnknownKeyAsNull() throws Exception { // first, via EnumMap EnumMap value = MAPPER .readerFor(new TypeReference>() { }) .with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL) .readValue("{\"unknown\":\"value\"}"); assertEquals(0, value.size()); // then regular Map Map value2 = MAPPER .readerFor(new TypeReference>() { }) .with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL) .readValue("{\"unknown\":\"value\"}"); // 04-Jan-2017, tatu: Not sure if this is weird or not, but since `null`s are typically // ok for "regular" JDK Maps... assertEquals(1, value2.size()); assertEquals("value", value2.get(null)); } } JDKAtomicTypesTest.java000066400000000000000000000227601325620701100366610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.Serializable; import java.math.BigDecimal; import java.util.concurrent.atomic.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class JDKAtomicTypesTest extends com.fasterxml.jackson.databind.BaseMapTest { @JsonTypeInfo(use = JsonTypeInfo.Id.NAME) @JsonSubTypes({ @JsonSubTypes.Type(Impl.class) }) static abstract class Base { } @JsonTypeName("I") static class Impl extends Base { public int value; public Impl() { } public Impl(int v) { value = v; } } static class RefWrapper { public AtomicReference w; public RefWrapper() { } public RefWrapper(Base b) { w = new AtomicReference(b); } public RefWrapper(int i) { w = new AtomicReference(new Impl(i)); } } static class SimpleWrapper { public AtomicReference value; public SimpleWrapper(Object o) { value = new AtomicReference(o); } } static class RefiningWrapper { @JsonDeserialize(contentAs=BigDecimal.class) public AtomicReference value; } // Additional tests for improvements with [databind#932] static class UnwrappingRefParent { @JsonUnwrapped(prefix = "XX.") public AtomicReference child = new AtomicReference(new Child()); } static class Child { public String name = "Bob"; } static class Parent { private Child child = new Child(); @JsonUnwrapped public Child getChild() { return child; } } static class WrappedString { String value; public WrappedString(String s) { value = s; } } static class AtomicRefReadWrapper { @JsonDeserialize(contentAs=WrappedString.class) public AtomicReference value; } static class LCStringWrapper { @JsonDeserialize(contentUsing=LowerCasingDeserializer.class) public AtomicReference value; public LCStringWrapper() { } } @JsonPropertyOrder({ "a", "b" }) static class Issue1256Bean { @JsonSerialize(as=AtomicReference.class) public Object a = new AtomicReference(); public AtomicReference b = new AtomicReference(); } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testAtomicBoolean() throws Exception { AtomicBoolean b = MAPPER.readValue("true", AtomicBoolean.class); assertTrue(b.get()); } public void testAtomicInt() throws Exception { AtomicInteger value = MAPPER.readValue("13", AtomicInteger.class); assertEquals(13, value.get()); } public void testAtomicLong() throws Exception { AtomicLong value = MAPPER.readValue("12345678901", AtomicLong.class); assertEquals(12345678901L, value.get()); } public void testAtomicReference() throws Exception { AtomicReference value = MAPPER.readValue("[1,2]", new com.fasterxml.jackson.core.type.TypeReference>() { }); Object ob = value.get(); assertNotNull(ob); assertEquals(long[].class, ob.getClass()); long[] longs = (long[]) ob; assertNotNull(longs); assertEquals(2, longs.length); assertEquals(1, longs[0]); assertEquals(2, longs[1]); } // for [databind#811] public void testAbsentExclusion() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT); assertEquals(aposToQuotes("{'value':true}"), mapper.writeValueAsString(new SimpleWrapper(Boolean.TRUE))); assertEquals(aposToQuotes("{}"), mapper.writeValueAsString(new SimpleWrapper(null))); } public void testSerPropInclusionAlways() throws Exception { JsonInclude.Value incl = JsonInclude.Value.construct(JsonInclude.Include.NON_ABSENT, JsonInclude.Include.ALWAYS); ObjectMapper mapper = new ObjectMapper(); mapper.setDefaultPropertyInclusion(incl); assertEquals(aposToQuotes("{'value':true}"), mapper.writeValueAsString(new SimpleWrapper(Boolean.TRUE))); } public void testSerPropInclusionNonNull() throws Exception { JsonInclude.Value incl = JsonInclude.Value.construct(JsonInclude.Include.NON_ABSENT, JsonInclude.Include.NON_NULL); ObjectMapper mapper = new ObjectMapper(); mapper.setDefaultPropertyInclusion(incl); assertEquals(aposToQuotes("{'value':true}"), mapper.writeValueAsString(new SimpleWrapper(Boolean.TRUE))); } public void testSerPropInclusionNonAbsent() throws Exception { JsonInclude.Value incl = JsonInclude.Value.construct(JsonInclude.Include.NON_ABSENT, JsonInclude.Include.NON_ABSENT); ObjectMapper mapper = new ObjectMapper(); mapper.setDefaultPropertyInclusion(incl); assertEquals(aposToQuotes("{'value':true}"), mapper.writeValueAsString(new SimpleWrapper(Boolean.TRUE))); } public void testSerPropInclusionNonEmpty() throws Exception { JsonInclude.Value incl = JsonInclude.Value.construct(JsonInclude.Include.NON_ABSENT, JsonInclude.Include.NON_EMPTY); ObjectMapper mapper = new ObjectMapper(); mapper.setDefaultPropertyInclusion(incl); assertEquals(aposToQuotes("{'value':true}"), mapper.writeValueAsString(new SimpleWrapper(Boolean.TRUE))); } // [databind#340] public void testPolymorphicAtomicReference() throws Exception { RefWrapper input = new RefWrapper(13); String json = MAPPER.writeValueAsString(input); RefWrapper result = MAPPER.readValue(json, RefWrapper.class); assertNotNull(result.w); Object ob = result.w.get(); assertEquals(Impl.class, ob.getClass()); assertEquals(13, ((Impl) ob).value); } // [databind#740] public void testFilteringOfAtomicReference() throws Exception { SimpleWrapper input = new SimpleWrapper(null); ObjectMapper mapper = MAPPER; // by default, include as null assertEquals(aposToQuotes("{'value':null}"), mapper.writeValueAsString(input)); // ditto with "no nulls" mapper = new ObjectMapper().setSerializationInclusion(JsonInclude .Include.NON_NULL); assertEquals(aposToQuotes("{'value':null}"), mapper.writeValueAsString(input)); // but not with "non empty" mapper = new ObjectMapper().setSerializationInclusion(JsonInclude .Include.NON_EMPTY); assertEquals("{}", mapper.writeValueAsString(input)); } public void testTypeRefinement() throws Exception { RefiningWrapper input = new RefiningWrapper(); BigDecimal bd = new BigDecimal("0.25"); input.value = new AtomicReference(bd); String json = MAPPER.writeValueAsString(input); // so far so good. But does it come back as expected? RefiningWrapper result = MAPPER.readValue(json, RefiningWrapper.class); assertNotNull(result.value); Object ob = result.value.get(); assertEquals(BigDecimal.class, ob.getClass()); assertEquals(bd, ob); } // [databind#882]: verify `@JsonDeserialize(contentAs=)` works with AtomicReference public void testDeserializeWithContentAs() throws Exception { AtomicRefReadWrapper result = MAPPER.readValue(aposToQuotes("{'value':'abc'}"), AtomicRefReadWrapper.class); Object v = result.value.get(); assertNotNull(v); assertEquals(WrappedString.class, v.getClass()); assertEquals("abc", ((WrappedString)v).value); } // [databind#932]: support unwrapping too public void testWithUnwrapping() throws Exception { String jsonExp = aposToQuotes("{'XX.name':'Bob'}"); String jsonAct = MAPPER.writeValueAsString(new UnwrappingRefParent()); assertEquals(jsonExp, jsonAct); } public void testWithCustomDeserializer() throws Exception { LCStringWrapper w = MAPPER.readValue(aposToQuotes("{'value':'FoobaR'}"), LCStringWrapper.class); assertEquals("foobar", w.value.get()); } public void testEmpty1256() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT); String json = mapper.writeValueAsString(new Issue1256Bean()); assertEquals("{}", json); } // [databind#1307] @SuppressWarnings("unchecked") public void testNullValueHandling() throws Exception { ObjectMapper mapper = new ObjectMapper(); AtomicReference inputData = new AtomicReference(); String json = mapper.writeValueAsString(inputData); AtomicReference readData = (AtomicReference) mapper.readValue(json, AtomicReference.class); assertNotNull(readData); assertNull(readData.get()); } } JDKCollectionsDeserTest.java000066400000000000000000000047761325620701100376700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.util.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; /** * Tests for special collection/map types via `java.util.Collections` */ public class JDKCollectionsDeserTest extends BaseMapTest { static class XBean { public int x; public XBean() { } public XBean(int x) { this.x = x; } } /* /********************************************************************** /* Test methods /********************************************************************** */ private final static ObjectMapper MAPPER = new ObjectMapper(); // And then a round-trip test for singleton collections public void testSingletonCollections() throws Exception { final TypeReference xbeanListType = new TypeReference>() { }; String json = MAPPER.writeValueAsString(Collections.singleton(new XBean(3))); Collection result = MAPPER.readValue(json, xbeanListType); assertNotNull(result); assertEquals(1, result.size()); assertEquals(3, result.iterator().next().x); json = MAPPER.writeValueAsString(Collections.singletonList(new XBean(28))); result = MAPPER.readValue(json, xbeanListType); assertNotNull(result); assertEquals(1, result.size()); assertEquals(28, result.iterator().next().x); } // [databind#1868]: Verify class name serialized as is public void testUnmodifiableSet() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); Set theSet = Collections.unmodifiableSet(Collections.singleton("a")); String json = mapper.writeValueAsString(theSet); assertEquals("[\"java.util.Collections$UnmodifiableSet\",[\"a\"]]", json); // 04-Jan-2018, tatu: Alas, no way to make this actually work well, at this point. // In theory could jiggle things back on deser, using one of two ways: // // 1) Do mapping to regular Set/List types (abstract type mapping): would work, but get rid of immutability // 2) Have actually separate deserializer OR ValueInstantiator /* Set result = mapper.readValue(json, Set.class); assertNotNull(result); assertEquals(1, result.size()); */ } } JDKNumberDeserTest.java000066400000000000000000000267371325620701100366430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.IOException; import java.io.StringReader; import java.math.BigDecimal; import java.math.BigInteger; import java.util.List; import java.util.Map; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.exc.MismatchedInputException; public class JDKNumberDeserTest extends BaseMapTest { /* /********************************************************************** /* Helper classes, beans /********************************************************************** */ static class MyBeanHolder { public Long id; public MyBeanDefaultValue defaultValue; } static class MyBeanDefaultValue { public MyBeanValue value; } @JsonDeserialize(using=MyBeanDeserializer.class) static class MyBeanValue { public BigDecimal decimal; public MyBeanValue() { this(null); } public MyBeanValue(BigDecimal d) { this.decimal = d; } } /* /********************************************************************** /* Helper classes, serializers/deserializers/resolvers /********************************************************************** */ static class MyBeanDeserializer extends JsonDeserializer { @Override public MyBeanValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { return new MyBeanValue(jp.getDecimalValue()); } } /* /********************************************************************** /* Unit tests /********************************************************************** */ final ObjectMapper MAPPER = new ObjectMapper(); public void testNaN() throws Exception { Float result = MAPPER.readValue(" \"NaN\"", Float.class); assertEquals(Float.valueOf(Float.NaN), result); Double d = MAPPER.readValue(" \"NaN\"", Double.class); assertEquals(Double.valueOf(Double.NaN), d); Number num = MAPPER.readValue(" \"NaN\"", Number.class); assertEquals(Double.valueOf(Double.NaN), num); } public void testDoubleInf() throws Exception { Double result = MAPPER.readValue(" \""+Double.POSITIVE_INFINITY+"\"", Double.class); assertEquals(Double.valueOf(Double.POSITIVE_INFINITY), result); result = MAPPER.readValue(" \""+Double.NEGATIVE_INFINITY+"\"", Double.class); assertEquals(Double.valueOf(Double.NEGATIVE_INFINITY), result); } // 01-Mar-2017, tatu: This is bit tricky... in some ways, mapping to "empty value" // would be best; but due to legacy reasons becomes `null` at this point public void testEmptyAsNumber() throws Exception { assertNull(MAPPER.readValue(quote(""), Byte.class)); assertNull(MAPPER.readValue(quote(""), Short.class)); assertNull(MAPPER.readValue(quote(""), Character.class)); assertNull(MAPPER.readValue(quote(""), Integer.class)); assertNull(MAPPER.readValue(quote(""), Long.class)); assertNull(MAPPER.readValue(quote(""), Float.class)); assertNull(MAPPER.readValue(quote(""), Double.class)); assertNull(MAPPER.readValue(quote(""), BigInteger.class)); assertNull(MAPPER.readValue(quote(""), BigDecimal.class)); } public void testTextualNullAsNumber() throws Exception { final String NULL_JSON = quote("null"); assertNull(MAPPER.readValue(NULL_JSON, Byte.class)); assertNull(MAPPER.readValue(NULL_JSON, Short.class)); // Character is bit special, can't do: // assertNull(MAPPER.readValue(JSON, Character.class)); assertNull(MAPPER.readValue(NULL_JSON, Integer.class)); assertNull(MAPPER.readValue(NULL_JSON, Long.class)); assertNull(MAPPER.readValue(NULL_JSON, Float.class)); assertNull(MAPPER.readValue(NULL_JSON, Double.class)); assertEquals(Byte.valueOf((byte) 0), MAPPER.readValue(NULL_JSON, Byte.TYPE)); assertEquals(Short.valueOf((short) 0), MAPPER.readValue(NULL_JSON, Short.TYPE)); // Character is bit special, can't do: // assertEquals(Character.valueOf((char) 0), MAPPER.readValue(JSON, Character.TYPE)); assertEquals(Integer.valueOf(0), MAPPER.readValue(NULL_JSON, Integer.TYPE)); assertEquals(Long.valueOf(0L), MAPPER.readValue(NULL_JSON, Long.TYPE)); assertEquals(Float.valueOf(0f), MAPPER.readValue(NULL_JSON, Float.TYPE)); assertEquals(Double.valueOf(0d), MAPPER.readValue(NULL_JSON, Double.TYPE)); assertNull(MAPPER.readValue(NULL_JSON, BigInteger.class)); assertNull(MAPPER.readValue(NULL_JSON, BigDecimal.class)); // Also: verify failure for at least some try { MAPPER.readerFor(Integer.TYPE).with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES) .readValue(NULL_JSON); fail("Should not have passed"); } catch (MismatchedInputException e) { verifyException(e, "Cannot coerce String \"null\""); } ObjectMapper noCoerceMapper = new ObjectMapper(); noCoerceMapper.disable(MapperFeature.ALLOW_COERCION_OF_SCALARS); try { noCoerceMapper.readValue(NULL_JSON, Integer.TYPE); fail("Should not have passed"); } catch (MismatchedInputException e) { verifyException(e, "Cannot coerce String \"null\""); } } public void testDeserializeDecimalHappyPath() throws Exception { String json = "{\"defaultValue\": { \"value\": 123 } }"; MyBeanHolder result = MAPPER.readValue(json, MyBeanHolder.class); assertEquals(BigDecimal.valueOf(123), result.defaultValue.value.decimal); } public void testDeserializeDecimalProperException() throws Exception { String json = "{\"defaultValue\": { \"value\": \"123\" } }"; try { MAPPER.readValue(json, MyBeanHolder.class); fail("should have raised exception"); } catch (JsonProcessingException e) { verifyException(e, "not numeric"); } } public void testDeserializeDecimalProperExceptionWhenIdSet() throws Exception { String json = "{\"id\": 5, \"defaultValue\": { \"value\": \"123\" } }"; try { MyBeanHolder result = MAPPER.readValue(json, MyBeanHolder.class); fail("should have raised exception instead value was set to " + result.defaultValue.value.decimal.toString()); } catch (JsonProcessingException e) { verifyException(e, "not numeric"); } } // And then [databind#852] public void testScientificNotationAsStringForNumber() throws Exception { Object ob = MAPPER.readValue("\"3E-8\"", Number.class); assertEquals(Double.class, ob.getClass()); ob = MAPPER.readValue("\"3e-8\"", Number.class); assertEquals(Double.class, ob.getClass()); ob = MAPPER.readValue("\"300000000\"", Number.class); assertEquals(Integer.class, ob.getClass()); ob = MAPPER.readValue("\"123456789012\"", Number.class); assertEquals(Long.class, ob.getClass()); } public void testIntAsNumber() throws Exception { /* Even if declared as 'generic' type, should return using most * efficient type... here, Integer */ Number result = MAPPER.readValue(" 123 ", Number.class); assertEquals(Integer.valueOf(123), result); } public void testLongAsNumber() throws Exception { // And beyond int range, should get long long exp = 1234567890123L; Number result = MAPPER.readValue(String.valueOf(exp), Number.class); assertEquals(Long.valueOf(exp), result); } public void testBigIntAsNumber() throws Exception { // and after long, BigInteger BigInteger biggie = new BigInteger("1234567890123456789012345678901234567890"); Number result = MAPPER.readValue(biggie.toString(), Number.class); assertEquals(BigInteger.class, biggie.getClass()); assertEquals(biggie, result); } public void testIntTypeOverride() throws Exception { /* Slight twist; as per [JACKSON-100], can also request binding * to BigInteger even if value would fit in Integer */ ObjectReader r = MAPPER.reader(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS); BigInteger exp = BigInteger.valueOf(123L); // first test as any Number Number result = r.forType(Number.class).readValue(" 123 "); assertEquals(BigInteger.class, result.getClass()); assertEquals(exp, result); // then as any Object /*Object value =*/ r.forType(Object.class).readValue("123"); assertEquals(BigInteger.class, result.getClass()); assertEquals(exp, result); // and as JsonNode JsonNode node = r.readTree(" 123"); assertTrue(node.isBigInteger()); assertEquals(123, node.asInt()); } public void testDoubleAsNumber() throws Exception { Number result = MAPPER.readValue(new StringReader(" 1.0 "), Number.class); assertEquals(Double.valueOf(1.0), result); } public void testFpTypeOverrideSimple() throws Exception { ObjectReader r = MAPPER.reader(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS); BigDecimal dec = new BigDecimal("0.1"); // First test generic stand-alone Number Number result = r.forType(Number.class).readValue(dec.toString()); assertEquals(BigDecimal.class, result.getClass()); assertEquals(dec, result); // Then plain old Object Object value = r.forType(Object.class).readValue(dec.toString()); assertEquals(BigDecimal.class, result.getClass()); assertEquals(dec, value); JsonNode node = r.readTree(dec.toString()); assertTrue(node.isBigDecimal()); assertEquals(dec.doubleValue(), node.asDouble()); } public void testFpTypeOverrideStructured() throws Exception { ObjectReader r = MAPPER.reader(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS); BigDecimal dec = new BigDecimal("-19.37"); // List element types @SuppressWarnings("unchecked") List list = (List) r.forType(List.class).readValue("[ "+dec.toString()+" ]"); assertEquals(1, list.size()); Object val = list.get(0); assertEquals(BigDecimal.class, val.getClass()); assertEquals(dec, val); // and a map Map map = r.forType(Map.class).readValue("{ \"a\" : "+dec.toString()+" }"); assertEquals(1, map.size()); val = map.get("a"); assertEquals(BigDecimal.class, val.getClass()); assertEquals(dec, val); } // [databind#504] public void testForceIntsToLongs() throws Exception { ObjectReader r = MAPPER.reader(DeserializationFeature.USE_LONG_FOR_INTS); Object ob = r.forType(Object.class).readValue("42"); assertEquals(Long.class, ob.getClass()); assertEquals(Long.valueOf(42L), ob); Number n = r.forType(Number.class).readValue("42"); assertEquals(Long.class, n.getClass()); assertEquals(Long.valueOf(42L), n); // and one more: should get proper node as well JsonNode node = r.readTree("42"); if (!node.isLong()) { fail("Expected LongNode, got: "+node.getClass().getName()); } assertEquals(42, node.asInt()); } } JDKScalarsTest.java000066400000000000000000000765311325620701100360150ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.*; import java.lang.reflect.Array; import org.junit.Assert; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying handling of simple basic non-structured * types; primitives (and/or their wrappers), Strings. */ public class JDKScalarsTest extends BaseMapTest { final static String NAN_STRING = "NaN"; final static class BooleanBean { boolean _v; void setV(boolean v) { _v = v; } } static class BooleanWrapper { public Boolean wrapper; public boolean primitive; protected Boolean ctor; @JsonCreator public BooleanWrapper(@JsonProperty("ctor") Boolean foo) { ctor = foo; } } static class IntBean { int _v; void setV(int v) { _v = v; } } static class LongBean { long _v; void setV(long v) { _v = v; } } final static class DoubleBean { double _v; void setV(double v) { _v = v; } } final static class FloatBean { float _v; void setV(float v) { _v = v; } } final static class CharacterBean { char _v; void setV(char v) { _v = v; } char getV() { return _v; } } final static class CharacterWrapperBean { Character _v; void setV(Character v) { _v = v; } Character getV() { return _v; } } /** * Also, let's ensure that it's ok to override methods. */ static class IntBean2 extends IntBean { @Override void setV(int v2) { super.setV(v2+1); } } static class PrimitivesBean { public boolean booleanValue = true; public byte byteValue = 3; public char charValue = 'a'; public short shortValue = 37; public int intValue = 1; public long longValue = 100L; public float floatValue = 0.25f; public double doubleValue = -1.0; } static class WrappersBean { public Boolean booleanValue; public Byte byteValue; public Character charValue; public Short shortValue; public Integer intValue; public Long longValue; public Float floatValue; public Double doubleValue; } private final ObjectMapper MAPPER = new ObjectMapper(); /* /********************************************************** /* Scalar tests for boolean /********************************************************** */ public void testBooleanPrimitive() throws Exception { // first, simple case: BooleanBean result = MAPPER.readValue("{\"v\":true}", BooleanBean.class); assertTrue(result._v); result = MAPPER.readValue("{\"v\":null}", BooleanBean.class); assertNotNull(result); assertFalse(result._v); result = MAPPER.readValue("{\"v\":1}", BooleanBean.class); assertNotNull(result); assertTrue(result._v); // should work with arrays too.. boolean[] array = MAPPER.readValue("[ null, false ]", boolean[].class); assertNotNull(array); assertEquals(2, array.length); assertFalse(array[0]); assertFalse(array[1]); } /** * Simple unit test to verify that we can map boolean values to * java.lang.Boolean. */ public void testBooleanWrapper() throws Exception { Boolean result = MAPPER.readValue("true", Boolean.class); assertEquals(Boolean.TRUE, result); result = MAPPER.readValue("false", Boolean.class); assertEquals(Boolean.FALSE, result); // should accept ints too, (0 == false, otherwise true) result = MAPPER.readValue("0", Boolean.class); assertEquals(Boolean.FALSE, result); result = MAPPER.readValue("1", Boolean.class); assertEquals(Boolean.TRUE, result); } // Test for verifying that Long values are coerced to boolean correctly as well public void testLongToBoolean() throws Exception { long value = 1L + Integer.MAX_VALUE; BooleanWrapper b = MAPPER.readValue("{\"primitive\" : "+value+", \"wrapper\":"+value+", \"ctor\":"+value+"}", BooleanWrapper.class); assertEquals(Boolean.TRUE, b.wrapper); assertTrue(b.primitive); assertEquals(Boolean.TRUE, b.ctor); // but ensure we can also get `false` b = MAPPER.readValue("{\"primitive\" : 0 , \"wrapper\":0, \"ctor\":0}", BooleanWrapper.class); assertEquals(Boolean.FALSE, b.wrapper); assertFalse(b.primitive); assertEquals(Boolean.FALSE, b.ctor); boolean[] boo = MAPPER.readValue("[ 0, 15, \"\", \"false\", \"True\" ]", boolean[].class); assertEquals(5, boo.length); assertFalse(boo[0]); assertTrue(boo[1]); assertFalse(boo[2]); assertFalse(boo[3]); assertTrue(boo[4]); } /* /********************************************************** /* Scalar tests for integral types /********************************************************** */ public void testByteWrapper() throws Exception { Byte result = MAPPER.readValue(" -42\t", Byte.class); assertEquals(Byte.valueOf((byte)-42), result); // Also: should be able to coerce floats, strings: result = MAPPER.readValue(" \"-12\"", Byte.class); assertEquals(Byte.valueOf((byte)-12), result); result = MAPPER.readValue(" 39.07", Byte.class); assertEquals(Byte.valueOf((byte)39), result); } public void testShortWrapper() throws Exception { Short result = MAPPER.readValue("37", Short.class); assertEquals(Short.valueOf((short)37), result); // Also: should be able to coerce floats, strings: result = MAPPER.readValue(" \"-1009\"", Short.class); assertEquals(Short.valueOf((short)-1009), result); result = MAPPER.readValue("-12.9", Short.class); assertEquals(Short.valueOf((short)-12), result); } public void testCharacterWrapper() throws Exception { // First: canonical value is 1-char string Character result = MAPPER.readValue("\"a\"", Character.class); assertEquals(Character.valueOf('a'), result); // But can also pass in ascii code result = MAPPER.readValue(" "+((int) 'X'), Character.class); assertEquals(Character.valueOf('X'), result); final CharacterWrapperBean wrapper = MAPPER.readValue("{\"v\":null}", CharacterWrapperBean.class); assertNotNull(wrapper); assertNull(wrapper.getV()); final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES); try { mapper.readValue("{\"v\":null}", CharacterBean.class); fail("Attempting to deserialize a 'null' JSON reference into a 'char' property did not throw an exception"); } catch (JsonMappingException e) { verifyException(e, "cannot map `null`"); //Exception thrown as required } mapper.disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES); final CharacterBean charBean = MAPPER.readValue("{\"v\":null}", CharacterBean.class); assertNotNull(wrapper); assertEquals('\u0000', charBean.getV()); } public void testIntWrapper() throws Exception { Integer result = MAPPER.readValue(" -42\t", Integer.class); assertEquals(Integer.valueOf(-42), result); // Also: should be able to coerce floats, strings: result = MAPPER.readValue(" \"-1200\"", Integer.class); assertEquals(Integer.valueOf(-1200), result); result = MAPPER.readValue(" 39.07", Integer.class); assertEquals(Integer.valueOf(39), result); } public void testIntPrimitive() throws Exception { // first, simple case: IntBean result = MAPPER.readValue("{\"v\":3}", IntBean.class); assertEquals(3, result._v); result = MAPPER.readValue("{\"v\":null}", IntBean.class); assertNotNull(result); assertEquals(0, result._v); // should work with arrays too.. int[] array = MAPPER.readValue("[ null ]", int[].class); assertNotNull(array); assertEquals(1, array.length); assertEquals(0, array[0]); // [databind#381] final ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); try { mapper.readValue("{\"v\":[3]}", IntBean.class); fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled"); } catch (JsonMappingException exp) { //Correctly threw exception } mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); result = mapper.readValue("{\"v\":[3]}", IntBean.class); assertEquals(3, result._v); result = mapper.readValue("[{\"v\":[3]}]", IntBean.class); assertEquals(3, result._v); try { mapper.readValue("[{\"v\":[3,3]}]", IntBean.class); fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled"); } catch (JsonMappingException exp) { //threw exception as required } result = mapper.readValue("{\"v\":[null]}", IntBean.class); assertNotNull(result); assertEquals(0, result._v); array = mapper.readValue("[ [ null ] ]", int[].class); assertNotNull(array); assertEquals(1, array.length); assertEquals(0, array[0]); } public void testLongWrapper() throws Exception { Long result = MAPPER.readValue("12345678901", Long.class); assertEquals(Long.valueOf(12345678901L), result); // Also: should be able to coerce floats, strings: result = MAPPER.readValue(" \"-9876\"", Long.class); assertEquals(Long.valueOf(-9876), result); result = MAPPER.readValue("1918.3", Long.class); assertEquals(Long.valueOf(1918), result); } public void testLongPrimitive() throws Exception { // first, simple case: LongBean result = MAPPER.readValue("{\"v\":3}", LongBean.class); assertEquals(3, result._v); result = MAPPER.readValue("{\"v\":null}", LongBean.class); assertNotNull(result); assertEquals(0, result._v); // should work with arrays too.. long[] array = MAPPER.readValue("[ null ]", long[].class); assertNotNull(array); assertEquals(1, array.length); assertEquals(0, array[0]); // [databind#381] final ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); try { mapper.readValue("{\"v\":[3]}", LongBean.class); fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled"); } catch (JsonMappingException exp) { //Correctly threw exception } mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); result = mapper.readValue("{\"v\":[3]}", LongBean.class); assertEquals(3, result._v); result = mapper.readValue("[{\"v\":[3]}]", LongBean.class); assertEquals(3, result._v); try { mapper.readValue("[{\"v\":[3,3]}]", LongBean.class); fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled"); } catch (JsonMappingException exp) { //threw exception as required } result = mapper.readValue("{\"v\":[null]}", LongBean.class); assertNotNull(result); assertEquals(0, result._v); array = mapper.readValue("[ [ null ] ]", long[].class); assertNotNull(array); assertEquals(1, array.length); assertEquals(0, array[0]); } /** * Beyond simple case, let's also ensure that method overriding works as * expected. */ public void testIntWithOverride() throws Exception { IntBean2 result = MAPPER.readValue("{\"v\":8}", IntBean2.class); assertEquals(9, result._v); } /* /********************************************************** /* Scalar tests for floating point types /********************************************************** */ public void testDoublePrimitive() throws Exception { // first, simple case: // bit tricky with binary fps but... final double value = 0.016; DoubleBean result = MAPPER.readValue("{\"v\":"+value+"}", DoubleBean.class); assertEquals(value, result._v); // then [JACKSON-79]: result = MAPPER.readValue("{\"v\":null}", DoubleBean.class); assertNotNull(result); assertEquals(0.0, result._v); // should work with arrays too.. double[] array = MAPPER.readValue("[ null ]", double[].class); assertNotNull(array); assertEquals(1, array.length); assertEquals(0.0, array[0]); } /* Note: dealing with floating-point values is tricky; not sure if * we can really use equality tests here... JDK does have decent * conversions though, to retain accuracy and round-trippability. * But still... */ public void testFloatWrapper() throws Exception { // Also: should be able to coerce floats, strings: String[] STRS = new String[] { "1.0", "0.0", "-0.3", "0.7", "42.012", "-999.0", NAN_STRING }; for (String str : STRS) { Float exp = Float.valueOf(str); Float result; if (NAN_STRING != str) { // First, as regular floating point value result = MAPPER.readValue(str, Float.class); assertEquals(exp, result); } // and then as coerced String: result = MAPPER.readValue(" \""+str+"\"", Float.class); assertEquals(exp, result); } } public void testDoubleWrapper() throws Exception { // Also: should be able to coerce doubles, strings: String[] STRS = new String[] { "1.0", "0.0", "-0.3", "0.7", "42.012", "-999.0", NAN_STRING }; for (String str : STRS) { Double exp = Double.valueOf(str); Double result; // First, as regular double value if (NAN_STRING != str) { result = MAPPER.readValue(str, Double.class); assertEquals(exp, result); } // and then as coerced String: result = MAPPER.readValue(" \""+str+"\"", Double.class); assertEquals(exp, result); } } public void testDoubleAsArray() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); final double value = 0.016; try { mapper.readValue("{\"v\":[" + value + "]}", DoubleBean.class); fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled"); } catch (JsonMappingException exp) { //Correctly threw exception } mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); DoubleBean result = mapper.readValue("{\"v\":[" + value + "]}", DoubleBean.class); assertEquals(value, result._v); result = mapper.readValue("[{\"v\":[" + value + "]}]", DoubleBean.class); assertEquals(value, result._v); try { mapper.readValue("[{\"v\":[" + value + "," + value + "]}]", DoubleBean.class); fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled"); } catch (JsonMappingException exp) { //threw exception as required } result = mapper.readValue("{\"v\":[null]}", DoubleBean.class); assertNotNull(result); assertEquals(0d, result._v); double[] array = mapper.readValue("[ [ null ] ]", double[].class); assertNotNull(array); assertEquals(1, array.length); assertEquals(0d, array[0]); } public void testDoublePrimitiveNonNumeric() throws Exception { // first, simple case: // bit tricky with binary fps but... double value = Double.POSITIVE_INFINITY; DoubleBean result = MAPPER.readValue("{\"v\":\""+value+"\"}", DoubleBean.class); assertEquals(value, result._v); // should work with arrays too.. double[] array = MAPPER.readValue("[ \"Infinity\" ]", double[].class); assertNotNull(array); assertEquals(1, array.length); assertEquals(Double.POSITIVE_INFINITY, array[0]); } public void testFloatPrimitiveNonNumeric() throws Exception { // bit tricky with binary fps but... float value = Float.POSITIVE_INFINITY; FloatBean result = MAPPER.readValue("{\"v\":\""+value+"\"}", FloatBean.class); assertEquals(value, result._v); // should work with arrays too.. float[] array = MAPPER.readValue("[ \"Infinity\" ]", float[].class); assertNotNull(array); assertEquals(1, array.length); assertEquals(Float.POSITIVE_INFINITY, array[0]); } /* /********************************************************** /* Scalar tests, other /********************************************************** */ public void testEmptyToNullCoercionForPrimitives() throws Exception { _testEmptyToNullCoercion(int.class, Integer.valueOf(0)); _testEmptyToNullCoercion(long.class, Long.valueOf(0)); _testEmptyToNullCoercion(double.class, Double.valueOf(0.0)); _testEmptyToNullCoercion(float.class, Float.valueOf(0.0f)); } private void _testEmptyToNullCoercion(Class primType, Object emptyValue) throws Exception { final String EMPTY = "\"\""; // as per [databind#1095] should only allow coercion from empty String, // if `null` is acceptable ObjectReader intR = MAPPER.readerFor(primType); assertEquals(emptyValue, intR.readValue(EMPTY)); try { intR.with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES) .readValue("\"\""); fail("Should not have passed"); } catch (JsonMappingException e) { verifyException(e, "Cannot coerce empty String"); } } public void testBase64Variants() throws Exception { final byte[] INPUT = "abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890X".getBytes("UTF-8"); // default encoding is "MIME, no linefeeds", so: Assert.assertArrayEquals(INPUT, MAPPER.readValue( quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA=="), byte[].class)); ObjectReader reader = MAPPER.readerFor(byte[].class); Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.MIME_NO_LINEFEEDS).readValue( quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA==" ))); // but others should be slightly different Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.MIME).readValue( quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1\\ndnd4eXoxMjM0NTY3ODkwWA==" ))); Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.MODIFIED_FOR_URL).readValue( quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA" ))); // PEM mandates 64 char lines: Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.PEM).readValue( quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamts\\nbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA==" ))); } /* /********************************************************** /* Sequence tests /********************************************************** */ /** * Then a unit test to verify that we can conveniently bind sequence of * space-separate simple values */ public void testSequenceOfInts() throws Exception { final int NR_OF_INTS = 100; StringBuilder sb = new StringBuilder(); for (int i = 0; i < NR_OF_INTS; ++i) { sb.append(" "); sb.append(i); } JsonParser jp = MAPPER.getFactory().createParser(sb.toString()); for (int i = 0; i < NR_OF_INTS; ++i) { Integer result = MAPPER.readValue(jp, Integer.class); assertEquals(Integer.valueOf(i), result); } jp.close(); } /* /********************************************************** /* Empty String coercion, handling /********************************************************** */ // by default, should return nulls, n'est pas? public void testEmptyStringForWrappers() throws IOException { WrappersBean bean; bean = MAPPER.readValue("{\"booleanValue\":\"\"}", WrappersBean.class); assertNull(bean.booleanValue); bean = MAPPER.readValue("{\"byteValue\":\"\"}", WrappersBean.class); assertNull(bean.byteValue); // char/Character is different... not sure if this should work or not: bean = MAPPER.readValue("{\"charValue\":\"\"}", WrappersBean.class); assertNull(bean.charValue); bean = MAPPER.readValue("{\"shortValue\":\"\"}", WrappersBean.class); assertNull(bean.shortValue); bean = MAPPER.readValue("{\"intValue\":\"\"}", WrappersBean.class); assertNull(bean.intValue); bean = MAPPER.readValue("{\"longValue\":\"\"}", WrappersBean.class); assertNull(bean.longValue); bean = MAPPER.readValue("{\"floatValue\":\"\"}", WrappersBean.class); assertNull(bean.floatValue); bean = MAPPER.readValue("{\"doubleValue\":\"\"}", WrappersBean.class); assertNull(bean.doubleValue); } public void testEmptyStringForPrimitives() throws IOException { PrimitivesBean bean; bean = MAPPER.readValue("{\"booleanValue\":\"\"}", PrimitivesBean.class); assertFalse(bean.booleanValue); bean = MAPPER.readValue("{\"byteValue\":\"\"}", PrimitivesBean.class); assertEquals((byte) 0, bean.byteValue); bean = MAPPER.readValue("{\"charValue\":\"\"}", PrimitivesBean.class); assertEquals((char) 0, bean.charValue); bean = MAPPER.readValue("{\"shortValue\":\"\"}", PrimitivesBean.class); assertEquals((short) 0, bean.shortValue); bean = MAPPER.readValue("{\"intValue\":\"\"}", PrimitivesBean.class); assertEquals(0, bean.intValue); bean = MAPPER.readValue("{\"longValue\":\"\"}", PrimitivesBean.class); assertEquals(0L, bean.longValue); bean = MAPPER.readValue("{\"floatValue\":\"\"}", PrimitivesBean.class); assertEquals(0.0f, bean.floatValue); bean = MAPPER.readValue("{\"doubleValue\":\"\"}", PrimitivesBean.class); assertEquals(0.0, bean.doubleValue); } private void _verifyEmptyStringFailForPrimitives(String propName) throws IOException { final ObjectReader reader = MAPPER .readerFor(PrimitivesBean.class) .with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES); try { reader.readValue(aposToQuotes("{'"+propName+"':''}")); fail("Expected failure for boolean + empty String"); } catch (JsonMappingException e) { verifyException(e, "Cannot coerce empty String (\"\")"); verifyException(e, "to Null value"); } } // for [databind#403] public void testEmptyStringFailForPrimitives() throws IOException { _verifyEmptyStringFailForPrimitives("booleanValue"); _verifyEmptyStringFailForPrimitives("byteValue"); _verifyEmptyStringFailForPrimitives("charValue"); _verifyEmptyStringFailForPrimitives("shortValue"); _verifyEmptyStringFailForPrimitives("intValue"); _verifyEmptyStringFailForPrimitives("longValue"); _verifyEmptyStringFailForPrimitives("floatValue"); _verifyEmptyStringFailForPrimitives("doubleValue"); } /* /********************************************************** /* Null handling for scalars in POJO /********************************************************** */ public void testNullForPrimitives() throws IOException { // by default, ok to rely on defaults PrimitivesBean bean = MAPPER.readValue( "{\"intValue\":null, \"booleanValue\":null, \"doubleValue\":null}", PrimitivesBean.class); assertNotNull(bean); assertEquals(0, bean.intValue); assertEquals(false, bean.booleanValue); assertEquals(0.0, bean.doubleValue); bean = MAPPER.readValue("{\"byteValue\":null, \"longValue\":null, \"floatValue\":null}", PrimitivesBean.class); assertNotNull(bean); assertEquals((byte) 0, bean.byteValue); assertEquals(0L, bean.longValue); assertEquals(0.0f, bean.floatValue); // but not when enabled final ObjectReader reader = MAPPER .readerFor(PrimitivesBean.class) .with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES); // boolean try { reader.readValue("{\"booleanValue\":null}"); fail("Expected failure for boolean + null"); } catch (JsonMappingException e) { verifyException(e, "Cannot map `null` into type boolean"); } // byte/char/short/int/long try { reader.readValue("{\"byteValue\":null}"); fail("Expected failure for byte + null"); } catch (JsonMappingException e) { verifyException(e, "Cannot map `null` into type byte"); } try { reader.readValue("{\"charValue\":null}"); fail("Expected failure for char + null"); } catch (JsonMappingException e) { verifyException(e, "Cannot map `null` into type char"); } try { reader.readValue("{\"shortValue\":null}"); fail("Expected failure for short + null"); } catch (JsonMappingException e) { verifyException(e, "Cannot map `null` into type short"); } try { reader.readValue("{\"intValue\":null}"); fail("Expected failure for int + null"); } catch (JsonMappingException e) { verifyException(e, "Cannot map `null` into type int"); } try { reader.readValue("{\"longValue\":null}"); fail("Expected failure for long + null"); } catch (JsonMappingException e) { verifyException(e, "Cannot map `null` into type long"); } // float/double try { reader.readValue("{\"floatValue\":null}"); fail("Expected failure for float + null"); } catch (JsonMappingException e) { verifyException(e, "Cannot map `null` into type float"); } try { reader.readValue("{\"doubleValue\":null}"); fail("Expected failure for double + null"); } catch (JsonMappingException e) { verifyException(e, "Cannot map `null` into type double"); } } public void testNullForPrimitiveArrays() throws IOException { _testNullForPrimitiveArrays(boolean[].class, Boolean.FALSE); _testNullForPrimitiveArrays(byte[].class, Byte.valueOf((byte) 0)); _testNullForPrimitiveArrays(char[].class, Character.valueOf((char) 0), false); _testNullForPrimitiveArrays(short[].class, Short.valueOf((short)0)); _testNullForPrimitiveArrays(int[].class, Integer.valueOf(0)); _testNullForPrimitiveArrays(long[].class, Long.valueOf(0L)); _testNullForPrimitiveArrays(float[].class, Float.valueOf(0f)); _testNullForPrimitiveArrays(double[].class, Double.valueOf(0d)); } private void _testNullForPrimitiveArrays(Class cls, Object defValue) throws IOException { _testNullForPrimitiveArrays(cls, defValue, true); } private void _testNullForPrimitiveArrays(Class cls, Object defValue, boolean testEmptyString) throws IOException { final String EMPTY_STRING_JSON = "[ \"\" ]"; final String JSON_WITH_NULL = "[ null ]"; final String SIMPLE_NAME = "`"+cls.getSimpleName()+"`"; final ObjectReader readerCoerceOk = MAPPER.readerFor(cls); final ObjectReader readerNoCoerce = readerCoerceOk .with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES); Object ob = readerCoerceOk.forType(cls).readValue(JSON_WITH_NULL); assertEquals(1, Array.getLength(ob)); assertEquals(defValue, Array.get(ob, 0)); try { readerNoCoerce.readValue(JSON_WITH_NULL); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot coerce `null`"); verifyException(e, "as content of type "+SIMPLE_NAME); } if (testEmptyString) { ob = readerCoerceOk.forType(cls).readValue(EMPTY_STRING_JSON); assertEquals(1, Array.getLength(ob)); assertEquals(defValue, Array.get(ob, 0)); try { readerNoCoerce.readValue(EMPTY_STRING_JSON); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot coerce empty String (\"\")"); verifyException(e, "as content of type "+SIMPLE_NAME); } } } /* /********************************************************** /* Test for invalid String values /********************************************************** */ public void testInvalidStringCoercionFail() throws IOException { _testInvalidStringCoercionFail(boolean[].class); _testInvalidStringCoercionFail(byte[].class); // char[] is special, cannot use generalized test here // _testInvalidStringCoercionFail(char[].class); _testInvalidStringCoercionFail(short[].class); _testInvalidStringCoercionFail(int[].class); _testInvalidStringCoercionFail(long[].class); _testInvalidStringCoercionFail(float[].class); _testInvalidStringCoercionFail(double[].class); } private void _testInvalidStringCoercionFail(Class cls) throws IOException { final String JSON = "[ \"foobar\" ]"; final String SIMPLE_NAME = cls.getSimpleName(); try { MAPPER.readerFor(cls).readValue(JSON); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Cannot deserialize value of type `"+SIMPLE_NAME+"` from String \"foobar\""); } } } JDKStringLikeTypesTest.java000066400000000000000000000361151325620701100375170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.*; import java.net.*; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.Currency; import java.util.Locale; import java.util.UUID; import java.util.regex.Pattern; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.Base64Variants; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.util.TokenBuffer; public class JDKStringLikeTypesTest extends BaseMapTest { static class ParamClassBean { public String name = "bar"; public Class clazz ; public ParamClassBean() { } public ParamClassBean(String name) { this.name = name; clazz = String.class; } } // [databind#429] static class StackTraceBean { public final static int NUM = 13; @JsonProperty("Location") @JsonDeserialize(using=MyStackTraceElementDeserializer.class) protected StackTraceElement location; } @SuppressWarnings("serial") static class MyStackTraceElementDeserializer extends StdDeserializer { public MyStackTraceElementDeserializer() { super(StackTraceElement.class); } @Override public StackTraceElement deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { jp.skipChildren(); return new StackTraceElement("a", "b", "b", StackTraceBean.NUM); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); // [databind#239] public void testByteBuffer() throws Exception { byte[] INPUT = new byte[] { 1, 3, 9, -1, 6 }; String exp = MAPPER.writeValueAsString(INPUT); ByteBuffer result = MAPPER.readValue(exp, ByteBuffer.class); assertNotNull(result); assertEquals(INPUT.length, result.remaining()); for (int i = 0; i < INPUT.length; ++i) { assertEquals(INPUT[i], result.get()); } assertEquals(0, result.remaining()); } public void testCharset() throws Exception { Charset UTF8 = Charset.forName("UTF-8"); assertSame(UTF8, MAPPER.readValue(quote("UTF-8"), Charset.class)); } public void testClass() throws IOException { ObjectMapper mapper = new ObjectMapper(); assertSame(String.class, mapper.readValue(quote("java.lang.String"), Class.class)); // then primitive types assertSame(Boolean.TYPE, mapper.readValue(quote("boolean"), Class.class)); assertSame(Byte.TYPE, mapper.readValue(quote("byte"), Class.class)); assertSame(Short.TYPE, mapper.readValue(quote("short"), Class.class)); assertSame(Character.TYPE, mapper.readValue(quote("char"), Class.class)); assertSame(Integer.TYPE, mapper.readValue(quote("int"), Class.class)); assertSame(Long.TYPE, mapper.readValue(quote("long"), Class.class)); assertSame(Float.TYPE, mapper.readValue(quote("float"), Class.class)); assertSame(Double.TYPE, mapper.readValue(quote("double"), Class.class)); assertSame(Void.TYPE, mapper.readValue(quote("void"), Class.class)); } public void testClassWithParams() throws IOException { String json = MAPPER.writeValueAsString(new ParamClassBean("Foobar")); ParamClassBean result = MAPPER.readValue(json, ParamClassBean.class); assertEquals("Foobar", result.name); assertSame(String.class, result.clazz); } public void testCurrency() throws IOException { Currency usd = Currency.getInstance("USD"); assertEquals(usd, new ObjectMapper().readValue(quote("USD"), Currency.class)); } public void testFile() throws Exception { // Not portable etc... has to do: File src = new File("/test").getAbsoluteFile(); String abs = src.getAbsolutePath(); // escape backslashes (for portability with windows) String json = MAPPER.writeValueAsString(abs); File result = MAPPER.readValue(json, File.class); assertEquals(abs, result.getAbsolutePath()); } public void testLocale() throws IOException { assertEquals(new Locale("en"), MAPPER.readValue(quote("en"), Locale.class)); assertEquals(new Locale("es", "ES"), MAPPER.readValue(quote("es_ES"), Locale.class)); assertEquals(new Locale("FI", "fi", "savo"), MAPPER.readValue(quote("fi_FI_savo"), Locale.class)); assertEquals(new Locale("en", "US"), MAPPER.readValue(quote("en-US"), Locale.class)); // [databind#1123] Locale loc = MAPPER.readValue(quote(""), Locale.class); assertSame(Locale.ROOT, loc); } public void testCharSequence() throws IOException { CharSequence cs = MAPPER.readValue("\"abc\"", CharSequence.class); assertEquals(String.class, cs.getClass()); assertEquals("abc", cs.toString()); } public void testInetAddress() throws IOException { InetAddress address = MAPPER.readValue(quote("127.0.0.1"), InetAddress.class); assertEquals("127.0.0.1", address.getHostAddress()); // should we try resolving host names? That requires connectivity... final String HOST = "google.com"; address = MAPPER.readValue(quote(HOST), InetAddress.class); assertEquals(HOST, address.getHostName()); } public void testInetSocketAddress() throws IOException { InetSocketAddress address = MAPPER.readValue(quote("127.0.0.1"), InetSocketAddress.class); assertEquals("127.0.0.1", address.getAddress().getHostAddress()); InetSocketAddress ip6 = MAPPER.readValue( quote("2001:db8:85a3:8d3:1319:8a2e:370:7348"), InetSocketAddress.class); assertEquals("2001:db8:85a3:8d3:1319:8a2e:370:7348", ip6.getAddress().getHostAddress()); InetSocketAddress ip6port = MAPPER.readValue( quote("[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443"), InetSocketAddress.class); assertEquals("2001:db8:85a3:8d3:1319:8a2e:370:7348", ip6port.getAddress().getHostAddress()); assertEquals(443, ip6port.getPort()); // should we try resolving host names? That requires connectivity... final String HOST = "www.google.com"; address = MAPPER.readValue(quote(HOST), InetSocketAddress.class); assertEquals(HOST, address.getHostName()); final String HOST_AND_PORT = HOST+":80"; address = MAPPER.readValue(quote(HOST_AND_PORT), InetSocketAddress.class); assertEquals(HOST, address.getHostName()); assertEquals(80, address.getPort()); } public void testRegexps() throws IOException { final String PATTERN_STR = "abc:\\s?(\\d+)"; Pattern exp = Pattern.compile(PATTERN_STR); /* Ok: easiest way is to just serialize first; problem * is the backslash */ String json = MAPPER.writeValueAsString(exp); Pattern result = MAPPER.readValue(json, Pattern.class); assertEquals(exp.pattern(), result.pattern()); } public void testStackTraceElement() throws Exception { StackTraceElement elem = null; try { throw new IllegalStateException(); } catch (Exception e) { elem = e.getStackTrace()[0]; } String json = MAPPER.writeValueAsString(elem); StackTraceElement back = MAPPER.readValue(json, StackTraceElement.class); assertEquals("testStackTraceElement", back.getMethodName()); assertEquals(elem.getLineNumber(), back.getLineNumber()); assertEquals(elem.getClassName(), back.getClassName()); assertEquals(elem.isNativeMethod(), back.isNativeMethod()); assertTrue(back.getClassName().endsWith("JDKStringLikeTypesTest")); assertFalse(back.isNativeMethod()); } // [databind#429] public void testStackTraceElementWithCustom() throws Exception { // first, via bean that contains StackTraceElement StackTraceBean bean = MAPPER.readValue(aposToQuotes("{'Location':'foobar'}"), StackTraceBean.class); assertNotNull(bean); assertNotNull(bean.location); assertEquals(StackTraceBean.NUM, bean.location.getLineNumber()); // and then directly, iff registered ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(StackTraceElement.class, new MyStackTraceElementDeserializer()); mapper.registerModule(module); StackTraceElement elem = mapper.readValue("123", StackTraceElement.class); assertNotNull(elem); assertEquals(StackTraceBean.NUM, elem.getLineNumber()); // and finally, even as part of real exception IOException ioe = mapper.readValue(aposToQuotes("{'stackTrace':[ 123, 456 ]}"), IOException.class); assertNotNull(ioe); StackTraceElement[] traces = ioe.getStackTrace(); assertNotNull(traces); assertEquals(2, traces.length); assertEquals(StackTraceBean.NUM, traces[0].getLineNumber()); assertEquals(StackTraceBean.NUM, traces[1].getLineNumber()); } public void testStringBuilder() throws Exception { StringBuilder sb = MAPPER.readValue(quote("abc"), StringBuilder.class); assertEquals("abc", sb.toString()); } public void testURI() throws Exception { final ObjectReader reader = MAPPER.readerFor(URI.class); final URI value = new URI("http://foo.com"); assertEquals(value, reader.readValue("\""+value.toString()+"\"")); // Also: empty String should be handled properly URI result = reader.readValue(quote("")); assertNotNull(result); assertEquals(URI.create(""), result); // and finally: broken URI should give proper failure try { result = reader.readValue(quote("a b")); fail("Should not accept malformed URI, instead got: "+result); } catch (InvalidFormatException e) { verifyException(e, "not a valid textual representation"); } } public void testURL() throws Exception { URL exp = new URL("http://foo.com"); assertEquals(exp, MAPPER.readValue("\""+exp.toString()+"\"", URL.class)); // trivial case; null to null, embedded URL to URL TokenBuffer buf = new TokenBuffer(null, false); buf.writeObject(null); assertNull(MAPPER.readValue(buf.asParser(), URL.class)); buf.close(); // then, URLitself come as is: buf = new TokenBuffer(null, false); buf.writeObject(exp); assertSame(exp, MAPPER.readValue(buf.asParser(), URL.class)); buf.close(); // and finally, invalid URL should be handled appropriately too try { URL result = MAPPER.readValue(quote("a b"), URL.class); fail("Should not accept malformed URI, instead got: "+result); } catch (InvalidFormatException e) { verifyException(e, "not a valid textual representation"); } } public void testUUID() throws Exception { final ObjectMapper mapper = objectMapper(); final String NULL_UUID = "00000000-0000-0000-0000-000000000000"; // first, couple of generated UUIDs: for (String value : new String[] { "76e6d183-5f68-4afa-b94a-922c1fdb83f8", "540a88d1-e2d8-4fb1-9396-9212280d0a7f", "2c9e441d-1cd0-472d-9bab-69838f877574", "591b2869-146e-41d7-8048-e8131f1fdec5", "82994ac2-7b23-49f2-8cc5-e24cf6ed77be", "00000007-0000-0000-0000-000000000000" }) { mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); UUID uuid = UUID.fromString(value); assertEquals(uuid, mapper.readValue(quote(value), UUID.class)); } // then use templating; note that these are not exactly valid UUIDs // wrt spec (type bits etc), but JDK UUID should deal ok final String TEMPL = NULL_UUID; final String chars = "123456789abcdefABCDEF"; for (int i = 0; i < chars.length(); ++i) { String value = TEMPL.replace('0', chars.charAt(i)); assertEquals(UUID.fromString(value).toString(), mapper.readValue(quote(value), UUID.class).toString()); } // also: see if base64 encoding works as expected String base64 = Base64Variants.getDefaultVariant().encode(new byte[16]); assertEquals(UUID.fromString(NULL_UUID), mapper.readValue(quote(base64), UUID.class)); } public void testUUIDInvalid() throws Exception { // and finally, exception handling too [databind#1000], for invalid cases try { MAPPER.readValue(quote("abcde"), UUID.class); fail("Should fail on invalid UUID string"); } catch (InvalidFormatException e) { verifyException(e, "UUID has to be represented by standard"); } try { MAPPER.readValue(quote("76e6d183-5f68-4afa-b94a-922c1fdb83fx"), UUID.class); fail("Should fail on invalid UUID string"); } catch (InvalidFormatException e) { verifyException(e, "non-hex character 'x'"); } // should also test from-bytes version, but that's trickier... leave for now. } public void testUUIDAux() throws Exception { // [JACKSON-393] fix: final UUID value = UUID.fromString("76e6d183-5f68-4afa-b94a-922c1fdb83f8"); // first, null should come as null TokenBuffer buf = new TokenBuffer(null, false); buf.writeObject(null); assertNull(MAPPER.readValue(buf.asParser(), UUID.class)); buf.close(); // then, UUID itself come as is: buf = new TokenBuffer(null, false); buf.writeObject(value); assertSame(value, MAPPER.readValue(buf.asParser(), UUID.class)); // and finally from byte[] // oh crap; JDK UUID just... sucks. Not even byte[] accessors or constructors? Huh? ByteArrayOutputStream bytes = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(bytes); out.writeLong(value.getMostSignificantBits()); out.writeLong(value.getLeastSignificantBits()); byte[] data = bytes.toByteArray(); assertEquals(16, data.length); buf.writeObject(data); UUID value2 = MAPPER.readValue(buf.asParser(), UUID.class); assertEquals(value, value2); buf.close(); } } MapDeserializationTest.java000066400000000000000000000435401325620701100376520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; @SuppressWarnings("serial") public class MapDeserializationTest extends BaseMapTest { static enum Key { KEY1, KEY2, WHATEVER; } static class BrokenMap extends HashMap { // No default ctor, nor @JsonCreators public BrokenMap(boolean dummy) { super(); } } @JsonDeserialize(using=CustomMapDeserializer.class) static class CustomMap extends LinkedHashMap { } static class CustomMapDeserializer extends StdDeserializer { public CustomMapDeserializer() { super(CustomMap.class); } @Override public CustomMap deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { CustomMap result = new CustomMap(); result.put("x", p.getText()); return result; } } static class KeyType { protected String value; private KeyType(String v, boolean bogus) { value = v; } @JsonCreator public static KeyType create(String v) { return new KeyType(v, true); } } public static class EnumMapContainer { @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") public EnumMap testTypes; } public static class ListContainer { public List testTypes; } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") public static interface ITestType { } public static enum KeyEnum { A, B } public static enum ConcreteType implements ITestType { ONE, TWO; } static class ClassStringMap extends HashMap,String> { } /* /********************************************************** /* Test methods, untyped (Object valued) maps /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testBigUntypedMap() throws Exception { Map map = new LinkedHashMap(); for (int i = 0; i < 1100; ++i) { if ((i & 1) == 0) { map.put(String.valueOf(i), Integer.valueOf(i)); } else { Map map2 = new LinkedHashMap(); map2.put("x", Integer.valueOf(i)); map.put(String.valueOf(i), map2); } } String json = MAPPER.writeValueAsString(map); Object bound = MAPPER.readValue(json, Object.class); assertEquals(map, bound); } /** * Let's also try another way to express "gimme a Map" deserialization; * this time by specifying a Map class, to reduce need to cast */ public void testUntypedMap2() throws Exception { // to get "untyped" default map-to-map, pass Object.class String JSON = "{ \"a\" : \"x\" }"; @SuppressWarnings("unchecked") HashMap result = /*(HashMap)*/ MAPPER.readValue(JSON, HashMap.class); assertNotNull(result); assertTrue(result instanceof Map); assertEquals(1, result.size()); assertEquals("x", result.get("a")); } /** * Unit test for [JACKSON-185] */ public void testUntypedMap3() throws Exception { String JSON = "{\"a\":[{\"a\":\"b\"},\"value\"]}"; Map result = MAPPER.readValue(JSON, Map.class); assertTrue(result instanceof Map); assertEquals(1, result.size()); Object ob = result.get("a"); assertNotNull(ob); Collection list = (Collection)ob; assertEquals(2, list.size()); JSON = "{ \"var1\":\"val1\", \"var2\":\"val2\", " +"\"subvars\": [" +" { \"subvar1\" : \"subvar2\", \"x\" : \"y\" }, " +" { \"a\":1 } ]" +" }" ; result = MAPPER.readValue(JSON, Map.class); assertTrue(result instanceof Map); assertEquals(3, result.size()); } private static final String UNTYPED_MAP_JSON = "{ \"double\":42.0, \"string\":\"string\"," +"\"boolean\":true, \"list\":[\"list0\"]," +"\"null\":null }"; static class ObjectWrapperMap extends HashMap { } public void testSpecialMap() throws IOException { final ObjectWrapperMap map = MAPPER.readValue(UNTYPED_MAP_JSON, ObjectWrapperMap.class); assertNotNull(map); _doTestUntyped(map); } public void testGenericMap() throws IOException { final Map map = MAPPER.readValue (UNTYPED_MAP_JSON, new TypeReference>() { }); _doTestUntyped(map); } private void _doTestUntyped(final Map map) { ObjectWrapper w = map.get("double"); assertNotNull(w); assertEquals(Double.valueOf(42), w.getObject()); assertEquals("string", map.get("string").getObject()); assertEquals(Boolean.TRUE, map.get("boolean").getObject()); assertEquals(Collections.singletonList("list0"), map.get("list").getObject()); assertTrue(map.containsKey("null")); assertNull(map.get("null")); assertEquals(5, map.size()); } // [JACKSON-620]: allow "" to mean 'null' for Maps public void testFromEmptyString() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); Map result = m.readValue(quote(""), Map.class); assertNull(result); } /* /********************************************************** /* Test methods, typed maps /********************************************************** */ public void testExactStringIntMap() throws Exception { // to get typing, must use type reference String JSON = "{ \"foo\" : 13, \"bar\" : -39, \n \"\" : 0 }"; Map result = MAPPER.readValue (JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(HashMap.class, result.getClass()); assertEquals(3, result.size()); assertEquals(Integer.valueOf(13), result.get("foo")); assertEquals(Integer.valueOf(-39), result.get("bar")); assertEquals(Integer.valueOf(0), result.get("")); assertNull(result.get("foobar")); assertNull(result.get(" ")); } /** * Let's also check that it is possible to do type conversions * to allow use of non-String Map keys. */ public void testIntBooleanMap() throws Exception { // to get typing, must use type reference String JSON = "{ \"1\" : true, \"-1\" : false }"; Map result = MAPPER.readValue (JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(HashMap.class, result.getClass()); assertEquals(2, result.size()); assertEquals(Boolean.TRUE, result.get(Integer.valueOf(1))); assertEquals(Boolean.FALSE, result.get(Integer.valueOf(-1))); assertNull(result.get("foobar")); assertNull(result.get(0)); } public void testExactStringStringMap() throws Exception { // to get typing, must use type reference String JSON = "{ \"a\" : \"b\" }"; Map result = MAPPER.readValue (JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(TreeMap.class, result.getClass()); assertEquals(1, result.size()); assertEquals("b", result.get("a")); assertNull(result.get("b")); } /** * Unit test that verifies that it's ok to have incomplete * information about Map class itself, as long as it's something * we good guess about: for example, Map.Class will * be replaced by something like HashMap.class, * if given. */ public void testGenericStringIntMap() throws Exception { // to get typing, must use type reference; but with abstract type String JSON = "{ \"a\" : 1, \"b\" : 2, \"c\" : -99 }"; Map result = MAPPER.readValue (JSON, new TypeReference>() { }); assertNotNull(result); assertTrue(result instanceof Map); assertEquals(3, result.size()); assertEquals(Integer.valueOf(-99), result.get("c")); assertEquals(Integer.valueOf(2), result.get("b")); assertEquals(Integer.valueOf(1), result.get("a")); assertNull(result.get("")); } /* /********************************************************** /* Test methods, maps with enums /********************************************************** */ public void testEnumMap() throws Exception { String JSON = "{ \"KEY1\" : \"\", \"WHATEVER\" : null }"; // to get typing, must use type reference EnumMap result = MAPPER.readValue (JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(EnumMap.class, result.getClass()); assertEquals(2, result.size()); assertEquals("", result.get(Key.KEY1)); // null should be ok too... assertTrue(result.containsKey(Key.WHATEVER)); assertNull(result.get(Key.WHATEVER)); // plus we have nothing for this key assertFalse(result.containsKey(Key.KEY2)); assertNull(result.get(Key.KEY2)); } public void testMapWithEnums() throws Exception { String JSON = "{ \"KEY2\" : \"WHATEVER\" }"; // to get typing, must use type reference Map,Enum> result = MAPPER.readValue (JSON, new TypeReference>() { }); assertNotNull(result); assertTrue(result instanceof Map); assertEquals(1, result.size()); assertEquals(Key.WHATEVER, result.get(Key.KEY2)); assertNull(result.get(Key.WHATEVER)); assertNull(result.get(Key.KEY1)); } public void testEnumPolymorphicSerializationTest() throws Exception { ObjectMapper mapper = new ObjectMapper(); List testTypesList = new ArrayList(); testTypesList.add(ConcreteType.ONE); testTypesList.add(ConcreteType.TWO); ListContainer listContainer = new ListContainer(); listContainer.testTypes = testTypesList; String json = mapper.writeValueAsString(listContainer); listContainer = mapper.readValue(json, ListContainer.class); EnumMapContainer enumMapContainer = new EnumMapContainer(); EnumMap testTypesMap = new EnumMap(KeyEnum.class); testTypesMap.put(KeyEnum.A, ConcreteType.ONE); testTypesMap.put(KeyEnum.B, ConcreteType.TWO); enumMapContainer.testTypes = testTypesMap; json = mapper.writeValueAsString(enumMapContainer); enumMapContainer = mapper.readValue(json, EnumMapContainer.class); } /* /********************************************************** /* Test methods, maps with Date /********************************************************** */ public void testDateMap() throws Exception { Date date1=new Date(123456000L); DateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); String JSON = "{ \""+ fmt.format(date1)+"\" : \"\", \""+new Date(0).getTime()+"\" : null }"; HashMap result= MAPPER.readValue (JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(HashMap.class, result.getClass()); assertEquals(2, result.size()); assertTrue(result.containsKey(date1)); assertEquals("", result.get(new Date(123456000L))); assertTrue(result.containsKey(new Date(0))); assertNull(result.get(new Date(0))); } /* /********************************************************** /* Test methods, maps with various alternative key types /********************************************************** */ public void testCalendarMap() throws Exception { // 18-Jun-2015, tatu: Should be safest to use default timezone that mapper would use TimeZone tz = MAPPER.getSerializationConfig().getTimeZone(); Calendar c = Calendar.getInstance(tz); c.setTimeInMillis(123456000L); DateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); String JSON = "{ \""+fmt.format(c.getTime())+"\" : \"\", \""+new Date(0).getTime()+"\" : null }"; HashMap result = MAPPER.readValue (JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(HashMap.class, result.getClass()); assertEquals(2, result.size()); assertTrue(result.containsKey(c)); assertEquals("", result.get(c)); c.setTimeInMillis(0); assertTrue(result.containsKey(c)); assertNull(result.get(c)); } public void testUUIDKeyMap() throws Exception { UUID key = UUID.nameUUIDFromBytes("foobar".getBytes("UTF-8")); String JSON = "{ \""+key+"\":4}"; Map result = MAPPER.readValue(JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(1, result.size()); Object ob = result.keySet().iterator().next(); assertNotNull(ob); assertEquals(UUID.class, ob.getClass()); assertEquals(key, ob); } public void testLocaleKeyMap() throws Exception { Locale key = Locale.CHINA; String JSON = "{ \"" + key + "\":4}"; Map result = MAPPER.readValue(JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(1, result.size()); Object ob = result.keySet().iterator().next(); assertNotNull(ob); assertEquals(Locale.class, ob.getClass()); assertEquals(key, ob); } public void testCurrencyKeyMap() throws Exception { Currency key = Currency.getInstance("USD"); String JSON = "{ \"" + key + "\":4}"; Map result = MAPPER.readValue(JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(1, result.size()); Object ob = result.keySet().iterator().next(); assertNotNull(ob); assertEquals(Currency.class, ob.getClass()); assertEquals(key, ob); } // Test confirming that @JsonCreator may be used with Map Key types public void testKeyWithCreator() throws Exception { // first, key should deserialize normally: KeyType key = MAPPER.readValue(quote("abc"), KeyType.class); assertEquals("abc", key.value); Map map = MAPPER.readValue("{\"foo\":3}", new TypeReference>() {} ); assertEquals(1, map.size()); key = map.keySet().iterator().next(); assertEquals("foo", key.value); } public void testClassKeyMap() throws Exception { ClassStringMap map = MAPPER.readValue(aposToQuotes("{'java.lang.String':'foo'}"), ClassStringMap.class); assertNotNull(map); assertEquals(1, map.size()); assertEquals("foo", map.get(String.class)); } public void testcharSequenceKeyMap() throws Exception { String JSON = aposToQuotes("{'a':'b'}"); Map result = MAPPER.readValue(JSON, new TypeReference>() { }); assertNotNull(result); assertEquals(1, result.size()); assertEquals("b", result.get("a")); } /* /********************************************************** /* Test methods, annotated Maps /********************************************************** */ /** * Simple test to ensure that @JsonDeserialize.using is * recognized */ public void testMapWithDeserializer() throws Exception { CustomMap result = MAPPER.readValue(quote("xyz"), CustomMap.class); assertEquals(1, result.size()); assertEquals("xyz", result.get("x")); } /* /********************************************************** /* Error tests /********************************************************** */ public void testMapError() throws Exception { try { Object result = MAPPER.readValue("[ 1, 2 ]", new TypeReference>() { }); fail("Expected an exception, but got result value: "+result); } catch (JsonMappingException jex) { verifyException(jex, "START_ARRAY"); } } public void testNoCtorMap() throws Exception { try { BrokenMap result = MAPPER.readValue("{ \"a\" : 3 }", BrokenMap.class); // should never get here; assert added to remove compiler warning assertNull(result); } catch (JsonMappingException e) { // instead, should get this exception: verifyException(e, "no default constructor found"); } } } MapDeserializerCachingTest.java000066400000000000000000000034571325620701100404260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.IOException; import java.util.Map; import java.util.TreeMap; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; // for [databind#1807] public class MapDeserializerCachingTest extends BaseMapTest { public static class NonAnnotatedMapHolderClass { public Map data = new TreeMap(); } public static class MapHolder { @JsonDeserialize(keyUsing = MyKeyDeserializer.class) public Map data = new TreeMap(); } public static class MyKeyDeserializer extends KeyDeserializer { @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { return key + " (CUSTOM)"; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testCachedSerialize() throws IOException { ObjectMapper mapper = new ObjectMapper(); String json = aposToQuotes("{'data':{'1st':'onedata','2nd':'twodata'}}"); // Do deserialization with non-annotated map property NonAnnotatedMapHolderClass ignored = mapper.readValue(json, NonAnnotatedMapHolderClass.class); assertTrue(ignored.data.containsKey("1st")); assertTrue(ignored.data.containsKey("2nd")); //mapper = new ObjectMapper(); MapHolder model2 = mapper.readValue(json, MapHolder.class); if (!model2.data.containsKey("1st (CUSTOM)") || !model2.data.containsKey("2nd (CUSTOM)")) { fail("Not using custom key deserializer for input: "+json+"; resulted in: "+model2.data); } } } MapKeyDeserializationTest.java000066400000000000000000000133261325620701100403220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.util.Map; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.core.Base64Variants; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import org.junit.Assert; public class MapKeyDeserializationTest extends BaseMapTest { static class FullName { private String _firstname, _lastname; private FullName(String firstname, String lastname) { _firstname = firstname; _lastname = lastname; } @JsonCreator public static FullName valueOf(String value) { String[] mySplit = value.split("\\."); return new FullName(mySplit[0], mySplit[1]); } public static FullName valueOf(String firstname, String lastname) { return new FullName(firstname, lastname); } @JsonValue @Override public String toString() { return _firstname + "." + _lastname; } } /* /********************************************************** /* Test methods, wrapper keys /********************************************************** */ final private ObjectMapper MAPPER = objectMapper(); public void testBooleanMapKeyDeserialization() throws Exception { TypeReference type = new TypeReference>() { }; MapWrapper result = MAPPER.readValue(aposToQuotes("{'map':{'true':'foobar'}}"), type); assertEquals(1, result.map.size()); Assert.assertEquals(Boolean.TRUE, result.map.entrySet().iterator().next().getKey()); result = MAPPER.readValue(aposToQuotes("{'map':{'false':'foobar'}}"), type); assertEquals(1, result.map.size()); Assert.assertEquals(Boolean.FALSE, result.map.entrySet().iterator().next().getKey()); } public void testByteMapKeyDeserialization() throws Exception { TypeReference type = new TypeReference>() { }; MapWrapper result = MAPPER.readValue(aposToQuotes("{'map':{'13':'foobar'}}"), type); assertEquals(1, result.map.size()); Assert.assertEquals(Byte.valueOf((byte) 13), result.map.entrySet().iterator().next().getKey()); } public void testShortMapKeyDeserialization() throws Exception { TypeReference type = new TypeReference>() { }; MapWrapper result = MAPPER.readValue(aposToQuotes("{'map':{'13':'foobar'}}"), type); assertEquals(1, result.map.size()); Assert.assertEquals(Short.valueOf((short) 13), result.map.entrySet().iterator().next().getKey()); } public void testIntegerMapKeyDeserialization() throws Exception { TypeReference type = new TypeReference>() { }; MapWrapper result = MAPPER.readValue(aposToQuotes("{'map':{'-3':'foobar'}}"), type); assertEquals(1, result.map.size()); Assert.assertEquals(Integer.valueOf(-3), result.map.entrySet().iterator().next().getKey()); } public void testLongMapKeyDeserialization() throws Exception { TypeReference type = new TypeReference>() { }; MapWrapper result = MAPPER.readValue(aposToQuotes("{'map':{'42':'foobar'}}"), type); assertEquals(1, result.map.size()); Assert.assertEquals(Long.valueOf(42), result.map.entrySet().iterator().next().getKey()); } public void testFloatMapKeyDeserialization() throws Exception { TypeReference type = new TypeReference>() { }; MapWrapper result = MAPPER.readValue(aposToQuotes("{'map':{'3.5':'foobar'}}"), type); assertEquals(1, result.map.size()); Assert.assertEquals(Float.valueOf(3.5f), result.map.entrySet().iterator().next().getKey()); } public void testDoubleMapKeyDeserialization() throws Exception { TypeReference type = new TypeReference>() { }; MapWrapper result = MAPPER.readValue(aposToQuotes("{'map':{'0.25':'foobar'}}"), type); assertEquals(1, result.map.size()); Assert.assertEquals(Double.valueOf(0.25), result.map.entrySet().iterator().next().getKey()); } /* /********************************************************** /* Test methods, other /********************************************************** */ public void testDeserializeKeyViaFactory() throws Exception { Map map = MAPPER.readValue("{\"first.last\": 42}", new TypeReference>() { }); Map.Entry entry = map.entrySet().iterator().next(); FullName key = entry.getKey(); assertEquals(key._firstname, "first"); assertEquals(key._lastname, "last"); assertEquals(entry.getValue().doubleValue(), 42, 0); } public void testByteArrayMapKeyDeserialization() throws Exception { byte[] binary = new byte[] { 1, 2, 4, 8, 16, 33, 79 }; String encoded = Base64Variants.MIME.encode(binary); MapWrapper result = MAPPER.readValue( aposToQuotes("{'map':{'"+encoded+"':'foobar'}}"), new TypeReference>() { }); assertEquals(1, result.map.size()); Map.Entry entry = result.map.entrySet().iterator().next(); assertEquals("foobar", entry.getValue()); byte[] key = entry.getKey(); Assert.assertArrayEquals(binary, key); } } MapRelatedTypesDeserTest.java000066400000000000000000000057531325620701100401200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.util.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class MapRelatedTypesDeserTest extends BaseMapTest { private final ObjectMapper MAPPER = new ObjectMapper(); /* /********************************************************** /* Test methods, Map.Entry /********************************************************** */ public void testMapEntrySimpleTypes() throws Exception { List> stuff = MAPPER.readValue(aposToQuotes("[{'a':15},{'b':42}]"), new TypeReference>>() { }); assertNotNull(stuff); assertEquals(2, stuff.size()); assertNotNull(stuff.get(1)); assertEquals("b", stuff.get(1).getKey()); assertEquals(Long.valueOf(42), stuff.get(1).getValue()); } public void testMapEntryWithStringBean() throws Exception { List> stuff = MAPPER.readValue(aposToQuotes("[{'28':'Foo'},{'13':'Bar'}]"), new TypeReference>>() { }); assertNotNull(stuff); assertEquals(2, stuff.size()); assertNotNull(stuff.get(1)); assertEquals(Integer.valueOf(13), stuff.get(1).getKey()); StringWrapper sw = stuff.get(1).getValue(); assertEquals("Bar", sw.str); } public void testMapEntryFail() throws Exception { try { /*List> stuff =*/ MAPPER.readValue(aposToQuotes("[{'28':'Foo','13':'Bar'}]"), new TypeReference>>() { }); fail("Should not have passed"); } catch (Exception e) { verifyException(e, "more than one entry in JSON"); } } /* /********************************************************** /* Test methods, other exotic Map types /********************************************************** */ // [databind#810] public void testReadProperties() throws Exception { Properties props = MAPPER.readValue(aposToQuotes("{'a':'foo', 'b':123, 'c':true}"), Properties.class); assertEquals(3, props.size()); assertEquals("foo", props.getProperty("a")); assertEquals("123", props.getProperty("b")); assertEquals("true", props.getProperty("c")); } // JDK singletonMap public void testSingletonMapRoundtrip() throws Exception { final TypeReference type = new TypeReference>() { }; String json = MAPPER.writeValueAsString(Collections.singletonMap("value", new IntWrapper(5))); Map result = MAPPER.readValue(json, type); assertNotNull(result); assertEquals(1, result.size()); IntWrapper w = result.get("value"); assertNotNull(w); assertEquals(5, w.i); } } TestDefaultForUtilCollections1868.java000066400000000000000000000071221325620701100415010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.util.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; // Unit tests for [databind#1868], related public class TestDefaultForUtilCollections1868 extends BaseMapTest { private final ObjectMapper DEFAULT_MAPPER = new ObjectMapper(); { DEFAULT_MAPPER.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); } /* /********************************************************** /* Unit tests, "empty" types /********************************************************** */ public void testEmptyList() throws Exception { _verifyCollection(Collections.emptyList()); } public void testEmptySet() throws Exception { _verifyCollection(Collections.emptySet()); } public void testEmptyMap() throws Exception { _verifyMap(Collections.emptyMap()); } /* /********************************************************** /* Unit tests, "singleton" types /********************************************************** */ public void testSingletonList() throws Exception { _verifyCollection(Collections.singletonList(Arrays.asList("TheOne"))); } public void testSingletonSet() throws Exception { _verifyCollection(Collections.singleton(Arrays.asList("TheOne"))); } public void testSingletonMap() throws Exception { _verifyMap(Collections.singletonMap("foo", "bar")); } /* /********************************************************** /* Unit tests, "unmodifiable" types /********************************************************** */ public void testUnmodifiableList() throws Exception { _verifyCollection(Collections.unmodifiableList(Arrays.asList("first", "second"))); } public void testUnmodifiableSet() throws Exception { Set input = new LinkedHashSet<>(Arrays.asList("first", "second")); _verifyCollection(Collections.unmodifiableSet(input)); } public void testUnmodifiableMap() throws Exception { Map input = new LinkedHashMap<>(); input.put("a", "b"); input.put("c", "d"); _verifyMap(Collections.unmodifiableMap(input)); } /* /********************************************************** /* Unit tests, other /********************************************************** */ public void testArraysAsList() throws Exception { // Here there are no semantics to preserve, so simply check that // contents remain the same List input = Arrays.asList("a", "bc", "def"); String json = DEFAULT_MAPPER.writeValueAsString(input); List result = DEFAULT_MAPPER.readValue(json, List.class); assertEquals(input, result); } /* /********************************************************** /* Helper methods /********************************************************** */ protected void _verifyCollection(Collection exp) throws Exception { String json = DEFAULT_MAPPER.writeValueAsString(exp); Collection act = DEFAULT_MAPPER.readValue(json, Collection.class); assertEquals(exp, act); assertEquals(exp.getClass(), act.getClass()); } protected void _verifyMap(Map exp) throws Exception { String json = DEFAULT_MAPPER.writeValueAsString(exp); Map act = DEFAULT_MAPPER.readValue(json, Map.class); assertEquals(exp, act); assertEquals(exp.getClass(), act.getClass()); } } UntypedDeserializationTest.java000066400000000000000000000337101325620701100405630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/jdkpackage com.fasterxml.jackson.databind.deser.jdk; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; /** * Unit tests for verifying "raw" (or "untyped") data binding from JSON to JDK objects; * one that only uses core JDK types; wrappers, Maps and Lists. */ @SuppressWarnings("serial") public class UntypedDeserializationTest extends BaseMapTest { static class UCStringDeserializer extends StdScalarDeserializer { public UCStringDeserializer() { super(String.class); } @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return p.getText().toUpperCase(); } } static class CustomNumberDeserializer extends StdScalarDeserializer { protected final Integer value; public CustomNumberDeserializer(int nr) { super(Number.class); value = nr; } @Override public Number deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return value; } } // Let's make this Contextual, to tease out cyclic resolution issues, if any static class ListDeserializer extends StdDeserializer> implements ContextualDeserializer { public ListDeserializer() { super(List.class); } @Override public List deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { ArrayList list = new ArrayList(); while (p.nextValue() != JsonToken.END_ARRAY) { list.add("X"+p.getText()); } return list; } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { // For now, we just need to access "untyped" deserializer; not use it. /*JsonDeserializer ob = */ ctxt.findContextualValueDeserializer(ctxt.constructType(Object.class), property); return this; } } static class YMapDeserializer extends StdDeserializer> { public YMapDeserializer() { super(Map.class); } @Override public Map deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Map map = new LinkedHashMap(); while (p.nextValue() != JsonToken.END_OBJECT) { map.put(p.getCurrentName(), "Y"+p.getText()); } return map; } } static class DelegatingUntyped { protected Object value; @JsonCreator // delegating public DelegatingUntyped(Object v) { value = v; } } static class WrappedPolymorphicUntyped { @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS) public Object value; } static class WrappedUntyped1460 { public Object value; } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); @SuppressWarnings("unchecked") public void testSampleDoc() throws Exception { final String JSON = SAMPLE_DOC_JSON_SPEC; /* To get "untyped" Mapping (to Maps, Lists, instead of beans etc), * we'll specify plain old Object.class as the target. */ Object root = MAPPER.readValue(JSON, Object.class); assertType(root, Map.class); Map rootMap = (Map) root; assertEquals(1, rootMap.size()); Map.Entry rootEntry = rootMap.entrySet().iterator().next(); assertEquals("Image", rootEntry.getKey()); Object image = rootEntry.getValue(); assertType(image, Map.class); Map imageMap = (Map) image; assertEquals(5, imageMap.size()); Object value = imageMap.get("Width"); assertType(value, Integer.class); assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_WIDTH), value); value = imageMap.get("Height"); assertType(value, Integer.class); assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_HEIGHT), value); assertEquals(SAMPLE_SPEC_VALUE_TITLE, imageMap.get("Title")); // Another Object, "thumbnail" value = imageMap.get("Thumbnail"); assertType(value, Map.class); Map tnMap = (Map) value; assertEquals(3, tnMap.size()); assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_TN_HEIGHT), tnMap.get("Height")); // for some reason, width is textual, not numeric... assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, tnMap.get("Width")); assertEquals(SAMPLE_SPEC_VALUE_TN_URL, tnMap.get("Url")); // And then number list, "IDs" value = imageMap.get("IDs"); assertType(value, List.class); List ids = (List) value; assertEquals(4, ids.size()); assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_TN_ID1), ids.get(0)); assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_TN_ID2), ids.get(1)); assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_TN_ID3), ids.get(2)); assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_TN_ID4), ids.get(3)); // and that's all folks! } @SuppressWarnings("unlikely-arg-type") public void testUntypedMap() throws Exception { // to get "untyped" default map-to-map, pass Object.class String JSON = "{ \"foo\" : \"bar\", \"crazy\" : true, \"null\" : null }"; // Not a guaranteed cast theoretically, but will work: @SuppressWarnings("unchecked") Map result = (Map)MAPPER.readValue(JSON, Object.class); assertNotNull(result); assertTrue(result instanceof Map); assertEquals(3, result.size()); assertEquals("bar", result.get("foo")); assertEquals(Boolean.TRUE, result.get("crazy")); assertNull(result.get("null")); // Plus, non existing: assertNull(result.get("bar")); assertNull(result.get(3)); } public void testNestedUntypes() throws IOException { // 05-Apr-2014, tatu: Odd failures if using shared mapper; so work around: Object root = MAPPER.readValue(aposToQuotes("{'a':3,'b':[1,2]}"), Object.class); assertTrue(root instanceof Map); Map map = (Map) root; assertEquals(2, map.size()); assertEquals(Integer.valueOf(3), map.get("a")); Object ob = map.get("b"); assertTrue(ob instanceof List); List l = (List) ob; assertEquals(2, l.size()); assertEquals(Integer.valueOf(2), l.get(1)); } // Allow 'upgrade' of big integers into Long, BigInteger public void testObjectSerializeWithLong() throws IOException { final ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(DefaultTyping.JAVA_LANG_OBJECT, As.PROPERTY); final long VALUE = 1337800584532L; String serialized = "{\"timestamp\":"+VALUE+"}"; // works fine as node JsonNode deserialized = mapper.readTree(serialized); assertEquals(VALUE, deserialized.get("timestamp").asLong()); // and actually should work in Maps too Map deserMap = mapper.readValue(serialized, Map.class); Number n = (Number) deserMap.get("timestamp"); assertNotNull(n); assertSame(Long.class, n.getClass()); assertEquals(Long.valueOf(VALUE), n); } public void testUntypedWithCustomScalarDesers() throws IOException { SimpleModule m = new SimpleModule("test-module"); m.addDeserializer(String.class, new UCStringDeserializer()); m.addDeserializer(Number.class, new CustomNumberDeserializer(13)); final ObjectMapper mapper = new ObjectMapper() .registerModule(m); Object ob = mapper.readValue("{\"a\":\"b\", \"nr\":1 }", Object.class); assertTrue(ob instanceof Map); Object value = ((Map) ob).get("a"); assertNotNull(value); assertTrue(value instanceof String); assertEquals("B", value); value = ((Map) ob).get("nr"); assertNotNull(value); assertTrue(value instanceof Number); assertEquals(Integer.valueOf(13), value); } // Test that exercises non-vanilla variant, with just one simple custom deserializer public void testNonVanilla() throws IOException { SimpleModule m = new SimpleModule("test-module"); m.addDeserializer(String.class, new UCStringDeserializer()); final ObjectMapper mapper = new ObjectMapper() .registerModule(m); // Also: since this is now non-vanilla variant, try more alternatives List l = (List) mapper.readValue("[ true, false, 7, 0.5, \"foo\"]", Object.class); assertEquals(5, l.size()); assertEquals(Boolean.TRUE, l.get(0)); assertEquals(Boolean.FALSE, l.get(1)); assertEquals(Integer.valueOf(7), l.get(2)); assertEquals(Double.valueOf(0.5), l.get(3)); assertEquals("FOO", l.get(4)); l = (List) mapper.readValue("[ {}, [] ]", Object.class); assertEquals(2, l.size()); assertTrue(l.get(0) instanceof Map); assertTrue(l.get(1) instanceof List); ObjectReader rDefault = mapper.readerFor(WrappedPolymorphicUntyped.class); ObjectReader rAlt = rDefault .with(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, DeserializationFeature.USE_BIG_INTEGER_FOR_INTS); WrappedPolymorphicUntyped w; w = rDefault.readValue(aposToQuotes("{'value':10}")); assertEquals(Integer.valueOf(10), w.value); w = rAlt.readValue(aposToQuotes("{'value':10}")); assertEquals(BigInteger.TEN, w.value); w = rDefault.readValue(aposToQuotes("{'value':5.0}")); assertEquals(Double.valueOf(5.0), w.value); w = rAlt.readValue(aposToQuotes("{'value':5.0}")); assertEquals(new BigDecimal("5.0"), w.value); StringBuilder sb = new StringBuilder(100).append("[0"); for (int i = 1; i < 100; ++i) { sb.append(", ").append(i); } sb.append("]"); final String INT_ARRAY_JSON = sb.toString(); // First read as-is, no type wrapping Object ob = mapper.readerFor(Object.class) .with(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY) .readValue(INT_ARRAY_JSON); assertTrue(ob instanceof Object[]); Object[] obs = (Object[]) ob; for (int i = 0; i < 100; ++i) { assertEquals(Integer.valueOf(i), obs[i]); } } public void testUntypedWithListDeser() throws IOException { SimpleModule m = new SimpleModule("test-module"); m.addDeserializer(List.class, new ListDeserializer()); final ObjectMapper mapper = new ObjectMapper() .registerModule(m); // And then list... Object ob = mapper.readValue("[1, 2, true]", Object.class); assertTrue(ob instanceof List); List l = (List) ob; assertEquals(3, l.size()); assertEquals("X1", l.get(0)); assertEquals("X2", l.get(1)); assertEquals("Xtrue", l.get(2)); } public void testUntypedWithMapDeser() throws IOException { SimpleModule m = new SimpleModule("test-module"); m.addDeserializer(Map.class, new YMapDeserializer()); final ObjectMapper mapper = new ObjectMapper() .registerModule(m); // And then list... Object ob = mapper.readValue("{\"a\":true}", Object.class); assertTrue(ob instanceof Map); Map map = (Map) ob; assertEquals(1, map.size()); assertEquals("Ytrue", map.get("a")); } public void testNestedUntyped989() throws IOException { DelegatingUntyped pojo; ObjectReader r = MAPPER.readerFor(DelegatingUntyped.class); pojo = r.readValue("[]"); assertTrue(pojo.value instanceof List); pojo = r.readValue("[{}]"); assertTrue(pojo.value instanceof List); pojo = r.readValue("{}"); assertTrue(pojo.value instanceof Map); pojo = r.readValue("{\"a\":[]}"); assertTrue(pojo.value instanceof Map); } public void testUntypedWithJsonArrays() throws Exception { // by default we get: Object ob = MAPPER.readValue("[1]", Object.class); assertTrue(ob instanceof List); // but can change to produce Object[]: MAPPER.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); ob = MAPPER.readValue("[1]", Object.class); assertEquals(Object[].class, ob.getClass()); } public void testUntypedIntAsLong() throws Exception { final String JSON = aposToQuotes("{'value':3}"); WrappedUntyped1460 w = MAPPER.readerFor(WrappedUntyped1460.class) .readValue(JSON); assertEquals(Integer.valueOf(3), w.value); w = MAPPER.readerFor(WrappedUntyped1460.class) .with(DeserializationFeature.USE_LONG_FOR_INTS) .readValue(JSON); assertEquals(Long.valueOf(3), w.value); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/merge/000077500000000000000000000000001325620701100327635ustar00rootroot00000000000000ArrayMergeTest.java000066400000000000000000000143371325620701100364550ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/mergepackage com.fasterxml.jackson.databind.deser.merge; import org.junit.Assert; import com.fasterxml.jackson.annotation.JsonMerge; import com.fasterxml.jackson.annotation.OptBoolean; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class ArrayMergeTest extends BaseMapTest { static class MergedX { @JsonMerge(OptBoolean.TRUE) public T value; public MergedX(T v) { value = v; } protected MergedX() { } } /* /******************************************************** /* Test methods /******************************************************** */ private final ObjectMapper MAPPER = newObjectMapper() // 26-Oct-2016, tatu: Make sure we'll report merge problems by default .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE) ; public void testObjectArrayMerging() throws Exception { MergedX input = new MergedX(new Object[] { "foo" }); final JavaType type = MAPPER.getTypeFactory().constructType(new TypeReference>() {}); MergedX result = MAPPER.readerFor(type) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':['bar']}")); assertSame(input, result); assertEquals(2, result.value.length); assertEquals("foo", result.value[0]); assertEquals("bar", result.value[1]); // and with one trick result = MAPPER.readerFor(type) .with(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':'zap'}")); assertSame(input, result); assertEquals(3, result.value.length); assertEquals("foo", result.value[0]); assertEquals("bar", result.value[1]); assertEquals("zap", result.value[2]); } public void testStringArrayMerging() throws Exception { MergedX input = new MergedX(new String[] { "foo" }); MergedX result = MAPPER .readerFor(new TypeReference>() {}) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':['bar']}")); assertSame(input, result); assertEquals(2, result.value.length); assertEquals("foo", result.value[0]); assertEquals("bar", result.value[1]); } public void testBooleanArrayMerging() throws Exception { MergedX input = new MergedX(new boolean[] { true, false }); MergedX result = MAPPER .readerFor(new TypeReference>() {}) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':[true]}")); assertSame(input, result); assertEquals(3, result.value.length); Assert.assertArrayEquals(new boolean[] { true, false, true }, result.value); } public void testByteArrayMerging() throws Exception { MergedX input = new MergedX(new byte[] { 1, 2 }); MergedX result = MAPPER .readerFor(new TypeReference>() {}) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':[4, 6.0, null]}")); assertSame(input, result); assertEquals(5, result.value.length); Assert.assertArrayEquals(new byte[] { 1, 2, 4, 6, 0 }, result.value); } public void testShortArrayMerging() throws Exception { MergedX input = new MergedX(new short[] { 1, 2 }); MergedX result = MAPPER .readerFor(new TypeReference>() {}) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':[4, 6]}")); assertSame(input, result); assertEquals(4, result.value.length); Assert.assertArrayEquals(new short[] { 1, 2, 4, 6 }, result.value); } public void testCharArrayMerging() throws Exception { MergedX input = new MergedX(new char[] { 'a', 'b' }); MergedX result = MAPPER .readerFor(new TypeReference>() {}) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':['c']}")); assertSame(input, result); Assert.assertArrayEquals(new char[] { 'a', 'b', 'c' }, result.value); // also some variation input = new MergedX(new char[] { }); result = MAPPER .readerFor(new TypeReference>() {}) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':['c']}")); assertSame(input, result); Assert.assertArrayEquals(new char[] { 'c' }, result.value); } public void testIntArrayMerging() throws Exception { MergedX input = new MergedX(new int[] { 1, 2 }); MergedX result = MAPPER .readerFor(new TypeReference>() {}) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':[4, 6]}")); assertSame(input, result); assertEquals(4, result.value.length); Assert.assertArrayEquals(new int[] { 1, 2, 4, 6 }, result.value); // also some variation input = new MergedX(new int[] { 3, 4, 6 }); result = MAPPER .readerFor(new TypeReference>() {}) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':[ ]}")); assertSame(input, result); Assert.assertArrayEquals(new int[] { 3, 4, 6 }, result.value); } public void testLongArrayMerging() throws Exception { MergedX input = new MergedX(new long[] { 1, 2 }); MergedX result = MAPPER .readerFor(new TypeReference>() {}) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':[4, 6]}")); assertSame(input, result); assertEquals(4, result.value.length); Assert.assertArrayEquals(new long[] { 1, 2, 4, 6 }, result.value); } } CollectionMergeTest.java000066400000000000000000000057471325620701100374770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/mergepackage com.fasterxml.jackson.databind.deser.merge; import java.util.*; import com.fasterxml.jackson.annotation.JsonMerge; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; public class CollectionMergeTest extends BaseMapTest { static class CollectionWrapper { @JsonMerge public Collection bag = new TreeSet(); { bag.add("a"); } } static class MergedList { @JsonMerge public List values = new ArrayList<>(); { values.add("a"); } } static class MergedEnumSet { @JsonMerge public EnumSet abc = EnumSet.of(ABC.B); } static class MergedX { @JsonMerge T value; public MergedX(T v) { value = v; } protected MergedX() { } public void setValue(T v) { value = v; } } /* /******************************************************** /* Test methods /******************************************************** */ private final ObjectMapper MAPPER = newObjectMapper() // 26-Oct-2016, tatu: Make sure we'll report merge problems by default .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE) ; public void testCollectionMerging() throws Exception { CollectionWrapper w = MAPPER.readValue(aposToQuotes("{'bag':['b']}"), CollectionWrapper.class); assertEquals(2, w.bag.size()); assertTrue(w.bag.contains("a")); assertTrue(w.bag.contains("b")); } public void testListMerging() throws Exception { MergedList w = MAPPER.readValue(aposToQuotes("{'values':['x']}"), MergedList.class); assertEquals(2, w.values.size()); assertTrue(w.values.contains("a")); assertTrue(w.values.contains("x")); } // Test that uses generic type public void testGenericListMerging() throws Exception { Collection l = new ArrayList<>(); l.add("foo"); MergedX> input = new MergedX>(l); MergedX> result = MAPPER .readerFor(new TypeReference>>() {}) .withValueToUpdate(input) .readValue(aposToQuotes("{'value':['bar']}")); assertSame(input, result); assertEquals(2, result.value.size()); Iterator it = result.value.iterator(); assertEquals("foo", it.next()); assertEquals("bar", it.next()); } public void testEnumSetMerging() throws Exception { MergedEnumSet result = MAPPER.readValue(aposToQuotes("{'abc':['A']}"), MergedEnumSet.class); assertEquals(2, result.abc.size()); assertTrue(result.abc.contains(ABC.B)); // original assertTrue(result.abc.contains(ABC.A)); // added } } MapMerge1844Test.java000066400000000000000000000044671325620701100364400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/mergepackage com.fasterxml.jackson.databind.deser.merge; import java.util.*; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; // for [databind#1844] public class MapMerge1844Test extends BaseMapTest { static class TestMap1844 { public Map getMapStringInteger() { return mapStringInteger; } @JsonProperty("key1") public void setMapStringInteger(Map mapStringInteger) { this.mapStringInteger = mapStringInteger; } public Map getMapIntegerInteger() { return mapIntegerInteger; } @JsonProperty("key2") public void setMapIntegerInteger(Map mapIntegerInteger) { this.mapIntegerInteger = mapIntegerInteger; } private Map mapStringInteger = new LinkedHashMap<>(); private Map mapIntegerInteger = new LinkedHashMap<>(); } // for [databind#1844] public void testMap1844() throws Exception { final ObjectMapper mapper = newObjectMapper(); mapper.setDefaultMergeable(true); final String f1 = aposToQuotes( "{ 'key1' : {\n" +" '1': 1, '2': 2, '3': 3\n" +"}, 'key2': {\n" +" '1': 1, '2': 2, '3': 3\n" +"} }" ); final String f2 = aposToQuotes( "{ 'key1' : {\n" +" '1': 2, '2': 3, '4': 5\n" +"}, 'key2': {\n" +" '1': 2, '2': 3, '4': 5\n" +"} }" ); TestMap1844 testMap = mapper.readerFor(TestMap1844.class).readValue(f1); testMap = mapper.readerForUpdating(testMap).readValue(f2); assertEquals(Integer.valueOf(2), testMap.getMapStringInteger().get("1")); assertEquals(Integer.valueOf(3), testMap.getMapStringInteger().get("2")); assertEquals(Integer.valueOf(3), testMap.getMapStringInteger().get("3")); assertEquals(Integer.valueOf(5), testMap.getMapStringInteger().get("4")); assertEquals(Integer.valueOf(2), testMap.getMapIntegerInteger().get(1)); assertEquals(Integer.valueOf(3), testMap.getMapIntegerInteger().get(2)); assertEquals(Integer.valueOf(3), testMap.getMapIntegerInteger().get(3)); assertEquals(Integer.valueOf(5), testMap.getMapIntegerInteger().get(4)); } }MapMergeTest.java000066400000000000000000000172231325620701100361110ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/mergepackage com.fasterxml.jackson.databind.deser.merge; import java.util.*; import com.fasterxml.jackson.annotation.JsonMerge; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.*; public class MapMergeTest extends BaseMapTest { static class MergedMap { @JsonMerge public Map values; protected MergedMap() { values = new LinkedHashMap<>(); values.put("a", "x"); } public MergedMap(String a, String b) { values = new LinkedHashMap<>(); values.put(a, b); } public MergedMap(Map src) { values = src; } } static class MergedIntMap { @JsonMerge public Map values; protected MergedIntMap() { values = new LinkedHashMap<>(); values.put(Integer.valueOf(13), "a"); } } /* /******************************************************** /* Test methods, Map merging /******************************************************** */ private final ObjectMapper MAPPER = newObjectMapper() // 26-Oct-2016, tatu: Make sure we'll report merge problems by default .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE) ; private final ObjectMapper MAPPER_SKIP_NULLS = newObjectMapper() .setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)); ; public void testShallowMapMerging() throws Exception { final String JSON = aposToQuotes("{'values':{'c':'y','d':null}}"); MergedMap v = MAPPER.readValue(JSON, MergedMap.class); assertEquals(3, v.values.size()); assertEquals("y", v.values.get("c")); assertEquals("x", v.values.get("a")); assertNull(v.values.get("d")); // but also, skip nulls v = MAPPER_SKIP_NULLS.readValue(JSON, MergedMap.class); assertEquals(2, v.values.size()); assertEquals("y", v.values.get("c")); assertEquals("x", v.values.get("a")); } public void testShallowNonStringMerging() throws Exception { final String JSON = aposToQuotes("{'values':{'72':'b','666':null}}"); MergedIntMap v = MAPPER.readValue(JSON , MergedIntMap.class); assertEquals(3, v.values.size()); assertEquals("a", v.values.get(Integer.valueOf(13))); assertEquals("b", v.values.get(Integer.valueOf(72))); assertNull(v.values.get(Integer.valueOf(666))); v = MAPPER_SKIP_NULLS.readValue(JSON , MergedIntMap.class); assertEquals(2, v.values.size()); assertEquals("a", v.values.get(Integer.valueOf(13))); assertEquals("b", v.values.get(Integer.valueOf(72))); } @SuppressWarnings("unchecked") public void testDeeperMapMerging() throws Exception { // first, create base Map MergedMap base = new MergedMap("name", "foobar"); Map props = new LinkedHashMap<>(); props.put("default", "yes"); props.put("x", "abc"); Map innerProps = new LinkedHashMap<>(); innerProps.put("z", Integer.valueOf(13)); props.put("extra", innerProps); base.values.put("props", props); // to be update MergedMap v = MAPPER.readerForUpdating(base) .readValue(aposToQuotes("{'values':{'props':{'x':'xyz','y' : '...','extra':{ 'ab' : true}}}}")); assertEquals(2, v.values.size()); assertEquals("foobar", v.values.get("name")); assertNotNull(v.values.get("props")); props = (Map) v.values.get("props"); assertEquals(4, props.size()); assertEquals("yes", props.get("default")); assertEquals("xyz", props.get("x")); assertEquals("...", props.get("y")); assertNotNull(props.get("extra")); innerProps = (Map) props.get("extra"); assertEquals(2, innerProps.size()); assertEquals(Integer.valueOf(13), innerProps.get("z")); assertEquals(Boolean.TRUE, innerProps.get("ab")); } @SuppressWarnings("unchecked") public void testMapMergingWithArray() throws Exception { // first, create base Map MergedMap base = new MergedMap("name", "foobar"); Map props = new LinkedHashMap<>(); List names = new ArrayList<>(); names.add("foo"); props.put("names", names); base.values.put("props", props); props.put("extra", "misc"); // to be update MergedMap v = MAPPER.readerForUpdating(base) .readValue(aposToQuotes("{'values':{'props':{'names': [ 'bar' ] }}}")); assertEquals(2, v.values.size()); assertEquals("foobar", v.values.get("name")); assertNotNull(v.values.get("props")); props = (Map) v.values.get("props"); assertEquals(2, props.size()); assertEquals("misc", props.get("extra")); assertNotNull(props.get("names")); names = (List) props.get("names"); assertEquals(2, names.size()); assertEquals("foo", names.get(0)); assertEquals("bar", names.get(1)); } /* /******************************************************** /* Forcing shallow merge of root Maps: /******************************************************** */ public void testDefaultDeepMapMerge() throws Exception { // First: deep merge should be enabled by default HashMap input = new HashMap<>(); input.put("list", new ArrayList<>(Arrays.asList("a"))); Map resultMap = MAPPER.readerForUpdating(input) .readValue(aposToQuotes("{'list':['b']}")); List resultList = (List) resultMap.get("list"); assertEquals(Arrays.asList("a", "b"), resultList); } public void testDisabledMergeViaGlobal() throws Exception { ObjectMapper mapper = newObjectMapper(); // disable merging, globally; does not affect main level mapper.setDefaultMergeable(false); HashMap input = new HashMap<>(); input.put("list", new ArrayList<>(Arrays.asList("a"))); Map resultMap = mapper.readerForUpdating(input) .readValue(aposToQuotes("{'list':['b']}")); List resultList = (List) resultMap.get("list"); assertEquals(Arrays.asList("b"), resultList); } public void testDisabledMergeByType() throws Exception { ObjectMapper mapper = newObjectMapper(); // disable merging for "untyped", that is, `Object.class` mapper.configOverride(Object.class) .setMergeable(false); HashMap input = new HashMap<>(); input.put("list", new ArrayList<>(Arrays.asList("a"))); Map resultMap = mapper.readerForUpdating(input) .readValue(aposToQuotes("{'list':['b']}")); List resultList = (List) resultMap.get("list"); assertEquals(Arrays.asList("b"), resultList); // and for extra points, disable by default but ENABLE for type, // which should once again allow merging mapper = newObjectMapper(); mapper.setDefaultMergeable(false); mapper.configOverride(Object.class) .setMergeable(true); input = new HashMap<>(); input.put("list", new ArrayList<>(Arrays.asList("x"))); resultMap = mapper.readerForUpdating(input) .readValue(aposToQuotes("{'list':['y']}")); resultList = (List) resultMap.get("list"); assertEquals(Arrays.asList("x", "y"), resultList); } } MergeWithNullTest.java000066400000000000000000000104221325620701100371340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/mergepackage com.fasterxml.jackson.databind.deser.merge; import com.fasterxml.jackson.annotation.JsonMerge; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; public class MergeWithNullTest extends BaseMapTest { static class ConfigDefault { @JsonMerge public AB loc = new AB(1, 2); protected ConfigDefault() { } public ConfigDefault(int a, int b) { loc = new AB(a, b); } } static class ConfigSkipNull { @JsonMerge @JsonSetter(nulls=Nulls.SKIP) public AB loc = new AB(1, 2); protected ConfigSkipNull() { } public ConfigSkipNull(int a, int b) { loc = new AB(a, b); } } static class ConfigAllowNullOverwrite { @JsonMerge @JsonSetter(nulls=Nulls.SET) public AB loc = new AB(1, 2); protected ConfigAllowNullOverwrite() { } public ConfigAllowNullOverwrite(int a, int b) { loc = new AB(a, b); } } // another variant where all we got is a getter static class NoSetterConfig { AB _value = new AB(2, 3); @JsonMerge public AB getValue() { return _value; } } static class AB { public int a; public int b; protected AB() { } public AB(int a0, int b0) { a = a0; b = b0; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper() // 26-Oct-2016, tatu: Make sure we'll report merge problems by default .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE) ; public void testBeanMergingWithNullDefault() throws Exception { // By default `null` should simply overwrite value ConfigDefault config = MAPPER.readerForUpdating(new ConfigDefault(5, 7)) .readValue(aposToQuotes("{'loc':null}")); assertNotNull(config); assertNull(config.loc); // but it should be possible to override setting to, say, skip // First: via specific type override // important! We'll specify for value type to be merged ObjectMapper mapper = newObjectMapper(); mapper.configOverride(AB.class) .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP)); config = mapper.readerForUpdating(new ConfigDefault(137, -3)) .readValue(aposToQuotes("{'loc':null}")); assertNotNull(config.loc); assertEquals(137, config.loc.a); assertEquals(-3, config.loc.b); // Second: by global defaults mapper = newObjectMapper(); mapper.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP)); config = mapper.readerForUpdating(new ConfigDefault(12, 34)) .readValue(aposToQuotes("{'loc':null}")); assertNotNull(config.loc); assertEquals(12, config.loc.a); assertEquals(34, config.loc.b); } public void testBeanMergingWithNullSkip() throws Exception { ConfigSkipNull config = MAPPER.readerForUpdating(new ConfigSkipNull(5, 7)) .readValue(aposToQuotes("{'loc':null}")); assertNotNull(config); assertNotNull(config.loc); assertEquals(5, config.loc.a); assertEquals(7, config.loc.b); } public void testBeanMergingWithNullSet() throws Exception { ConfigAllowNullOverwrite config = MAPPER.readerForUpdating(new ConfigAllowNullOverwrite(5, 7)) .readValue(aposToQuotes("{'loc':null}")); assertNotNull(config); assertNull(config.loc); } public void testSetterlessMergingWithNull() throws Exception { NoSetterConfig input = new NoSetterConfig(); NoSetterConfig result = MAPPER.readerForUpdating(input) .readValue(aposToQuotes("{'value':null}")); assertNotNull(result.getValue()); assertEquals(2, result.getValue().a); assertEquals(3, result.getValue().b); assertSame(input, result); } } NodeMergeTest.java000066400000000000000000000102011325620701100362460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/mergepackage com.fasterxml.jackson.databind.deser.merge; import com.fasterxml.jackson.annotation.JsonMerge; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ArrayNode; public class NodeMergeTest extends BaseMapTest { private final static ObjectMapper MAPPER = newObjectMapper() // 26-Oct-2016, tatu: Make sure we'll report merge problems by default .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE) ; static class ObjectNodeWrapper { @JsonMerge public ObjectNode props = MAPPER.createObjectNode(); { props.put("default", "enabled"); } } static class ArrayNodeWrapper { @JsonMerge public ArrayNode list = MAPPER.createArrayNode(); { list.add(123); } } /* /******************************************************** /* Test methods /******************************************************** */ public void testObjectNodeUpdateValue() throws Exception { ObjectNode base = MAPPER.createObjectNode(); base.put("first", "foo"); assertSame(base, MAPPER.readerForUpdating(base) .readValue(aposToQuotes("{'second':'bar', 'third':5, 'fourth':true}"))); assertEquals(4, base.size()); assertEquals("bar", base.path("second").asText()); assertEquals("foo", base.path("first").asText()); assertEquals(5, base.path("third").asInt()); assertTrue(base.path("fourth").asBoolean()); } public void testObjectNodeMerge() throws Exception { ObjectNodeWrapper w = MAPPER.readValue(aposToQuotes("{'props':{'stuff':'xyz'}}"), ObjectNodeWrapper.class); assertEquals(2, w.props.size()); assertEquals("enabled", w.props.path("default").asText()); assertEquals("xyz", w.props.path("stuff").asText()); } public void testObjectDeepUpdate() throws Exception { ObjectNode base = MAPPER.createObjectNode(); ObjectNode props = base.putObject("props"); props.put("base", 123); props.put("value", 456); ArrayNode a = props.putArray("array"); a.add(true); base.putNull("misc"); assertSame(base, MAPPER.readerForUpdating(base) .readValue(aposToQuotes( "{'props':{'value':true, 'extra':25.5, 'array' : [ 3 ]}}"))); assertEquals(2, base.size()); ObjectNode resultProps = (ObjectNode) base.get("props"); assertEquals(4, resultProps.size()); assertEquals(123, resultProps.path("base").asInt()); assertTrue(resultProps.path("value").asBoolean()); assertEquals(25.5, resultProps.path("extra").asDouble()); JsonNode n = resultProps.get("array"); assertEquals(ArrayNode.class, n.getClass()); assertEquals(2, n.size()); assertEquals(3, n.get(1).asInt()); } public void testArrayNodeUpdateValue() throws Exception { ArrayNode base = MAPPER.createArrayNode(); base.add("first"); assertSame(base, MAPPER.readerForUpdating(base) .readValue(aposToQuotes("['second',false,null]"))); assertEquals(4, base.size()); assertEquals("first", base.path(0).asText()); assertEquals("second", base.path(1).asText()); assertFalse(base.path(2).asBoolean()); assertTrue(base.path(3).isNull()); } public void testArrayNodeMerge() throws Exception { ArrayNodeWrapper w = MAPPER.readValue(aposToQuotes("{'list':[456,true,{}, [], 'foo']}"), ArrayNodeWrapper.class); assertEquals(6, w.list.size()); assertEquals(123, w.list.get(0).asInt()); assertEquals(456, w.list.get(1).asInt()); assertTrue(w.list.get(2).asBoolean()); JsonNode n = w.list.get(3); assertTrue(n.isObject()); assertEquals(0, n.size()); n = w.list.get(4); assertTrue(n.isArray()); assertEquals(0, n.size()); assertEquals("foo", w.list.get(5).asText()); } } PropertyMergeTest.java000066400000000000000000000157411325620701100372230ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/mergepackage com.fasterxml.jackson.databind.deser.merge; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat.Shape; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; /** * Tests to make sure that the new "merging" property of * JsonSetter annotation works as expected. * * @since 2.9 */ @SuppressWarnings("serial") public class PropertyMergeTest extends BaseMapTest { static class Config { @JsonMerge public AB loc = new AB(1, 2); protected Config() { } public Config(int a, int b) { loc = new AB(a, b); } } static class NonMergeConfig { public AB loc = new AB(1, 2); } // another variant where all we got is a getter static class NoSetterConfig { AB _value = new AB(1, 2); @JsonMerge public AB getValue() { return _value; } } static class AB { public int a; public int b; protected AB() { } public AB(int a0, int b0) { a = a0; b = b0; } } @JsonPropertyOrder(alphabetic=true) @JsonFormat(shape=Shape.ARRAY) static class ABAsArray { public int a; public int b; } // Custom type that would be deserializable by default static class StringReference extends AtomicReference { public StringReference(String str) { set(str); } } static class MergedReference { @JsonMerge public StringReference value = new StringReference("default"); } static class MergedX { @JsonMerge public T value; public MergedX(T v) { value = v; } protected MergedX() { } } // // // Classes with invalid merge definition(s) static class CantMergeInts { @JsonMerge public int value; } /* /******************************************************** /* Test methods, POJO merging /******************************************************** */ private final ObjectMapper MAPPER = newObjectMapper() // 26-Oct-2016, tatu: Make sure we'll report merge problems by default .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE) ; public void testBeanMergingViaProp() throws Exception { Config config = MAPPER.readValue(aposToQuotes("{'loc':{'b':3}}"), Config.class); assertEquals(1, config.loc.a); assertEquals(3, config.loc.b); config = MAPPER.readerForUpdating(new Config(5, 7)) .readValue(aposToQuotes("{'loc':{'b':2}}")); assertEquals(5, config.loc.a); assertEquals(2, config.loc.b); } public void testBeanMergingViaType() throws Exception { // by default, no merging NonMergeConfig config = MAPPER.readValue(aposToQuotes("{'loc':{'a':3}}"), NonMergeConfig.class); assertEquals(3, config.loc.a); assertEquals(0, config.loc.b); // not passed, nor merge from original // but with type-overrides ObjectMapper mapper = newObjectMapper(); mapper.configOverride(AB.class).setMergeable(true); config = mapper.readValue(aposToQuotes("{'loc':{'a':3}}"), NonMergeConfig.class); assertEquals(3, config.loc.a); assertEquals(2, config.loc.b); // original, merged } public void testBeanMergingViaGlobal() throws Exception { // but with type-overrides ObjectMapper mapper = newObjectMapper() .setDefaultMergeable(true); NonMergeConfig config = mapper.readValue(aposToQuotes("{'loc':{'a':3}}"), NonMergeConfig.class); assertEquals(3, config.loc.a); assertEquals(2, config.loc.b); // original, merged // also, test with bigger POJO type; just as smoke test FiveMinuteUser user0 = new FiveMinuteUser("Bob", "Bush", true, FiveMinuteUser.Gender.MALE, new byte[] { 1, 2, 3, 4, 5 }); FiveMinuteUser user = mapper.readerFor(FiveMinuteUser.class) .withValueToUpdate(user0) .readValue(aposToQuotes("{'name':{'last':'Brown'}}")); assertEquals("Bob", user.getName().getFirst()); assertEquals("Brown", user.getName().getLast()); } // should even work with no setter public void testBeanMergingWithoutSetter() throws Exception { NoSetterConfig config = MAPPER.readValue(aposToQuotes("{'value':{'b':99}}"), NoSetterConfig.class); assertEquals(99, config._value.b); assertEquals(1, config._value.a); } /* /******************************************************** /* Test methods, as array /******************************************************** */ public void testBeanAsArrayMerging() throws Exception { ABAsArray input = new ABAsArray(); input.a = 4; input.b = 6; assertSame(input, MAPPER.readerForUpdating(input) .readValue("[1, 3]")); assertEquals(1, input.a); assertEquals(3, input.b); // then with one too few assertSame(input, MAPPER.readerForUpdating(input) .readValue("[9]")); assertEquals(9, input.a); assertEquals(3, input.b); // and finally with extra, failing try { MAPPER.readerForUpdating(input) .readValue("[9, 8, 14]"); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "expected at most 2 properties"); } try { MAPPER.readerForUpdating(input) .readValue("\"blob\""); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "Cannot deserialize"); verifyException(e, "from non-Array representation"); } } /* /******************************************************** /* Test methods, reference types /******************************************************** */ public void testReferenceMerging() throws Exception { MergedReference result = MAPPER.readValue(aposToQuotes("{'value':'override'}"), MergedReference.class); assertEquals("override", result.value.get()); } /* /******************************************************** /* Test methods, failure checking /******************************************************** */ public void testInvalidPropertyMerge() throws Exception { ObjectMapper mapper = newObjectMapper() .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE); try { mapper.readValue("{\"value\":3}", CantMergeInts.class); fail("Should not pass"); } catch (InvalidDefinitionException e) { verifyException(e, "cannot be merged"); } } } UpdateValueTest.java000066400000000000000000000030671325620701100366340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/deser/mergepackage com.fasterxml.jackson.databind.deser.merge; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; public class UpdateValueTest extends BaseMapTest { static class Bean { private String a; private String b; @JsonCreator public Bean(@JsonProperty("a") String a, @JsonProperty("b") String b) { this.a = a; this.b = b; } String getA() { return a; } void setA(String a) { this.a = a; } String getB() { return b; } void setB(String b) { this.b = b; } } private final ObjectMapper MAPPER = newObjectMapper(); // [databind#318] (and Scala module issue #83] public void testValueUpdateWithCreator() throws Exception { Bean bean = new Bean("abc", "def"); MAPPER.readerFor(Bean.class).withValueToUpdate(bean).readValue("{\"a\":\"ghi\",\"b\":\"jkl\"}"); assertEquals("ghi", bean.getA()); assertEquals("jkl", bean.getB()); } public void testValueUpdateOther() throws Exception { Bean bean = new Bean("abc", "def"); ObjectReader r = MAPPER.readerFor(Bean.class).withValueToUpdate(bean); // but, changed our minds, no update r = r.withValueToUpdate(null); // should be safe to read regardless Bean result = r.readValue(aposToQuotes("{'a':'x'}")); assertNotNull(result); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/exc/000077500000000000000000000000001325620701100313415ustar00rootroot00000000000000BasicExceptionTest.java000066400000000000000000000101331325620701100356630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import java.io.StringWriter; import java.util.Collection; import java.util.Collections; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.type.TypeFactory; public class BasicExceptionTest extends BaseMapTest { final ObjectMapper MAPPER = new ObjectMapper(); final JsonFactory JSON_F = MAPPER.getFactory(); public void testBadDefinition() throws Exception { JavaType t = TypeFactory.defaultInstance().constructType(String.class); JsonParser p = JSON_F.createParser("[]"); InvalidDefinitionException e = new InvalidDefinitionException(p, "Testing", t); assertEquals("Testing", e.getOriginalMessage()); assertEquals(String.class, e.getType().getRawClass()); assertNull(e.getBeanDescription()); assertNull(e.getProperty()); assertSame(p, e.getProcessor()); p.close(); // and via factory method: BeanDescription beanDef = MAPPER.getSerializationConfig().introspectClassAnnotations(getClass()); e = InvalidDefinitionException.from(p, "Testing", beanDef, (BeanPropertyDefinition) null); assertEquals(beanDef.getType(), e.getType()); assertNotNull(e); // and the other constructor too JsonGenerator g = JSON_F.createGenerator(new StringWriter()); e = new InvalidDefinitionException(p, "Testing", t); assertEquals("Testing", e.getOriginalMessage()); assertEquals(String.class, e.getType().getRawClass()); // and factory e = InvalidDefinitionException.from(g, "Testing", beanDef, (BeanPropertyDefinition) null); assertEquals(beanDef.getType(), e.getType()); assertNotNull(e); g.close(); } @SuppressWarnings("deprecation") public void testInvalidFormat() throws Exception { // deprecated methods should still work: InvalidFormatException e = new InvalidFormatException("Testing", Boolean.TRUE, String.class); assertSame(Boolean.TRUE, e.getValue()); assertNull(e.getProcessor()); assertNotNull(e); e = new InvalidFormatException("Testing", JsonLocation.NA, Boolean.TRUE, String.class); assertSame(Boolean.TRUE, e.getValue()); assertNull(e.getProcessor()); assertNotNull(e); } public void testIgnoredProperty() throws Exception { // first just construct valid instance with some variations JsonParser p = JSON_F.createParser("{ }"); IgnoredPropertyException e = IgnoredPropertyException.from(p, this, // to get class from "testProp", Collections.singletonList("x")); assertNotNull(e); e = IgnoredPropertyException.from(p, getClass(), "testProp", null); assertNotNull(e); assertNull(e.getKnownPropertyIds()); p.close(); // also, verify failure if null passed for "value" try { IgnoredPropertyException.from(p, null, "testProp", Collections.singletonList("x")); fail("Should not pass"); } catch (NullPointerException e2) { } } public void testUnrecognizedProperty() throws Exception { JsonParser p = JSON_F.createParser("{ }"); UnrecognizedPropertyException e = UnrecognizedPropertyException.from(p, this, "testProp", Collections.singletonList("y")); assertNotNull(e); assertEquals(getClass(), e.getReferringClass()); Collection ids = e.getKnownPropertyIds(); assertNotNull(ids); assertEquals(1, ids.size()); assertTrue(ids.contains("y")); e = UnrecognizedPropertyException.from(p, getClass(), "testProp", Collections.singletonList("y")); assertEquals(getClass(), e.getReferringClass()); p.close(); } } DeserExceptionTypeTest.java000066400000000000000000000110131325620701100365440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import java.io.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; /** * Unit test for verifying that exceptions are properly handled (caught, * re-thrown or wrapped, depending) with Object deserialization, * including using concrete subtypes of {@link JsonMappingException} * (or, for low-level parsing, {@link JsonParseException}). */ public class DeserExceptionTypeTest extends BaseMapTest { static class Bean { public String propX; } // Class that has no applicable creators and thus cannot be instantiated; // definition problem static class NoCreatorsBean { public int x; // Constructor that is not detectable as Creator public NoCreatorsBean(boolean foo, int foo2) { } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testHandlingOfUnrecognized() throws Exception { UnrecognizedPropertyException exc = null; try { MAPPER.readValue("{\"bar\":3}", Bean.class); } catch (UnrecognizedPropertyException e) { exc = e; } if (exc == null) { fail("Should have failed binding"); } assertEquals("bar", exc.getPropertyName()); assertEquals(Bean.class, exc.getReferringClass()); // also: should get list of known properties verifyException(exc, "propX"); } /** * Simple test to check behavior when end-of-stream is encountered * without content. Used to expect EOFException (Jackson 1.x); but * nowadays ought to be JsonMappingException */ public void testExceptionWithEmpty() throws Exception { try { Object result = MAPPER.readValue(" ", Object.class); fail("Expected an exception, but got result value: "+result); } catch (Exception e) { verifyException(e, MismatchedInputException.class, "No content"); } } @SuppressWarnings("resource") public void testExceptionWithIncomplete() throws Exception { BrokenStringReader r = new BrokenStringReader("[ 1, ", "TEST"); JsonParser p = MAPPER.getFactory().createParser(r); try { @SuppressWarnings("unused") Object ob = MAPPER.readValue(p, Object.class); fail("Should have gotten an exception"); } catch (IOException e) { /* For "bona fide" IO problems (due to low-level problem, * thrown by reader/stream), IOException must be thrown */ verifyException(e, IOException.class, "TEST"); } } public void testExceptionWithEOF() throws Exception { JsonParser p = MAPPER.getFactory().createParser(" 3"); Integer I = MAPPER.readValue(p, Integer.class); assertEquals(3, I.intValue()); // and then end-of-input... try { I = MAPPER.readValue(p, Integer.class); fail("Should have gotten an exception"); } catch (IOException e) { verifyException(e, MismatchedInputException.class, "No content"); } // also: should have no current token after end-of-input JsonToken t = p.getCurrentToken(); if (t != null) { fail("Expected current token to be null after end-of-stream, was: "+t); } p.close(); } // [databind#1414] public void testExceptionForNoCreators() throws Exception { try { NoCreatorsBean b = MAPPER.readValue("{}", NoCreatorsBean.class); fail("Should not succeed, got: "+b); } catch (JsonMappingException e) { verifyException(e, InvalidDefinitionException.class, "no Creators"); } } /* /********************************************************** /* Helper methods /********************************************************** */ void verifyException(Exception e, Class expType, String expMsg) throws Exception { if (e.getClass() != expType) { fail("Expected exception of type "+expType.getName()+", got "+e.getClass().getName()); } if (expMsg != null) { verifyException(e, expMsg); } } } ExceptionDeserializationTest.java000066400000000000000000000141231325620701100377730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying that simple exceptions can be deserialized. */ public class ExceptionDeserializationTest extends BaseMapTest { @SuppressWarnings("serial") static class MyException extends Exception { protected int value; protected String myMessage; protected HashMap stuff = new HashMap(); @JsonCreator MyException(@JsonProperty("message") String msg, @JsonProperty("value") int v) { super(msg); myMessage = msg; value = v; } public int getValue() { return value; } public String getFoo() { return "bar"; } @JsonAnySetter public void setter(String key, Object value) { stuff.put(key, value); } } @SuppressWarnings("serial") static class MyNoArgException extends Exception { @JsonCreator MyNoArgException() { } } /* /********************************************************** /* Tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testIOException() throws IOException { IOException ioe = new IOException("TEST"); String json = MAPPER.writeValueAsString(ioe); IOException result = MAPPER.readValue(json, IOException.class); assertEquals(ioe.getMessage(), result.getMessage()); } public void testWithCreator() throws IOException { final String MSG = "the message"; String json = MAPPER.writeValueAsString(new MyException(MSG, 3)); MyException result = MAPPER.readValue(json, MyException.class); assertEquals(MSG, result.getMessage()); assertEquals(3, result.value); assertEquals(1, result.stuff.size()); assertEquals(result.getFoo(), result.stuff.get("foo")); } public void testWithNullMessage() throws IOException { final ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); String json = mapper.writeValueAsString(new IOException((String) null)); IOException result = mapper.readValue(json, IOException.class); assertNotNull(result); assertNull(result.getMessage()); } public void testNoArgsException() throws IOException { MyNoArgException exc = MAPPER.readValue("{}", MyNoArgException.class); assertNotNull(exc); } // try simulating JDK 7 behavior public void testJDK7SuppressionProperty() throws IOException { Exception exc = MAPPER.readValue("{\"suppressed\":[]}", IOException.class); assertNotNull(exc); } // [databind#381] public void testSingleValueArrayDeserialization() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); final IOException exp; try { throw new IOException("testing"); } catch (IOException internal) { exp = internal; } final String value = "[" + mapper.writeValueAsString(exp) + "]"; final IOException cloned = mapper.readValue(value, IOException.class); assertEquals(exp.getMessage(), cloned.getMessage()); assertEquals(exp.getStackTrace().length, cloned.getStackTrace().length); for (int i = 0; i < exp.getStackTrace().length; i ++) { _assertEquality(i, exp.getStackTrace()[i], cloned.getStackTrace()[i]); } } protected void _assertEquality(int ix, StackTraceElement exp, StackTraceElement act) { _assertEquality(ix, "className", exp.getClassName(), act.getClassName()); _assertEquality(ix, "methodName", exp.getMethodName(), act.getMethodName()); _assertEquality(ix, "fileName", exp.getFileName(), act.getFileName()); _assertEquality(ix, "lineNumber", exp.getLineNumber(), act.getLineNumber()); } protected void _assertEquality(int ix, String prop, Object exp, Object act) { if (exp == null) { if (act == null) { return; } } else { if (exp.equals(act)) { return; } } fail(String.format("StackTraceElement #%d, property '%s' differs: expected %s, actual %s", ix, prop, exp, act)); } public void testSingleValueArrayDeserializationException() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); final IOException exp; try { throw new IOException("testing"); } catch (IOException internal) { exp = internal; } final String value = "[" + mapper.writeValueAsString(exp) + "]"; try { mapper.readValue(value, IOException.class); fail("Exception not thrown when attempting to deserialize an IOException wrapped in a single value array with UNWRAP_SINGLE_VALUE_ARRAYS disabled"); } catch (JsonMappingException exp2) { verifyException(exp2, "out of START_ARRAY"); } } // mostly to help with XML module (and perhaps CSV) public void testLineNumberAsString() throws IOException { Exception exc = MAPPER.readValue(aposToQuotes( "{'message':'Test',\n'stackTrace': " +"[ { 'lineNumber':'50' } ] }" ), IOException.class); assertNotNull(exc); } // [databind#1842]: public void testNullAsMessage() throws IOException { Exception exc = MAPPER.readValue(aposToQuotes( "{'message':null, 'localizedMessage':null }" ), IOException.class); assertNotNull(exc); assertNull(exc.getMessage()); assertNull(exc.getLocalizedMessage()); } } ExceptionPathTest.java000066400000000000000000000024111325620701100355360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class ExceptionPathTest extends BaseMapTest { static class Outer { public Inner inner = new Inner(); } static class Inner { public int x; @JsonCreator public static Inner create(@JsonProperty("x") int x) { throw new RuntimeException("test-exception"); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testReferenceChainForInnerClass() throws Exception { String json = MAPPER.writeValueAsString(new Outer()); try { MAPPER.readValue(json, Outer.class); fail("Should not pass"); } catch (JsonMappingException e) { JsonMappingException.Reference reference = e.getPath().get(0); assertEquals(getClass().getName()+"$Outer[\"inner\"]", reference.toString()); } } public static void main(String[] args) { System.err.println("Int, full: "+Integer.TYPE.getName()); } } ExceptionSerializationTest.java000066400000000000000000000111031325620701100374550ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying that simple exceptions can be serialized. */ public class ExceptionSerializationTest extends BaseMapTest { @SuppressWarnings("serial") @JsonIgnoreProperties({ "bogus1" }) static class ExceptionWithIgnoral extends RuntimeException { public int bogus1 = 3; public int bogus2 = 5; protected ExceptionWithIgnoral() { } public ExceptionWithIgnoral(String msg) { super(msg); } } // [databind#1368] static class NoSerdeConstructor { private String strVal; public String getVal() { return strVal; } public NoSerdeConstructor( String strVal ) { this.strVal = strVal; } } /* /********************************************************** /* Tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimple() throws Exception { String TEST = "test exception"; Map result = writeAndMap(MAPPER, new Exception(TEST)); // JDK 7 has introduced a new property 'suppressed' to Throwable Object ob = result.get("suppressed"); if (ob != null) { assertEquals(5, result.size()); } else { assertEquals(4, result.size()); } assertEquals(TEST, result.get("message")); assertNull(result.get("cause")); assertEquals(TEST, result.get("localizedMessage")); // hmmh. what should we get for stack traces? Object traces = result.get("stackTrace"); if (!(traces instanceof List)) { fail("Expected a List for exception member 'stackTrace', got: "+traces); } } // to double-check [databind#1413] public void testSimpleOther() throws Exception { JsonParser p = MAPPER.getFactory().createParser("{ }"); InvalidFormatException exc = InvalidFormatException.from(p, "Test", getClass(), String.class); String json = MAPPER.writeValueAsString(exc); p.close(); assertNotNull(json); } // for [databind#877] @SuppressWarnings("unchecked") public void testIgnorals() throws Exception { ExceptionWithIgnoral input = new ExceptionWithIgnoral("foobar"); input.initCause(new IOException("surprise!")); // First, should ignore anything with class annotations String json = MAPPER .writerWithDefaultPrettyPrinter() .writeValueAsString(input); Map result = MAPPER.readValue(json, Map.class); assertEquals("foobar", result.get("message")); assertNull(result.get("bogus1")); assertNotNull(result.get("bogus2")); // and then also remova second property with config overrides ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(ExceptionWithIgnoral.class) .setIgnorals(JsonIgnoreProperties.Value.forIgnoredProperties("bogus2")); String json2 = mapper .writeValueAsString(new ExceptionWithIgnoral("foobar")); Map result2 = mapper.readValue(json2, Map.class); assertNull(result2.get("bogus1")); assertNull(result2.get("bogus2")); // and try to deserialize as well ExceptionWithIgnoral output = mapper.readValue(json2, ExceptionWithIgnoral.class); assertNotNull(output); assertEquals("foobar", output.getMessage()); } // [databind#1368] public void testJsonMappingExceptionSerialization() throws IOException { Exception e = null; // cant deserialize due to unexpected constructor try { MAPPER.readValue( "{ \"val\": \"foo\" }", NoSerdeConstructor.class ); fail("Should not pass"); } catch (JsonMappingException e0) { verifyException(e0, "cannot deserialize from Object"); e = e0; } // but should be able to serialize new exception we got String json = MAPPER.writeValueAsString(e); JsonNode root = MAPPER.readTree(json); String msg = root.path("message").asText(); String MATCH = "cannot construct instance"; if (!msg.toLowerCase().contains(MATCH)) { fail("Exception should contain '"+MATCH+"', does not: '"+msg+"'"); } } } StackTraceElementTest.java000066400000000000000000000023621325620701100363260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // for [databind#1794] public class StackTraceElementTest extends BaseMapTest { public static class ErrorObject { public String throwable; public String message; // @JsonDeserialize(contentUsing = StackTraceElementDeserializer.class) public StackTraceElement[] stackTrace; ErrorObject() {} public ErrorObject(Throwable throwable) { this.throwable = throwable.getClass().getName(); message = throwable.getMessage(); stackTrace = throwable.getStackTrace(); } } // for [databind#1794] where extra `declaringClass` is serialized from private field. public void testCustomStackTraceDeser() throws Exception { ObjectMapper mapper = newObjectMapper(); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); String json = mapper .writerWithDefaultPrettyPrinter() .writeValueAsString(new ErrorObject(new Exception("exception message"))); ErrorObject result = mapper.readValue(json, ErrorObject.class); assertNotNull(result); } } TestExceptionHandlingWithDefaultDeserialization.java000066400000000000000000000025351325620701100436050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; public class TestExceptionHandlingWithDefaultDeserialization extends BaseMapTest { static class Foo { private Bar bar; public Foo() { } public Bar getBar() { return bar; } } static class Bar { private Baz baz; public Bar() { } public Baz getBaz() { return baz; } } static class Baz { private String qux; public Baz() { } public String getQux() { return qux; } } public void testShouldThrowJsonMappingExceptionWithPathReference() throws IOException { // given ObjectMapper mapper = new ObjectMapper(); String input = "{\"bar\":{\"baz\":{qux:\"quxValue\"))}"; final String THIS = getClass().getName(); // when try { mapper.readValue(input, Foo.class); fail("Upsss! Exception has not been thrown."); } catch (JsonMappingException ex) { // then assertEquals(THIS+"$Foo[\"bar\"]->"+THIS+"$Bar[\"baz\"]", ex.getPathReference()); } } } TestExceptionHandlingWithJsonCreatorDeserialization.java000066400000000000000000000033161325620701100444500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; public class TestExceptionHandlingWithJsonCreatorDeserialization extends BaseMapTest { static class Foo { private Bar bar; @JsonCreator public Foo(@JsonProperty("bar") Bar bar) { this.bar = bar; } public Bar getBar() { return bar; } } static class Bar { private Baz baz; @JsonCreator public Bar(@JsonProperty("baz") Baz baz) { this.baz = baz; } public Baz getBaz() { return baz; } } static class Baz { private String qux; @JsonCreator public Baz(@JsonProperty("qux") String qux) { this.qux = qux; } public String getQux() { return qux; } } public void testShouldThrowJsonMappingExceptionWithPathReference() throws IOException { // given ObjectMapper mapper = new ObjectMapper(); String input = "{\"bar\":{\"baz\":{qux:\"quxValue\"))}"; final String THIS = getClass().getName(); // when try { mapper.readValue(input, Foo.class); fail("Upsss! Exception has not been thrown."); } catch (JsonMappingException ex) { // then assertEquals(THIS+"$Foo[\"bar\"]->"+THIS+"$Bar[\"baz\"]", ex.getPathReference()); } } } TestExceptionsDuringWriting.java000066400000000000000000000113431325620701100376250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/excpackage com.fasterxml.jackson.databind.exc; import java.io.*; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; /** * Unit test for verifying that exceptions are properly handled (caught, * re-thrown or wrapped, depending) * with Object serialization. */ public class TestExceptionsDuringWriting extends BaseMapTest { /* /********************************************************** /* Helper classes /********************************************************** */ static class Bean { // no methods, we'll use our custom serializer } static class SerializerWithErrors extends JsonSerializer { @Override public void serialize(Bean value, JsonGenerator jgen, SerializerProvider provider) { throw new IllegalArgumentException("test string"); } } /* /********************************************************** /* Tests /********************************************************** */ /** * Unit test that verifies that by default all exceptions except for * JsonMappingException are caught and wrapped. */ public void testCatchAndRethrow() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test-exceptions", Version.unknownVersion()); module.addSerializer(Bean.class, new SerializerWithErrors()); mapper.registerModule(module); try { StringWriter sw = new StringWriter(); /* And just to make things more interesting, let's create * a nested data struct... */ Bean[] b = { new Bean() }; List l = new ArrayList(); l.add(b); mapper.writeValue(sw, l); fail("Should have gotten an exception"); } catch (IOException e) { // should contain original message somewhere verifyException(e, "test string"); Throwable root = e.getCause(); assertNotNull(root); if (!(root instanceof IllegalArgumentException)) { fail("Wrapped exception not IAE, but "+root.getClass()); } } } /** * Unit test for verifying that regular IOExceptions are not wrapped * but are passed through as is. */ @SuppressWarnings("resource") public void testExceptionWithSimpleMapper() throws Exception { ObjectMapper mapper = new ObjectMapper(); try { BrokenStringWriter sw = new BrokenStringWriter("TEST"); mapper.writeValue(sw, createLongObject()); fail("Should have gotten an exception"); } catch (IOException e) { verifyException(e, IOException.class, "TEST"); } } @SuppressWarnings("resource") public void testExceptionWithMapperAndGenerator() throws Exception { ObjectMapper mapper = new ObjectMapper(); JsonFactory f = new MappingJsonFactory(); BrokenStringWriter sw = new BrokenStringWriter("TEST"); JsonGenerator jg = f.createGenerator(sw); try { mapper.writeValue(jg, createLongObject()); fail("Should have gotten an exception"); } catch (IOException e) { verifyException(e, IOException.class, "TEST"); } } @SuppressWarnings("resource") public void testExceptionWithGeneratorMapping() throws Exception { JsonFactory f = new MappingJsonFactory(); JsonGenerator jg = f.createGenerator(new BrokenStringWriter("TEST")); try { jg.writeObject(createLongObject()); fail("Should have gotten an exception"); } catch (Exception e) { verifyException(e, IOException.class, "TEST"); } } /* /********************************************************** /* Helper methods /********************************************************** */ void verifyException(Exception e, Class expType, String expMsg) throws Exception { if (e.getClass() != expType) { fail("Expected exception of type "+expType.getName()+", got "+e.getClass().getName()); } if (expMsg != null) { verifyException(e, expMsg); } } Object createLongObject() { List leaf = new ArrayList(); for (int i = 0; i < 256; ++i) { leaf.add(Integer.valueOf(i)); } List root = new ArrayList(256); for (int i = 0; i < 256; ++i) { root.add(leaf); } return root; } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ext/000077500000000000000000000000001325620701100313625ustar00rootroot00000000000000TestCoreXMLTypes.java000066400000000000000000000115041325620701100353050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import javax.xml.datatype.*; import javax.xml.namespace.QName; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ext.CoreXMLDeserializers; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Core XML types (javax.xml) are considered "external" (or more precisely "optional") * since some Java(-like) platforms do not include them: specifically, Google AppEngine * and Android seem to skimp on their inclusion. As such, they are dynamically loaded * only as needed, and need bit special handling. * * @author tatu */ public class TestCoreXMLTypes extends BaseMapTest { /* /********************************************************** /* Serializer tests /********************************************************** */ public void testQNameSer() throws Exception { QName qn = new QName("http://abc", "tag", "prefix"); assertEquals(quote(qn.toString()), serializeAsString(qn)); } public void testDurationSer() throws Exception { DatatypeFactory dtf = DatatypeFactory.newInstance(); // arbitrary value Duration dur = dtf.newDurationDayTime(false, 15, 19, 58, 1); assertEquals(quote(dur.toString()), serializeAsString(dur)); } public void testXMLGregorianCalendarSerAndDeser() throws Exception { DatatypeFactory dtf = DatatypeFactory.newInstance(); XMLGregorianCalendar cal = dtf.newXMLGregorianCalendar (1974, 10, 10, 18, 15, 17, 123, 0); /* Due to [JACKSON-308], 1.6 will use configurable Date serialization; * and it defaults to using timestamp. So let's try couple of combinations. */ ObjectMapper mapper = new ObjectMapper(); long timestamp = cal.toGregorianCalendar().getTimeInMillis(); String numStr = String.valueOf(timestamp); assertEquals(numStr, mapper.writeValueAsString(cal)); // [JACKSON-403] Needs to come back ok as well: XMLGregorianCalendar calOut = mapper.readValue(numStr, XMLGregorianCalendar.class); assertNotNull(calOut); assertEquals(timestamp, calOut.toGregorianCalendar().getTimeInMillis()); // and then textual variant mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // this is ALMOST same as default for XMLGregorianCalendar... just need to unify Z/+0000 String exp = cal.toXMLFormat(); String act = mapper.writeValueAsString(cal); act = act.substring(1, act.length() - 1); // remove quotes exp = removeZ(exp); act = removeZ(act); assertEquals(exp, act); } private String removeZ(String dateStr) { if (dateStr.endsWith("Z")) { return dateStr.substring(0, dateStr.length()-1); } if (dateStr.endsWith("+0000")) { return dateStr.substring(0, dateStr.length()-5); } return dateStr; } /* /********************************************************** /* Deserializer tests /********************************************************** */ // First things first: must be able to load the deserializers... public void testDeserializerLoading() { CoreXMLDeserializers sers = new CoreXMLDeserializers(); TypeFactory f = TypeFactory.defaultInstance(); sers.findBeanDeserializer(f.constructType(Duration.class), null, null); sers.findBeanDeserializer(f.constructType(XMLGregorianCalendar.class), null, null); sers.findBeanDeserializer(f.constructType(QName.class), null, null); } public void testQNameDeser() throws Exception { QName qn = new QName("http://abc", "tag", "prefix"); String qstr = qn.toString(); ObjectMapper mapper = new ObjectMapper(); assertEquals("Should deserialize to equal QName (exp serialization: '"+qstr+"')", qn, mapper.readValue(quote(qstr), QName.class)); } public void testCalendarDeser() throws Exception { DatatypeFactory dtf = DatatypeFactory.newInstance(); XMLGregorianCalendar cal = dtf.newXMLGregorianCalendar (1974, 10, 10, 18, 15, 17, 123, 0); String exp = cal.toXMLFormat(); assertEquals("Should deserialize to equal XMLGregorianCalendar ('"+exp+"')", cal, new ObjectMapper().readValue(quote(exp), XMLGregorianCalendar.class)); } public void testDurationDeser() throws Exception { DatatypeFactory dtf = DatatypeFactory.newInstance(); // arbitrary value, like... say, 27d5h15m59s Duration dur = dtf.newDurationDayTime(true, 27, 5, 15, 59); String exp = dur.toString(); assertEquals("Should deserialize to equal Duration ('"+exp+"')", dur, new ObjectMapper().readValue(quote(exp), Duration.class)); } } TestDOM.java000066400000000000000000000075111325620701100334310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import java.io.StringReader; import javax.xml.parsers.DocumentBuilderFactory; import org.xml.sax.InputSource; import org.w3c.dom.*; import com.fasterxml.jackson.databind.ObjectMapper; public class TestDOM extends com.fasterxml.jackson.databind.BaseMapTest { final static String SIMPLE_XML = "Rock & Roll!"; final static String SIMPLE_XML_NS = ""; private final ObjectMapper MAPPER = new ObjectMapper(); public void testSerializeSimpleNonNS() throws Exception { // Let's just parse first, easiest Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse (new InputSource(new StringReader(SIMPLE_XML))); assertNotNull(doc); // need to strip xml declaration, if any String outputRaw = MAPPER.writeValueAsString(doc); // And re-parse as String, since JSON has quotes... String output = MAPPER.readValue(outputRaw, String.class); /* ... and finally, normalize to (close to) canonical XML * output (single vs double quotes, xml declaration etc) */ assertEquals(SIMPLE_XML, normalizeOutput(output)); } public void testDeserializeNonNS() throws Exception { for (int i = 0; i < 2; ++i) { Document doc; if (i == 0) { // First, as Document: doc = MAPPER.readValue(quote(SIMPLE_XML), Document.class); } else { // and then as plain Node (no difference) Node node = MAPPER.readValue(quote(SIMPLE_XML), Node.class); doc = (Document) node; } Element root = doc.getDocumentElement(); assertNotNull(root); // non-ns, simple... assertEquals("root", root.getTagName()); assertEquals("3", root.getAttribute("attr")); assertEquals(1, root.getAttributes().getLength()); NodeList nodes = root.getChildNodes(); assertEquals(2, nodes.getLength()); Element leaf = (Element) nodes.item(0); assertEquals("leaf", leaf.getTagName()); assertEquals(0, leaf.getAttributes().getLength()); //"Rock & Roll!"; ProcessingInstruction pi = (ProcessingInstruction) nodes.item(1); assertEquals("proc", pi.getTarget()); assertEquals("instr", pi.getData()); } } public void testDeserializeNS() throws Exception { Document doc = MAPPER.readValue(quote(SIMPLE_XML_NS), Document.class); Element root = doc.getDocumentElement(); assertNotNull(root); assertEquals("root", root.getTagName()); // Not sure if it ought to be "" or null... String uri = root.getNamespaceURI(); assertTrue((uri == null) || "".equals(uri)); // no child nodes: assertEquals(0, root.getChildNodes().getLength()); // DOM is weird, includes ns decls as attributes... assertEquals(2, root.getAttributes().getLength()); assertEquals("abc", root.getAttributeNS("http://foo", "attr")); } /* /********************************************************** /* Helper methods /********************************************************** */ protected static String normalizeOutput(String output) { // XML declaration to get rid of? output = output.trim(); if (output.startsWith("' of xml decl... output = output.substring(output.indexOf('>')+1).trim(); } // And replace double quotes with single-quotes... return output.replace('"', '\''); } } TestJava6Types.java000066400000000000000000000014741325620701100350100ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import java.util.Deque; import java.util.NavigableSet; import com.fasterxml.jackson.databind.ObjectMapper; /** * Tests to ensure that we can handle 1.6-only types, even if * registrations are done without direct refs */ public class TestJava6Types extends com.fasterxml.jackson.databind.BaseMapTest { // for [databind#216] public void test16Types() throws Exception { final ObjectMapper mapper = new ObjectMapper(); Deque dq = mapper.readValue("[1]", Deque.class); assertNotNull(dq); assertEquals(1, dq.size()); assertTrue(dq instanceof Deque); NavigableSet ns = mapper.readValue("[ true ]", NavigableSet.class); assertEquals(1, ns.size()); assertTrue(ns instanceof NavigableSet); } } TestJava7Types.java000066400000000000000000000023521325620701100350050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/extpackage com.fasterxml.jackson.databind.ext; import java.nio.file.Path; import java.nio.file.Paths; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; /** * @since 2.7 */ public class TestJava7Types extends BaseMapTest { public void testPathRoundtrip() throws Exception { ObjectMapper mapper = new ObjectMapper(); Path input = Paths.get("/tmp", "foo.txt"); String json = mapper.writeValueAsString(input); assertNotNull(json); Path p = mapper.readValue(json, Path.class); assertNotNull(p); assertEquals(input.toUri(), p.toUri()); assertEquals(input, p); } // [databind#1688]: public void testPolymorphicPath() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(DefaultTyping.NON_FINAL); Path input = Paths.get("/tmp", "foo.txt"); String json = mapper.writeValueAsString(new Object[] { input }); Object[] obs = mapper.readValue(json, Object[].class); assertEquals(1, obs.length); Object ob = obs[0]; assertTrue(ob instanceof Path); assertEquals(input.toString(), ob.toString()); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/filter/000077500000000000000000000000001325620701100320475ustar00rootroot00000000000000ProblemHandler1767Test.java000066400000000000000000000022411325620701100367150ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/filterpackage com.fasterxml.jackson.databind.filter; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; public class ProblemHandler1767Test extends BaseMapTest { static class IntHandler extends DeserializationProblemHandler { @Override public Object handleWeirdStringValue(DeserializationContext ctxt, Class targetType, String valueToConvert, String failureMsg) { if (targetType != Integer.TYPE) { return NOT_HANDLED; } return 1; } } static class TestBean { int a; public int getA() { return a; } public void setA(int a) { this.a = a; } } public void testPrimitivePropertyWithHandler() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.addHandler(new IntHandler()); TestBean result = mapper.readValue(aposToQuotes("{'a': 'not-a-number'}"), TestBean.class); assertNotNull(result); assertEquals(1, result.a); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/format/000077500000000000000000000000001325620701100320525ustar00rootroot00000000000000BooleanFormatTest.java000066400000000000000000000041431325620701100362300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/formatpackage com.fasterxml.jackson.databind.format; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; // [databind#1480] public class BooleanFormatTest extends BaseMapTest { @JsonPropertyOrder({ "b1", "b2", "b3" }) static class BeanWithBoolean { @JsonFormat(shape=JsonFormat.Shape.NUMBER) public boolean b1; @JsonFormat(shape=JsonFormat.Shape.NUMBER) public Boolean b2; public boolean b3; public BeanWithBoolean() { } public BeanWithBoolean(boolean b1, Boolean b2, boolean b3) { this.b1 = b1; this.b2 = b2; this.b3 = b3; } } /** * Simple wrapper around boolean types, usually to test value * conversions or wrapping */ protected static class BooleanWrapper { public Boolean b; public BooleanWrapper() { } public BooleanWrapper(Boolean value) { b = value; } } static class AltBoolean extends BooleanWrapper { public AltBoolean() { } public AltBoolean(Boolean b) { super(b); } } /* /********************************************************** /* Test methods /********************************************************** */ private final static ObjectMapper MAPPER = newObjectMapper(); public void testShapeViaDefaults() throws Exception { assertEquals(aposToQuotes("{'b':true}"), MAPPER.writeValueAsString(new BooleanWrapper(true))); ObjectMapper m = newObjectMapper(); m.configOverride(Boolean.class) .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.NUMBER)); assertEquals(aposToQuotes("{'b':1}"), m.writeValueAsString(new BooleanWrapper(true))); } public void testShapeOnProperty() throws Exception { assertEquals(aposToQuotes("{'b1':1,'b2':0,'b3':true}"), MAPPER.writeValueAsString(new BeanWithBoolean(true, false, true))); } } ColletionFormatShapeTest.java000066400000000000000000000033421325620701100375620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/formatpackage com.fasterxml.jackson.databind.format; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat.Shape; import com.fasterxml.jackson.databind.*; public class ColletionFormatShapeTest extends BaseMapTest { // [databind#40]: Allow serialization 'as POJO' (resulting in JSON Object) @JsonPropertyOrder({ "size", "value" }) @JsonFormat(shape=Shape.OBJECT) @JsonIgnoreProperties({ "empty" }) // from 'isEmpty()' static class CollectionAsPOJO extends ArrayList { private static final long serialVersionUID = 1L; @JsonProperty("size") public int foo() { return size(); } public List getValues() { return new ArrayList(this); } public void setValues(List v) { addAll(v); } // bogus setter to handle "size" property public void setSize(int i) { } } /* /********************************************************** /* Test methods /********************************************************** */ private final static ObjectMapper MAPPER = newObjectMapper(); public void testListAsObjectRoundtrip() throws Exception { // First, serialize a "POJO-List" CollectionAsPOJO list = new CollectionAsPOJO(); list.add("a"); list.add("b"); String json = MAPPER.writeValueAsString(list); assertEquals("{\"size\":2,\"values\":[\"a\",\"b\"]}", json); // and then bring it back! CollectionAsPOJO result = MAPPER.readValue(json, CollectionAsPOJO.class); assertEquals(2, result.size()); } } DateFormatTest.java000066400000000000000000000024201325620701100355220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/formatpackage com.fasterxml.jackson.databind.format; import java.util.Calendar; import java.util.Date; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.*; public class DateFormatTest extends BaseMapTest { protected static class DateWrapper { public Date value; public DateWrapper() { } public DateWrapper(long l) { value = new Date(l); } public DateWrapper(Date v) { value = v; } } public void testTypeDefaults() throws Exception { ObjectMapper mapper = newObjectMapper(); mapper.configOverride(Date.class) .setFormat(JsonFormat.Value.forPattern("yyyy.dd.MM")); // First serialize, should result in this (in UTC): String json = mapper.writeValueAsString(new DateWrapper(0L)); assertEquals(aposToQuotes("{'value':'1970.01.01'}"), json); // and then read back DateWrapper w = mapper.readValue(aposToQuotes("{'value':'1981.13.3'}"), DateWrapper.class); assertNotNull(w); // arbitrary TimeZone, but good enough to ensure year is right Calendar c = Calendar.getInstance(); c.setTime(w.value); assertEquals(1981, c.get(Calendar.YEAR)); assertEquals(Calendar.MARCH, c.get(Calendar.MONTH)); } } EnumFormatShapeTest.java000066400000000000000000000061421325620701100365370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/formatpackage com.fasterxml.jackson.databind.format; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat.Shape; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying serialization of simple basic non-structured * types; primitives (and/or their wrappers), Strings. */ public class EnumFormatShapeTest extends BaseMapTest { @JsonFormat(shape=JsonFormat.Shape.OBJECT) static enum PoNUM { A("a1"), B("b2"); @JsonProperty protected final String value; private PoNUM(String v) { value = v; } public String getValue() { return value; } } static enum OK { V1("v1"); protected String key; OK(String key) { this.key = key; } } static class PoNUMContainer { @JsonFormat(shape=Shape.NUMBER) public OK text = OK.V1; } @JsonFormat(shape=JsonFormat.Shape.ARRAY) // alias for 'number', as of 2.5 static enum PoAsArray { A, B; } // for [databind#572] static class PoOverrideAsString { @JsonFormat(shape=Shape.STRING) public PoNUM value = PoNUM.B; } static class PoOverrideAsNumber { @JsonFormat(shape=Shape.NUMBER) public PoNUM value = PoNUM.B; } // for [databind#1543] @JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) enum Color { RED, YELLOW, GREEN } static class ColorWrapper { public final Color color; ColorWrapper(Color color) { this.color = color; } } /* /********************************************************** /* Tests /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); // Tests for JsonFormat.shape public void testEnumAsObjectValid() throws Exception { assertEquals("{\"value\":\"a1\"}", MAPPER.writeValueAsString(PoNUM.A)); } public void testEnumAsIndexViaAnnotations() throws Exception { assertEquals("{\"text\":0}", MAPPER.writeValueAsString(new PoNUMContainer())); } // As of 2.5, use of Shape.ARRAY is legal alias for "write as number" public void testEnumAsObjectBroken() throws Exception { assertEquals("0", MAPPER.writeValueAsString(PoAsArray.A)); } // [databind#572] public void testOverrideEnumAsString() throws Exception { assertEquals("{\"value\":\"B\"}", MAPPER.writeValueAsString(new PoOverrideAsString())); } public void testOverrideEnumAsNumber() throws Exception { assertEquals("{\"value\":1}", MAPPER.writeValueAsString(new PoOverrideAsNumber())); } // for [databind#1543] public void testEnumValueAsNumber() throws Exception { assertEquals(String.valueOf(Color.GREEN.ordinal()), MAPPER.writeValueAsString(Color.GREEN)); } public void testEnumPropertyAsNumber() throws Exception { assertEquals(String.format(aposToQuotes("{'color':%s}"), Color.GREEN.ordinal()), MAPPER.writeValueAsString(new ColorWrapper(Color.GREEN))); } } MapEntryFormatTest.java000066400000000000000000000151741325620701100364160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/formatpackage com.fasterxml.jackson.databind.format; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; public class MapEntryFormatTest extends BaseMapTest { static class BeanWithMapEntry { // would work with any other shape than OBJECT, or without annotation: @JsonFormat(shape=JsonFormat.Shape.NATURAL) public Map.Entry entry; protected BeanWithMapEntry() { } public BeanWithMapEntry(String key, String value) { Map map = new HashMap<>(); map.put(key, value); entry = map.entrySet().iterator().next(); } } @JsonFormat(shape=JsonFormat.Shape.OBJECT) static class MapEntryAsObject implements Map.Entry { protected String key, value; protected MapEntryAsObject() { } public MapEntryAsObject(String k, String v) { key = k; value = v; } @Override public String getKey() { return key; } @Override public String getValue() { return value; } @Override public String setValue(String v) { value = v; return v; // wrong, whatever } } static class EntryWithNullWrapper { @JsonInclude(value=JsonInclude.Include.NON_EMPTY, content=JsonInclude.Include.NON_NULL) public Map.Entry entry; public EntryWithNullWrapper(String key, String value) { HashMap map = new HashMap<>(); map.put(key, value); entry = map.entrySet().iterator().next(); } } static class EntryWithDefaultWrapper { @JsonInclude(value=JsonInclude.Include.NON_EMPTY, content=JsonInclude.Include.NON_DEFAULT) public Map.Entry entry; public EntryWithDefaultWrapper(String key, String value) { HashMap map = new HashMap<>(); map.put(key, value); entry = map.entrySet().iterator().next(); } } static class EntryWithNonAbsentWrapper { @JsonInclude(value=JsonInclude.Include.NON_EMPTY, content=JsonInclude.Include.NON_ABSENT) public Map.Entry> entry; public EntryWithNonAbsentWrapper(String key, String value) { HashMap> map = new HashMap<>(); map.put(key, new AtomicReference(value)); entry = map.entrySet().iterator().next(); } } static class EmptyEntryWrapper { @JsonInclude(value=JsonInclude.Include.NON_EMPTY, content=JsonInclude.Include.NON_EMPTY) public Map.Entry entry; public EmptyEntryWrapper(String key, String value) { HashMap map = new HashMap<>(); map.put(key, value); entry = map.entrySet().iterator().next(); } } /* /********************************************************** /* Test methods, basic /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testInclusion() throws Exception { assertEquals(aposToQuotes("{'entry':{'a':'b'}}"), MAPPER.writeValueAsString(new EmptyEntryWrapper("a", "b"))); assertEquals(aposToQuotes("{'entry':{'a':'b'}}"), MAPPER.writeValueAsString(new EntryWithDefaultWrapper("a", "b"))); assertEquals(aposToQuotes("{'entry':{'a':'b'}}"), MAPPER.writeValueAsString(new EntryWithNullWrapper("a", "b"))); assertEquals(aposToQuotes("{}"), MAPPER.writeValueAsString(new EmptyEntryWrapper("a", ""))); assertEquals(aposToQuotes("{}"), MAPPER.writeValueAsString(new EntryWithDefaultWrapper("a", ""))); assertEquals(aposToQuotes("{'entry':{'a':''}}"), MAPPER.writeValueAsString(new EntryWithNullWrapper("a", ""))); assertEquals(aposToQuotes("{}"), MAPPER.writeValueAsString(new EntryWithNullWrapper("a", null))); } public void testInclusionWithReference() throws Exception { assertEquals(aposToQuotes("{'entry':{'a':'b'}}"), MAPPER.writeValueAsString(new EntryWithNonAbsentWrapper("a", "b"))); // empty String not excluded since reference is not absent, just points to empty // (so would need 3rd level inclusion definition) assertEquals(aposToQuotes("{'entry':{'a':''}}"), MAPPER.writeValueAsString(new EntryWithNonAbsentWrapper("a", ""))); assertEquals(aposToQuotes("{}"), MAPPER.writeValueAsString(new EntryWithNonAbsentWrapper("a", null))); } /* /********************************************************** /* Test methods, as-Object (Shape) /********************************************************** */ public void testAsNaturalRoundtrip() throws Exception { BeanWithMapEntry input = new BeanWithMapEntry("foo" ,"bar"); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'entry':{'foo':'bar'}}"), json); BeanWithMapEntry result = MAPPER.readValue(json, BeanWithMapEntry.class); assertEquals("foo", result.entry.getKey()); assertEquals("bar", result.entry.getValue()); } // should work via class annotation public void testAsObjectRoundtrip() throws Exception { MapEntryAsObject input = new MapEntryAsObject("foo" ,"bar"); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'key':'foo','value':'bar'}"), json); // 16-Oct-2016, tatu: Happens to work by default because it's NOT basic // `Map.Entry` but subtype. MapEntryAsObject result = MAPPER.readValue(json, MapEntryAsObject.class); assertEquals("foo", result.getKey()); assertEquals("bar", result.getValue()); } // [databind#1895] public void testDefaultShapeOverride() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(Map.Entry.class) .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.OBJECT)); Map.Entry input = new BeanWithMapEntry("foo", "bar").entry; assertEquals(aposToQuotes("{'key':'foo','value':'bar'}"), mapper.writeValueAsString(input)); } } MapFormatShapeTest.java000066400000000000000000000132701325620701100363500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/formatpackage com.fasterxml.jackson.databind.format; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; @SuppressWarnings("serial") public class MapFormatShapeTest extends BaseMapTest { @JsonPropertyOrder({ "extra" }) static class Map476Base extends LinkedHashMap { public int extra = 13; } @JsonFormat(shape=JsonFormat.Shape.OBJECT) static class Map476AsPOJO extends Map476Base { } @JsonPropertyOrder({ "a", "b", "c" }) @JsonInclude(JsonInclude.Include.NON_NULL) static class Bean476Container { public Map476AsPOJO a; public Map476Base b; @JsonFormat(shape=JsonFormat.Shape.OBJECT) public Map476Base c; public Bean476Container(int forA, int forB, int forC) { if (forA != 0) { a = new Map476AsPOJO(); a.put("value", forA); } if (forB != 0) { b = new Map476Base(); b.put("value", forB); } if (forC != 0) { c = new Map476Base(); c.put("value", forC); } } } static class Bean476Override { @JsonFormat(shape=JsonFormat.Shape.NATURAL) public Map476AsPOJO stuff; public Bean476Override(int value) { stuff = new Map476AsPOJO(); stuff.put("value", value); } } // from [databind#1540] @JsonFormat(shape = JsonFormat.Shape.OBJECT) @JsonPropertyOrder({ "property", "map" }) static class Map1540Implementation implements Map { public int property; public Map map = new HashMap<>(); public Map getMap() { return map; } public void setMap(Map map) { this.map = map; } @Override public Integer put(Integer key, Integer value) { return map.put(key, value); } @Override public int size() { return map.size(); } @JsonIgnore @Override public boolean isEmpty() { return map.isEmpty(); } @Override public boolean containsKey(Object key) { return map.containsKey(key); } @Override public boolean containsValue(Object value) { return map.containsValue(value); } @Override public Integer get(Object key) { return map.get(key); } @Override public Integer remove(Object key) { return map.remove(key); } @Override public void putAll(Map m) { map.putAll(m); } @Override public void clear() { map.clear(); } @Override public Set keySet() { return map.keySet(); } @Override public Collection values() { return map.values(); } @Override public Set> entrySet() { return map.entrySet(); } } /* /********************************************************** /* Test methods, serialization /********************************************************** */ final private ObjectMapper MAPPER = objectMapper(); // for [databind#476]: Maps as POJOs public void testSerializeAsPOJOViaClass() throws Exception { String result = MAPPER.writeValueAsString(new Bean476Container(1,2,0)); assertEquals(aposToQuotes("{'a':{'extra':13,'empty':false},'b':{'value':2}}"), result); } // Can't yet use per-property overrides at all, see [databind#1419] /* public void testSerializeAsPOJOViaProperty() throws Exception { String result = MAPPER.writeValueAsString(new Bean476Container(1,0,3)); assertEquals(aposToQuotes("{'a':{'extra':13,'empty':false},'c':{'empty':false,'value':3}}"), result); } public void testSerializeNaturalViaOverride() throws Exception { String result = MAPPER.writeValueAsString(new Bean476Override(123)); assertEquals(aposToQuotes("{'stuff':{'value':123}}"), result); } */ /* /********************************************************** /* Test methods, deserialization/roundtrip /********************************************************** */ // [databind#1540] public void testRoundTrip() throws Exception { Map1540Implementation input = new Map1540Implementation(); input.property = 55; input.put(12, 45); input.put(6, 88); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'property':55,'map':{'6':88,'12':45}}"), json); Map1540Implementation result = MAPPER.readValue(json, Map1540Implementation.class); assertEquals(result.property, input.property); assertEquals(input.getMap(), input.getMap()); } // [databind#1554] public void testDeserializeAsPOJOViaClass() throws Exception { Map476AsPOJO result = MAPPER.readValue(aposToQuotes("{'extra':42}"), Map476AsPOJO.class); assertEquals(0, result.size()); assertEquals(42, result.extra); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/interop/000077500000000000000000000000001325620701100322425ustar00rootroot00000000000000DeprecatedTypeHandling1102Test.java000066400000000000000000000065461325620701100405540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/interoppackage com.fasterxml.jackson.databind.interop; import java.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.MapType; import com.fasterxml.jackson.databind.type.SimpleType; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Set of tests to ensure that changes between 2.6 and 2.7 can * be handled somewhat gracefully. */ public class DeprecatedTypeHandling1102Test extends BaseMapTest { static class Point { public int x; int _y; public void setY(int y0) { _y = y0; } public int getY() { return _y; } } static class Point3D extends Point { public int z; } final ObjectMapper MAPPER = objectMapper(); @SuppressWarnings("deprecation") public void testSimplePOJOType() throws Exception { JavaType elem = SimpleType.construct(Point.class); Point p = MAPPER.readValue(aposToQuotes("{'x':1,'y':2}"), elem); assertNotNull(p); assertEquals(1, p.x); assertEquals(2, p.getY()); } @SuppressWarnings("deprecation") public void testPOJOSubType() throws Exception { JavaType elem = SimpleType.construct(Point3D.class); Point3D p = MAPPER.readValue(aposToQuotes("{'x':1,'z':3,'y':2}"), elem); assertNotNull(p); assertEquals(1, p.x); assertEquals(2, p.getY()); assertEquals(3, p.z); } @SuppressWarnings("deprecation") public void testExplicitCollectionType() throws Exception { JavaType elem = SimpleType.construct(Point.class); JavaType t = CollectionType.construct(List.class, elem); final String json = aposToQuotes("[ {'x':1,'y':2}, {'x':3,'y':6 }]"); List l = MAPPER.readValue(json, t); assertNotNull(l); assertEquals(2, l.size()); Object ob = l.get(0); assertEquals(Point.class, ob.getClass()); Point p = (Point) ob; assertEquals(1, p.x); assertEquals(2, p.getY()); } @SuppressWarnings("deprecation") public void testExplicitMapType() throws Exception { JavaType key = SimpleType.construct(String.class); JavaType elem = SimpleType.construct(Point.class); JavaType t = MapType.construct(Map.class, key, elem); final String json = aposToQuotes("{'x':{'x':3,'y':5}}"); Map m = MAPPER.readValue(json, t); assertNotNull(m); assertEquals(1, m.size()); Object ob = m.values().iterator().next(); assertEquals(Point.class, ob.getClass()); Point p = (Point) ob; assertEquals(3, p.x); assertEquals(5, p.getY()); } @SuppressWarnings("deprecation") public void testDeprecatedTypeResolution() throws Exception { TypeFactory tf = MAPPER.getTypeFactory(); // first, with real (if irrelevant) context JavaType t = tf.constructType(Point.class, getClass()); assertEquals(Point.class, t.getRawClass()); // and then missing context JavaType t2 = tf.constructType(Point.class, (Class) null); assertEquals(Point.class, t2.getRawClass()); JavaType ctxt = tf.constructType(getClass()); JavaType t3 = tf.constructType(Point.class, ctxt); assertEquals(Point.class, t3.getRawClass()); } } ExceptionSerializableTest1195.java000066400000000000000000000050111325620701100404700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/interoppackage com.fasterxml.jackson.databind.interop; import java.io.*; import java.util.List; import com.fasterxml.jackson.databind.*; public class ExceptionSerializableTest1195 extends BaseMapTest { static class ClassToRead { public int x; } static class ContainerClassToRead { public ClassToRead classToRead; } static class ContainerClassesToRead { public List classesToRead; } final ObjectMapper MAPPER = new ObjectMapper(); public void testExceptionSerializabilitySimple() throws Exception { try { MAPPER.readValue("{\"x\": \"B\"}", ClassToRead.class); fail("Should not have passed"); } catch (JsonMappingException e) { verifyException(e, "not a valid Integer"); _testSerializability(e); } try { MAPPER.readValue("{\"classToRead\": {\"x\": \"B\"}}", ContainerClassToRead.class); fail("Should not have passed"); } catch (JsonMappingException e) { verifyException(e, "not a valid Integer"); _testSerializability(e); } } public void testExceptionSerializabilityStructured() throws Exception { try { MAPPER.readValue("{\"classesToRead\": [{\"x\": 1}, {\"x\": \"B\"}]}", ContainerClassesToRead.class); fail("Should not have passed"); } catch (JsonMappingException e) { verifyException(e, "not a valid Integer"); _testSerializability(e); } } /* /********************************************************** /* Helper methods /********************************************************** */ private void _testSerializability(Exception e) throws IOException { ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000); ObjectOutputStream stream = new ObjectOutputStream(bytes); try { stream.writeObject(e); stream.close(); } catch (Exception e2) { fail("Failed to JDK serialize "+e.getClass().getName()+": "+e2); } // and then back... byte[] b = bytes.toByteArray(); ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(b)); Object result = null; try { result = objIn.readObject(); } catch (Exception e2) { fail("Failed to JDK deserialize "+e.getClass().getName()+": "+e2); } objIn.close(); assertNotNull(result); } } IllegalTypesCheckTest.java000066400000000000000000000122421325620701100372230ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/interoppackage com.fasterxml.jackson.databind.interop; import java.util.*; import org.springframework.jacksontest.BogusApplicationContext; import org.springframework.jacksontest.BogusPointcutAdvisor; import org.springframework.jacksontest.GrantedAuthority; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; import com.mchange.v2.c3p0.jacksontest.ComboPooledDataSource; /** * Test case(s) to guard against handling of types that are illegal to handle * due to security constraints. */ public class IllegalTypesCheckTest extends BaseMapTest { static class Bean1599 { public int id; public Object obj; } static class PolyWrapper { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY) public Object v; } static class Authentication1872 { public List authorities = new ArrayList(); } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); // // // Tests for [databind#1599] public void testXalanTypes1599() throws Exception { final String clsName = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"; final String JSON = aposToQuotes( "{'id': 124,\n" +" 'obj':[ '"+clsName+"',\n" +" {\n" +" 'transletBytecodes' : [ 'AAIAZQ==' ],\n" +" 'transletName' : 'a.b',\n" +" 'outputProperties' : { }\n" +" }\n" +" ]\n" +"}" ); ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(); try { mapper.readValue(JSON, Bean1599.class); fail("Should not pass"); } catch (JsonMappingException e) { _verifySecurityException(e, clsName); } } // // // Tests for [databind#1737] public void testJDKTypes1737() throws Exception { _testIllegalType(java.util.logging.FileHandler.class); _testIllegalType(java.rmi.server.UnicastRemoteObject.class); } // // // Tests for [databind#1855] public void testJDKTypes1855() throws Exception { // apparently included by JDK? _testIllegalType("com.sun.org.apache.bcel.internal.util.ClassLoader"); // also: we can try some form of testing, even if bit contrived... _testIllegalType(BogusPointcutAdvisor.class); _testIllegalType(BogusApplicationContext.class); } // 17-Aug-2017, tatu: Ideally would test handling of 3rd party types, too, // but would require adding dependencies. This may be practical when // checking done by separate module, but for now let's not do that for databind. /* public void testSpringTypes1737() throws Exception { _testIllegalType("org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor"); _testIllegalType("org.springframework.beans.factory.config.PropertyPathFactoryBean"); } */ // // // Tests for [databind#1872] public void testJDKTypes1872() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); String json = aposToQuotes(String.format("{'@class':'%s','authorities':['java.util.ArrayList',[]]}", Authentication1872.class.getName())); Authentication1872 result = mapper.readValue(json, Authentication1872.class); assertNotNull(result); } // [databind#1931] public void testC3P0Types() throws Exception { _testIllegalType(ComboPooledDataSource.class); // [databind#1931] } private void _testIllegalType(Class nasty) throws Exception { _testIllegalType(nasty.getName()); } private void _testIllegalType(String clsName) throws Exception { // While usually exploited via default typing let's not require // it here; mechanism still the same String json = aposToQuotes( "{'v':['"+clsName+"','/tmp/foobar.txt']}" ); try { MAPPER.readValue(json, PolyWrapper.class); fail("Should not pass"); } catch (JsonMappingException e) { _verifySecurityException(e, clsName); } } protected void _verifySecurityException(Throwable t, String clsName) throws Exception { _verifyException(t, InvalidDefinitionException.class, "Illegal type", "to deserialize", "prevented for security reasons"); verifyException(t, clsName); } protected void _verifyException(Throwable t, Class expExcType, String... patterns) throws Exception { Class actExc = t.getClass(); if (!expExcType.isAssignableFrom(actExc)) { fail("Expected Exception of type '"+expExcType.getName()+"', got '" +actExc.getName()+"', message: "+t.getMessage()); } for (String pattern : patterns) { verifyException(t, pattern); } } } TestExternalizable.java000066400000000000000000000156671325620701100366560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/interoppackage com.fasterxml.jackson.databind.interop; import java.io.*; import com.fasterxml.jackson.databind.*; /** * Simple test to ensure that we can make POJOs use Jackson * for JDK serialization, via {@link Externalizable} * * @since 2.1 */ public class TestExternalizable extends BaseMapTest { /* Not pretty, but needed to make ObjectMapper accessible from * static context (alternatively could use ThreadLocal). */ static class MapperHolder { private final ObjectMapper mapper = new ObjectMapper(); private final static MapperHolder instance = new MapperHolder(); public static ObjectMapper mapper() { return instance.mapper; } } /** * Helper class we need to adapt {@link ObjectOutput} as * {@link OutputStream} */ final static class ExternalizableInput extends InputStream { private final ObjectInput in; public ExternalizableInput(ObjectInput in) { this.in = in; } @Override public int available() throws IOException { return in.available(); } @Override public void close() throws IOException { in.close(); } @Override public boolean markSupported() { return false; } @Override public int read() throws IOException { return in.read(); } @Override public int read(byte[] buffer) throws IOException { return in.read(buffer); } @Override public int read(byte[] buffer, int offset, int len) throws IOException { return in.read(buffer, offset, len); } @Override public long skip(long n) throws IOException { return in.skip(n); } } /** * Helper class we need to adapt {@link ObjectOutput} as * {@link OutputStream} */ final static class ExternalizableOutput extends OutputStream { private final ObjectOutput out; public ExternalizableOutput(ObjectOutput out) { this.out = out; } @Override public void flush() throws IOException { out.flush(); } @Override public void close() throws IOException { out.close(); } @Override public void write(int ch) throws IOException { out.write(ch); } @Override public void write(byte[] data) throws IOException { out.write(data); } @Override public void write(byte[] data, int offset, int len) throws IOException { out.write(data, offset, len); } } // @com.fasterxml.jackson.annotation.JsonFormat(shape=com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY) @SuppressWarnings("resource") static class MyPojo implements Externalizable { public int id; public String name; public int[] values; public MyPojo() { } // for deserialization public MyPojo(int id, String name, int[] values) { this.id = id; this.name = name; this.values = values; } @Override public void readExternal(ObjectInput in) throws IOException { // MapperHolder.mapper().readValue( MapperHolder.mapper().readerForUpdating(this).readValue(new ExternalizableInput(in)); } @Override public void writeExternal(ObjectOutput oo) throws IOException { MapperHolder.mapper().writeValue(new ExternalizableOutput(oo), this); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; MyPojo other = (MyPojo) o; if (other.id != id) return false; if (!other.name.equals(name)) return false; if (other.values.length != values.length) return false; for (int i = 0, end = values.length; i < end; ++i) { if (values[i] != other.values[i]) return false; } return true; } } /* /********************************************************** /* Actual tests /********************************************************** */ // Comparison, using JDK native static class MyPojoNative implements Serializable { private static final long serialVersionUID = 1L; public int id; public String name; public int[] values; public MyPojoNative(int id, String name, int[] values) { this.id = id; this.name = name; this.values = values; } } @SuppressWarnings("unused") public void testSerializeAsExternalizable() throws Exception { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ObjectOutputStream obs = new ObjectOutputStream(bytes); final MyPojo input = new MyPojo(13, "Foobar", new int[] { 1, 2, 3 } ); obs.writeObject(input); obs.close(); byte[] ser = bytes.toByteArray(); // Ok: just verify it contains stuff it should byte[] json = MapperHolder.mapper().writeValueAsBytes(input); int ix = indexOf(ser, json); if (ix < 0) { fail("Serialization ("+ser.length+") does NOT contain JSON (of "+json.length+")"); } // Sanity check: if (false) { bytes = new ByteArrayOutputStream(); obs = new ObjectOutputStream(bytes); MyPojoNative p = new MyPojoNative(13, "Foobar", new int[] { 1, 2, 3 } ); obs.writeObject(p); obs.close(); System.out.println("Native size: "+bytes.size()+", vs JSON: "+ser.length); } // then read back! ObjectInputStream ins = new ObjectInputStream(new ByteArrayInputStream(ser)); MyPojo output = (MyPojo) ins.readObject(); ins.close(); assertNotNull(output); assertEquals(input, output); } /* /********************************************************** /* Helper methods /********************************************************** */ private int indexOf(byte[] full, byte[] fragment) { final byte first = fragment[0]; for (int i = 0, end = full.length-fragment.length; i < end; ++i) { if (full[i] != first) continue; if (matches(full, i, fragment)) { return i; } } return -1; } private boolean matches(byte[] full, int index, byte[] fragment) { for (int i = 1, end = fragment.length; i < end; ++i) { if (fragment[i] != full[index+i]) { return false; } } return true; } } TestFormatDetection.java000066400000000000000000000051161325620701100367600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/interoppackage com.fasterxml.jackson.databind.interop; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; public class TestFormatDetection extends BaseMapTest { private final ObjectReader READER = objectReader(); static class POJO { public int x, y; public POJO() { } public POJO(int x, int y) { this.x = x; this.y = y; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testSimpleWithJSON() throws Exception { ObjectReader detecting = READER.forType(POJO.class); detecting = detecting.withFormatDetection(detecting); POJO pojo = detecting.readValue(utf8Bytes("{\"x\":1}")); assertNotNull(pojo); assertEquals(1, pojo.x); } public void testSequenceWithJSON() throws Exception { ObjectReader detecting = READER.forType(POJO.class); detecting = detecting.withFormatDetection(detecting); MappingIterator it = detecting. readValues(utf8Bytes(aposToQuotes("{'x':1}\n{'x':2,'y':5}"))); assertTrue(it.hasNextValue()); POJO pojo = it.nextValue(); assertEquals(1, pojo.x); assertTrue(it.hasNextValue()); pojo = it.nextValue(); assertEquals(2, pojo.x); assertEquals(5, pojo.y); assertFalse(it.hasNextValue()); it.close(); // And again with nodes ObjectReader r2 = READER.forType(JsonNode.class); r2 = r2.withFormatDetection(r2); MappingIterator nodes = r2. readValues(utf8Bytes(aposToQuotes("{'x':1}\n{'x':2,'y':5}"))); assertTrue(nodes.hasNextValue()); JsonNode n = nodes.nextValue(); assertEquals(1, n.size()); assertTrue(nodes.hasNextValue()); n = nodes.nextValue(); assertEquals(2, n.size()); assertEquals(2, n.path("x").asInt()); assertEquals(5, n.path("y").asInt()); assertFalse(nodes.hasNextValue()); nodes.close(); } public void testInvalid() throws Exception { ObjectReader detecting = READER.forType(POJO.class); detecting = detecting.withFormatDetection(detecting); try { detecting.readValue(utf8Bytes("1")); fail("Should have failed"); } catch (JsonProcessingException e) { verifyException(e, "Cannot detect format from input"); } } } TestJDKProxy.java000066400000000000000000000041731325620701100353450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/interoppackage com.fasterxml.jackson.databind.interop; import java.lang.reflect.*; import com.fasterxml.jackson.databind.*; // mostly for [Issue#57] public class TestJDKProxy extends BaseMapTest { final ObjectMapper MAPPER = new ObjectMapper(); public interface IPlanet { String getName(); String setName(String s); } // bit silly example; usually wouldn't implement interface (no need to proxy if it did) static class Planet implements IPlanet { private String name; public Planet() { } public Planet(String s) { name = s; } @Override public String getName(){return name;} @Override public String setName(String iName) {name = iName; return name; } } /* /******************************************************** /* Test methods /******************************************************** */ public void testSimple() throws Exception { IPlanet input = getProxy(IPlanet.class, new Planet("Foo")); String json = MAPPER.writeValueAsString(input); assertEquals("{\"name\":\"Foo\"}", json); // and just for good measure Planet output = MAPPER.readValue(json, Planet.class); assertEquals("Foo", output.getName()); } /* /******************************************************** /* Helper methods /******************************************************** */ public static T getProxy(Class type, Object obj) { class ProxyUtil implements InvocationHandler { Object _obj; public ProxyUtil(Object o) { _obj = o; } @Override public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { Object result = null; result = m.invoke(_obj, args); return result; } } @SuppressWarnings("unchecked") T proxy = (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, new ProxyUtil(obj)); return proxy; } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspect/000077500000000000000000000000001325620701100327545ustar00rootroot00000000000000AutoDetect1947Test.java000066400000000000000000000027571325620701100370010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; // Test(s) for [databind#1947], regression for 2.9 public class AutoDetect1947Test extends BaseMapTest { static class Entity1947 { public int shouldBeDetected; public String shouldNotBeDetected; @JsonProperty public int getShouldBeDetected() { return shouldBeDetected; } public void setShouldBeDetected(int shouldBeDetected) { this.shouldBeDetected = shouldBeDetected; } public String getShouldNotBeDetected() { return shouldNotBeDetected; } public void setShouldNotBeDetected(String shouldNotBeDetected) { this.shouldNotBeDetected = shouldNotBeDetected; } } public void testDisablingAll() throws Exception { ObjectMapper mapper = new ObjectMapper() .disable(MapperFeature.AUTO_DETECT_SETTERS) .disable(MapperFeature.AUTO_DETECT_FIELDS) .disable(MapperFeature.AUTO_DETECT_GETTERS) .disable(MapperFeature.AUTO_DETECT_CREATORS) .disable(MapperFeature.AUTO_DETECT_IS_GETTERS); String json = mapper.writeValueAsString(new Entity1947()); JsonNode n = mapper.readTree(json); assertEquals(1, n.size()); assertTrue(n.has("shouldBeDetected")); assertFalse(n.has("shouldNotBeDetected")); } } BeanDescriptionTest.java000066400000000000000000000012731325620701100374540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.JsonClassDescription; import com.fasterxml.jackson.databind.*; public class BeanDescriptionTest extends BaseMapTest { private final ObjectMapper MAPPER = objectMapper(); private final static String CLASS_DESC = "Description, yay!"; @JsonClassDescription(CLASS_DESC) static class DocumentedBean { public int x; } public void testClassDesc() throws Exception { BeanDescription beanDesc = MAPPER.getDeserializationConfig().introspect(MAPPER.constructType(DocumentedBean.class)); assertEquals(CLASS_DESC, beanDesc.findClassDescription()); } } BeanNamingTest.java000066400000000000000000000021141325620701100363750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.databind.*; // Tests for [databind#653] public class BeanNamingTest extends BaseMapTest { static class URLBean { public String getURL() { return "http://foo"; } } static class ABean { public int getA() { return 3; } } public void testSimple() throws Exception { ObjectMapper mapper = new ObjectMapper(); assertFalse(mapper.isEnabled(MapperFeature.USE_STD_BEAN_NAMING)); assertEquals(aposToQuotes("{'url':'http://foo'}"), mapper.writeValueAsString(new URLBean())); assertEquals(aposToQuotes("{'a':3}"), mapper.writeValueAsString(new ABean())); mapper = new ObjectMapper(); mapper.enable(MapperFeature.USE_STD_BEAN_NAMING); assertEquals(aposToQuotes("{'URL':'http://foo'}"), mapper.writeValueAsString(new URLBean())); assertEquals(aposToQuotes("{'a':3}"), mapper.writeValueAsString(new ABean())); } } CustomAnnotationIntrospector1756Test.java000066400000000000000000000066351325620701100426560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.io.IOException; import java.lang.annotation.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.module.SimpleModule; @SuppressWarnings("serial") public class CustomAnnotationIntrospector1756Test extends BaseMapTest { @Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface Field1756 { String value() default ""; } public interface Foobar { @JsonIgnore // Comment out this annotation or ... String foo(); @JsonDeserialize(using = CustomStringDeserializer.class) // ... this annotation to unbreak deserialization. String bar(); } /** * Custom String deserializer. */ private static class CustomStringDeserializer extends JsonDeserializer { @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return p.getText(); } } /** * A concrete implementation. */ public static class FoobarImpl implements Foobar { private final String foo; private final String bar; public FoobarImpl(@Field1756("foo") String foo, @Field1756("bar") String bar) { this.foo = foo; this.bar = bar; } @Override public String foo() { return foo; } @Override public String bar() { return bar; } } /** * Instructs jackson that {@link Foobar#foo()}, {@link Foobar#bar()} and the {@code foo} and {@code bar} constructor * arguments map to the {@code foo} and {@code bar} properties. */ public static class FoobarAnnotationIntrospector extends NopAnnotationIntrospector { @Override public String findImplicitPropertyName(final AnnotatedMember member) { // Constructor parameter if (member instanceof AnnotatedParameter) { final Field1756 field = member.getAnnotation(Field1756.class); if (field == null) { return null; } return field.value(); } // Getter if (member instanceof AnnotatedMethod) { return member.getName(); } return null; } @SuppressWarnings("deprecation") @Override public boolean hasCreatorAnnotation(Annotated a) { final AnnotatedConstructor ctor = (AnnotatedConstructor) a; return (ctor.getParameterCount() > 0) && (ctor.getParameter(0).getAnnotation(Field1756.class) != null); } } public static class Issue1756Module extends SimpleModule { @Override public void setupModule(final SetupContext context) { super.setupModule(context); context.appendAnnotationIntrospector(new FoobarAnnotationIntrospector()); } } public void testIssue1756() throws Exception { Issue1756Module m = new Issue1756Module(); m.addAbstractTypeMapping(Foobar.class, FoobarImpl.class); final ObjectMapper mapper = new ObjectMapper() .registerModule(m); final Foobar foobar = mapper.readValue(aposToQuotes("{'bar':'bar', 'foo':'foo'}"), Foobar.class); assertNotNull(foobar); } } IgnoredCreatorProperty1572Test.java000066400000000000000000000042201325620701100413710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class IgnoredCreatorProperty1572Test extends BaseMapTest { static class InnerTest { public String str; public String otherStr; } static class OuterTest { InnerTest innerTest; @JsonIgnore String otherOtherStr; @JsonCreator public OuterTest(/*@JsonProperty("innerTest")*/ InnerTest inner, /*@JsonProperty("otherOtherStr")*/ String otherStr) { this.innerTest = inner; } } static class ImplicitNames extends JacksonAnnotationIntrospector { private static final long serialVersionUID = 1L; @Override public String findImplicitPropertyName(AnnotatedMember member) { if (member instanceof AnnotatedParameter) { // A placeholder for legitimate property name detection // such as what the JDK8 module provides AnnotatedParameter param = (AnnotatedParameter) member; switch (param.getIndex()) { case 0: return "innerTest"; case 1: return "otherOtherStr"; default: } } return null; } } /* /******************************************************** /* Test methods /******************************************************** */ // [databind#1572] public void testIgnoredCtorParam() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new ImplicitNames()); String JSON = aposToQuotes("{'innerTest': {\n" +"'str':'str',\n" +"'otherStr': 'otherStr'\n" +"}}\n"); OuterTest result = mapper.readValue(JSON, OuterTest.class); assertNotNull(result); assertNotNull(result.innerTest); assertEquals("otherStr", result.innerTest.otherStr); } } IntrospectorPairTest.java000066400000000000000000000474161325620701100377230ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Annotation; import java.util.*; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.deser.std.StringDeserializer; import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.ser.std.StringSerializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; // started with [databind#1025] in mind @SuppressWarnings("serial") public class IntrospectorPairTest extends BaseMapTest { static class Introspector1 extends AnnotationIntrospector { @Override public Version version() { return Version.unknownVersion(); } @Override public JsonInclude.Value findPropertyInclusion(Annotated a) { return JsonInclude.Value.empty() .withContentInclusion(JsonInclude.Include.ALWAYS) .withValueInclusion(JsonInclude.Include.NON_ABSENT); } } static class Introspector2 extends AnnotationIntrospector { @Override public Version version() { return Version.unknownVersion(); } @Override public JsonInclude.Value findPropertyInclusion(Annotated a) { return JsonInclude.Value.empty() .withContentInclusion(JsonInclude.Include.NON_EMPTY) .withValueInclusion(JsonInclude.Include.USE_DEFAULTS); } } static class IntrospectorWithHandlers extends AnnotationIntrospector { final Object _deserializer; final Object _serializer; public IntrospectorWithHandlers(Object deser, Object ser) { _deserializer = deser; _serializer = ser; } @Override public Version version() { return Version.unknownVersion(); } @Override public Object findDeserializer(Annotated am) { return _deserializer; } @Override public Object findSerializer(Annotated am) { return _serializer; } } static class IntrospectorWithMap extends AnnotationIntrospector { private final Map values = new HashMap<>(); private Version version = Version.unknownVersion(); public IntrospectorWithMap add(String key, Object value) { values.put(key, value); return this; } public IntrospectorWithMap version(Version v) { version = v; return this; } @Override public Version version() { return version; } @Override public JsonInclude.Value findPropertyInclusion(Annotated a) { return JsonInclude.Value.empty() .withContentInclusion(JsonInclude.Include.NON_EMPTY) .withValueInclusion(JsonInclude.Include.USE_DEFAULTS); } @Override public boolean isAnnotationBundle(Annotation ann) { return _boolean("isAnnotationBundle"); } /* /****************************************************** /* General class annotations /****************************************************** */ @Override public PropertyName findRootName(AnnotatedClass ac) { return (PropertyName) values.get("findRootName"); } @Override public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated a) { return (JsonIgnoreProperties.Value) values.get("findPropertyIgnorals"); } @Override public Boolean isIgnorableType(AnnotatedClass ac) { return (Boolean) values.get("isIgnorableType"); } @Override public Object findFilterId(Annotated ann) { return (Object) values.get("findFilterId"); } @Override public Object findNamingStrategy(AnnotatedClass ac) { return (Object) values.get("findNamingStrategy"); } @Override public String findClassDescription(AnnotatedClass ac) { return (String) values.get("findClassDescription"); } /* /****************************************************** /* Property auto-detection /****************************************************** */ @Override public VisibilityChecker findAutoDetectVisibility(AnnotatedClass ac, VisibilityChecker checker) { VisibilityChecker vc = (VisibilityChecker) values.get("findAutoDetectVisibility"); // not really good but: return (vc == null) ? checker : vc; } /* /****************************************************** /* Type handling /****************************************************** */ @Override public TypeResolverBuilder findTypeResolver(MapperConfig config, AnnotatedClass ac, JavaType baseType) { return (TypeResolverBuilder) values.get("findTypeResolver"); } @Override public TypeResolverBuilder findPropertyTypeResolver(MapperConfig config, AnnotatedMember am, JavaType baseType) { return (TypeResolverBuilder) values.get("findPropertyTypeResolver"); } @Override public TypeResolverBuilder findPropertyContentTypeResolver(MapperConfig config, AnnotatedMember am, JavaType baseType) { return (TypeResolverBuilder) values.get("findPropertyContentTypeResolver"); } @SuppressWarnings("unchecked") @Override public List findSubtypes(Annotated a) { return (List) values.get("findSubtypes"); } @Override public String findTypeName(AnnotatedClass ac) { return (String) values.get("findTypeName"); } /* /****************************************************** /* Deserialization introspection /****************************************************** */ @Override public Boolean hasAnySetter(Annotated a) { return (Boolean) values.get("hasAnySetter"); } /* /****************************************************** /* Helper methods /****************************************************** */ private boolean _boolean(String key) { Object ob = values.get(key); return Boolean.TRUE.equals(ob); } } /* /********************************************************** /* Test methods, misc /********************************************************** */ private final AnnotationIntrospector NO_ANNOTATIONS = AnnotationIntrospector.nopInstance(); public void testVersion() throws Exception { Version v = new Version(1, 2, 3, null, "com.fasterxml", "IntrospectorPairTest"); IntrospectorWithMap withVersion = new IntrospectorWithMap() .version(v); assertEquals(v, new AnnotationIntrospectorPair(withVersion, NO_ANNOTATIONS).version()); IntrospectorWithMap noVersion = new IntrospectorWithMap(); assertEquals(Version.unknownVersion(), new AnnotationIntrospectorPair(noVersion, withVersion).version()); } public void testAccess() throws Exception { IntrospectorWithMap intr1 = new IntrospectorWithMap(); AnnotationIntrospectorPair pair = new AnnotationIntrospectorPair(intr1, NO_ANNOTATIONS); Collection intrs = pair.allIntrospectors(); assertEquals(2, intrs.size()); Iterator it = intrs.iterator(); assertSame(intr1, it.next()); assertSame(NO_ANNOTATIONS, it.next()); } public void testAnnotationBundle() throws Exception { IntrospectorWithMap isBundle = new IntrospectorWithMap() .add("isAnnotationBundle", true); assertTrue(new AnnotationIntrospectorPair(NO_ANNOTATIONS, isBundle) .isAnnotationBundle(null)); assertTrue(new AnnotationIntrospectorPair(isBundle, NO_ANNOTATIONS) .isAnnotationBundle(null)); assertFalse(new AnnotationIntrospectorPair(NO_ANNOTATIONS, NO_ANNOTATIONS) .isAnnotationBundle(null)); } /* /********************************************************** /* Test methods, general class annotations /********************************************************** */ public void testFindRootName() throws Exception { PropertyName name = new PropertyName("test"); IntrospectorWithMap intr = new IntrospectorWithMap() .add("findRootName", name); assertNull(new AnnotationIntrospectorPair(NO_ANNOTATIONS, NO_ANNOTATIONS).findRootName(null)); assertEquals(name, new AnnotationIntrospectorPair(NO_ANNOTATIONS, intr).findRootName(null)); assertEquals(name, new AnnotationIntrospectorPair(intr, NO_ANNOTATIONS).findRootName(null)); } public void testPropertyIgnorals() throws Exception { JsonIgnoreProperties.Value incl = JsonIgnoreProperties.Value.forIgnoredProperties("foo"); IntrospectorWithMap intr = new IntrospectorWithMap() .add("findPropertyIgnorals", incl); IntrospectorWithMap intrEmpty = new IntrospectorWithMap() .add("findPropertyIgnorals", JsonIgnoreProperties.Value.empty()); assertEquals(JsonIgnoreProperties.Value.empty(), new AnnotationIntrospectorPair(intrEmpty, intrEmpty).findPropertyIgnorals(null)); // should actually verify inclusion combining, but there are separate tests for that assertEquals(incl, new AnnotationIntrospectorPair(intrEmpty, intr).findPropertyIgnorals(null)); assertEquals(incl, new AnnotationIntrospectorPair(intr, intrEmpty).findPropertyIgnorals(null)); } public void testIsIgnorableType() throws Exception { IntrospectorWithMap intr1 = new IntrospectorWithMap() .add("isIgnorableType", Boolean.TRUE); IntrospectorWithMap intr2 = new IntrospectorWithMap() .add("isIgnorableType", Boolean.FALSE); assertNull(new AnnotationIntrospectorPair(NO_ANNOTATIONS, NO_ANNOTATIONS).isIgnorableType(null)); assertEquals(Boolean.TRUE, new AnnotationIntrospectorPair(intr1, intr2).isIgnorableType(null)); assertEquals(Boolean.FALSE, new AnnotationIntrospectorPair(intr2, intr1).isIgnorableType(null)); } public void testFindFilterId() throws Exception { IntrospectorWithMap intr1 = new IntrospectorWithMap() .add("findFilterId", "a"); IntrospectorWithMap intr2 = new IntrospectorWithMap() .add("findFilterId", "b"); assertNull(new AnnotationIntrospectorPair(NO_ANNOTATIONS, NO_ANNOTATIONS).findFilterId(null)); assertEquals("a", new AnnotationIntrospectorPair(intr1, intr2).findFilterId(null)); assertEquals("b", new AnnotationIntrospectorPair(intr2, intr1).findFilterId(null)); } public void testFindNamingStrategy() throws Exception { // shouldn't be bogus Classes for real use, but works here IntrospectorWithMap intr1 = new IntrospectorWithMap() .add("findNamingStrategy", Integer.class); IntrospectorWithMap intr2 = new IntrospectorWithMap() .add("findNamingStrategy", String.class); assertNull(new AnnotationIntrospectorPair(NO_ANNOTATIONS, NO_ANNOTATIONS).findNamingStrategy(null)); assertEquals(Integer.class, new AnnotationIntrospectorPair(intr1, intr2).findNamingStrategy(null)); assertEquals(String.class, new AnnotationIntrospectorPair(intr2, intr1).findNamingStrategy(null)); } public void testFindClassDescription() throws Exception { IntrospectorWithMap intr1 = new IntrospectorWithMap() .add("findClassDescription", "Desc1"); IntrospectorWithMap intr2 = new IntrospectorWithMap() .add("findClassDescription", "Desc2"); assertNull(new AnnotationIntrospectorPair(NO_ANNOTATIONS, NO_ANNOTATIONS).findClassDescription(null)); assertEquals("Desc1", new AnnotationIntrospectorPair(intr1, intr2).findClassDescription(null)); assertEquals("Desc2", new AnnotationIntrospectorPair(intr2, intr1).findClassDescription(null)); } // // // 3 deprecated methods, skip /* /********************************************************** /* Test methods, ser/deser /********************************************************** */ public void testFindSerializer() throws Exception { final JsonSerializer serString = new StringSerializer(); final JsonSerializer serToString = ToStringSerializer.instance; AnnotationIntrospector intr1 = new IntrospectorWithHandlers(null, serString); AnnotationIntrospector intr2 = new IntrospectorWithHandlers(null, serToString); AnnotationIntrospector nop = AnnotationIntrospector.nopInstance(); AnnotationIntrospector nop2 = new IntrospectorWithHandlers(null, JsonSerializer.None.class); assertSame(serString, new AnnotationIntrospectorPair(intr1, intr2).findSerializer(null)); assertSame(serToString, new AnnotationIntrospectorPair(intr2, intr1).findSerializer(null)); // also: no-op instance should not block real one, regardless assertSame(serString, new AnnotationIntrospectorPair(nop, intr1).findSerializer(null)); assertSame(serString, new AnnotationIntrospectorPair(nop2, intr1).findSerializer(null)); // nor should no-op result in non-null result assertNull(new AnnotationIntrospectorPair(nop, nop2).findSerializer(null)); assertNull(new AnnotationIntrospectorPair(nop2, nop).findSerializer(null)); } public void testFindDeserializer() throws Exception { final JsonDeserializer deserString = StringDeserializer.instance; final JsonDeserializer deserObject = UntypedObjectDeserializer.Vanilla.std; AnnotationIntrospector intr1 = new IntrospectorWithHandlers(deserString, null); AnnotationIntrospector intr2 = new IntrospectorWithHandlers(deserObject, null); AnnotationIntrospector nop = AnnotationIntrospector.nopInstance(); AnnotationIntrospector nop2 = new IntrospectorWithHandlers(JsonDeserializer.None.class, null); assertSame(deserString, new AnnotationIntrospectorPair(intr1, intr2).findDeserializer(null)); assertSame(deserObject, new AnnotationIntrospectorPair(intr2, intr1).findDeserializer(null)); // also: no-op instance should not block real one, regardless assertSame(deserString, new AnnotationIntrospectorPair(nop, intr1).findDeserializer(null)); assertSame(deserString, new AnnotationIntrospectorPair(nop2, intr1).findDeserializer(null)); // nor should no-op result in non-null result assertNull(new AnnotationIntrospectorPair(nop, nop2).findDeserializer(null)); assertNull(new AnnotationIntrospectorPair(nop2, nop).findDeserializer(null)); } /* /****************************************************** /* Property auto-detection /****************************************************** */ public void testFindAutoDetectVisibility() throws Exception { VisibilityChecker vc = VisibilityChecker.Std.defaultInstance(); IntrospectorWithMap intr1 = new IntrospectorWithMap() .add("findAutoDetectVisibility", vc); assertNull(new AnnotationIntrospectorPair(NO_ANNOTATIONS, NO_ANNOTATIONS) .findAutoDetectVisibility(null, null)); assertSame(vc, new AnnotationIntrospectorPair(intr1, NO_ANNOTATIONS) .findAutoDetectVisibility(null, null)); assertSame(vc, new AnnotationIntrospectorPair(NO_ANNOTATIONS, intr1) .findAutoDetectVisibility(null, null)); } /* /****************************************************** /* Type handling /****************************************************** */ public void testFindTypeResolver() throws Exception { /* TypeResolverBuilder findTypeResolver(MapperConfig config, AnnotatedClass ac, JavaType baseType) return (TypeResolverBuilder) values.get("findTypeResolver"); */ } public void testFindPropertyTypeResolver() { } public void testFindPropertyContentTypeResolver() { } public void testFindSubtypes() { } public void testFindTypeName() { IntrospectorWithMap intr1 = new IntrospectorWithMap() .add("findTypeName", "type1"); IntrospectorWithMap intr2 = new IntrospectorWithMap() .add("findTypeName", "type2"); assertNull(new AnnotationIntrospectorPair(NO_ANNOTATIONS, NO_ANNOTATIONS).findTypeName(null)); assertEquals("type1", new AnnotationIntrospectorPair(intr1, intr2).findTypeName(null)); assertEquals("type2", new AnnotationIntrospectorPair(intr2, intr1).findTypeName(null)); } /* /****************************************************** /* Deserialization introspection /****************************************************** */ // for [databind#1672] public void testHasAnySetter() { IntrospectorWithMap intr1 = new IntrospectorWithMap() .add("hasAnySetter", Boolean.TRUE); IntrospectorWithMap intr2 = new IntrospectorWithMap() .add("hasAnySetter", Boolean.FALSE); assertNull(new AnnotationIntrospectorPair(NO_ANNOTATIONS, NO_ANNOTATIONS).hasAnySetter(null)); assertEquals(Boolean.TRUE, new AnnotationIntrospectorPair(intr1, intr2).hasAnySetter(null)); assertEquals(Boolean.TRUE, new AnnotationIntrospectorPair(NO_ANNOTATIONS, intr1).hasAnySetter(null)); assertEquals(Boolean.FALSE, new AnnotationIntrospectorPair(intr2, intr1).hasAnySetter(null)); assertEquals(Boolean.FALSE, new AnnotationIntrospectorPair(NO_ANNOTATIONS, intr2).hasAnySetter(null)); } /* /********************************************************** /* Test methods, others /********************************************************** */ private final AnnotationIntrospectorPair introPair12 = new AnnotationIntrospectorPair(new Introspector1(), new Introspector2()); private final AnnotationIntrospectorPair introPair21 = new AnnotationIntrospectorPair(new Introspector2(), new Introspector1()); // for [databind#1025] public void testInclusionMerging() throws Exception { // argument is ignored by test introspectors, may be null JsonInclude.Value v12 = introPair12.findPropertyInclusion(null); JsonInclude.Value v21 = introPair21.findPropertyInclusion(null); assertEquals(JsonInclude.Include.ALWAYS, v12.getContentInclusion()); assertEquals(JsonInclude.Include.NON_ABSENT, v12.getValueInclusion()); assertEquals(JsonInclude.Include.NON_EMPTY, v21.getContentInclusion()); assertEquals(JsonInclude.Include.NON_ABSENT, v21.getValueInclusion()); } } NoClassDefFoundWorkaroundTest.java000066400000000000000000000026401325620701100414330ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import javax.measure.Measure; import java.util.List; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; // Tests for [databind#636] public class NoClassDefFoundWorkaroundTest extends BaseMapTest { public static class Parent { public List child; } public static class Child { public Measure measure; } public void testClassIsMissing() { try { Class.forName("javax.measure.Measure"); fail("Should not have found javax.measure.Measure"); } catch (ClassNotFoundException ex) { ; // expected case } } public void testDeserialize() throws Exception { ObjectMapper m = new ObjectMapper(); Parent result = null; try { result = m.readValue(" { } ", Parent.class); } catch (Exception e) { fail("Should not have had issues, got: "+e); } assertNotNull(result); } public void testUseMissingClass() throws Exception { boolean missing = false; try { ObjectMapper m = new ObjectMapper(); m.readValue(" { \"child\" : [{}] } ", Parent.class); } catch (NoClassDefFoundError ex) { missing = true; } assertTrue("cannot instantiate a missing class", missing); } } POJOPropertiesCollectorTest.java000066400000000000000000000447551325620701100411120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.math.BigDecimal; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class POJOPropertiesCollectorTest extends BaseMapTest { static class Simple { public int value; @JsonProperty("value") public void valueSetter(int v) { value = v; } @JsonProperty("value") public int getFoobar() { return value; } } static class SimpleFieldDeser { @JsonDeserialize String[] values; } static class SimpleGetterVisibility { public int getA() { return 0; } protected int getB() { return 1; } @SuppressWarnings("unused") private int getC() { return 2; } } // Class for testing 'shared ignore' static class Empty { public int value; public void setValue(int v) { value = v; } @JsonIgnore public int getValue() { return value; } } static class IgnoredSetter { @JsonProperty public int value; @JsonIgnore public void setValue(int v) { value = v; } public int getValue() { return value; } } static class ImplicitIgnores { @JsonIgnore public int a; @JsonIgnore public void setB(int b) { } public int c; } // Should find just one setter for "y", due to partial ignore static class IgnoredRenamedSetter { @JsonIgnore public void setY(int value) { } @JsonProperty("y") void foobar(int value) { } } // should produce a single property, "x" static class RenamedProperties { @JsonProperty("x") public int value; public void setValue(int v) { value = v; } public int getX() { return value; } } static class RenamedProperties2 { @JsonProperty("renamed") public int getValue() { return 1; } public void setValue(int x) { } } // Testing that we can "merge" properties with renaming static class MergedProperties { public int x; @JsonProperty("x") public void setFoobar(int v) { x = v; } } // Testing that property order is obeyed, even for deserialization purposes @JsonPropertyOrder({"a", "b", "c", "d"}) static class SortedProperties { public int b; public int c; public void setD(int value) { } public void setA(int value) { } } // [JACKSON-700]: test property type detection, selection static class TypeTestBean { protected Long value; @JsonCreator public TypeTestBean(@JsonProperty("value") String value) { } // If you remove this method, the test will pass public Integer getValue() { return 0; } } static class Jackson703 { private List location = new ArrayList(); { location.add(new FoodOrgLocation()); } public List getLocation() { return location; } } static class FoodOrgLocation { protected Long id; public String name; protected Location location; public FoodOrgLocation() { location = new Location(); } public FoodOrgLocation(final Location foodOrg) { } public FoodOrgLocation(final Long id, final String name, final Location location) { } public Location getLocation() { return location; } } static class Location { public BigDecimal lattitude; public BigDecimal longitude; public Location() { } public Location(final BigDecimal lattitude, final BigDecimal longitude) { } } class Issue701Bean { // important: non-static! private int i; // annotation does not matter -- just need one on the last argument public Issue701Bean(@JsonProperty int i) { this.i = i; } public int getX() { return i; } } static class Issue744Bean { protected Map additionalProperties; @JsonAnySetter public void addAdditionalProperty(String key, Object value) { if (additionalProperties == null) additionalProperties = new HashMap(); additionalProperties.put(key,value); } public void setAdditionalProperties(Map additionalProperties) { this.additionalProperties = additionalProperties; } @JsonAnyGetter public Map getAdditionalProperties() { return additionalProperties; } @JsonIgnore public String getName() { return (String) additionalProperties.get("name"); } } static class PropDescBean { public final static String A_DESC = "That's A!"; public final static int B_INDEX = 3; @JsonPropertyDescription(A_DESC) public String a; protected int b; public String getA() { return a; } public void setA(String a) { this.a = a; } @JsonProperty(required=true, index=B_INDEX, defaultValue="13") public int getB() { return b; } } @Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation @interface A {} @Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation @interface B {} static class DuplicateGetterBean { @A public boolean isBloop() { return true; } @B public boolean getBloop() { return true; } } static class DuplicateGetterCreatorBean { public DuplicateGetterCreatorBean(@JsonProperty("bloop") @A boolean bloop) {} public boolean isBloop() { return true; } public boolean getBloop() { return true; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testSimple() { POJOPropertiesCollector coll = collector(MAPPER, Simple.class, true); Map props = coll.getPropertyMap(); assertEquals(1, props.size()); POJOPropertyBuilder prop = props.get("value"); assertNotNull(prop); assertTrue(prop.hasSetter()); assertTrue(prop.hasGetter()); assertTrue(prop.hasField()); } public void testSimpleFieldVisibility() { // false -> deserialization POJOPropertiesCollector coll = collector(MAPPER, SimpleFieldDeser.class, false); Map props = coll.getPropertyMap(); assertEquals(1, props.size()); POJOPropertyBuilder prop = props.get("values"); assertNotNull(prop); assertFalse(prop.hasSetter()); assertFalse(prop.hasGetter()); assertTrue(prop.hasField()); } public void testSimpleGetterVisibility() { POJOPropertiesCollector coll = collector(MAPPER, SimpleGetterVisibility.class, true); Map props = coll.getPropertyMap(); assertEquals(1, props.size()); POJOPropertyBuilder prop = props.get("a"); assertNotNull(prop); assertFalse(prop.hasSetter()); assertTrue(prop.hasGetter()); assertFalse(prop.hasField()); } // Unit test for verifying that a single @JsonIgnore can remove the // whole property, unless explicit property marker exists public void testEmpty() { POJOPropertiesCollector coll = collector(MAPPER, Empty.class, true); Map props = coll.getPropertyMap(); assertEquals(0, props.size()); } // Unit test for verifying handling of 'partial' @JsonIgnore; that is, // if there is at least one explicit annotation to indicate property, // only parts that are ignored are, well, ignored public void testPartialIgnore() { POJOPropertiesCollector coll = collector(MAPPER, IgnoredSetter.class, true); Map props = coll.getPropertyMap(); assertEquals(1, props.size()); POJOPropertyBuilder prop = props.get("value"); assertNotNull(prop); assertFalse(prop.hasSetter()); assertTrue(prop.hasGetter()); assertTrue(prop.hasField()); } public void testSimpleRenamed() { POJOPropertiesCollector coll = collector(MAPPER, RenamedProperties.class, true); Map props = coll.getPropertyMap(); assertEquals(1, props.size()); POJOPropertyBuilder prop = props.get("x"); assertNotNull(prop); assertTrue(prop.hasSetter()); assertTrue(prop.hasGetter()); assertTrue(prop.hasField()); } public void testSimpleRenamed2() { POJOPropertiesCollector coll = collector(MAPPER, RenamedProperties2.class, true); Map props = coll.getPropertyMap(); assertEquals(1, props.size()); POJOPropertyBuilder prop = props.get("renamed"); assertNotNull(prop); assertTrue(prop.hasSetter()); assertTrue(prop.hasGetter()); assertFalse(prop.hasField()); } public void testMergeWithRename() { POJOPropertiesCollector coll = collector(MAPPER, MergedProperties.class, true); Map props = coll.getPropertyMap(); assertEquals(1, props.size()); POJOPropertyBuilder prop = props.get("x"); assertNotNull(prop); assertTrue(prop.hasSetter()); assertFalse(prop.hasGetter()); assertTrue(prop.hasField()); } public void testSimpleIgnoreAndRename() { POJOPropertiesCollector coll = collector(MAPPER, IgnoredRenamedSetter.class, true); Map props = coll.getPropertyMap(); assertEquals(1, props.size()); POJOPropertyBuilder prop = props.get("y"); assertNotNull(prop); assertTrue(prop.hasSetter()); assertFalse(prop.hasGetter()); assertFalse(prop.hasField()); } public void testGlobalVisibilityForGetters() { ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.AUTO_DETECT_GETTERS, false); POJOPropertiesCollector coll = collector(m, SimpleGetterVisibility.class, true); // should be 1, expect that we disabled getter auto-detection, so Map props = coll.getPropertyMap(); assertEquals(0, props.size()); } public void testCollectionOfIgnored() { POJOPropertiesCollector coll = collector(MAPPER, ImplicitIgnores.class, false); // should be 1, due to ignorals Map props = coll.getPropertyMap(); assertEquals(1, props.size()); // but also have 2 ignored properties Collection ign = coll.getIgnoredPropertyNames(); assertEquals(2, ign.size()); assertTrue(ign.contains("a")); assertTrue(ign.contains("b")); } public void testSimpleOrderingForDeserialization() { POJOPropertiesCollector coll = collector(MAPPER, SortedProperties.class, false); List props = coll.getProperties(); assertEquals(4, props.size()); assertEquals("a", props.get(0).getName()); assertEquals("b", props.get(1).getName()); assertEquals("c", props.get(2).getName()); assertEquals("d", props.get(3).getName()); } public void testSimpleWithType() { // first for serialization; should base choice on getter POJOPropertiesCollector coll = collector(MAPPER, TypeTestBean.class, true); List props = coll.getProperties(); assertEquals(1, props.size()); assertEquals("value", props.get(0).getName()); AnnotatedMember m = props.get(0).getAccessor(); assertTrue(m instanceof AnnotatedMethod); assertEquals(Integer.class, m.getRawType()); // then for deserialization; prefer ctor param coll = collector(MAPPER, TypeTestBean.class, false); props = coll.getProperties(); assertEquals(1, props.size()); assertEquals("value", props.get(0).getName()); m = props.get(0).getMutator(); assertEquals(AnnotatedParameter.class, m.getClass()); assertEquals(String.class, m.getRawType()); } public void testInnerClassWithAnnotationsInCreator() throws Exception { BasicBeanDescription beanDesc; // first with serialization beanDesc = MAPPER.getSerializationConfig().introspect(MAPPER.constructType(Issue701Bean.class)); assertNotNull(beanDesc); // then with deserialization beanDesc = MAPPER.getDeserializationConfig().introspect(MAPPER.constructType(Issue701Bean.class)); assertNotNull(beanDesc); } public void testUseAnnotationsFalse() throws Exception { // note: need a separate mapper, need to reconfigure ObjectMapper mapper = new ObjectMapper(); mapper.configure(MapperFeature.USE_ANNOTATIONS, false); BasicBeanDescription beanDesc = mapper.getSerializationConfig().introspect(mapper.constructType(Jackson703.class)); assertNotNull(beanDesc); Jackson703 bean = new Jackson703(); String json = mapper.writeValueAsString(bean); assertNotNull(json); } public void testJackson744() throws Exception { BeanDescription beanDesc = MAPPER.getDeserializationConfig().introspect (MAPPER.constructType(Issue744Bean.class)); assertNotNull(beanDesc); AnnotatedMember setter = beanDesc.findAnySetterAccessor(); assertNotNull(setter); assertEquals("addAdditionalProperty", setter.getName()); assertTrue(setter instanceof AnnotatedMethod); } // [databind#269]: Support new @JsonPropertyDescription public void testPropertyDesc() throws Exception { // start via deser BeanDescription beanDesc = MAPPER.getDeserializationConfig().introspect(MAPPER.constructType(PropDescBean.class)); _verifyProperty(beanDesc, true, false, "13"); // and then via ser: beanDesc = MAPPER.getSerializationConfig().introspect(MAPPER.constructType(PropDescBean.class)); _verifyProperty(beanDesc, true, false, "13"); } // [databind#438]: Support @JsonProperty.index public void testPropertyIndex() throws Exception { BeanDescription beanDesc = MAPPER.getDeserializationConfig().introspect(MAPPER.constructType(PropDescBean.class)); _verifyProperty(beanDesc, false, true, "13"); beanDesc = MAPPER.getSerializationConfig().introspect(MAPPER.constructType(PropDescBean.class)); _verifyProperty(beanDesc, false, true, "13"); } public void testDuplicateGetters() throws Exception { POJOPropertiesCollector coll = collector(MAPPER, DuplicateGetterBean.class, true); List props = coll.getProperties(); assertEquals(1, props.size()); BeanPropertyDefinition prop = props.get(0); assertEquals("bloop", prop.getName()); assertTrue(prop.getGetter().hasAnnotation(A.class)); assertTrue(prop.getGetter().hasAnnotation(B.class)); } public void testDuplicateGettersCreator() throws Exception { POJOPropertiesCollector coll = collector(MAPPER, DuplicateGetterCreatorBean.class, true); List props = coll.getProperties(); assertEquals(1, props.size()); POJOPropertyBuilder prop = (POJOPropertyBuilder) props.get(0); assertEquals("bloop", prop.getName()); // Can't call getGetter or the duplicate will be removed assertTrue(prop._getters.value.hasAnnotation(A.class)); assertNotNull(prop._getters.next); assertTrue(prop._getters.next.value.hasAnnotation(A.class)); } private void _verifyProperty(BeanDescription beanDesc, boolean verifyDesc, boolean verifyIndex, String expDefaultValue) { assertNotNull(beanDesc); List props = beanDesc.findProperties(); assertEquals(2, props.size()); for (BeanPropertyDefinition prop : props) { String name = prop.getName(); final PropertyMetadata md = prop.getMetadata(); if ("a".equals(name)) { assertFalse(md.isRequired()); assertNull(md.getRequired()); if (verifyDesc) { assertEquals(PropDescBean.A_DESC, md.getDescription()); } if (verifyIndex) { assertNull(md.getIndex()); } } else if ("b".equals(name)) { assertTrue(md.isRequired()); assertEquals(Boolean.TRUE, md.getRequired()); if (verifyDesc) { assertNull(md.getDescription()); } if (verifyIndex) { assertEquals(Integer.valueOf(PropDescBean.B_INDEX), md.getIndex()); } if (expDefaultValue != null) { assertEquals(expDefaultValue, md.getDefaultValue()); } } else { fail("Unrecognized property '"+name+"'"); } } } /* /********************************************************** /* Helper methods /********************************************************** */ protected POJOPropertiesCollector collector(ObjectMapper m0, Class cls, boolean forSerialization) { BasicClassIntrospector bci = new BasicClassIntrospector(); // no real difference between serialization, deserialization, at least here if (forSerialization) { return bci.collectProperties(m0.getSerializationConfig(), m0.constructType(cls), null, true, "set"); } return bci.collectProperties(m0.getDeserializationConfig(), m0.constructType(cls), null, false, "set"); } } PropertyMetadataTest.java000066400000000000000000000055541325620701100376760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.*; public class PropertyMetadataTest extends BaseMapTest { public void testPropertyName() { PropertyName name = PropertyName.NO_NAME; assertFalse(name.hasSimpleName()); assertFalse(name.hasNamespace()); assertSame(name, name.internSimpleName()); assertSame(name, name.withSimpleName(null)); assertSame(name, name.withSimpleName("")); assertSame(name, name.withNamespace(null)); assertEquals("", name.toString()); assertTrue(name.isEmpty()); assertFalse(name.hasSimpleName("foo")); // just to trigger it, ensure to exception name.hashCode(); PropertyName newName = name.withNamespace(""); assertNotSame(name, newName); assertTrue(name.equals(name)); assertFalse(name.equals(newName)); assertFalse(newName.equals(name)); name = name.withSimpleName("foo"); assertEquals("foo", name.toString()); assertTrue(name.hasSimpleName("foo")); assertFalse(name.isEmpty()); newName = name.withNamespace("ns"); assertEquals("{ns}foo", newName.toString()); assertFalse(newName.equals(name)); assertFalse(name.equals(newName)); // just to trigger it, ensure to exception name.hashCode(); } public void testPropertyMetadata() { PropertyMetadata md = PropertyMetadata.STD_OPTIONAL; assertNull(md.getValueNulls()); assertNull(md.getContentNulls()); assertNull(md.getDefaultValue()); assertEquals(Boolean.FALSE, md.getRequired()); md = md.withNulls(Nulls.AS_EMPTY, Nulls.FAIL); assertEquals(Nulls.AS_EMPTY, md.getValueNulls()); assertEquals(Nulls.FAIL, md.getContentNulls()); assertFalse(md.hasDefaultValue()); assertSame(md, md.withDefaultValue(null)); assertSame(md, md.withDefaultValue("")); md = md.withDefaultValue("foo"); assertEquals("foo", md.getDefaultValue()); assertTrue(md.hasDefaultValue()); assertSame(md, md.withDefaultValue("foo")); md = md.withDefaultValue(null); assertFalse(md.hasDefaultValue()); assertNull(md.getDefaultValue()); md = md.withRequired(null); assertNull(md.getRequired()); assertFalse(md.isRequired()); md = md.withRequired(Boolean.TRUE); assertTrue(md.isRequired()); assertSame(md, md.withRequired(Boolean.TRUE)); md = md.withRequired(null); assertNull(md.getRequired()); assertFalse(md.isRequired()); assertFalse(md.hasIndex()); md = md.withIndex(Integer.valueOf(3)); assertTrue(md.hasIndex()); assertEquals(Integer.valueOf(3), md.getIndex()); } } SetterConflictTest.java000066400000000000000000000016441325620701100373350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.databind.*; // mostly for [databind#1033] public class SetterConflictTest extends BaseMapTest { // Should prefer primitives over Strings, more complex types, by default static class Issue1033Bean { public int value; public void setValue(int v) { value = v; } public void setValue(Issue1033Bean foo) { throw new Error("Should not get called"); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testSetterPriority() throws Exception { Issue1033Bean bean = MAPPER.readValue(aposToQuotes("{'value':42}"), Issue1033Bean.class); assertEquals(42, bean.value); } } TestAnnotationBundles.java000066400000000000000000000112501325620701100400260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyName; /* Tests mostly for [JACKSON-754]: ability to create "annotation bundles" */ public class TestAnnotationBundles extends com.fasterxml.jackson.databind.BaseMapTest { @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonIgnore private @interface MyIgnoral { } @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonProperty("foobar") private @interface MyRename { } protected final static class Bean { @MyIgnoral public String getIgnored() { return "foo"; } @MyRename public int renamed = 13; } @Retention(RetentionPolicy.RUNTIME) @JsonAutoDetect(fieldVisibility=Visibility.NONE, getterVisibility=Visibility.NONE, isGetterVisibility=Visibility.NONE) @JacksonAnnotationsInside public @interface JsonAutoDetectOff {} @JsonAutoDetectOff public class NoAutoDetect { public int getA() { return 13; } @JsonProperty public int getB() { return 5; } } @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonProperty("_id") public @interface Bundle92 {} public class Bean92 { @Bundle92 protected String id = "abc"; } @HolderB @JacksonAnnotationsInside @Retention(RetentionPolicy.RUNTIME) static @interface HolderA {} @HolderA @JacksonAnnotationsInside @Retention(RetentionPolicy.RUNTIME) static @interface HolderB {} static class RecursiveHolder { @HolderA public int unimportant = 42; } static class RecursiveHolder2 { @HolderA public int getValue() { return 28; } } static class RecursiveHolder3 { public int x; @JsonCreator @HolderA public RecursiveHolder3(int x) { this.x = x; } } @JsonProperty @JacksonAnnotationsInside @Retention(RetentionPolicy.RUNTIME) static @interface InformativeHolder { // doesn't really contribute to the test, but would be impossible without this feature boolean important() default true; } static class InformingHolder { @InformativeHolder public int unimportant = 42; } @SuppressWarnings("serial") static class BundleAnnotationIntrospector extends JacksonAnnotationIntrospector { @Override public PropertyName findNameForSerialization(Annotated a) { InformativeHolder informativeHolder = a.getAnnotation(InformativeHolder.class); if ((informativeHolder != null) && informativeHolder.important()) { return PropertyName.construct("important"); } return super.findNameForSerialization(a); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testKeepAnnotationBundle() throws Exception { MAPPER.setAnnotationIntrospector(new BundleAnnotationIntrospector()); assertEquals("{\"important\":42}", MAPPER.writeValueAsString(new InformingHolder())); } public void testRecursiveBundlesField() throws Exception { assertEquals("{\"unimportant\":42}", MAPPER.writeValueAsString(new RecursiveHolder())); } public void testRecursiveBundlesMethod() throws Exception { assertEquals("{\"value\":28}", MAPPER.writeValueAsString(new RecursiveHolder2())); } public void testRecursiveBundlesConstructor() throws Exception { RecursiveHolder3 result = MAPPER.readValue("17", RecursiveHolder3.class); assertNotNull(result); assertEquals(17, result.x); } public void testBundledIgnore() throws Exception { assertEquals("{\"foobar\":13}", MAPPER.writeValueAsString(new Bean())); } public void testVisibilityBundle() throws Exception { assertEquals("{\"b\":5}", MAPPER.writeValueAsString(new NoAutoDetect())); } public void testIssue92() throws Exception { assertEquals("{\"_id\":\"abc\"}", MAPPER.writeValueAsString(new Bean92())); } } TestAnnotationMerging.java000066400000000000000000000053561325620701100400340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; /** * Tests to verify that annotations are shared and merged between members * of a property (getter and setter and so on) */ public class TestAnnotationMerging extends BaseMapTest { static class Wrapper { protected Object value; public Wrapper() { } public Wrapper(Object o) { value = o; } @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) public Object getValue() { return value; } public void setValue(Object o) { value = o; } } static class SharedName { @JsonProperty("x") protected int value; public SharedName(int v) { value = v; } public int getValue() { return value; } } static class SharedName2 { @JsonProperty("x") public int getValue() { return 1; } public void setValue(int x) { } } // Testing to ensure that ctor param and getter can "share" @JsonTypeInfo stuff static class TypeWrapper { protected Object value; @JsonCreator public TypeWrapper( @JsonProperty("value") @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) Object o) { value = o; } public Object getValue() { return value; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testSharedNames() throws Exception { ObjectMapper mapper = new ObjectMapper(); assertEquals("{\"x\":6}", mapper.writeValueAsString(new SharedName(6))); } public void testSharedNamesFromGetterToSetter() throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(new SharedName2()); assertEquals("{\"x\":1}", json); SharedName2 result = mapper.readValue(json, SharedName2.class); assertNotNull(result); } public void testSharedTypeInfo() throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(new Wrapper(13L)); Wrapper result = mapper.readValue(json, Wrapper.class); assertEquals(Long.class, result.value.getClass()); } public void testSharedTypeInfoWithCtor() throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(new TypeWrapper(13L)); TypeWrapper result = mapper.readValue(json, TypeWrapper.class); assertEquals(Long.class, result.value.getClass()); } } TestAutoDetect.java000066400000000000000000000071161325620701100364460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.VisibilityChecker; public class TestAutoDetect extends BaseMapTest { static class PrivateBean { String a; private PrivateBean() { } private PrivateBean(String a) { this.a = a; } } // test for [databind#1347], config overrides for visibility @JsonPropertyOrder(alphabetic=true) static class Feature1347SerBean { public int field = 2; public int getValue() { return 3; } } // let's promote use of fields; but not block setters yet @JsonAutoDetect(fieldVisibility=Visibility.NON_PRIVATE) static class Feature1347DeserBean { int value; public void setValue(int x) { throw new IllegalArgumentException("Should NOT get called"); } } /* /******************************************************** /* Unit tests /******************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testPrivateCtor() throws Exception { // first, default settings, with which construction works ok ObjectMapper m = new ObjectMapper(); PrivateBean bean = m.readValue("\"abc\"", PrivateBean.class); assertEquals("abc", bean.a); // then by increasing visibility requirement: m = new ObjectMapper(); VisibilityChecker vc = m.getVisibilityChecker(); vc = vc.withCreatorVisibility(JsonAutoDetect.Visibility.PUBLIC_ONLY); m.setVisibility(vc); try { m.readValue("\"abc\"", PrivateBean.class); fail("Expected exception for missing constructor"); } catch (JsonProcessingException e) { verifyException(e, "no String-argument constructor/factory"); } } // [databind#1347] public void testVisibilityConfigOverridesForSer() throws Exception { // first, by default, both field/method should be visible final Feature1347SerBean input = new Feature1347SerBean(); assertEquals(aposToQuotes("{'field':2,'value':3}"), MAPPER.writeValueAsString(input)); ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(Feature1347SerBean.class) .setVisibility(JsonAutoDetect.Value.construct(PropertyAccessor.GETTER, Visibility.NONE)); assertEquals(aposToQuotes("{'field':2}"), mapper.writeValueAsString(input)); } // [databind#1347] public void testVisibilityConfigOverridesForDeser() throws Exception { final String JSON = aposToQuotes("{'value':3}"); // by default, should throw exception try { /*Feature1347DeserBean bean =*/ MAPPER.readValue(JSON, Feature1347DeserBean.class); fail("Should not pass"); } catch (JsonMappingException e) { verifyException(e, "Should NOT get called"); } // but when instructed to ignore setter, should work ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(Feature1347DeserBean.class) .setVisibility(JsonAutoDetect.Value.construct(PropertyAccessor.SETTER, Visibility.NONE)); Feature1347DeserBean result = mapper.readValue(JSON, Feature1347DeserBean.class); assertEquals(3, result.value); } } TestBuilderMethods.java000066400000000000000000000033351325620701100373160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.util.Map; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.BasicClassIntrospector; import com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector; import com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder; public class TestBuilderMethods extends BaseMapTest { static class SimpleBuilder { public int x; public SimpleBuilder withX(int x0) { this.x = x0; return this; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper mapper = new ObjectMapper(); public void testSimple() { POJOPropertiesCollector coll = collector(SimpleBuilder.class, "with"); Map props = coll.getPropertyMap(); assertEquals(1, props.size()); POJOPropertyBuilder prop = props.get("x"); assertNotNull(prop); assertTrue(prop.hasField()); assertFalse(prop.hasGetter()); assertTrue(prop.hasSetter()); } /* /********************************************************** /* Helper methods /********************************************************** */ protected POJOPropertiesCollector collector(Class cls, String prefix) { BasicClassIntrospector bci = new BasicClassIntrospector(); // no real difference between serialization, deserialization, at least here return bci.collectProperties(mapper.getSerializationConfig(), mapper.constructType(cls), null, false, prefix); } } TestInferredMutators.java000066400000000000000000000041221325620701100376740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; public class TestInferredMutators extends BaseMapTest { public static class Point { protected int x; public int getX() { return x; } } public static class FixedPoint { protected final int x; public FixedPoint() { x = 0; } public int getX() { return x; } } /* /********************************************************** /* Unit tests /********************************************************** */ // for #190 public void testFinalFieldIgnoral() throws Exception { ObjectMapper mapper = new ObjectMapper(); // default value is 'enabled', for backwards compatibility assertTrue(mapper.isEnabled(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS)); mapper.disable(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS); try { /*p =*/ mapper.readValue("{\"x\":2}", FixedPoint.class); fail("Should not try to use final field"); } catch (JsonMappingException e) { verifyException(e, "unrecognized field \"x\""); } } // for #195 public void testDeserializationInference() throws Exception { final String JSON = "{\"x\":2}"; ObjectMapper mapper = new ObjectMapper(); // First: default case, inference enabled: assertTrue(mapper.isEnabled(MapperFeature.INFER_PROPERTY_MUTATORS)); Point p = mapper.readValue(JSON, Point.class); assertEquals(2, p.x); // but without it, should fail: mapper = new ObjectMapper(); mapper.disable(MapperFeature.INFER_PROPERTY_MUTATORS); try { p = mapper.readValue(JSON, Point.class); fail("Should not succeeed"); } catch (JsonMappingException e) { verifyException(e, "unrecognized field \"x\""); } } } TestJacksonAnnotationIntrospector.java000066400000000000000000000152421325620701100424430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.io.IOException; import java.io.StringWriter; import java.util.*; import javax.xml.namespace.QName; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.*; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder; import com.fasterxml.jackson.databind.type.TypeFactory; @SuppressWarnings("serial") public class TestJacksonAnnotationIntrospector extends BaseMapTest { public static enum EnumExample { VALUE1; } public static class JacksonExample { protected String attributeProperty; protected String elementProperty; protected List wrappedElementProperty; protected EnumExample enumProperty; protected QName qname; @JsonSerialize(using=QNameSerializer.class) public QName getQname() { return qname; } @JsonDeserialize(using=QNameDeserializer.class) public void setQname(QName qname) { this.qname = qname; } @JsonProperty("myattribute") public String getAttributeProperty() { return attributeProperty; } @JsonProperty("myattribute") public void setAttributeProperty(String attributeProperty) { this.attributeProperty = attributeProperty; } @JsonProperty("myelement") public String getElementProperty() { return elementProperty; } @JsonProperty("myelement") public void setElementProperty(String elementProperty) { this.elementProperty = elementProperty; } @JsonProperty("mywrapped") public List getWrappedElementProperty() { return wrappedElementProperty; } @JsonProperty("mywrapped") public void setWrappedElementProperty(List wrappedElementProperty) { this.wrappedElementProperty = wrappedElementProperty; } public EnumExample getEnumProperty() { return enumProperty; } public void setEnumProperty(EnumExample enumProperty) { this.enumProperty = enumProperty; } } public static class QNameSerializer extends JsonSerializer { @Override public void serialize(QName value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString(value.toString()); } } public static class QNameDeserializer extends StdDeserializer { public QNameDeserializer() { super(QName.class); } @Override public QName deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return QName.valueOf(jp.readValueAs(String.class)); } } public static class DummyBuilder extends StdTypeResolverBuilder // { } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS) @JsonTypeResolver(DummyBuilder.class) static class TypeResolverBean { } // @since 1.7 @JsonIgnoreType static class IgnoredType { } static class IgnoredSubType extends IgnoredType { } // Test to ensure we can override enum settings static class LcEnumIntrospector extends JacksonAnnotationIntrospector { private static final long serialVersionUID = 1L; @Override public String[] findEnumValues(Class enumType, Enum[] enumValues, String[] names) { // kinda sorta wrong, but for testing's sake... for (int i = 0, len = enumValues.length; i < len; ++i) { names[i] = enumValues[i].name().toLowerCase(); } return names; } } /* /********************************************************** /* Unit tests /********************************************************** */ /** * tests getting serializer/deserializer instances. */ public void testSerializeDeserializeWithJaxbAnnotations() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.INDENT_OUTPUT); JacksonExample ex = new JacksonExample(); QName qname = new QName("urn:hi", "hello"); ex.setQname(qname); ex.setAttributeProperty("attributeValue"); ex.setElementProperty("elementValue"); ex.setWrappedElementProperty(Arrays.asList("wrappedElementValue")); ex.setEnumProperty(EnumExample.VALUE1); StringWriter writer = new StringWriter(); mapper.writeValue(writer, ex); writer.flush(); writer.close(); String json = writer.toString(); JacksonExample readEx = mapper.readValue(json, JacksonExample.class); assertEquals(ex.qname, readEx.qname); assertEquals(ex.attributeProperty, readEx.attributeProperty); assertEquals(ex.elementProperty, readEx.elementProperty); assertEquals(ex.wrappedElementProperty, readEx.wrappedElementProperty); assertEquals(ex.enumProperty, readEx.enumProperty); } public void testJsonTypeResolver() throws Exception { ObjectMapper mapper = new ObjectMapper(); JacksonAnnotationIntrospector ai = new JacksonAnnotationIntrospector(); AnnotatedClass ac = AnnotatedClassResolver.resolveWithoutSuperTypes(mapper.getSerializationConfig(), TypeResolverBean.class); JavaType baseType = TypeFactory.defaultInstance().constructType(TypeResolverBean.class); TypeResolverBuilder rb = ai.findTypeResolver(mapper.getDeserializationConfig(), ac, baseType); assertNotNull(rb); assertSame(DummyBuilder.class, rb.getClass()); } public void testEnumHandling() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new LcEnumIntrospector()); assertEquals("\"value1\"", mapper.writeValueAsString(EnumExample.VALUE1)); EnumExample result = mapper.readValue(quote("value1"), EnumExample.class); assertEquals(EnumExample.VALUE1, result); } } TestMixinMerging.java000066400000000000000000000032051325620701100367750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; public class TestMixinMerging extends BaseMapTest { public interface Contact { String getCity(); } static class ContactImpl implements Contact { @Override public String getCity() { return "Seattle"; } } static class ContactMixin implements Contact { @Override @JsonProperty public String getCity() { return null; } } public interface Person extends Contact {} static class PersonImpl extends ContactImpl implements Person {} static class PersonMixin extends ContactMixin implements Person {} /* /********************************************************** /* Unit tests /********************************************************** */ // for [Issue#515] public void testDisappearingMixins515() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.disable(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS) .disable(MapperFeature.AUTO_DETECT_FIELDS) .disable(MapperFeature.AUTO_DETECT_GETTERS) .disable(MapperFeature.AUTO_DETECT_IS_GETTERS) .disable(MapperFeature.INFER_PROPERTY_MUTATORS); SimpleModule module = new SimpleModule("Test"); module.setMixInAnnotation(Person.class, PersonMixin.class); mapper.registerModule(module); assertEquals("{\"city\":\"Seattle\"}", mapper.writeValueAsString(new PersonImpl())); } } TestNameConflicts.java000066400000000000000000000067111325620701100371320ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestNameConflicts extends BaseMapTest { @JsonAutoDetect (fieldVisibility= JsonAutoDetect.Visibility.NONE,getterVisibility=JsonAutoDetect.Visibility.NONE, setterVisibility= JsonAutoDetect.Visibility.NONE, isGetterVisibility= JsonAutoDetect.Visibility.NONE) static class CoreBean158 { protected String bar = "x"; @JsonProperty public String getBar() { return bar; } @JsonProperty public void setBar(String bar) { this.bar = bar; } public void setBar(java.io.Serializable bar) { this.bar = bar.toString(); } } static class Bean193 { @JsonProperty("val1") private int x; @JsonIgnore private int value2; public Bean193(@JsonProperty("val1")int value1, @JsonProperty("val2")int value2) { this.x = value1; this.value2 = value2; } @JsonProperty("val2") int x() { return value2; } } /* We should only report an exception for cases where there is * real ambiguity as to how to rename things; but not when everything * has been explicitly defined */ // [Issue#327] @JsonPropertyOrder({ "prop1", "prop2" }) static class BogusConflictBean { @JsonProperty("prop1") public int a = 2; @JsonProperty("prop2") public int getA() { return 1; } } // Bean that should not have conflicts, but could be problematic static class MultipleTheoreticalGetters { public MultipleTheoreticalGetters() { } public MultipleTheoreticalGetters(@JsonProperty("a") int foo) { ; } @JsonProperty public int getA() { return 3; } public int a() { return 5; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); // [Issue#193] public void testIssue193() throws Exception { String json = objectWriter().writeValueAsString(new Bean193(1, 2)); assertNotNull(json); } // [Issue#327] public void testNonConflict() throws Exception { String json = MAPPER.writeValueAsString(new BogusConflictBean()); assertEquals(aposToQuotes("{'prop1':2,'prop2':1}"), json); } public void testHypotheticalGetters() throws Exception { String json = objectWriter().writeValueAsString(new MultipleTheoreticalGetters()); assertEquals(aposToQuotes("{'a':3}"), json); } // for [jackson-core#158] public void testOverrideName() throws Exception { final ObjectMapper mapper = objectMapper(); String json = mapper.writeValueAsString(new CoreBean158()); assertEquals(aposToQuotes("{'bar':'x'}"), json); // and back CoreBean158 result = null; try { result = mapper.readValue(aposToQuotes("{'bar':'y'}"), CoreBean158.class); } catch (Exception e) { fail("Unexpected failure when reading CoreBean158: "+e); } assertNotNull(result); assertEquals("y", result.bar); } } TestNamingStrategyCustom.java000066400000000000000000000201721325620701100405310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.annotation.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.AnnotatedField; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; /** * Unit tests to verify functioning of {@link PropertyNamingStrategy}. */ @SuppressWarnings("serial") public class TestNamingStrategyCustom extends BaseMapTest { /* /********************************************************************** /* Helper classes /********************************************************************** */ static class PrefixStrategy extends PropertyNamingStrategy { @Override public String nameForField(MapperConfig config, AnnotatedField field, String defaultName) { return "Field-"+defaultName; } @Override public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return "Get-"+defaultName; } @Override public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return "Set-"+defaultName; } } static class CStyleStrategy extends PropertyNamingStrategy { @Override public String nameForField(MapperConfig config, AnnotatedField field, String defaultName) { return convert(defaultName); } @Override public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return convert(defaultName); } @Override public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return convert(defaultName); } private String convert(String input) { // easy: replace capital letters with underscore, lower-cases equivalent StringBuilder result = new StringBuilder(); for (int i = 0, len = input.length(); i < len; ++i) { char c = input.charAt(i); if (Character.isUpperCase(c)) { result.append('_'); c = Character.toLowerCase(c); } result.append(c); } return result.toString(); } } static class GetterBean { public int getKey() { return 123; } } static class SetterBean { protected int value; public void setKey(int v) { value = v; } } static class FieldBean { public int key; public FieldBean() { this(0); } public FieldBean(int v) { key = v; } } @JsonPropertyOrder({"first_name", "last_name"}) static class PersonBean { public String firstName; public String lastName; public int age; public PersonBean() { this(null, null, 0); } public PersonBean(String f, String l, int a) { firstName = f; lastName = l; age = a; } } static class Value { public int intValue; public Value() { this(0); } public Value(int v) { intValue = v; } } static class SetterlessWithValue { protected ArrayList values = new ArrayList(); public List getValueList() { return values; } public SetterlessWithValue add(int v) { values.add(new Value(v)); return this; } } static class LcStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase { @Override public String translate(String propertyName) { return propertyName.toLowerCase(); } } static class RenamedCollectionBean { // @JsonDeserialize @JsonProperty private List theValues = Collections.emptyList(); // intentionally odd name, to be renamed by naming strategy public List getTheValues() { return theValues; } } // [Issue#45]: Support @JsonNaming @JsonNaming(PrefixStrategy.class) static class BeanWithPrefixNames { protected int a = 3; public int getA() { return a; } public void setA(int value) { a = value; } } /* /********************************************************************** /* Test methods /********************************************************************** */ public void testSimpleGetters() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new PrefixStrategy()); assertEquals("{\"Get-key\":123}", mapper.writeValueAsString(new GetterBean())); } public void testSimpleSetters() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new PrefixStrategy()); SetterBean bean = mapper.readValue("{\"Set-key\":13}", SetterBean.class); assertEquals(13, bean.value); } public void testSimpleFields() throws Exception { // First serialize ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new PrefixStrategy()); String json = mapper.writeValueAsString(new FieldBean(999)); assertEquals("{\"Field-key\":999}", json); // then deserialize FieldBean result = mapper.readValue(json, FieldBean.class); assertEquals(999, result.key); } public void testCStyleNaming() throws Exception { // First serialize ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new CStyleStrategy()); String json = mapper.writeValueAsString(new PersonBean("Joe", "Sixpack", 42)); assertEquals("{\"first_name\":\"Joe\",\"last_name\":\"Sixpack\",\"age\":42}", json); // then deserialize PersonBean result = mapper.readValue(json, PersonBean.class); assertEquals("Joe", result.firstName); assertEquals("Sixpack", result.lastName); assertEquals(42, result.age); } public void testWithGetterAsSetter() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new CStyleStrategy()); SetterlessWithValue input = new SetterlessWithValue().add(3); String json = mapper.writeValueAsString(input); assertEquals("{\"value_list\":[{\"int_value\":3}]}", json); SetterlessWithValue result = mapper.readValue(json, SetterlessWithValue.class); assertNotNull(result.values); assertEquals(1, result.values.size()); assertEquals(3, result.values.get(0).intValue); } public void testLowerCase() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new LcStrategy()); // mapper.disable(DeserializationConfig.DeserializationFeature.USE_GETTERS_AS_SETTERS); RenamedCollectionBean result = mapper.readValue("{\"thevalues\":[\"a\"]}", RenamedCollectionBean.class); assertNotNull(result.getTheValues()); assertEquals(1, result.getTheValues().size()); assertEquals("a", result.getTheValues().get(0)); } // @JsonNaming / [databind#45] public void testPerClassAnnotation() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new LcStrategy()); BeanWithPrefixNames input = new BeanWithPrefixNames(); String json = mapper.writeValueAsString(input); assertEquals("{\"Get-a\":3}", json); BeanWithPrefixNames output = mapper.readValue("{\"Set-a\":7}", BeanWithPrefixNames.class); assertEquals(7, output.a); } } TestNamingStrategyStd.java000066400000000000000000000356501325620701100400200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.util.Arrays; import java.util.List; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.fasterxml.jackson.databind.introspect.TestNamingStrategyCustom.PersonBean; import com.fasterxml.jackson.databind.node.ObjectNode; /** * Unit tests to verify functioning of standard {@link PropertyNamingStrategy} * implementations Jackson includes out of the box. */ public class TestNamingStrategyStd extends BaseMapTest { @JsonPropertyOrder({"www", "some_url", "some_uris"}) static class Acronyms { public String WWW; public String someURL; public String someURIs; public Acronyms() {this(null, null, null);} public Acronyms(String WWW, String someURL, String someURIs) { this.WWW = WWW; this.someURL = someURL; this.someURIs = someURIs; } } @JsonPropertyOrder({"from_user", "user", "from$user", "from7user", "_x"}) static class UnchangedNames { public String from_user; public String _user; public String from$user; public String from7user; // Used to test "_", but it's explicitly deprecated in JDK8 so... public String _x; public UnchangedNames() {this(null, null, null, null, null);} public UnchangedNames(String from_user, String _user, String from$user, String from7user, String _x) { this.from_user = from_user; this._user = _user; this.from$user = from$user; this.from7user = from7user; this._x = _x; } } @JsonPropertyOrder({"results", "user", "__", "$_user"}) static class OtherNonStandardNames { public String Results; public String _User; public String ___; public String $User; public OtherNonStandardNames() {this(null, null, null, null);} public OtherNonStandardNames(String Results, String _User, String ___, String $User) { this.Results = Results; this._User = _User; this.___ = ___; this.$User = $User; } } static class Bean428 { @JsonProperty("fooBar") public String whatever() {return "";} } @JsonPropertyOrder({ "firstName", "lastName" }) @JsonNaming(PropertyNamingStrategy.LowerCaseStrategy.class) static class BoringBean { public String firstName = "Bob"; public String lastName = "Burger"; } public static class ClassWithObjectNodeField { public String id; public ObjectNode json; } static class ExplicitBean { @JsonProperty("firstName") String userFirstName = "Peter"; @JsonProperty("lastName") String userLastName = "Venkman"; @JsonProperty String userAge = "35"; } @JsonNaming() static class DefaultNaming { public int someValue = 3; } static class FirstNameBean { public String firstName; protected FirstNameBean() { } public FirstNameBean(String n) { firstName = n; } } /* /********************************************************** /* Set up /********************************************************** */ final static List SNAKE_CASE_NAME_TRANSLATIONS = Arrays.asList(new Object[][] { {null, null}, {"", ""}, {"a", "a"}, {"abc", "abc"}, {"1", "1"}, {"123", "123"}, {"1a", "1a"}, {"a1", "a1"}, {"$", "$"}, {"$a", "$a"}, {"a$", "a$"}, {"$_a", "$_a"}, {"a_$", "a_$"}, {"a$a", "a$a"}, {"$A", "$_a"}, {"$_A", "$_a"}, {"_", "_"}, {"__", "_"}, {"___", "__"}, {"A", "a"}, {"A1", "a1"}, {"1A", "1_a"}, {"_a", "a"}, {"_A", "a"}, {"a_a", "a_a"}, {"a_A", "a_a"}, {"A_A", "a_a"}, {"A_a", "a_a"}, {"WWW", "www"}, {"someURI", "some_uri"}, {"someURIs", "some_uris"}, {"Results", "results"}, {"_Results", "results"}, {"_results", "results"}, {"__results", "_results"}, {"__Results", "_results"}, {"___results", "__results"}, {"___Results", "__results"}, {"userName", "user_name"}, {"user_name", "user_name"}, {"user__name", "user__name"}, {"UserName", "user_name"}, {"User_Name", "user_name"}, {"User__Name", "user__name"}, {"_user_name", "user_name"}, {"_UserName", "user_name"}, {"_User_Name", "user_name"}, {"UGLY_NAME", "ugly_name"}, {"_Bars", "bars" }, // [databind#1026] {"usId", "us_id" }, {"uId", "u_id" }, }); private ObjectMapper _lcWithUndescoreMapper; @Override public void setUp() throws Exception { super.setUp(); _lcWithUndescoreMapper = new ObjectMapper(); _lcWithUndescoreMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); } /* /********************************************************** /* Test methods for SNAKE_CASE /********************************************************** */ /** * Unit test to verify translations of * {@link PropertyNamingStrategy#SNAKE_CASE} * outside the context of an ObjectMapper. */ public void testLowerCaseStrategyStandAlone() { for (Object[] pair : SNAKE_CASE_NAME_TRANSLATIONS) { String translatedJavaName = PropertyNamingStrategy.SNAKE_CASE.nameForField(null, null, (String) pair[0]); assertEquals((String) pair[1], translatedJavaName); } } public void testLowerCaseTranslations() throws Exception { // First serialize String json = _lcWithUndescoreMapper.writeValueAsString(new PersonBean("Joe", "Sixpack", 42)); assertEquals("{\"first_name\":\"Joe\",\"last_name\":\"Sixpack\",\"age\":42}", json); // then deserialize PersonBean result = _lcWithUndescoreMapper.readValue(json, PersonBean.class); assertEquals("Joe", result.firstName); assertEquals("Sixpack", result.lastName); assertEquals(42, result.age); } public void testLowerCaseAcronymsTranslations() throws Exception { // First serialize String json = _lcWithUndescoreMapper.writeValueAsString(new Acronyms("world wide web", "http://jackson.codehaus.org", "/path1/,/path2/")); assertEquals("{\"www\":\"world wide web\",\"some_url\":\"http://jackson.codehaus.org\",\"some_uris\":\"/path1/,/path2/\"}", json); // then deserialize Acronyms result = _lcWithUndescoreMapper.readValue(json, Acronyms.class); assertEquals("world wide web", result.WWW); assertEquals("http://jackson.codehaus.org", result.someURL); assertEquals("/path1/,/path2/", result.someURIs); } public void testLowerCaseOtherNonStandardNamesTranslations() throws Exception { // First serialize String json = _lcWithUndescoreMapper.writeValueAsString(new OtherNonStandardNames("Results", "_User", "___", "$User")); assertEquals("{\"results\":\"Results\",\"user\":\"_User\",\"__\":\"___\",\"$_user\":\"$User\"}", json); // then deserialize OtherNonStandardNames result = _lcWithUndescoreMapper.readValue(json, OtherNonStandardNames.class); assertEquals("Results", result.Results); assertEquals("_User", result._User); assertEquals("___", result.___); assertEquals("$User", result.$User); } public void testLowerCaseUnchangedNames() throws Exception { // First serialize String json = _lcWithUndescoreMapper.writeValueAsString(new UnchangedNames("from_user", "_user", "from$user", "from7user", "_x")); assertEquals("{\"from_user\":\"from_user\",\"user\":\"_user\",\"from$user\":\"from$user\",\"from7user\":\"from7user\",\"x\":\"_x\"}", json); // then deserialize UnchangedNames result = _lcWithUndescoreMapper.readValue(json, UnchangedNames.class); assertEquals("from_user", result.from_user); assertEquals("_user", result._user); assertEquals("from$user", result.from$user); assertEquals("from7user", result.from7user); assertEquals("_x", result._x); } /* /********************************************************** /* Test methods for UPPER_CAMEL_CASE /********************************************************** */ /** * Unit test to verify translations of * {@link PropertyNamingStrategy#UPPER_CAMEL_CASE } * outside the context of an ObjectMapper. */ public void testPascalCaseStandAlone() { assertEquals("UserName", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "userName")); assertEquals("User", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "User")); assertEquals("User", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "user")); assertEquals("X", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "x")); assertEquals("BADPublicName", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "bADPublicName")); assertEquals("BADPublicName", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForGetterMethod(null, null, "bADPublicName")); } // [databind#428] public void testIssue428PascalWithOverrides() throws Exception { String json = new ObjectMapper() .setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE) .writeValueAsString(new Bean428()); if (!json.contains(quote("fooBar"))) { fail("Should use name 'fooBar', does not: "+json); } } /* /********************************************************** /* Test methods for LOWER_CASE /********************************************************** */ // For [databind#461] public void testSimpleLowerCase() throws Exception { final BoringBean input = new BoringBean(); ObjectMapper m = objectMapper(); assertEquals(aposToQuotes("{'firstname':'Bob','lastname':'Burger'}"), m.writeValueAsString(input)); } /* /********************************************************** /* Test methods for KEBAB_CASE /********************************************************** */ public void testKebabCaseStrategyStandAlone() { assertEquals("some-value", PropertyNamingStrategy.KEBAB_CASE.nameForField(null, null, "someValue")); assertEquals("some-value", PropertyNamingStrategy.KEBAB_CASE.nameForField(null, null, "SomeValue")); assertEquals("url", PropertyNamingStrategy.KEBAB_CASE.nameForField(null, null, "URL")); assertEquals("url-stuff", PropertyNamingStrategy.KEBAB_CASE.nameForField(null, null, "URLStuff")); assertEquals("some-url-stuff", PropertyNamingStrategy.KEBAB_CASE.nameForField(null, null, "SomeURLStuff")); } public void testSimpleKebabCase() throws Exception { final FirstNameBean input = new FirstNameBean("Bob"); ObjectMapper m = new ObjectMapper() .setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE); assertEquals(aposToQuotes("{'first-name':'Bob'}"), m.writeValueAsString(input)); FirstNameBean result = m.readValue(aposToQuotes("{'first-name':'Billy'}"), FirstNameBean.class); assertEquals("Billy", result.firstName); } /* /********************************************************** /* Test methods, other /********************************************************** */ /** * Test [databind#815], problems with ObjectNode, naming strategy */ public void testNamingWithObjectNode() throws Exception { ObjectMapper m = new ObjectMapper() .setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE); ClassWithObjectNodeField result = m.readValue( "{ \"id\": \"1\", \"json\": { \"foo\": \"bar\", \"baz\": \"bing\" } }", ClassWithObjectNodeField.class); assertNotNull(result); assertEquals("1", result.id); assertNotNull(result.json); assertEquals(2, result.json.size()); assertEquals("bing", result.json.path("baz").asText()); } public void testExplicitRename() throws Exception { ObjectMapper m = new ObjectMapper(); m.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); m.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); // by default, renaming will not take place on explicitly named fields assertEquals(aposToQuotes("{'firstName':'Peter','lastName':'Venkman','user_age':'35'}"), m.writeValueAsString(new ExplicitBean())); m = new ObjectMapper(); m.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); m.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); m.enable(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING); // w/ feature enabled, ALL property names should get re-written assertEquals(aposToQuotes("{'first_name':'Peter','last_name':'Venkman','user_age':'35'}"), m.writeValueAsString(new ExplicitBean())); // test deserialization as well ExplicitBean bean = m.readValue(aposToQuotes("{'first_name':'Egon','last_name':'Spengler','user_age':'32'}"), ExplicitBean.class); assertNotNull(bean); assertEquals("Egon", bean.userFirstName); assertEquals("Spengler", bean.userLastName); assertEquals("32", bean.userAge); } // Also verify that "no naming strategy" should be ok public void testExplicitNoNaming() throws Exception { ObjectMapper mapper = objectMapper(); String json = mapper.writeValueAsString(new DefaultNaming()); assertEquals(aposToQuotes("{'someValue':3}"), json); } } TestPropertyConflicts.java000066400000000000000000000113411325620701100400710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; /** * Unit tests verifying handling of potential and actual * conflicts, regarding property handling. */ public class TestPropertyConflicts extends BaseMapTest { // error message for conflicting getters sub-optimal static class BeanWithConflict { public int getX() { return 3; } public boolean getx() { return false; } } // [databind#238] protected static class Getters1A { @JsonProperty protected int value = 3; public int getValue() { return value+1; } public boolean isValue() { return false; } } // variant where order of declarations is reversed; to try to // ensure declaration order won't break things protected static class Getters1B { public boolean isValue() { return false; } @JsonProperty protected int value = 3; public int getValue() { return value+1; } } protected static class InferingIntrospector extends JacksonAnnotationIntrospector { private static final long serialVersionUID = 1L; @Override public String findImplicitPropertyName(AnnotatedMember member) { String name = member.getName(); if (name.startsWith("_")) { return name.substring(1); } return null; } } static class Infernal { public String _name() { return "foo"; } public String getName() { return "Bob"; } public void setStuff(String value) { ; // ok } public void _stuff(String value) { throw new UnsupportedOperationException(); } } // For [databind#541] static class Bean541 { protected String str; @JsonCreator public Bean541(@JsonProperty("str") String str) { this.str = str; } @JsonProperty("s") public String getStr() { return str; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testFailWithDupProps() throws Exception { BeanWithConflict bean = new BeanWithConflict(); try { String json = objectWriter().writeValueAsString(bean); fail("Should have failed due to conflicting accessor definitions; got JSON = "+json); } catch (JsonProcessingException e) { verifyException(e, "Conflicting getter definitions"); } } // [databind#238]: ok to have getter, "isGetter" public void testRegularAndIsGetter() throws Exception { final ObjectWriter writer = objectWriter(); // first, serialize without probs: assertEquals("{\"value\":4}", writer.writeValueAsString(new Getters1A())); assertEquals("{\"value\":4}", writer.writeValueAsString(new Getters1B())); // and similarly, deserialize ObjectMapper mapper = objectMapper(); assertEquals(1, mapper.readValue("{\"value\":1}", Getters1A.class).value); assertEquals(2, mapper.readValue("{\"value\":2}", Getters1B.class).value); } public void testInferredNameConflictsWithGetters() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new InferingIntrospector()); String json = mapper.writeValueAsString(new Infernal()); assertEquals(aposToQuotes("{'name':'Bob'}"), json); } public void testInferredNameConflictsWithSetters() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new InferingIntrospector()); Infernal inf = mapper.readValue(aposToQuotes("{'stuff':'Bob'}"), Infernal.class); assertNotNull(inf); } public void testIssue541() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.disable( MapperFeature.AUTO_DETECT_CREATORS, MapperFeature.AUTO_DETECT_FIELDS, MapperFeature.AUTO_DETECT_GETTERS, MapperFeature.AUTO_DETECT_IS_GETTERS, MapperFeature.AUTO_DETECT_SETTERS, MapperFeature.USE_GETTERS_AS_SETTERS ); Bean541 data = mapper.readValue("{\"str\":\"the string\"}", Bean541.class); if (data == null) { throw new IllegalStateException("data is null"); } if (!"the string".equals(data.getStr())) { throw new IllegalStateException("bad value for data.str"); } } } TestPropertyRename.java000066400000000000000000000040041325620701100373520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests verifying handling of potential and actual * conflicts, regarding property handling. */ public class TestPropertyRename extends BaseMapTest { static class Bean323WithIgnore { @JsonIgnore private int a; public Bean323WithIgnore(@JsonProperty("a") final int a ) { this.a = a; } @JsonProperty("b") private int getA () { return a; } } @JsonPropertyOrder({ "a","b" }) static class Bean323WithExplicitCleave1 { @JsonProperty("a") private int a; public Bean323WithExplicitCleave1(@JsonProperty("a") final int a ) { this.a = a; } @JsonProperty("b") private int getA () { return a; } } @JsonPropertyOrder({ "a","b" }) static class Bean323WithExplicitCleave2 { @JsonProperty("b") private int a; public Bean323WithExplicitCleave2(@JsonProperty("a") final int a ) { this.a = a; } @JsonProperty("b") private int getA () { return a; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testCreatorPropRenameWithIgnore() throws Exception { Bean323WithIgnore input = new Bean323WithIgnore(7); assertEquals("{\"b\":7}", objectWriter().writeValueAsString(input)); } public void testCreatorPropRenameWithCleave() throws Exception { assertEquals("{\"a\":7,\"b\":7}", objectWriter().writeValueAsString(new Bean323WithExplicitCleave1(7))); // note: 'a' NOT included as only ctor property found for it, no getter/field assertEquals("{\"b\":7}", objectWriter().writeValueAsString(new Bean323WithExplicitCleave2(7))); } } TestScalaLikeImplicitProperties.java000066400000000000000000000142451325620701100420060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; /** * Tests Scala-style JVM naming patterns for properties. * * Scala uses identifiers that are legal JVM names, but not legal Java names: * *
    *
  • prop␣ (trailing space) for fields
  • *
  • prop for getters
  • *
  • prop_= for setters
  • *
* * Scala sources turn property accesses into method calls in most cases; the * backing field and the particulars of the method names are implementation details. * * Since I can't reproduce them in Java, I've substituted legal but uncommonly * used characters as placeholders. */ public class TestScalaLikeImplicitProperties extends BaseMapTest { static class NameMangler extends JacksonAnnotationIntrospector { private static final long serialVersionUID = 1L; @Override public String findImplicitPropertyName(AnnotatedMember member) { String name = null; if (member instanceof AnnotatedField) { name = member.getName(); if (name.endsWith("‿")) { return name.substring(0, name.length()-1); } } else if (member instanceof AnnotatedMethod) { name = member.getName(); if (name.endsWith("_⁀")) { return name.substring(0, name.length()-2); } if (!name.startsWith("get") && !name.startsWith("set")) { return name; } } else if (member instanceof AnnotatedParameter) { // A placeholder for legitimate property name detection // such as what the JDK8 module provides return "prop"; } return null; } /* Deprecated since 2.9 @Override public boolean hasCreatorAnnotation(Annotated a) { return (a instanceof AnnotatedConstructor); } */ @Override public JsonCreator.Mode findCreatorAnnotation(MapperConfig config, Annotated a) { // A placeholder for legitimate creator detection. // In Scala, all primary constructors should be creators, // but I can't obtain a reference to the AnnotatedClass from the // AnnotatedConstructor, so it's simulated here. return (a instanceof AnnotatedConstructor) ? JsonCreator.Mode.DEFAULT : null; } } static class ValProperty { private final String prop‿; public String prop() { return prop‿; } public ValProperty(String prop) { prop‿ = prop; } } static class ValWithBeanProperty { private final String prop‿; public String prop() { return prop‿; } public String getProp() { return prop‿; } public ValWithBeanProperty(String prop) { prop‿ = prop; } } static class VarProperty { private String prop‿; public String prop() { return prop‿; } public void prop_⁀(String p) { prop‿ = p; } public VarProperty(String prop) { prop‿ = prop; } } static class VarWithBeanProperty { private String prop‿; public String prop() { return prop‿; } public void prop_⁀(String p) { prop‿ = p; } public String getProp() { return prop‿; } public void setProp(String p) { prop‿ = p; } public VarWithBeanProperty(String prop) { prop‿ = prop; } } static class GetterSetterProperty { // Different name to represent an arbitrary implementation, not necessarily local to this class. private String _prop_impl = "get/set"; public String prop() { return _prop_impl; } public void prop_⁀(String p) { _prop_impl = p; } // Getter/Setters are typically not in the constructor because they are implemented // by the end user, not the compiler. They should be detected similar to 'bean-style' // getProp/setProp pairs. } /* /********************************************************** /* Test methods /********************************************************** */ public void testValProperty() throws Exception { ObjectMapper m = manglingMapper(); assertEquals("{\"prop\":\"val\"}", m.writeValueAsString(new ValProperty("val"))); } public void testValWithBeanProperty() throws Exception { ObjectMapper m = manglingMapper(); assertEquals("{\"prop\":\"val\"}", m.writeValueAsString(new ValWithBeanProperty("val"))); } public void testVarProperty() throws Exception { ObjectMapper m = manglingMapper(); assertEquals("{\"prop\":\"var\"}", m.writeValueAsString(new VarProperty("var"))); VarProperty result = m.readValue("{\"prop\":\"read\"}", VarProperty.class); assertEquals("read", result.prop()); } public void testVarWithBeanProperty() throws Exception { ObjectMapper m = manglingMapper(); assertEquals("{\"prop\":\"var\"}", m.writeValueAsString(new VarWithBeanProperty("var"))); VarWithBeanProperty result = m.readValue("{\"prop\":\"read\"}", VarWithBeanProperty.class); assertEquals("read", result.prop()); } public void testGetterSetterProperty() throws Exception { ObjectMapper m = manglingMapper(); assertEquals("{\"prop\":\"get/set\"}", m.writeValueAsString(new GetterSetterProperty())); GetterSetterProperty result = m.readValue("{\"prop\":\"read\"}", GetterSetterProperty.class); assertEquals("read", result.prop()); } /* /********************************************************** /* Helper methods /********************************************************** */ private ObjectMapper manglingMapper() { ObjectMapper m = new ObjectMapper(); m.setAnnotationIntrospector(new NameMangler()); return m; } } TransientTest.java000066400000000000000000000047021325620701100363520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.beans.Transient; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; /** * Tests for both `transient` keyword and JDK 7 * {@link java.beans.Transient} annotation. */ public class TransientTest extends BaseMapTest { // for [databind#296] @JsonPropertyOrder({ "x" }) static class ClassyTransient { public transient int value = 3; public int getValue() { return value; } public int getX() { return 42; } } static class SimplePrunableTransient { public int a = 1; public transient int b = 2; } // for [databind#857] static class BeanTransient { @Transient public int getX() { return 3; } public int getY() { return 4; } } // for [databind#1184] static class OverridableTransient { @JsonProperty // @JsonProperty("value") // should override transient here, to force inclusion public transient int tValue; public OverridableTransient(int v) { tValue = v; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); // for [databind#296] public void testTransientFieldHandling() throws Exception { // default handling: remove transient field but do not propagate assertEquals(aposToQuotes("{'x':42,'value':3}"), MAPPER.writeValueAsString(new ClassyTransient())); assertEquals(aposToQuotes("{'a':1}"), MAPPER.writeValueAsString(new SimplePrunableTransient())); // but may change that ObjectMapper m = new ObjectMapper() .enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER); assertEquals(aposToQuotes("{'x':42}"), m.writeValueAsString(new ClassyTransient())); } // for [databind#857] public void testBeanTransient() throws Exception { assertEquals(aposToQuotes("{'y':4}"), MAPPER.writeValueAsString(new BeanTransient())); } // for [databind#1184] public void testOverridingTransient() throws Exception { assertEquals(aposToQuotes("{'tValue':38}"), MAPPER.writeValueAsString(new OverridableTransient(38))); } } TypeCoercion1592Test.java000066400000000000000000000017541325620701100373330ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; // [databind#1592]: allow "coercion" between primitive/wrapper (mostly just ignoring) public class TypeCoercion1592Test extends BaseMapTest { static class Bean1592 { @JsonSerialize(as=Integer.class) public int i; @JsonDeserialize(as=Long.class) public long l; } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testTypeCoercion1592() throws Exception { // first, serialize MAPPER.writeValueAsString(new Bean1592()); Bean1592 result = MAPPER.readValue("{}", Bean1592.class); assertNotNull(result); } } VisibilityForSerializationTest.java000066400000000000000000000133011325620701100417320ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/introspectpackage com.fasterxml.jackson.databind.introspect; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; /** * Unit tests for checking handling of some of {@link MapperFeature}s * and {@link SerializationFeature}s for serialization. */ public class VisibilityForSerializationTest extends BaseMapTest { /** * Class with one explicitly defined getter, one name-based * auto-detectable getter. */ static class GetterClass { @JsonProperty("x") public int getX() { return -2; } public int getY() { return 1; } } /** * Another test-class that explicitly disables auto-detection */ @JsonAutoDetect(getterVisibility=Visibility.NONE) static class DisabledGetterClass { @JsonProperty("x") public int getX() { return -2; } public int getY() { return 1; } } /** * Another test-class that explicitly enables auto-detection */ @JsonAutoDetect(isGetterVisibility=Visibility.NONE) static class EnabledGetterClass { @JsonProperty("x") public int getX() { return -2; } public int getY() { return 1; } // not auto-detected, since "is getter" auto-detect disabled public boolean isOk() { return true; } } /** * One more: only detect "isXxx", not "getXXX" */ @JsonAutoDetect(getterVisibility=Visibility.NONE) static class EnabledIsGetterClass { // Won't be auto-detected any more public int getY() { return 1; } // but this will be public boolean isOk() { return true; } } static class TCls { @JsonProperty("groupname") private String groupname; public void setName(String str) { this.groupname = str; } public String getName() { return groupname; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testGlobalAutoDetection() throws IOException { // First: auto-detection enabled (default): ObjectMapper m = new ObjectMapper(); Map result = writeAndMap(m, new GetterClass()); assertEquals(2, result.size()); assertEquals(Integer.valueOf(-2), result.get("x")); assertEquals(Integer.valueOf(1), result.get("y")); // Then auto-detection disabled. But note: we MUST create a new // mapper, since old version of serializer may be cached by now m = new ObjectMapper(); m.configure(MapperFeature.AUTO_DETECT_GETTERS, false); result = writeAndMap(m, new GetterClass()); assertEquals(1, result.size()); assertTrue(result.containsKey("x")); } public void testPerClassAutoDetection() throws IOException { // First: class-level auto-detection disabling ObjectMapper m = new ObjectMapper(); Map result = writeAndMap(m, new DisabledGetterClass()); assertEquals(1, result.size()); assertTrue(result.containsKey("x")); // And then class-level auto-detection enabling, should override defaults m.configure(MapperFeature.AUTO_DETECT_GETTERS, true); result = writeAndMap(m, new EnabledGetterClass()); assertEquals(2, result.size()); assertTrue(result.containsKey("x")); assertTrue(result.containsKey("y")); } public void testPerClassAutoDetectionForIsGetter() throws IOException { ObjectMapper m = new ObjectMapper(); // class level should override m.configure(MapperFeature.AUTO_DETECT_GETTERS, true); m.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false); Map result = writeAndMap(m, new EnabledIsGetterClass()); assertEquals(0, result.size()); assertFalse(result.containsKey("ok")); } // Simple test verifying that chainable methods work ok... public void testConfigChainability() { ObjectMapper m = new ObjectMapper(); assertTrue(m.isEnabled(MapperFeature.AUTO_DETECT_SETTERS)); assertTrue(m.isEnabled(MapperFeature.AUTO_DETECT_GETTERS)); m.configure(MapperFeature.AUTO_DETECT_SETTERS, false) .configure(MapperFeature.AUTO_DETECT_GETTERS, false); assertFalse(m.isEnabled(MapperFeature.AUTO_DETECT_SETTERS)); assertFalse(m.isEnabled(MapperFeature.AUTO_DETECT_GETTERS)); } public void testVisibilityFeatures() throws Exception { ObjectMapper om = new ObjectMapper(); // Only use explicitly specified values to be serialized/deserialized (i.e., JSONProperty). om.configure(MapperFeature.AUTO_DETECT_FIELDS, false); om.configure(MapperFeature.AUTO_DETECT_GETTERS, false); om.configure(MapperFeature.AUTO_DETECT_SETTERS, false); om.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false); om.configure(MapperFeature.USE_GETTERS_AS_SETTERS, false); om.configure(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS, true); om.configure(MapperFeature.INFER_PROPERTY_MUTATORS, false); om.configure(MapperFeature.USE_ANNOTATIONS, true); JavaType javaType = om.getTypeFactory().constructType(TCls.class); BeanDescription desc = (BeanDescription) om.getSerializationConfig().introspect(javaType); List props = desc.findProperties(); if (props.size() != 1) { fail("Should find 1 property, not "+props.size()+"; properties = "+props); } } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsonschema/000077500000000000000000000000001325620701100327145ustar00rootroot00000000000000NewSchemaTest.java000066400000000000000000000323501325620701100362150ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsonschemapackage com.fasterxml.jackson.databind.jsonschema; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.core.JsonParser.NumberType; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.*; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.std.StdSerializer; /** * Basic tests to exercise low-level support added for JSON Schema module and * other modules that use type introspection. */ public class NewSchemaTest extends BaseMapTest { enum TestEnum { A, B, C; @Override public String toString() { return "ToString:"+name(); } } enum TestEnumWithJsonValue { A, B, C; @JsonValue public String forSerialize() { return "value-"+name(); } } // silly little class to exercise basic traversal static class POJO { public List children; public POJO[] childOrdering; public Map times; public Map conversions; public EnumMap weights; } static class POJOWithScalars { public boolean boo; public byte b; public char c; public short s; public int i; public long l; public float f; public double d; public byte[] arrayBoo; public byte[] arrayb; public char[] arrayc; public short[] arrays; public int[] arrayi; public long[] arrayl; public float[] arrayf; public double[] arrayd; public Boolean Boo; public Byte B; public Character C; public Short S; public Integer I; public Long L; public Float F; public Double D; public TestEnum en; public String str; public String[] strs; public java.util.Date date; public java.util.Calendar calendar; } static class POJOWithRefs { public AtomicReference maybePOJO; public AtomicReference maybeString; } // [databind#1793] static class POJOWithJsonValue { private Point[] value; @JsonCreator(mode=JsonCreator.Mode.DELEGATING) public POJOWithJsonValue(Point[] v) { value = v; } @JsonValue public Point[] serialization() { return value; } } @JsonPropertyOrder({ "dec", "bigInt" }) static class Numbers { public BigDecimal dec; public BigInteger bigInt; } static class BogusJsonFormatVisitorWrapper extends JsonFormatVisitorWrapper.Base { // Implement handlers just to get more exercise... @Override public JsonObjectFormatVisitor expectObjectFormat(JavaType type) { return new JsonObjectFormatVisitor.Base(getProvider()) { @Override public void property(BeanProperty prop) throws JsonMappingException { _visit(prop); } @Override public void property(String name, JsonFormatVisitable handler, JavaType propertyTypeHint) { } @Override public void optionalProperty(BeanProperty prop) throws JsonMappingException { _visit(prop); } @Override public void optionalProperty(String name, JsonFormatVisitable handler, JavaType propertyTypeHint) throws JsonMappingException { } private void _visit(BeanProperty prop) throws JsonMappingException { if (!(prop instanceof BeanPropertyWriter)) { return; } BeanPropertyWriter bpw = (BeanPropertyWriter) prop; JsonSerializer ser = bpw.getSerializer(); final SerializerProvider prov = getProvider(); if (ser == null) { if (prov == null) { throw new Error("SerializerProvider missing"); } ser = prov.findValueSerializer(prop.getType(), prop); } // and this just for bit of extra coverage... if (ser instanceof StdSerializer) { assertNotNull(((StdSerializer) ser).getSchema(prov, prop.getType())); } JsonFormatVisitorWrapper visitor = new JsonFormatVisitorWrapper.Base(getProvider()); ser.acceptJsonFormatVisitor(visitor, prop.getType()); } }; } @Override public JsonArrayFormatVisitor expectArrayFormat(JavaType type) { return new JsonArrayFormatVisitor.Base(getProvider()); } @Override public JsonStringFormatVisitor expectStringFormat(JavaType type) { return new JsonStringFormatVisitor.Base(); } @Override public JsonNumberFormatVisitor expectNumberFormat(JavaType type) { return new JsonNumberFormatVisitor.Base(); } @Override public JsonIntegerFormatVisitor expectIntegerFormat(JavaType type) { return new JsonIntegerFormatVisitor.Base(); } @Override public JsonBooleanFormatVisitor expectBooleanFormat(JavaType type) { return new JsonBooleanFormatVisitor.Base(); } @Override public JsonNullFormatVisitor expectNullFormat(JavaType type) { return new JsonNullFormatVisitor.Base(); } @Override public JsonAnyFormatVisitor expectAnyFormat(JavaType type) { return new JsonAnyFormatVisitor.Base(); } @Override public JsonMapFormatVisitor expectMapFormat(JavaType type) { return new JsonMapFormatVisitor.Base(); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); /* Silly little test for simply triggering traversal, without attempting to * verify what is being reported. Smoke test that should trigger problems * if basic POJO type/serializer traversal had issues. */ public void testBasicTraversal() throws Exception { MAPPER.acceptJsonFormatVisitor(POJO.class, new BogusJsonFormatVisitorWrapper()); MAPPER.acceptJsonFormatVisitor(POJOWithScalars.class, new BogusJsonFormatVisitorWrapper()); MAPPER.acceptJsonFormatVisitor(LinkedHashMap.class, new BogusJsonFormatVisitorWrapper()); MAPPER.acceptJsonFormatVisitor(ArrayList.class, new BogusJsonFormatVisitorWrapper()); MAPPER.acceptJsonFormatVisitor(EnumSet.class, new BogusJsonFormatVisitorWrapper()); MAPPER.acceptJsonFormatVisitor(POJOWithRefs.class, new BogusJsonFormatVisitorWrapper()); MAPPER.acceptJsonFormatVisitor(POJOWithJsonValue.class, new BogusJsonFormatVisitorWrapper()); } public void testSimpleEnum() throws Exception { final Set values = new TreeSet(); ObjectWriter w = MAPPER.writer(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); w.acceptJsonFormatVisitor(TestEnum.class, new JsonFormatVisitorWrapper.Base() { @Override public JsonStringFormatVisitor expectStringFormat(JavaType type) { return new JsonStringFormatVisitor() { @Override public void enumTypes(Set enums) { values.addAll(enums); } @Override public void format(JsonValueFormat format) { } }; } }); assertEquals(3, values.size()); TreeSet exp = new TreeSet(Arrays.asList( "ToString:A", "ToString:B", "ToString:C" )); assertEquals(exp, values); } public void testEnumWithJsonValue() throws Exception { final Set values = new TreeSet(); MAPPER.acceptJsonFormatVisitor(TestEnumWithJsonValue.class, new JsonFormatVisitorWrapper.Base() { @Override public JsonStringFormatVisitor expectStringFormat(JavaType type) { return new JsonStringFormatVisitor() { @Override public void enumTypes(Set enums) { values.addAll(enums); } @Override public void format(JsonValueFormat format) { } }; } }); assertEquals(3, values.size()); TreeSet exp = new TreeSet(Arrays.asList( "value-A", "value-B", "value-C" )); assertEquals(exp, values); } // Ensure JsonValueFormat serializes/deserializes as expected public void testJsonValueFormatHandling() throws Exception { // first: serialize using 'toString()', not name final String EXP = quote("host-name"); assertEquals(EXP, MAPPER.writeValueAsString(JsonValueFormat.HOST_NAME)); // and second, deserialize ok from that as well assertSame(JsonValueFormat.HOST_NAME, MAPPER.readValue(EXP, JsonValueFormat.class)); } // [databind#1045], regression wrt BigDecimal public void testSimpleNumbers() throws Exception { final StringBuilder sb = new StringBuilder(); MAPPER.acceptJsonFormatVisitor(Numbers.class, new JsonFormatVisitorWrapper.Base() { @Override public JsonObjectFormatVisitor expectObjectFormat(final JavaType type) { return new JsonObjectFormatVisitor.Base(getProvider()) { @Override public void optionalProperty(BeanProperty prop) throws JsonMappingException { sb.append("[optProp ").append(prop.getName()).append("("); JsonSerializer ser = null; if (prop instanceof BeanPropertyWriter) { BeanPropertyWriter bpw = (BeanPropertyWriter) prop; ser = bpw.getSerializer(); } final SerializerProvider prov = getProvider(); if (ser == null) { ser = prov.findValueSerializer(prop.getType(), prop); } ser.acceptJsonFormatVisitor(new JsonFormatVisitorWrapper.Base() { @Override public JsonNumberFormatVisitor expectNumberFormat( JavaType t) throws JsonMappingException { return new JsonNumberFormatVisitor() { @Override public void format(JsonValueFormat format) { sb.append("[numberFormat=").append(format).append("]"); } @Override public void enumTypes(Set enums) { } @Override public void numberType(NumberType numberType) { sb.append("[numberType=").append(numberType).append("]"); } }; } @Override public JsonIntegerFormatVisitor expectIntegerFormat(JavaType t) throws JsonMappingException { return new JsonIntegerFormatVisitor() { @Override public void format(JsonValueFormat format) { sb.append("[integerFormat=").append(format).append("]"); } @Override public void enumTypes(Set enums) { } @Override public void numberType(NumberType numberType) { sb.append("[numberType=").append(numberType).append("]"); } }; } }, prop.getType()); sb.append(")]"); } }; } }); assertEquals("[optProp dec([numberType=BIG_DECIMAL])][optProp bigInt([numberType=BIG_INTEGER])]", sb.toString()); } } TestGenerateJsonSchema.java000066400000000000000000000201711325620701100400460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsonschemapackage com.fasterxml.jackson.databind.jsonschema; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collection; import java.util.Map; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; /** * @author Ryan Heaton */ @SuppressWarnings("deprecation") public class TestGenerateJsonSchema extends com.fasterxml.jackson.databind.BaseMapTest { /* /********************************************************** /* Helper classes /********************************************************** */ public static class SimpleBean { private int property1; private String property2; private String[] property3; private Collection property4; @JsonProperty(required=true) private String property5; public int getProperty1() { return property1; } public void setProperty1(int property1) { this.property1 = property1; } public String getProperty2() { return property2; } public void setProperty2(String property2) { this.property2 = property2; } public String[] getProperty3() { return property3; } public void setProperty3(String[] property3) { this.property3 = property3; } public Collection getProperty4() { return property4; } public void setProperty4(Collection property4) { this.property4 = property4; } public String getProperty5() { return property5; } public void setProperty5(String property5) { this.property5 = property5; } } public class TrivialBean { public String name; } @JsonSerializableSchema(id="myType") public class BeanWithId { public String value; } static class UnwrappingRoot { public int age; @JsonUnwrapped(prefix="name.") public Name name; } static class Name { public String first, last; } @JsonPropertyOrder({ "dec", "bigInt" }) static class Numbers { public BigDecimal dec; public BigInteger bigInt; } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); /** * tests generating json-schema stuff. */ public void testOldSchemaGeneration() throws Exception { JsonSchema jsonSchema = MAPPER.generateJsonSchema(SimpleBean.class); assertNotNull(jsonSchema); // test basic equality, and that equals() handles null, other obs assertTrue(jsonSchema.equals(jsonSchema)); assertFalse(jsonSchema.equals(null)); assertFalse(jsonSchema.equals("foo")); // other basic things assertNotNull(jsonSchema.toString()); assertNotNull(JsonSchema.getDefaultSchemaNode()); ObjectNode root = jsonSchema.getSchemaNode(); assertEquals("object", root.get("type").asText()); assertEquals(false, root.path("required").booleanValue()); JsonNode propertiesSchema = root.get("properties"); assertNotNull(propertiesSchema); JsonNode property1Schema = propertiesSchema.get("property1"); assertNotNull(property1Schema); assertEquals("integer", property1Schema.get("type").asText()); assertEquals(false, property1Schema.path("required").booleanValue()); JsonNode property2Schema = propertiesSchema.get("property2"); assertNotNull(property2Schema); assertEquals("string", property2Schema.get("type").asText()); assertEquals(false, property2Schema.path("required").booleanValue()); JsonNode property3Schema = propertiesSchema.get("property3"); assertNotNull(property3Schema); assertEquals("array", property3Schema.get("type").asText()); assertEquals(false, property3Schema.path("required").booleanValue()); assertEquals("string", property3Schema.get("items").get("type").asText()); JsonNode property4Schema = propertiesSchema.get("property4"); assertNotNull(property4Schema); assertEquals("array", property4Schema.get("type").asText()); assertEquals(false, property4Schema.path("required").booleanValue()); assertEquals("number", property4Schema.get("items").get("type").asText()); } @JsonFilter("filteredBean") protected static class FilteredBean { @JsonProperty private String secret = "secret"; @JsonProperty private String obvious = "obvious"; public String getSecret() { return secret; } public void setSecret(String s) { secret = s; } public String getObvious() { return obvious; } public void setObvious(String s) {obvious = s; } } final static FilterProvider secretFilterProvider = new SimpleFilterProvider() .addFilter("filteredBean", SimpleBeanPropertyFilter.filterOutAllExcept(new String[]{"obvious"})); public void testGeneratingJsonSchemaWithFilters() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setFilters(secretFilterProvider); JsonSchema schema = mapper.generateJsonSchema(FilteredBean.class); JsonNode node = schema.getSchemaNode().get("properties"); assertTrue(node.has("obvious")); assertFalse(node.has("secret")); } /** * Additional unit test for verifying that schema object itself * can be properly serialized */ public void testSchemaSerialization() throws Exception { JsonSchema jsonSchema = MAPPER.generateJsonSchema(SimpleBean.class); Map result = writeAndMap(MAPPER, jsonSchema); assertNotNull(result); // no need to check out full structure, just basics... assertEquals("object", result.get("type")); // only add 'required' if it is true... assertNull(result.get("required")); assertNotNull(result.get("properties")); } public void testThatObjectsHaveNoItems() throws Exception { JsonSchema jsonSchema = MAPPER.generateJsonSchema(TrivialBean.class); String json = jsonSchema.toString().replaceAll("\"", "'"); // can we count on ordering being stable? I think this is true with current ObjectNode impl // as perh [JACKSON-563]; 'required' is only included if true assertEquals("{'type':'object','properties':{'name':{'type':'string'}}}", json); } public void testSchemaId() throws Exception { JsonSchema jsonSchema = MAPPER.generateJsonSchema(BeanWithId.class); String json = jsonSchema.toString().replaceAll("\"", "'"); assertEquals("{'type':'object','id':'myType','properties':{'value':{'type':'string'}}}", json); } // [databind#271] public void testUnwrapping() throws Exception { JsonSchema jsonSchema = MAPPER.generateJsonSchema(UnwrappingRoot.class); String json = jsonSchema.toString().replaceAll("\"", "'"); String EXP = "{'type':'object'," +"'properties':{'age':{'type':'integer'}," +"'name.first':{'type':'string'},'name.last':{'type':'string'}}}"; assertEquals(EXP, json); } // public void testNumberTypes() throws Exception { JsonSchema jsonSchema = MAPPER.generateJsonSchema(Numbers.class); String json = quotesToApos(jsonSchema.toString()); String EXP = "{'type':'object'," +"'properties':{'dec':{'type':'number'}," +"'bigInt':{'type':'integer'}}}"; assertEquals(EXP, json); } } TestReadJsonSchema.java000066400000000000000000000034621325620701100371730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsonschemapackage com.fasterxml.jackson.databind.jsonschema; import java.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonschema.JsonSchema; /** * Trivial test to ensure JsonSchema can be also deserialized */ @SuppressWarnings("deprecation") public class TestReadJsonSchema extends com.fasterxml.jackson.databind.BaseMapTest { enum SchemaEnum { YES, NO; } static class Schemable { public String name; public char[] nameBuffer; // We'll include tons of stuff, just to force generation of schema public boolean[] states; public byte[] binaryData; public short[] shorts; public int[] ints; public long[] longs; public float[] floats; public double[] doubles; public Object[] objects; public JsonSerializable someSerializable; public Iterable iterableOhYeahBaby; public List extra; public ArrayList extra2; public Iterator extra3; public Map sizes; public EnumMap> whatever; SchemaEnum testEnum; public EnumSet testEnums; } /** * Verifies that a simple schema that is serialized can be * deserialized back to equal schema instance */ public void testDeserializeSimple() throws Exception { ObjectMapper mapper = new ObjectMapper(); JsonSchema schema = mapper.generateJsonSchema(Schemable.class); assertNotNull(schema); String schemaStr = mapper.writeValueAsString(schema); assertNotNull(schemaStr); JsonSchema result = mapper.readValue(schemaStr, JsonSchema.class); assertEquals("Trying to read from '"+schemaStr+"'", schema, result); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontype/000077500000000000000000000000001325620701100324355ustar00rootroot00000000000000AbstractTypeMapping1186Test.java000066400000000000000000000026551325620701100403320ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.List; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; public class AbstractTypeMapping1186Test extends BaseMapTest { public interface IContainer { @JsonProperty("ts") List getTs(); } static class MyContainer implements IContainer { final List ts; @JsonCreator public MyContainer(@JsonProperty("ts") List ts) { this.ts = ts; } @Override public List getTs() { return ts; } } public static class MyObject { public String msg; } public void testDeserializeMyContainer() throws Exception { SimpleModule module = new SimpleModule().addAbstractTypeMapping(IContainer.class, MyContainer.class); final ObjectMapper mapper = new ObjectMapper().registerModule(module); String json = "{\"ts\": [ { \"msg\": \"hello\"} ] }"; final Object o = mapper.readValue(json, mapper.getTypeFactory().constructParametricType(IContainer.class, MyObject.class)); assertEquals(MyContainer.class, o.getClass()); MyContainer myc = (MyContainer) o; assertEquals(1, myc.ts.size()); Object value = myc.ts.get(0); assertEquals(MyObject.class, value.getClass()); } } DefaultTypingWithPrimitivesTest.java000066400000000000000000000025351325620701100415550ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder; import java.util.*; // [databind#1395]: prevent attempts at including type info for primitives public class DefaultTypingWithPrimitivesTest extends BaseMapTest { static class Data { public long key; } public void testDefaultTypingWithLong() throws Exception { Data data = new Data(); data.key = 1L; Map mapData = new HashMap(); mapData.put("longInMap", 2L); mapData.put("longAsField", data); // Configure Jackson to preserve types ObjectMapper mapper = new ObjectMapper(); StdTypeResolverBuilder resolver = new StdTypeResolverBuilder(); resolver.init(JsonTypeInfo.Id.CLASS, null); resolver.inclusion(JsonTypeInfo.As.PROPERTY); resolver.typeProperty("__t"); mapper.setDefaultTyping(resolver); mapper.enable(SerializationFeature.INDENT_OUTPUT); // Serialize String json = mapper.writeValueAsString(mapData); // Deserialize Map result = mapper.readValue(json, Map.class); assertNotNull(result); assertEquals(2, result.size()); } } ExistingPropertyTest.java000066400000000000000000000415311325620701100374240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class ExistingPropertyTest extends BaseMapTest { /** * Polymorphic base class - existing property as simple property on subclasses */ @JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "type", visible=true) @JsonSubTypes({ @Type(value = Apple.class, name = "apple") , @Type(value = Orange.class, name = "orange") }) static abstract class Fruit { public String name; protected Fruit(String n) { name = n; } } @JsonTypeName("apple") static class Apple extends Fruit { public int seedCount; public String type; private Apple() { super(null); } public Apple(String name, int b) { super(name); seedCount = b; type = "apple"; } } @JsonTypeName("orange") static class Orange extends Fruit { public String color; public String type; private Orange() { super(null); } public Orange(String name, String c) { super(name); color = c; type = "orange"; } } static class FruitWrapper { public Fruit fruit; public FruitWrapper() {} public FruitWrapper(Fruit f) { fruit = f; } } /** * Polymorphic base class - existing property forced by abstract method */ @JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "type") @JsonSubTypes({ @Type(value = Dog.class, name = "doggie") , @Type(value = Cat.class, name = "kitty") }) static abstract class Animal { public String name; protected Animal(String n) { name = n; } public abstract String getType(); } @JsonTypeName("doggie") static class Dog extends Animal { public int boneCount; private Dog() { super(null); } public Dog(String name, int b) { super(name); boneCount = b; } @Override public String getType() { return "doggie"; } } @JsonTypeName("kitty") static class Cat extends Animal { public String furColor; private Cat() { super(null); } public Cat(String name, String c) { super(name); furColor = c; } @Override public String getType() { return "kitty"; } } static class AnimalWrapper { public Animal animal; public AnimalWrapper() {} public AnimalWrapper(Animal a) { animal = a; } } /** * Polymorphic base class - existing property NOT forced by abstract method on base class */ @JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "type") @JsonSubTypes({ @Type(value = Accord.class, name = "accord") , @Type(value = Camry.class, name = "camry") }) static abstract class Car { public String name; protected Car(String n) { name = n; } } @JsonTypeName("accord") static class Accord extends Car { public int speakerCount; private Accord() { super(null); } public Accord(String name, int b) { super(name); speakerCount = b; } public String getType() { return "accord"; } } @JsonTypeName("camry") static class Camry extends Car { public String exteriorColor; private Camry() { super(null); } public Camry(String name, String c) { super(name); exteriorColor = c; } public String getType() { return "camry"; } } static class CarWrapper { public Car car; public CarWrapper() {} public CarWrapper(Car c) { car = c; } } // for [databind#1635] @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, // IMPORTANT! Must be defined as `visible` visible=true, property = "type", defaultImpl=Bean1635Default.class) @JsonSubTypes({ @JsonSubTypes.Type(Bean1635A.class) }) static class Bean1635 { public ABC type; } @JsonTypeName("A") static class Bean1635A extends Bean1635 { public int value; } static class Bean1635Default extends Bean1635 { } /* /********************************************************** /* Mock data /********************************************************** */ private static final Orange mandarin = new Orange("Mandarin Orange", "orange"); private static final String mandarinJson = "{\"name\":\"Mandarin Orange\",\"color\":\"orange\",\"type\":\"orange\"}"; private static final Apple pinguo = new Apple("Apple-A-Day", 16); private static final String pinguoJson = "{\"name\":\"Apple-A-Day\",\"seedCount\":16,\"type\":\"apple\"}"; private static final FruitWrapper pinguoWrapper = new FruitWrapper(pinguo); private static final String pinguoWrapperJson = "{\"fruit\":" + pinguoJson + "}"; private static final List fruitList = Arrays.asList(pinguo, mandarin); private static final String fruitListJson = "[" + pinguoJson + "," + mandarinJson + "]"; private static final Cat beelzebub = new Cat("Beelzebub", "tabby"); private static final String beelzebubJson = "{\"name\":\"Beelzebub\",\"furColor\":\"tabby\",\"type\":\"kitty\"}"; private static final Dog rover = new Dog("Rover", 42); private static final String roverJson = "{\"name\":\"Rover\",\"boneCount\":42,\"type\":\"doggie\"}"; private static final AnimalWrapper beelzebubWrapper = new AnimalWrapper(beelzebub); private static final String beelzebubWrapperJson = "{\"animal\":" + beelzebubJson + "}"; private static final List animalList = Arrays.asList(beelzebub, rover); private static final String animalListJson = "[" + beelzebubJson + "," + roverJson + "]"; private static final Camry camry = new Camry("Sweet Ride", "candy-apple-red"); private static final String camryJson = "{\"name\":\"Sweet Ride\",\"exteriorColor\":\"candy-apple-red\",\"type\":\"camry\"}"; private static final Accord accord = new Accord("Road Rage", 6); private static final String accordJson = "{\"name\":\"Road Rage\",\"speakerCount\":6,\"type\":\"accord\"}"; private static final CarWrapper camryWrapper = new CarWrapper(camry); private static final String camryWrapperJson = "{\"car\":" + camryJson + "}"; private static final List carList = Arrays.asList(camry, accord); private static final String carListJson = "[" + camryJson + "," + accordJson + "]"; /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); /** * Fruits - serialization tests for simple property on sub-classes */ public void testExistingPropertySerializationFruits() throws Exception { Map result = writeAndMap(MAPPER, pinguo); assertEquals(3, result.size()); assertEquals(pinguo.name, result.get("name")); assertEquals(pinguo.seedCount, result.get("seedCount")); assertEquals(pinguo.type, result.get("type")); result = writeAndMap(MAPPER, mandarin); assertEquals(3, result.size()); assertEquals(mandarin.name, result.get("name")); assertEquals(mandarin.color, result.get("color")); assertEquals(mandarin.type, result.get("type")); String pinguoSerialized = MAPPER.writeValueAsString(pinguo); assertEquals(pinguoSerialized, pinguoJson); String mandarinSerialized = MAPPER.writeValueAsString(mandarin); assertEquals(mandarinSerialized, mandarinJson); String fruitWrapperSerialized = MAPPER.writeValueAsString(pinguoWrapper); assertEquals(fruitWrapperSerialized, pinguoWrapperJson); String fruitListSerialized = MAPPER.writeValueAsString(fruitList); assertEquals(fruitListSerialized, fruitListJson); } /** * Fruits - deserialization tests for simple property on sub-classes */ public void testSimpleClassAsExistingPropertyDeserializationFruits() throws Exception { Fruit pinguoDeserialized = MAPPER.readValue(pinguoJson, Fruit.class); assertTrue(pinguoDeserialized instanceof Apple); assertSame(pinguoDeserialized.getClass(), Apple.class); assertEquals(pinguo.name, pinguoDeserialized.name); assertEquals(pinguo.seedCount, ((Apple) pinguoDeserialized).seedCount); assertEquals(pinguo.type, ((Apple) pinguoDeserialized).type); FruitWrapper pinguoWrapperDeserialized = MAPPER.readValue(pinguoWrapperJson, FruitWrapper.class); Fruit pinguoExtracted = pinguoWrapperDeserialized.fruit; assertTrue(pinguoExtracted instanceof Apple); assertSame(pinguoExtracted.getClass(), Apple.class); assertEquals(pinguo.name, pinguoExtracted.name); assertEquals(pinguo.seedCount, ((Apple) pinguoExtracted).seedCount); assertEquals(pinguo.type, ((Apple) pinguoExtracted).type); Fruit[] fruits = MAPPER.readValue(fruitListJson, Fruit[].class); assertEquals(2, fruits.length); assertEquals(Apple.class, fruits[0].getClass()); assertEquals("apple", ((Apple) fruits[0]).type); assertEquals(Orange.class, fruits[1].getClass()); assertEquals("orange", ((Orange) fruits[1]).type); List f2 = MAPPER.readValue(fruitListJson, new TypeReference>() { }); assertNotNull(f2); assertTrue(f2.size() == 2); assertEquals(Apple.class, f2.get(0).getClass()); assertEquals(Orange.class, f2.get(1).getClass()); } /** * Animals - serialization tests for abstract method in base class */ public void testExistingPropertySerializationAnimals() throws Exception { Map result = writeAndMap(MAPPER, beelzebub); assertEquals(3, result.size()); assertEquals(beelzebub.name, result.get("name")); assertEquals(beelzebub.furColor, result.get("furColor")); assertEquals(beelzebub.getType(), result.get("type")); result = writeAndMap(MAPPER, rover); assertEquals(3, result.size()); assertEquals(rover.name, result.get("name")); assertEquals(rover.boneCount, result.get("boneCount")); assertEquals(rover.getType(), result.get("type")); String beelzebubSerialized = MAPPER.writeValueAsString(beelzebub); assertEquals(beelzebubSerialized, beelzebubJson); String roverSerialized = MAPPER.writeValueAsString(rover); assertEquals(roverSerialized, roverJson); String animalWrapperSerialized = MAPPER.writeValueAsString(beelzebubWrapper); assertEquals(animalWrapperSerialized, beelzebubWrapperJson); String animalListSerialized = MAPPER.writeValueAsString(animalList); assertEquals(animalListSerialized, animalListJson); } /** * Animals - deserialization tests for abstract method in base class */ public void testSimpleClassAsExistingPropertyDeserializationAnimals() throws Exception { Animal beelzebubDeserialized = MAPPER.readValue(beelzebubJson, Animal.class); assertTrue(beelzebubDeserialized instanceof Cat); assertSame(beelzebubDeserialized.getClass(), Cat.class); assertEquals(beelzebub.name, beelzebubDeserialized.name); assertEquals(beelzebub.furColor, ((Cat) beelzebubDeserialized).furColor); assertEquals(beelzebub.getType(), beelzebubDeserialized.getType()); AnimalWrapper beelzebubWrapperDeserialized = MAPPER.readValue(beelzebubWrapperJson, AnimalWrapper.class); Animal beelzebubExtracted = beelzebubWrapperDeserialized.animal; assertTrue(beelzebubExtracted instanceof Cat); assertSame(beelzebubExtracted.getClass(), Cat.class); assertEquals(beelzebub.name, beelzebubExtracted.name); assertEquals(beelzebub.furColor, ((Cat) beelzebubExtracted).furColor); assertEquals(beelzebub.getType(), beelzebubExtracted.getType()); @SuppressWarnings("unchecked") List animalListDeserialized = MAPPER.readValue(animalListJson, List.class); assertNotNull(animalListDeserialized); assertTrue(animalListDeserialized.size() == 2); Animal cat = MAPPER.convertValue(animalListDeserialized.get(0), Animal.class); assertTrue(cat instanceof Cat); assertSame(cat.getClass(), Cat.class); Animal dog = MAPPER.convertValue(animalListDeserialized.get(1), Animal.class); assertTrue(dog instanceof Dog); assertSame(dog.getClass(), Dog.class); } /** * Cars - serialization tests for no abstract method or type variable in base class */ public void testExistingPropertySerializationCars() throws Exception { Map result = writeAndMap(MAPPER, camry); assertEquals(3, result.size()); assertEquals(camry.name, result.get("name")); assertEquals(camry.exteriorColor, result.get("exteriorColor")); assertEquals(camry.getType(), result.get("type")); result = writeAndMap(MAPPER, accord); assertEquals(3, result.size()); assertEquals(accord.name, result.get("name")); assertEquals(accord.speakerCount, result.get("speakerCount")); assertEquals(accord.getType(), result.get("type")); String camrySerialized = MAPPER.writeValueAsString(camry); assertEquals(camrySerialized, camryJson); String accordSerialized = MAPPER.writeValueAsString(accord); assertEquals(accordSerialized, accordJson); String carWrapperSerialized = MAPPER.writeValueAsString(camryWrapper); assertEquals(carWrapperSerialized, camryWrapperJson); String carListSerialized = MAPPER.writeValueAsString(carList); assertEquals(carListSerialized, carListJson); } /** * Cars - deserialization tests for no abstract method or type variable in base class */ public void testSimpleClassAsExistingPropertyDeserializationCars() throws Exception { Car camryDeserialized = MAPPER.readValue(camryJson, Camry.class); assertTrue(camryDeserialized instanceof Camry); assertSame(camryDeserialized.getClass(), Camry.class); assertEquals(camry.name, camryDeserialized.name); assertEquals(camry.exteriorColor, ((Camry) camryDeserialized).exteriorColor); assertEquals(camry.getType(), ((Camry) camryDeserialized).getType()); CarWrapper camryWrapperDeserialized = MAPPER.readValue(camryWrapperJson, CarWrapper.class); Car camryExtracted = camryWrapperDeserialized.car; assertTrue(camryExtracted instanceof Camry); assertSame(camryExtracted.getClass(), Camry.class); assertEquals(camry.name, camryExtracted.name); assertEquals(camry.exteriorColor, ((Camry) camryExtracted).exteriorColor); assertEquals(camry.getType(), ((Camry) camryExtracted).getType()); @SuppressWarnings("unchecked") List carListDeserialized = MAPPER.readValue(carListJson, List.class); assertNotNull(carListDeserialized); assertTrue(carListDeserialized.size() == 2); Car result = MAPPER.convertValue(carListDeserialized.get(0), Car.class); assertTrue(result instanceof Camry); assertSame(result.getClass(), Camry.class); result = MAPPER.convertValue(carListDeserialized.get(1), Car.class); assertTrue(result instanceof Accord); assertSame(result.getClass(), Accord.class); } // for [databind#1635]: simple usage public void testExistingEnumTypeId() throws Exception { Bean1635 result = MAPPER.readValue(aposToQuotes("{'value':3, 'type':'A'}"), Bean1635.class); assertEquals(Bean1635A.class, result.getClass()); Bean1635A bean = (Bean1635A) result; assertEquals(3, bean.value); assertEquals(ABC.A, bean.type); } // for [databind#1635]: verify that `defaultImpl` does not block assignment of // type id public void testExistingEnumTypeIdViaDefault() throws Exception { Bean1635 result = MAPPER.readValue(aposToQuotes("{'type':'C'}"), Bean1635.class); assertEquals(Bean1635Default.class, result.getClass()); assertEquals(ABC.C, result.type); } } Generic1128Test.java000066400000000000000000000041701325620701100357530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class Generic1128Test extends BaseMapTest { @SuppressWarnings("rawtypes") static abstract class HObj { public long id; // important: do not serialize as subtype, but only as type that // is statically recognizable here. @JsonSerialize(typing=JsonSerialize.Typing.STATIC) public M parent; } static class DevBase extends HObj { public String tag; // for some reason, setter is needed to expose this... public void setTag(String t) { tag = t; } //public String getTag() { return tag; } } static class Dev extends DevBase { public long p1; public void setP1(long l) { p1 = l; } public long getP1() { return p1; } } static class DevM extends Dev { private long m1; public long getM1() { return m1; } // public void setM1(int m) { m1 = m; } } static abstract class ContainerBase { public T entity; } static class DevMContainer extends ContainerBase{ } public void testIssue1128() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); final DevMContainer devMContainer1 = new DevMContainer(); final DevM entity = new DevM(); final Dev parent = new Dev(); parent.id = 2L; entity.parent = parent; devMContainer1.entity = entity; String json = mapper.writeValueAsString(devMContainer1); // System.out.println("serializedContainer = " + json); final DevMContainer devMContainer = mapper.readValue(json, DevMContainer.class); long id = devMContainer.entity.parent.id; // System.out.println("devMContainer.getEntity().getParent().getId() = " + id); assertEquals(2, id); } } GenericTypeId1735Test.java000066400000000000000000000037351325620701100371040ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidTypeIdException; // for [databind#1735]: public class GenericTypeId1735Test extends BaseMapTest { static class Wrapper1735 { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") public Payload1735 w; } static class Payload1735 { public void setValue(String str) { } } static class Nefarious1735 { public Nefarious1735() { throw new Error("Never call this constructor"); } public void setValue(String str) { throw new Error("Never call this setter"); } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); private final static String NEF_CLASS = Nefarious1735.class.getName(); // Existing checks should kick in fine public void testSimpleTypeCheck1735() throws Exception { try { MAPPER.readValue(aposToQuotes( "{'w':{'type':'"+NEF_CLASS+"'}}"), Wrapper1735.class); fail("Should not pass"); } catch (InvalidTypeIdException e) { verifyException(e, "could not resolve type id"); verifyException(e, "not a subtype"); } } // but this was not being verified early enough public void testNestedTypeCheck1735() throws Exception { try { MAPPER.readValue(aposToQuotes( "{'w':{'type':'java.util.HashMap'}}"), Wrapper1735.class); fail("Should not pass"); } catch (InvalidTypeIdException e) { verifyException(e, "could not resolve type id"); verifyException(e, "not a subtype"); } } } NoTypeInfoTest.java000066400000000000000000000022301325620701100361100ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class NoTypeInfoTest extends BaseMapTest { @JsonTypeInfo(use=JsonTypeInfo.Id.NONE) @JsonDeserialize(as=NoType.class) static interface NoTypeInterface { } final static class NoType implements NoTypeInterface { public int a = 3; } /* /********************************************************** /* Test methods /********************************************************** */ public void testWithIdNone() throws Exception { final ObjectMapper mapper = newObjectMapper(); mapper.enableDefaultTyping(); // serialize without type info String json = mapper.writeValueAsString(new NoType()); assertEquals("{\"a\":3}", json); // and deserialize successfully NoTypeInterface bean = mapper.readValue("{\"a\":6}", NoTypeInterface.class); assertNotNull(bean); NoType impl = (NoType) bean; assertEquals(6, impl.a); } } PolymorphicList1451SerTest.java000066400000000000000000000032021325620701100402040ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class PolymorphicList1451SerTest extends BaseMapTest { @JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") public static class A { public String a; } public static class B extends A { public String b; } private final String CLASS_NAME = getClass().getSimpleName(); public void testCollectionWithTypeInfo() throws Exception { ObjectMapper mapper = new ObjectMapper() .disable(SerializationFeature.EAGER_SERIALIZER_FETCH) // .disable(DeserializationFeature.EAGER_DESERIALIZER_FETCH) ; List input = new ArrayList(); A a = new A(); a.a = "a1"; input.add(a); B b = new B(); b.b = "b"; b.a = "a2"; input.add(b); final TypeReference typeRef = new TypeReference>(){}; ObjectWriter writer = mapper.writerFor(typeRef); String result = writer.writeValueAsString(input); assertEquals(aposToQuotes( "[{'@class':'."+CLASS_NAME+"$A','a':'a1'},{'@class':'."+CLASS_NAME+"$B','a':'a2','b':'b'}]" ), result); List output = mapper.readerFor(typeRef) .readValue(result); assertEquals(2, output.size()); assertEquals(A.class, output.get(0).getClass()); assertEquals(B.class, output.get(1).getClass()); } } PolymorphicViaRefTypeTest.java000066400000000000000000000051021325620701100403230ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; public class PolymorphicViaRefTypeTest extends BaseMapTest { @JsonSubTypes({ @JsonSubTypes.Type(name = "impl5", value = ImplForAtomic.class) }) static class BaseForAtomic { } static class ImplForAtomic extends BaseForAtomic { public int x; protected ImplForAtomic() { } public ImplForAtomic(int x) { this.x = x; } } static class TypeInfoAtomic { @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "$type") public AtomicReference value; } static class AtomicStringWrapper { public AtomicReference wrapper; protected AtomicStringWrapper() { } public AtomicStringWrapper(String str) { wrapper = new AtomicReference(new StringWrapper(str)); } } /* /********************************************************************** /* Test methods /********************************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testPolymorphicAtomicRefProperty() throws Exception { TypeInfoAtomic data = new TypeInfoAtomic(); data.value = new AtomicReference(new ImplForAtomic(42)); String json = MAPPER.writeValueAsString(data); TypeInfoAtomic result = MAPPER.readValue(json, TypeInfoAtomic.class); assertNotNull(result); BaseForAtomic value = result.value.get(); assertNotNull(value); assertEquals(ImplForAtomic.class, value.getClass()); assertEquals(42, ((ImplForAtomic) value).x); } public void testAtomicRefViaDefaultTyping() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(DefaultTyping.NON_FINAL); AtomicStringWrapper data = new AtomicStringWrapper("foo"); String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(data); AtomicStringWrapper result = mapper.readValue(json, AtomicStringWrapper.class); assertNotNull(result); assertNotNull(result.wrapper); assertEquals(AtomicReference.class, result.wrapper.getClass()); StringWrapper w = result.wrapper.get(); assertEquals("foo", w.str); } } TestAbstractContainers.java000066400000000000000000000053061325620701100376560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * For [databind#292] */ @SuppressWarnings("serial") public class TestAbstractContainers extends BaseMapTest { // Polymorphic abstract Map type, wrapper @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type") @JsonSubTypes({ @JsonSubTypes.Type(value = MapWrapper.class, name = "wrapper"), }) static class MapWrapper { public IDataValueMap map = new DataValueMap(); // This does NOT work } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="_type_") @JsonSubTypes({ @JsonSubTypes.Type(value = DataValueMap.class, name = "DataValueMap") }) public interface IDataValueMap extends Map { } static class DataValueMap extends HashMap implements IDataValueMap { } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type") @JsonSubTypes({ @JsonSubTypes.Type(value = ListWrapper.class, name = "wrapper"), }) static class ListWrapper { public IDataValueList list = new DataValueList(); // This does NOT work } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type") @JsonSubTypes({ @JsonSubTypes.Type(value = DataValueList.class, name = "list") }) public interface IDataValueList extends List { } static class DataValueList extends LinkedList implements IDataValueList { } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testAbstractLists() throws Exception { ListWrapper w = new ListWrapper(); w.list.add("x"); String json = MAPPER.writeValueAsString(w); Object o = MAPPER.readValue(json, ListWrapper.class); assertEquals(ListWrapper.class, o.getClass()); ListWrapper out = (ListWrapper) o; assertNotNull(out.list); assertEquals(1, out.list.size()); assertEquals("x", out.list.get(0)); } public void testAbstractMaps() throws Exception { MapWrapper w = new MapWrapper(); w.map.put("key1", "name1"); String json = MAPPER.writeValueAsString(w); Object o = MAPPER.readValue(json, MapWrapper.class); assertEquals(MapWrapper.class, o.getClass()); MapWrapper out = (MapWrapper) o; assertEquals(1, out.map.size()); } } TestAbstractTypeNames.java000066400000000000000000000105421325620701100374540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; /** * Unit tests for checking how combination of interfaces, implementation * classes are handled, with respect to type names. */ public class TestAbstractTypeNames extends BaseMapTest { @JsonTypeName("Employee") public interface Employee extends User { public abstract String getEmployer(); } @JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="userType") @JsonTypeName("User") @JsonSubTypes({ @JsonSubTypes.Type(value=Employee.class,name="Employee") }) public interface User { public abstract String getName(); public abstract List getFriends(); } @JsonTypeName("Employee") static class DefaultEmployee extends DefaultUser implements Employee { private String _employer; @JsonCreator public DefaultEmployee(@JsonProperty("name") String name, @JsonProperty("friends") List friends, @JsonProperty("employer") String employer) { super(name, friends); _employer = employer; } @Override public String getEmployer() { return _employer; } } @JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="userType") @JsonTypeName("User") @JsonSubTypes({ @JsonSubTypes.Type(value=DefaultEmployee.class,name="Employee") }) static class DefaultUser implements User { private String _name; private List _friends; @JsonCreator public DefaultUser(@JsonProperty("name") String name, @JsonProperty("friends") List friends) { super(); _name = name; _friends = friends; } @Override public String getName() { return _name; } @Override public List getFriends() { return _friends; } } static class BaseValue { public int value = 42; public int getValue() { return value; } } final static class BeanWithAnon { public BaseValue bean = new BaseValue() { @Override public String toString() { return "sub!"; } }; } /* /********************************************************** /* Unit tests /********************************************************** */ // Testing [JACKSON-498], partial fix public void testEmptyCollection() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.INDENT_OUTPUT, true); Listfriends = new ArrayList(); friends.add(new DefaultUser("Joe Hildebrandt", null)); friends.add(new DefaultEmployee("Richard Nasr",null,"MDA")); User user = new DefaultEmployee("John Vanspronssen", friends, "MDA"); String json = mapper.writeValueAsString(user); /* 24-Feb-2011, tatu: For now let's simply require registration of * concrete subtypes; can't think of a way to avoid that for now */ mapper = new ObjectMapper(); mapper.registerSubtypes(DefaultEmployee.class); mapper.registerSubtypes(DefaultUser.class); User result = mapper.readValue(json, User.class); assertNotNull(result); assertEquals(DefaultEmployee.class, result.getClass()); friends = result.getFriends(); assertEquals(2, friends.size()); assertEquals(DefaultUser.class, friends.get(0).getClass()); assertEquals(DefaultEmployee.class, friends.get(1).getClass()); } // [JACKSON-584]: change anonymous non-static inner type into static type: public void testInnerClassWithType() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(DefaultTyping.NON_FINAL); String json = mapper.writeValueAsString(new BeanWithAnon()); BeanWithAnon result = mapper.readValue(json, BeanWithAnon.class); assertEquals(BeanWithAnon.class, result.getClass()); } } TestCustomTypeIdResolver.java000066400000000000000000000154421325620701100402020ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver; import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; import com.fasterxml.jackson.databind.type.TypeFactory; public class TestCustomTypeIdResolver extends BaseMapTest { @JsonTypeInfo(use=Id.CUSTOM, include=As.WRAPPER_OBJECT) @JsonTypeIdResolver(CustomResolver.class) static abstract class CustomBean { } static class CustomBeanImpl extends CustomBean { public int x; public CustomBeanImpl() { } public CustomBeanImpl(int x) { this.x = x; } } static class ExtBeanWrapper { @JsonTypeInfo(use=Id.CUSTOM, include=As.EXTERNAL_PROPERTY, property="type") @JsonTypeIdResolver(ExtResolver.class) public ExtBean value; } static class CustomResolver extends TestCustomResolverBase { // yes, static: just for test purposes, not real use static List initTypes; public CustomResolver() { super(CustomBean.class, CustomBeanImpl.class); } @Override public void init(JavaType baseType) { if (initTypes != null) { initTypes.add(baseType); } } } static abstract class ExtBean { } static class ExtBeanImpl extends ExtBean { public int y; public ExtBeanImpl() { } public ExtBeanImpl(int y) { this.y = y; } } static class ExtResolver extends TestCustomResolverBase { public ExtResolver() { super(ExtBean.class, ExtBeanImpl.class); } } static class TestCustomResolverBase extends TypeIdResolverBase { protected final Class superType; protected final Class subType; public TestCustomResolverBase(Class baseType, Class implType) { superType = baseType; subType = implType; } @Override public Id getMechanism() { return Id.CUSTOM; } @Override public String idFromValue(Object value) { if (superType.isAssignableFrom(value.getClass())) { return "*"; } return "unknown"; } @Override public String idFromValueAndType(Object value, Class type) { return idFromValue(value); } @Override public void init(JavaType baseType) { } @Override public JavaType typeFromId(DatabindContext context, String id) { if ("*".equals(id)) { return TypeFactory.defaultInstance().constructType(subType); } return null; } @Override public String idFromBaseType() { return "xxx"; } } // for [databind#1270] static class Top1270 { @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonTypeIdResolver(Resolver1270.class) public Base1270 b; } static class Base1270 { public O options; public String val; } static abstract class Poly1Base { } static class Poly1 extends Poly1Base { public String val; } static class Resolver1270 implements TypeIdResolver { public Resolver1270() { } @Override public void init(JavaType baseType) { } @Override public String idFromValue(Object value) { if (value.getClass() == Base1270.class) { return "poly1"; } return null; } @Override public String idFromValueAndType(Object value, Class suggestedType) { return idFromValue(value); } @Override public String idFromBaseType() { return null; } @Override public JavaType typeFromId(DatabindContext context, String id) { if ("poly1".equals(id)) { return context.getTypeFactory() .constructType(new TypeReference>() { }); } return null; } @Override public String getDescForKnownTypeIds() { return null; } @Override public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.CUSTOM; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testCustomTypeIdResolver() throws Exception { List types = new ArrayList(); CustomResolver.initTypes = types; String json = MAPPER.writeValueAsString(new CustomBean[] { new CustomBeanImpl(28) }); assertEquals("[{\"*\":{\"x\":28}}]", json); assertEquals(1, types.size()); assertEquals(CustomBean.class, types.get(0).getRawClass()); types = new ArrayList(); CustomResolver.initTypes = types; CustomBean[] result = MAPPER.readValue(json, CustomBean[].class); assertNotNull(result); assertEquals(1, result.length); assertEquals(28, ((CustomBeanImpl) result[0]).x); assertEquals(1, types.size()); assertEquals(CustomBean.class, types.get(0).getRawClass()); } public void testCustomWithExternal() throws Exception { ExtBeanWrapper w = new ExtBeanWrapper(); w.value = new ExtBeanImpl(12); String json = MAPPER.writeValueAsString(w); ExtBeanWrapper out = MAPPER.readValue(json, ExtBeanWrapper.class); assertNotNull(out); assertEquals(12, ((ExtBeanImpl) out.value).y); } // for [databind#1270] public void testPolymorphicTypeViaCustom() throws Exception { Base1270 req = new Base1270(); Poly1 o = new Poly1(); o.val = "optionValue"; req.options = o; req.val = "some value"; Top1270 top = new Top1270(); top.b = req; String json = MAPPER.writeValueAsString(top); JsonNode tree = MAPPER.readTree(json); assertNotNull(tree.get("b")); assertNotNull(tree.get("b").get("options")); assertNotNull(tree.get("b").get("options").get("val")); // Can we reverse the process? I have some doubts Top1270 itemRead = MAPPER.readValue(json, Top1270.class); assertNotNull(itemRead); assertNotNull(itemRead.b); } } TestDefaultForArrays.java000066400000000000000000000135101325620701100372760ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; public class TestDefaultForArrays extends BaseMapTest { /* /********************************************************** /* Helper types /********************************************************** */ static class ArrayBean { public Object[] values; public ArrayBean() { this(null); } public ArrayBean(Object[] v) { values = v; } } static class PrimitiveArrayBean { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) public Object stuff; protected PrimitiveArrayBean() { } public PrimitiveArrayBean(Object value) { stuff = value; } } /* /********************************************************** /* Unit tests /********************************************************** */ /** * Simple unit test for verifying that we get String array * back, even though declared type is Object array */ public void testArrayTypingSimple() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(DefaultTyping.NON_CONCRETE_AND_ARRAYS); ArrayBean bean = new ArrayBean(new String[0]); String json = m.writeValueAsString(bean); ArrayBean result = m.readValue(json, ArrayBean.class); assertNotNull(result.values); assertEquals(String[].class, result.values.getClass()); } // And let's try it with deeper array as well public void testArrayTypingNested() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(DefaultTyping.NON_CONCRETE_AND_ARRAYS); ArrayBean bean = new ArrayBean(new String[0][0]); String json = m.writeValueAsString(bean); ArrayBean result = m.readValue(json, ArrayBean.class); assertNotNull(result.values); assertEquals(String[][].class, result.values.getClass()); } public void testNodeInArray() throws Exception { JsonNode node = new ObjectMapper().readTree("{\"a\":3}"); ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(DefaultTyping.JAVA_LANG_OBJECT); Object[] obs = new Object[] { node }; String json = m.writeValueAsString(obs); Object[] result = m.readValue(json, Object[].class); assertEquals(1, result.length); Object ob = result[0]; assertTrue(ob instanceof JsonNode); } @SuppressWarnings("deprecation") public void testNodeInEmptyArray() throws Exception { Map> outerMap = new HashMap>(); outerMap.put("inner", new ArrayList()); ObjectMapper m = new ObjectMapper().disable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS); JsonNode tree = m.convertValue(outerMap, JsonNode.class); String json = m.writeValueAsString(tree); assertEquals("{}", json); JsonNode node = new ObjectMapper().readTree("{\"a\":[]}"); m.enableDefaultTyping(DefaultTyping.JAVA_LANG_OBJECT); Object[] obs = new Object[] { node }; json = m.writeValueAsString(obs); Object[] result = m.readValue(json, Object[].class); assertEquals("{}", result[0].toString()); } public void testArraysOfArrays() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); Object value = new Object[][] { new Object[] {} }; String json = mapper.writeValueAsString(value); // try with different (but valid) nominal types: _testArraysAs(mapper, json, Object[][].class); _testArraysAs(mapper, json, Object[].class); _testArraysAs(mapper, json, Object.class); } public void testArrayTypingForPrimitiveArrays() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(DefaultTyping.NON_CONCRETE_AND_ARRAYS); _testArrayTypingForPrimitiveArrays(m, new int[] { 1, 2, 3 }); _testArrayTypingForPrimitiveArrays(m, new long[] { 1, 2, 3 }); _testArrayTypingForPrimitiveArrays(m, new short[] { 1, 2, 3 }); _testArrayTypingForPrimitiveArrays(m, new double[] { 0.5, 5.5, -1.0 }); _testArrayTypingForPrimitiveArrays(m, new float[] { 0.5f, 5.5f, -1.0f }); _testArrayTypingForPrimitiveArrays(m, new boolean[] { true, false }); _testArrayTypingForPrimitiveArrays(m, new byte[] { 1, 2, 3 }); _testArrayTypingForPrimitiveArrays(m, new char[] { 'a', 'b' }); } private void _testArrayTypingForPrimitiveArrays(ObjectMapper mapper, Object v) throws Exception { PrimitiveArrayBean input = new PrimitiveArrayBean(v); String json = mapper.writeValueAsString(input); PrimitiveArrayBean result = mapper.readValue(json, PrimitiveArrayBean.class); assertNotNull(result.stuff); assertSame(v.getClass(), result.stuff.getClass()); } /* /********************************************************** /* Helper methods /********************************************************** */ protected void _testArraysAs(ObjectMapper mapper, String json, Class type) throws Exception { Object o = mapper.readValue(json, type); assertNotNull(o); assertTrue(o instanceof Object[]); Object[] main = (Object[]) o; assertEquals(1, main.length); Object element = main[0]; assertNotNull(element); assertTrue(element instanceof Object[]); assertEquals(0, ((Object[]) element).length); } } TestDefaultForEnums.java000066400000000000000000000046361325620701100371350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.concurrent.TimeUnit; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class TestDefaultForEnums extends BaseMapTest { public enum TestEnum { A, B; } static final class EnumHolder { public Object value; // "untyped" public EnumHolder() { } public EnumHolder(TestEnum e) { value = e; } } protected static class TimeUnitBean { public TimeUnit timeUnit; } /* /********************************************************** /* Test methods /********************************************************** */ public void testSimpleEnumBean() throws Exception { TimeUnitBean bean = new TimeUnitBean(); bean.timeUnit = TimeUnit.SECONDS; // First, without type info ObjectMapper m = new ObjectMapper(); String json = m.writeValueAsString(bean); TimeUnitBean result = m.readValue(json, TimeUnitBean.class); assertEquals(TimeUnit.SECONDS, result.timeUnit); // then with type info m = new ObjectMapper(); m.enableDefaultTyping(); json = m.writeValueAsString(bean); result = m.readValue(json, TimeUnitBean.class); assertEquals(TimeUnit.SECONDS, result.timeUnit); } public void testSimpleEnumsInObjectArray() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); // Typing is needed for enums String json = m.writeValueAsString(new Object[] { TestEnum.A }); assertEquals("[[\"com.fasterxml.jackson.databind.jsontype.TestDefaultForEnums$TestEnum\",\"A\"]]", json); // and let's verify we get it back ok as well: Object[] value = m.readValue(json, Object[].class); assertEquals(1, value.length); assertSame(TestEnum.A, value[0]); } public void testSimpleEnumsAsField() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); String json = m.writeValueAsString(new EnumHolder(TestEnum.B)); assertEquals("{\"value\":[\"com.fasterxml.jackson.databind.jsontype.TestDefaultForEnums$TestEnum\",\"B\"]}", json); EnumHolder holder = m.readValue(json, EnumHolder.class); assertSame(TestEnum.B, holder.value); } } TestDefaultForLists.java000066400000000000000000000113701325620701100371350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; public class TestDefaultForLists extends BaseMapTest { /* /********************************************************** /* Helper types /********************************************************** */ /** * Wrapper bean needed before there is a way to force * type of the root value. Long is used because it is a final * type, but not one of "untypeable" ones. */ static class ListOfLongs { public List longs; public ListOfLongs() { } public ListOfLongs(Long ... ls) { longs = new ArrayList(); for (Long l: ls) { longs.add(l); } } } static class ListOfNumbers { public List nums; public ListOfNumbers() { } public ListOfNumbers(Number ... numbers) { nums = new ArrayList(); for (Number n : numbers) { nums.add(n); } } } static class ObjectListBean { public List values; } interface Foo { } static class SetBean { public Set names; public SetBean() { } public SetBean(String str) { names = new HashSet(); names.add(str); } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testListOfLongs() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); ListOfLongs input = new ListOfLongs(1L, 2L, 3L); String json = m.writeValueAsString(input); assertEquals("{\"longs\":[\"java.util.ArrayList\",[1,2,3]]}", json); ListOfLongs output = m.readValue(json, ListOfLongs.class); assertNotNull(output.longs); assertEquals(3, output.longs.size()); assertEquals(Long.valueOf(1L), output.longs.get(0)); assertEquals(Long.valueOf(2L), output.longs.get(1)); assertEquals(Long.valueOf(3L), output.longs.get(2)); } /** * Then bit more heterogenous list; also tests mixing of * regular scalar types, and non-typed ones (int and double * will never have type info added; other numbers will if * necessary) */ public void testListOfNumbers() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); ListOfNumbers input = new ListOfNumbers(Long.valueOf(1L), Integer.valueOf(2), Double.valueOf(3.0)); String json = m.writeValueAsString(input); assertEquals("{\"nums\":[\"java.util.ArrayList\",[[\"java.lang.Long\",1],2,3.0]]}", json); ListOfNumbers output = m.readValue(json, ListOfNumbers.class); assertNotNull(output.nums); assertEquals(3, output.nums.size()); assertEquals(Long.valueOf(1L), output.nums.get(0)); assertEquals(Integer.valueOf(2), output.nums.get(1)); assertEquals(Double.valueOf(3.0), output.nums.get(2)); } public void testDateTypes() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); ObjectListBean input = new ObjectListBean(); List inputList = new ArrayList(); inputList.add(TimeZone.getTimeZone("EST")); inputList.add(Locale.CHINESE); input.values = inputList; String json = m.writeValueAsString(input); ObjectListBean output = m.readValue(json, ObjectListBean.class); List outputList = output.values; assertEquals(2, outputList.size()); assertTrue(outputList.get(0) instanceof TimeZone); assertTrue(outputList.get(1) instanceof Locale); } public void testJackson628() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(DefaultTyping.NON_FINAL); ArrayList data = new ArrayList(); String json = mapper.writeValueAsString(data); List output = mapper.readValue(json, List.class); assertTrue(output.isEmpty()); } public void testJackson667() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); String json = mapper.writeValueAsString(new SetBean("abc")); SetBean bean = mapper.readValue(json, SetBean.class); assertNotNull(bean); assertTrue(bean.names instanceof HashSet); } } TestDefaultForMaps.java000066400000000000000000000132371325620701100367430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.jsontype.impl.TypeNameIdResolver; import com.fasterxml.jackson.databind.type.TypeFactory; public class TestDefaultForMaps extends BaseMapTest { static class MapKey { public String key; public MapKey(String k) { key = k; } @Override public String toString() { return key; } } static class MapKeyDeserializer extends KeyDeserializer { @Override public Object deserializeKey(String key, DeserializationContext ctxt) { return new MapKey(key); } } static class MapHolder { @JsonDeserialize(keyAs=MapKey.class, keyUsing=MapKeyDeserializer.class) public Map> map; } // // For #234 static class ItemList { public String value; public List childItems = new LinkedList(); public void addChildItem(ItemList l) { childItems.add(l); } } static class ItemMap { public String value; public Map> childItems = new HashMap>(); public void addChildItem(String key, ItemMap childItem) { List items; if (childItems.containsKey(key)) { items = childItems.get(key); } else { items = new ArrayList(); } items.add(childItem); childItems.put(key, items); } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testJackson428() throws Exception { ObjectMapper serMapper = new ObjectMapper(); TypeResolverBuilder serializerTyper = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL); serializerTyper = serializerTyper.init(JsonTypeInfo.Id.NAME, createTypeNameIdResolver(true)); serializerTyper = serializerTyper.inclusion(JsonTypeInfo.As.PROPERTY); serMapper.setDefaultTyping(serializerTyper); // Let's start by constructing something to serialize first MapHolder holder = new MapHolder(); holder.map = new HashMap>(); List ints = new ArrayList(); ints.add(Integer.valueOf(3)); holder.map.put(new MapKey("key"), ints); String json = serMapper.writeValueAsString(holder); // Then deserialize: need separate mapper to initialize type id resolver appropriately ObjectMapper deserMapper = new ObjectMapper(); TypeResolverBuilder deserializerTyper = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL); deserializerTyper = deserializerTyper.init(JsonTypeInfo.Id.NAME, createTypeNameIdResolver(false)); deserializerTyper = deserializerTyper.inclusion(JsonTypeInfo.As.PROPERTY); deserMapper.setDefaultTyping(deserializerTyper); MapHolder result = deserMapper.readValue(json, MapHolder.class); assertNotNull(result); Map map = result.map; assertEquals(1, map.size()); Map.Entry entry = map.entrySet().iterator().next(); Object key = entry.getKey(); assertEquals(MapKey.class, key.getClass()); Object value = entry.getValue(); assertTrue(value instanceof List); List list = (List) value; assertEquals(1, list.size()); assertEquals(Integer.class, list.get(0).getClass()); assertEquals(Integer.valueOf(3), list.get(0)); } protected TypeNameIdResolver createTypeNameIdResolver(boolean forSerialization) { Collection subtypes = new ArrayList(); subtypes.add(new NamedType(MapHolder.class, "mapHolder")); subtypes.add(new NamedType(ArrayList.class, "AList")); subtypes.add(new NamedType(HashMap.class, "HMap")); ObjectMapper mapper = new ObjectMapper(); return TypeNameIdResolver.construct(mapper.getDeserializationConfig(), TypeFactory.defaultInstance().constructType(Object.class), subtypes, forSerialization, !forSerialization); } public void testList() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.PROPERTY); ItemList child = new ItemList(); child.value = "I am child"; ItemList parent = new ItemList(); parent.value = "I am parent"; parent.addChildItem(child); String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(parent); Object o = mapper.readValue(json, ItemList.class); assertNotNull(o); } public void testMap() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.PROPERTY); ItemMap child = new ItemMap(); child.value = "I am child"; ItemMap parent = new ItemMap(); parent.value = "I am parent"; parent.addChildItem("child", child); String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(parent); Object o = mapper.readValue(json, ItemMap.class); assertNotNull(o); } } TestDefaultForObject.java000066400000000000000000000342741325620701100372550ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.util.TokenBuffer; public class TestDefaultForObject extends BaseMapTest { static abstract class AbstractBean { } static class StringBean extends AbstractBean { // ha, punny! public String name; public StringBean() { this(null); } protected StringBean(String n) { name = n; } } enum Choice { YES, NO; } /** * Another enum type, but this time forcing sub-classing */ enum ComplexChoice { MAYBE(true), PROBABLY_NOT(false); private boolean state; private ComplexChoice(boolean b) { state = b; } @Override public String toString() { return String.valueOf(state); } } static class PolymorphicType { public String foo; public Object bar; public PolymorphicType() { } public PolymorphicType(String foo, int bar) { this.foo = foo; this.bar = bar; } } final static class BeanHolder { public AbstractBean bean; public BeanHolder() { } public BeanHolder(AbstractBean b) { bean = b; } } final static class ObjectHolder { public Object value; public ObjectHolder() { } public ObjectHolder(Object v) { value = v; } } static class DomainBean { public int weight; } static class DiscussBean extends DomainBean { public String subject; } static public class DomainBeanWrapper { public String name; public Object myBean; } /* /********************************************************** /* Unit tests /********************************************************** */ /** * Unit test that verifies that a bean is stored with type information, * when declared type is Object.class (since it is within * Object[]), and default type information is enabled. */ public void testBeanAsObject() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); // note: need to wrap, to get declared as Object String str = m.writeValueAsString(new Object[] { new StringBean("abc") }); _verifySerializationAsMap(str); // Ok: serialization seems to work as expected. Now deserialize: Object ob = m.readValue(str, Object[].class); assertNotNull(ob); Object[] result = (Object[]) ob; assertNotNull(result[0]); assertEquals(StringBean.class, result[0].getClass()); assertEquals("abc", ((StringBean) result[0]).name); } // with 2.5, another test to check that "as-property" is valid option public void testBeanAsObjectUsingAsProperty() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, ".hype"); // note: need to wrap, to get declared as Object String json = m.writeValueAsString(new StringBean("abc")); // Ok: serialization seems to work as expected. Now deserialize: Object result = m.readValue(json, Object.class); assertNotNull(result); assertEquals(StringBean.class, result.getClass()); assertEquals("abc", ((StringBean) result).name); } /** * Unit test that verifies that an abstract bean is stored with type information * if default type information is enabled for non-concrete types. */ public void testAbstractBean() throws Exception { // First, let's verify that we'd fail without enabling default type info ObjectMapper m = new ObjectMapper(); AbstractBean[] input = new AbstractBean[] { new StringBean("xyz") }; String serial = m.writeValueAsString(input); try { m.readValue(serial, AbstractBean[].class); fail("Should have failed"); } catch (JsonMappingException e) { // let's use whatever is currently thrown exception... may change tho verifyException(e, "cannot construct"); } // and then that we will succeed with default type info m = new ObjectMapper(); m.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); serial = m.writeValueAsString(input); AbstractBean[] beans = m.readValue(serial, AbstractBean[].class); assertEquals(1, beans.length); assertEquals(StringBean.class, beans[0].getClass()); assertEquals("xyz", ((StringBean) beans[0]).name); } /** * Unit test to verify that type information is included for * all non-final types, if default typing suitably configured */ public void testNonFinalBean() throws Exception { ObjectMapper m = new ObjectMapper(); // first: use "object or abstract" typing: should produce no type info: m.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); StringBean bean = new StringBean("x"); assertEquals("{\"name\":\"x\"}", m.writeValueAsString(bean)); // then non-final, and voila: m = new ObjectMapper(); m.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); assertEquals("[\""+StringBean.class.getName()+"\",{\"name\":\"x\"}]", m.writeValueAsString(bean)); } public void testNullValue() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); BeanHolder h = new BeanHolder(); String json = m.writeValueAsString(h); assertNotNull(json); BeanHolder result = m.readValue(json, BeanHolder.class); assertNotNull(result); assertNull(result.bean); } public void testEnumAsObject() throws Exception { // wrapping to be declared as object Object[] input = new Object[] { Choice.YES }; Object[] input2 = new Object[] { ComplexChoice.MAYBE}; // first, without type info: assertEquals("[\"YES\"]", serializeAsString(input)); assertEquals("[\"MAYBE\"]", serializeAsString(input2)); // and then with it ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); String json = m.writeValueAsString(input); assertEquals("[[\""+Choice.class.getName()+"\",\"YES\"]]", json); // which we should get back same way Object[] output = m.readValue(json, Object[].class); assertEquals(1, output.length); assertEquals(Choice.YES, output[0]); // ditto for more complicated enum json = m.writeValueAsString(input2); assertEquals("[[\""+ComplexChoice.class.getName()+"\",\"MAYBE\"]]", json); output = m.readValue(json, Object[].class); assertEquals(1, output.length); assertEquals(ComplexChoice.MAYBE, output[0]); } @SuppressWarnings("unchecked") public void testEnumSet() throws Exception { EnumSet set = EnumSet.of(Choice.NO); Object[] input = new Object[] { set }; ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); String json = m.writeValueAsString(input); Object[] output = m.readValue(json, Object[].class); assertEquals(1, output.length); Object ob = output[0]; assertTrue(ob instanceof EnumSet); EnumSet set2 = (EnumSet) ob; assertEquals(1, set2.size()); assertTrue(set2.contains(Choice.NO)); assertFalse(set2.contains(Choice.YES)); } @SuppressWarnings("unchecked") public void testEnumMap() throws Exception { EnumMap map = new EnumMap(Choice.class); map.put(Choice.NO, "maybe"); Object[] input = new Object[] { map }; ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); String json = m.writeValueAsString(input); Object[] output = m.readValue(json, Object[].class); assertEquals(1, output.length); Object ob = output[0]; assertTrue(ob instanceof EnumMap); EnumMap map2 = (EnumMap) ob; assertEquals(1, map2.size()); assertEquals("maybe", map2.get(Choice.NO)); assertNull(map2.get(Choice.YES)); } public void testJackson311() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); String json = mapper.writeValueAsString(new PolymorphicType("hello", 2)); PolymorphicType value = mapper.readValue(json, PolymorphicType.class); assertEquals("hello", value.foo); assertEquals(Integer.valueOf(2), value.bar); } // Also, let's ensure TokenBuffer gets properly handled public void testTokenBuffer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); // Ok, first test JSON Object containing buffer: TokenBuffer buf = new TokenBuffer(mapper, false); buf.writeStartObject(); buf.writeNumberField("num", 42); buf.writeEndObject(); String json = mapper.writeValueAsString(new ObjectHolder(buf)); ObjectHolder holder = mapper.readValue(json, ObjectHolder.class); assertNotNull(holder.value); assertSame(TokenBuffer.class, holder.value.getClass()); JsonParser jp = ((TokenBuffer) holder.value).asParser(); assertToken(JsonToken.START_OBJECT, jp.nextToken()); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertToken(JsonToken.END_OBJECT, jp.nextToken()); assertNull(jp.nextToken()); jp.close(); buf.close(); // then as an array: buf = new TokenBuffer(mapper, false); buf.writeStartArray(); buf.writeBoolean(true); buf.writeEndArray(); json = mapper.writeValueAsString(new ObjectHolder(buf)); holder = mapper.readValue(json, ObjectHolder.class); assertNotNull(holder.value); assertSame(TokenBuffer.class, holder.value.getClass()); jp = ((TokenBuffer) holder.value).asParser(); assertToken(JsonToken.START_ARRAY, jp.nextToken()); assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); assertToken(JsonToken.END_ARRAY, jp.nextToken()); assertNull(jp.nextToken()); jp.close(); buf.close(); // and finally as scalar buf = new TokenBuffer(mapper, false); buf.writeNumber(321); json = mapper.writeValueAsString(new ObjectHolder(buf)); holder = mapper.readValue(json, ObjectHolder.class); assertNotNull(holder.value); assertSame(TokenBuffer.class, holder.value.getClass()); jp = ((TokenBuffer) holder.value).asParser(); assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertEquals(321, jp.getIntValue()); assertNull(jp.nextToken()); jp.close(); buf.close(); } /** * Test for [JACKSON-352] */ public void testIssue352() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping (ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.PROPERTY); DiscussBean d1 = new DiscussBean(); d1.subject = "mouse"; d1.weight=88; DomainBeanWrapper wrapper = new DomainBeanWrapper(); wrapper.name = "mickey"; wrapper.myBean = d1; String json = mapper.writeValueAsString(wrapper); DomainBeanWrapper result = mapper.readValue(json, DomainBeanWrapper.class); assertNotNull(result); assertNotNull(wrapper.myBean); assertSame(DiscussBean.class, wrapper.myBean.getClass()); } // Test to ensure we can also use "As.PROPERTY" inclusion and custom property name public void testFeature432() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, "*CLASS*"); String json = mapper.writeValueAsString(new BeanHolder(new StringBean("punny"))); assertEquals("{\"bean\":{\"*CLASS*\":\"com.fasterxml.jackson.databind.jsontype.TestDefaultForObject$StringBean\",\"name\":\"punny\"}}", json); } public void testNoGoWithExternalProperty() throws Exception { ObjectMapper mapper = new ObjectMapper(); try { mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.As.EXTERNAL_PROPERTY); fail("Should not have passed"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot use includeAs of EXTERNAL_PROPERTY"); } } /* /********************************************************** /* Helper methods /********************************************************** */ @SuppressWarnings("unchecked") private void _verifySerializationAsMap(String str) throws Exception { // First: validate that structure looks correct (as Map etc) // note: should look something like: // "[["org.codehaus.jackson.map.jsontype.TestDefaultForObject$StringBean",{"name":"abc"}]]") // note: must have default mapper, default typer NOT enabled (to get 'plain' map) ObjectMapper m = new ObjectMapper(); List list = m.readValue(str, List.class); assertEquals(1, list.size()); // no type for main List, just single entry Object entryOb = list.get(0); assertTrue(entryOb instanceof List); // but then type wrapper for bean List entryList = (List)entryOb; assertEquals(2, entryList.size()); assertEquals(StringBean.class.getName(), entryList.get(0)); assertTrue(entryList.get(1) instanceof Map); Map map = (Map) entryList.get(1); assertEquals(1, map.size()); assertEquals("abc", map.get("name")); } } TestDefaultForScalars.java000066400000000000000000000075721325620701100374400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import static org.junit.Assert.*; import com.fasterxml.jackson.databind.*; /** * Unit tests to verify that Java/JSON scalar values (non-structured values) * are handled properly with respect to additional type information. */ public class TestDefaultForScalars extends BaseMapTest { static class Jackson417Bean { public String foo = "bar"; public java.io.Serializable bar = new Integer(13); } /* /********************************************************** /* Unit tests /********************************************************** */ /** * Unit test to verify that limited number of core types do NOT include * type information, even if declared as Object. This is only done for types * that JSON scalar values natively map to: String, Integer and Boolean (and * nulls never have type information) */ public void testNumericScalars() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); // no typing for Integer, Double, yes for others assertEquals("[123]", m.writeValueAsString(new Object[] { Integer.valueOf(123) })); assertEquals("[[\"java.lang.Long\",37]]", m.writeValueAsString(new Object[] { Long.valueOf(37) })); assertEquals("[0.25]", m.writeValueAsString(new Object[] { Double.valueOf(0.25) })); assertEquals("[[\"java.lang.Float\",0.5]]", m.writeValueAsString(new Object[] { Float.valueOf(0.5f) })); } public void testDateScalars() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); long ts = 12345678L; assertEquals("[[\"java.util.Date\","+ts+"]]", m.writeValueAsString(new Object[] { new Date(ts) })); // Calendar is trickier... hmmh. Need to ensure round-tripping Calendar c = Calendar.getInstance(); c.setTimeInMillis(ts); String json = m.writeValueAsString(new Object[] { c }); assertEquals("[[\""+c.getClass().getName()+"\","+ts+"]]", json); // and let's make sure it also comes back same way: Object[] result = m.readValue(json, Object[].class); assertEquals(1, result.length); assertTrue(result[0] instanceof Calendar); assertEquals(ts, ((Calendar) result[0]).getTimeInMillis()); } public void testMiscScalars() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); // no typing for Strings, booleans assertEquals("[\"abc\"]", m.writeValueAsString(new Object[] { "abc" })); assertEquals("[true,null,false]", m.writeValueAsString(new Boolean[] { true, null, false })); } /** * Test for verifying that contents of "untyped" homogenous arrays are properly * handled, */ public void testScalarArrays() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT); Object[] input = new Object[] { "abc", new Date(1234567), null, Integer.valueOf(456) }; String json = m.writeValueAsString(input); assertEquals("[\"abc\",[\"java.util.Date\",1234567],null,456]", json); // and should deserialize back as well: Object[] output = m.readValue(json, Object[].class); assertArrayEquals(input, output); } /** * Loosely scalar; for [JACKSON-417] */ public void test417() throws Exception { ObjectMapper m = new ObjectMapper(); m.enableDefaultTyping(); Jackson417Bean input = new Jackson417Bean(); String json = m.writeValueAsString(input); Jackson417Bean result = m.readValue(json, Jackson417Bean.class); assertEquals(input.foo, result.foo); assertEquals(input.bar, result.bar); } } TestDefaultForTreeNodes.java000066400000000000000000000023241325620701100377260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; public class TestDefaultForTreeNodes extends BaseMapTest { public static class Foo { public String bar; public Foo() { } public Foo(String b) { bar = b; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper DEFAULT_MAPPER = new ObjectMapper(); { DEFAULT_MAPPER.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); } public void testValueAsStringWithDefaultTyping() throws Exception { Foo foo = new Foo("baz"); String json = DEFAULT_MAPPER.writeValueAsString(foo); JsonNode jsonNode = DEFAULT_MAPPER.readTree(json); assertEquals(jsonNode.get("bar").textValue(), foo.bar); } public void testValueToTreeWithDefaultTyping() throws Exception { Foo foo = new Foo("baz"); JsonNode jsonNode = DEFAULT_MAPPER.valueToTree(foo); assertEquals(jsonNode.get("bar").textValue(), foo.bar); } } TestDefaultWithCreators.java000066400000000000000000000053541325620701100400130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import org.junit.Assert; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class TestDefaultWithCreators extends BaseMapTest { static abstract class Job { public long id; } static class UrlJob extends Job { private final String url; private final int count; @JsonCreator public UrlJob(@JsonProperty("id") long id, @JsonProperty("url") String url, @JsonProperty("count") int count) { this.id = id; this.url = url; this.count = count; } public String getUrl() { return url; } public int getCount() { return count; } } // [databind#1385] static class Bean1385Wrapper { public Object value; protected Bean1385Wrapper() { } public Bean1385Wrapper(Object v) { value = v; } } static class Bean1385 { private byte[] raw; @JsonCreator(mode=JsonCreator.Mode.DELEGATING) public Bean1385(byte[] raw) { this.raw = raw.clone(); } @JsonValue public byte[] getBytes() { return raw; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testWithCreators() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); UrlJob input = new UrlJob(123L, "http://foo", 3); String json = mapper.writeValueAsString(input); assertNotNull(json); Job output = mapper.readValue(json, Job.class); assertNotNull(output); assertSame(UrlJob.class, output.getClass()); UrlJob o2 = (UrlJob) output; assertEquals(123L, o2.id); assertEquals("http://foo", o2.getUrl()); assertEquals(3, o2.getCount()); } // [databind#1385] public void testWithCreatorAndJsonValue() throws Exception { final byte[] BYTES = new byte[] { 1, 2, 3, 4, 5 }; ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(); String json = mapper.writeValueAsString(new Bean1385Wrapper( new Bean1385(BYTES) )); Bean1385Wrapper result = mapper.readValue(json, Bean1385Wrapper.class); assertNotNull(result); assertNotNull(result.value); assertEquals(Bean1385.class, result.value.getClass()); Bean1385 b = (Bean1385) result.value; Assert.assertArrayEquals(BYTES, b.raw); } } TestEnumTyping.java000066400000000000000000000063211325620701100361620ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; @SuppressWarnings("serial") public class TestEnumTyping extends BaseMapTest { /* /********************************************************** /* Helper types /********************************************************** */ // note: As.WRAPPER_ARRAY worked initially; but as per [JACKSON-485], As.PROPERTY had issues @JsonTypeInfo(use=JsonTypeInfo.Id.MINIMAL_CLASS, include=JsonTypeInfo.As.PROPERTY) public interface EnumInterface { } public enum Tag implements EnumInterface { A, B }; static class EnumInterfaceWrapper { public EnumInterface value; } static class EnumInterfaceList extends ArrayList { } static class TagList extends ArrayList { } static enum TestEnum { A, B, C; } static class UntypedEnumBean { @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="__type") public Object value; public UntypedEnumBean() { } public UntypedEnumBean(TestEnum v) { value = v; } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="__type") public void setValue(Object o) { value = o; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testTagList() throws Exception { ObjectMapper m = new ObjectMapper(); TagList list = new TagList(); list.add(Tag.A); list.add(Tag.B); String json = m.writeValueAsString(list); TagList result = m.readValue(json, TagList.class); assertEquals(2, result.size()); assertSame(Tag.A, result.get(0)); assertSame(Tag.B, result.get(1)); } public void testEnumInterface() throws Exception { ObjectMapper m = new ObjectMapper(); String json = m.writeValueAsString(Tag.B); EnumInterface result = m.readValue(json, EnumInterface.class); assertSame(Tag.B, result); } public void testEnumInterfaceList() throws Exception { ObjectMapper m = new ObjectMapper(); EnumInterfaceList list = new EnumInterfaceList(); list.add(Tag.A); list.add(Tag.B); String json = m.writeValueAsString(list); EnumInterfaceList result = m.readValue(json, EnumInterfaceList.class); assertEquals(2, result.size()); assertSame(Tag.A, result.get(0)); assertSame(Tag.B, result.get(1)); } public void testUntypedEnum() throws Exception { ObjectMapper mapper = new ObjectMapper(); String str = mapper.writeValueAsString(new UntypedEnumBean(TestEnum.B)); UntypedEnumBean result = mapper.readValue(str, UntypedEnumBean.class); assertNotNull(result); assertNotNull(result.value); Object ob = result.value; assertSame(TestEnum.class, ob.getClass()); assertEquals(TestEnum.B, result.value); } } TestGenericListSerialization.java000066400000000000000000000052201325620701100410260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.type.TypeFactory; public class TestGenericListSerialization extends BaseMapTest { // [JACKSON-356] public static class JSONResponse { private T result; public T getResult() { return result; } public void setResult(T result) { this.result = result; } } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") public static class Parent { public String parentContent = "PARENT"; } public static class Child1 extends Parent { public String childContent1 = "CHILD1"; } public static class Child2 extends Parent { public String childContent2 = "CHILD2"; } /* /********************************************************** /* Unit tests /********************************************************** */ public void testSubTypesFor356() throws Exception { ObjectMapper mapper = new ObjectMapper(); JSONResponse> input = new JSONResponse>(); List embedded = new ArrayList(); embedded.add(new Child1()); embedded.add(new Child2()); input.setResult(embedded); mapper.configure(MapperFeature.USE_STATIC_TYPING, true); JavaType rootType = TypeFactory.defaultInstance().constructType(new TypeReference>>() { }); byte[] json = mapper.writerFor(rootType).writeValueAsBytes(input); JSONResponse> out = mapper.readValue(json, 0, json.length, rootType); List deserializedContent = out.getResult(); assertEquals(2, deserializedContent.size()); assertTrue(deserializedContent.get(0) instanceof Parent); assertTrue(deserializedContent.get(0) instanceof Child1); assertFalse(deserializedContent.get(0) instanceof Child2); assertTrue(deserializedContent.get(1) instanceof Child2); assertFalse(deserializedContent.get(1) instanceof Child1); assertEquals("PARENT", ((Child1) deserializedContent.get(0)).parentContent); assertEquals("PARENT", ((Child2) deserializedContent.get(1)).parentContent); assertEquals("CHILD1", ((Child1) deserializedContent.get(0)).childContent1); assertEquals("CHILD2", ((Child2) deserializedContent.get(1)).childContent2); } } TestOverlappingTypeIdNames.java000066400000000000000000000035071325620701100404570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestOverlappingTypeIdNames extends BaseMapTest { @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(name = "a", value = Impl312.class), @JsonSubTypes.Type(name = "b", value = Impl312.class) }) static abstract class Base312 { } static class Impl312 extends Base312 { public int x; } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(name = "a", value = Impl312B1.class), @JsonSubTypes.Type(name = "a", value = Impl312B2.class) }) static class Base312B { public int value = 1; } static class Impl312B1 extends Base312B { } static class Impl312B2 extends Base312B { } final ObjectMapper MAPPER = objectMapper(); public void testOverlappingNameDeser() throws Exception { Base312 value; // Ensure both type ids are acceptable value = MAPPER.readValue(aposToQuotes("{'type':'a','x':7}"), Base312.class); assertNotNull(value); assertEquals(Impl312.class, value.getClass()); assertEquals(7, ((Impl312) value).x); value = MAPPER.readValue(aposToQuotes("{'type':'b','x':3}"), Base312.class); assertNotNull(value); assertEquals(Impl312.class, value.getClass()); assertEquals(3, ((Impl312) value).x); } public void testOverlappingNameSer() throws Exception { assertEquals(aposToQuotes("{'type':'a','value':1}"), MAPPER.writeValueAsString(new Impl312B1())); assertEquals(aposToQuotes("{'type':'a','value':1}"), MAPPER.writeValueAsString(new Impl312B2())); } } TestPolymorphicDeserialization676.java000066400000000000000000000104371325620701100417050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import java.io.IOException; import java.util.*; /** * Reproduction of [https://github.com/FasterXML/jackson-databind/issues/676] *

* Deserialization of class with generic collection inside * depends on how is was deserialized first time. */ public class TestPolymorphicDeserialization676 extends BaseMapTest { private static final int TIMESTAMP = 123456; @JsonInclude(JsonInclude.Include.NON_NULL) public static class MapContainer { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") public Map map; public MapContainer() { } public MapContainer(Map map) { this.map = map; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof MapContainer)) return false; return map.equals(((MapContainer) o).map); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[MapContainer:"); for (Map.Entry entry : map.entrySet()) { sb.append(" '").append(entry.getKey()).append("' : "); Object value = entry.getValue(); if (value == null) { sb.append("null"); } else { sb.append("(").append(value.getClass().getName()).append(") "); sb.append(String.valueOf(value)); } } return sb.append(']').toString(); } } @JsonInclude(JsonInclude.Include.NON_NULL) public static class PolymorphicValueWrapper { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") public Object value; } private final MapContainer originMap; public TestPolymorphicDeserialization676() { Map localMap = new LinkedHashMap(); localMap.put("DateValue", new Date(TIMESTAMP)); originMap = new MapContainer(localMap); } /** * If the class was first deserialized as polymorphic field, * deserialization will fail at complex type. */ public void testDeSerFail() throws IOException { ObjectMapper mapper = new ObjectMapper(); MapContainer deserMapBad = createDeSerMapContainer(originMap, mapper); assertEquals(originMap, deserMapBad); assertEquals(originMap, mapper.readValue(mapper.writeValueAsString(originMap), MapContainer.class)); } public void testDeSerCorrect() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS); Map map = new HashMap(); map.put("1", 1); // commenting out the following statement will fail the test assertEquals(new MapContainer(map), mapper.readValue(mapper.writeValueAsString(new MapContainer(map)), MapContainer.class)); MapContainer deserMapGood = createDeSerMapContainer(originMap, mapper); assertEquals(originMap, deserMapGood); assertEquals(new Date(TIMESTAMP), deserMapGood.map.get("DateValue")); assertEquals(originMap, mapper.readValue(mapper.writeValueAsString(originMap), MapContainer.class)); } private MapContainer createDeSerMapContainer(MapContainer src, ObjectMapper mapper) throws IOException { PolymorphicValueWrapper result = new PolymorphicValueWrapper(); result.value = src; String json = mapper.writeValueAsString(result); assertEquals("{\"value\":{\"@class\":" + "\""+getClass().getName()+"$MapContainer\"," + "\"map\":{\"DateValue\":[\"java.util.Date\",123456]}}}", json); PolymorphicValueWrapper deserializedResult = mapper.readValue(json, PolymorphicValueWrapper.class); return (MapContainer) deserializedResult.value; } } TestPolymorphicWithDefaultImpl.java000066400000000000000000000242621325620701100413570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.NoClass; import com.fasterxml.jackson.databind.exc.InvalidTypeIdException; /** * Unit tests related to specialized handling of "default implementation" * ({@link JsonTypeInfo#defaultImpl}), as well as related * cases that allow non-default settings (such as missing type id). */ public class TestPolymorphicWithDefaultImpl extends BaseMapTest { @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = LegacyInter.class) @JsonSubTypes(value = {@JsonSubTypes.Type(name = "mine", value = MyInter.class)}) public static interface Inter { } public static class MyInter implements Inter { @JsonProperty("blah") public List blah; } public static class LegacyInter extends MyInter { @JsonCreator LegacyInter(Object obj) { if (obj instanceof List) { blah = new ArrayList(); for (Object o : (List) obj) { blah.add(o.toString()); } } else if (obj instanceof String) { blah = Arrays.asList(((String) obj).split(",")); } else { throw new IllegalArgumentException("Unknown type: " + obj.getClass()); } } } /** * Note: NoClass here has special meaning, of mapping invalid * types into null instances. */ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = NoClass.class) public static class DefaultWithNoClass { } /** * Also another variant to verify that from 2.5 on, can use non-deprecated * value for the same. */ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = Void.class) public static class DefaultWithVoidAsDefault { } // and then one with no defaultImpl nor listed subtypes @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") abstract static class MysteryPolymorphic { } // [databind#511] types @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) @JsonSubTypes(@JsonSubTypes.Type(name="sub1", value = BadSub1.class)) public static class BadItem {} public static class BadSub1 extends BadItem { public String a ; } public static class Good { public List many; } public static class Bad { public List many; } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) @JsonSubTypes({@JsonSubTypes.Type(name="sub1", value = GoodSub1.class), @JsonSubTypes.Type(name="sub2", value = GoodSub2.class) }) public static class GoodItem {} public static class GoodSub1 extends GoodItem { public String a; } public static class GoodSub2 extends GoodItem { public String b; } // for [databind#656] @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include= JsonTypeInfo.As.WRAPPER_OBJECT, defaultImpl=ImplFor656.class) static abstract class BaseFor656 { } static class ImplFor656 extends BaseFor656 { public int a; } static class CallRecord { public float version; public String application; public Item item; public Item item2; public CallRecord() {} } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true) @JsonSubTypes({@JsonSubTypes.Type(value = Event.class, name = "event")}) @JsonIgnoreProperties(ignoreUnknown=true) public interface Item { } static class Event implements Item { public String location; public Event() {} } @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "clazz") abstract static class BaseClass { } static class BaseWrapper { public BaseClass value; } // [databind#1533] @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") static class AsProperty { } static class AsPropertyWrapper { public AsProperty value; } /* /********************************************************** /* Unit tests, deserialization /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testDeserializationWithObject() throws Exception { Inter inter = MAPPER.readerFor(Inter.class).readValue("{\"type\": \"mine\", \"blah\": [\"a\", \"b\", \"c\"]}"); assertTrue(inter instanceof MyInter); assertFalse(inter instanceof LegacyInter); assertEquals(Arrays.asList("a", "b", "c"), ((MyInter) inter).blah); } public void testDeserializationWithString() throws Exception { Inter inter = MAPPER.readerFor(Inter.class).readValue("\"a,b,c,d\""); assertTrue(inter instanceof LegacyInter); assertEquals(Arrays.asList("a", "b", "c", "d"), ((MyInter) inter).blah); } public void testDeserializationWithArray() throws Exception { Inter inter = MAPPER.readerFor(Inter.class).readValue("[\"a\", \"b\", \"c\", \"d\"]"); assertTrue(inter instanceof LegacyInter); assertEquals(Arrays.asList("a", "b", "c", "d"), ((MyInter) inter).blah); } public void testDeserializationWithArrayOfSize2() throws Exception { Inter inter = MAPPER.readerFor(Inter.class).readValue("[\"a\", \"b\"]"); assertTrue(inter instanceof LegacyInter); assertEquals(Arrays.asList("a", "b"), ((MyInter) inter).blah); } // [databind#148] public void testDefaultAsNoClass() throws Exception { Object ob = MAPPER.readerFor(DefaultWithNoClass.class).readValue("{ }"); assertNull(ob); ob = MAPPER.readerFor(DefaultWithNoClass.class).readValue("{ \"bogus\":3 }"); assertNull(ob); } // same, with 2.5 and Void.class public void testDefaultAsVoid() throws Exception { Object ob = MAPPER.readerFor(DefaultWithVoidAsDefault.class).readValue("{ }"); assertNull(ob); ob = MAPPER.readerFor(DefaultWithVoidAsDefault.class).readValue("{ \"bogus\":3 }"); assertNull(ob); } // [databind#148] public void testBadTypeAsNull() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); Object ob = mapper.readValue("{}", MysteryPolymorphic.class); assertNull(ob); ob = mapper.readValue("{ \"whatever\":13}", MysteryPolymorphic.class); assertNull(ob); } // [databind#511] public void testInvalidTypeId511() throws Exception { ObjectReader reader = MAPPER.reader().without( DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES ); String json = "{\"many\":[{\"sub1\":{\"a\":\"foo\"}},{\"sub2\":{\"b\":\"bar\"}}]}" ; Good goodResult = reader.forType(Good.class).readValue(json) ; assertNotNull(goodResult) ; Bad badResult = reader.forType(Bad.class).readValue(json); assertNotNull(badResult); } // [databind#656] public void testDefaultImplWithObjectWrapper() throws Exception { BaseFor656 value = MAPPER.readValue(aposToQuotes("{'foobar':{'a':3}}"), BaseFor656.class); assertNotNull(value); assertEquals(ImplFor656.class, value.getClass()); assertEquals(3, ((ImplFor656) value).a); } public void testUnknownTypeIDRecovery() throws Exception { ObjectReader reader = MAPPER.readerFor(CallRecord.class).without( DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); String json = aposToQuotes("{'version':0.0,'application':'123'," +"'item':{'type':'xevent','location':'location1'}," +"'item2':{'type':'event','location':'location1'}}"); // can't read item2 - which is valid CallRecord r = reader.readValue(json); assertNull(r.item); assertNotNull(r.item2); json = aposToQuotes("{'item':{'type':'xevent','location':'location1'}, 'version':0.0,'application':'123'}"); CallRecord r3 = reader.readValue(json); assertNull(r3.item); assertEquals("123", r3.application); } public void testUnknownClassAsSubtype() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); BaseWrapper w = mapper.readValue(aposToQuotes ("{'value':{'clazz':'com.foobar.Nothing'}}'"), BaseWrapper.class); assertNotNull(w); assertNull(w.value); } public void testWithoutEmptyStringAsNullObject1533() throws Exception { ObjectReader r = MAPPER.readerFor(AsPropertyWrapper.class) .without(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); try { r.readValue("{ \"value\": \"\" }"); fail("Expected " + JsonMappingException.class); } catch (InvalidTypeIdException e) { verifyException(e, "missing type id property 'type'"); } } // [databind#1533] public void testWithEmptyStringAsNullObject1533() throws Exception { ObjectReader r = MAPPER.readerFor(AsPropertyWrapper.class) .with(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); AsPropertyWrapper wrapper = r.readValue("{ \"value\": \"\" }"); assertNull(wrapper.value); } /* /********************************************************** /* Unit tests, serialization /********************************************************** */ /* public void testDontWriteIfDefaultImpl() throws Exception { String json = MAPPER.writeValueAsString(new MyInter()); assertEquals("{\"blah\":null}", json); } */ } TestPropertyTypeInfo.java000066400000000000000000000201701325620701100373630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; /** * Testing to verify that {@link JsonTypeInfo} works * for properties as well as types. */ @SuppressWarnings("serial") public class TestPropertyTypeInfo extends BaseMapTest { protected static class BooleanValue { public Boolean b; @JsonCreator public BooleanValue(Boolean value) { b = value; } @JsonValue public Boolean value() { return b; } } static class FieldWrapperBean { @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) public Object value; public FieldWrapperBean() { } public FieldWrapperBean(Object o) { value = o; } } static class FieldWrapperBeanList extends ArrayList { } static class FieldWrapperBeanMap extends HashMap { } static class FieldWrapperBeanArray { @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) public FieldWrapperBean[] beans; public FieldWrapperBeanArray() { } public FieldWrapperBeanArray(FieldWrapperBean[] beans) { this.beans = beans; } } static class MethodWrapperBean { protected Object value; @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) public Object getValue() { return value; } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) public void setValue(Object v) { value = v; } public MethodWrapperBean() { } public MethodWrapperBean(Object o) { value = o; } } static class MethodWrapperBeanList extends ArrayList { } static class MethodWrapperBeanMap extends HashMap { } static class MethodWrapperBeanArray { protected MethodWrapperBean[] beans; @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) public MethodWrapperBean[] getValue() { return beans; } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) public void setValue(MethodWrapperBean[] v) { beans = v; } public MethodWrapperBeanArray() { } public MethodWrapperBeanArray(MethodWrapperBean[] beans) { this.beans = beans; } } static class OtherBean { public int x = 1, y = 1; } /* /********************************************************** /* Unit tests /********************************************************** */ public void testSimpleField() throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(new FieldWrapperBean(new StringWrapper("foo"))); //System.out.println("JSON/field+object == "+json); FieldWrapperBean bean = mapper.readValue(json, FieldWrapperBean.class); assertNotNull(bean.value); assertEquals(StringWrapper.class, bean.value.getClass()); assertEquals(((StringWrapper) bean.value).str, "foo"); } public void testSimpleMethod() throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(new FieldWrapperBean(new IntWrapper(37))); //System.out.println("JSON/method+object == "+json); FieldWrapperBean bean = mapper.readValue(json, FieldWrapperBean.class); assertNotNull(bean.value); assertEquals(IntWrapper.class, bean.value.getClass()); assertEquals(((IntWrapper) bean.value).i, 37); } public void testSimpleListField() throws Exception { ObjectMapper mapper = new ObjectMapper(); FieldWrapperBeanList list = new FieldWrapperBeanList(); list.add(new FieldWrapperBean(new OtherBean())); String json = mapper.writeValueAsString(list); //System.out.println("JSON/field+list == "+json); FieldWrapperBeanList result = mapper.readValue(json, FieldWrapperBeanList.class); assertNotNull(result); assertEquals(1, result.size()); FieldWrapperBean bean = list.get(0); assertEquals(OtherBean.class, bean.value.getClass()); assertEquals(((OtherBean) bean.value).x, 1); assertEquals(((OtherBean) bean.value).y, 1); } public void testSimpleListMethod() throws Exception { ObjectMapper mapper = new ObjectMapper(); MethodWrapperBeanList list = new MethodWrapperBeanList(); list.add(new MethodWrapperBean(new BooleanValue(true))); list.add(new MethodWrapperBean(new StringWrapper("x"))); list.add(new MethodWrapperBean(new OtherBean())); String json = mapper.writeValueAsString(list); MethodWrapperBeanList result = mapper.readValue(json, MethodWrapperBeanList.class); assertNotNull(result); assertEquals(3, result.size()); MethodWrapperBean bean = result.get(0); assertEquals(BooleanValue.class, bean.value.getClass()); assertEquals(((BooleanValue) bean.value).b, Boolean.TRUE); bean = result.get(1); assertEquals(StringWrapper.class, bean.value.getClass()); assertEquals(((StringWrapper) bean.value).str, "x"); bean = result.get(2); assertEquals(OtherBean.class, bean.value.getClass()); } public void testSimpleArrayField() throws Exception { ObjectMapper mapper = new ObjectMapper(); FieldWrapperBeanArray array = new FieldWrapperBeanArray(new FieldWrapperBean[] { new FieldWrapperBean(new BooleanValue(true)) }); String json = mapper.writeValueAsString(array); FieldWrapperBeanArray result = mapper.readValue(json, FieldWrapperBeanArray.class); assertNotNull(result); FieldWrapperBean[] beans = result.beans; assertEquals(1, beans.length); FieldWrapperBean bean = beans[0]; assertEquals(BooleanValue.class, bean.value.getClass()); assertEquals(((BooleanValue) bean.value).b, Boolean.TRUE); } public void testSimpleArrayMethod() throws Exception { ObjectMapper mapper = new ObjectMapper(); MethodWrapperBeanArray array = new MethodWrapperBeanArray(new MethodWrapperBean[] { new MethodWrapperBean(new StringWrapper("A")) }); String json = mapper.writeValueAsString(array); MethodWrapperBeanArray result = mapper.readValue(json, MethodWrapperBeanArray.class); assertNotNull(result); MethodWrapperBean[] beans = result.beans; assertEquals(1, beans.length); MethodWrapperBean bean = beans[0]; assertEquals(StringWrapper.class, bean.value.getClass()); assertEquals(((StringWrapper) bean.value).str, "A"); } public void testSimpleMapField() throws Exception { ObjectMapper mapper = new ObjectMapper(); FieldWrapperBeanMap map = new FieldWrapperBeanMap(); map.put("foop", new FieldWrapperBean(new IntWrapper(13))); String json = mapper.writeValueAsString(map); FieldWrapperBeanMap result = mapper.readValue(json, FieldWrapperBeanMap.class); assertNotNull(result); assertEquals(1, result.size()); FieldWrapperBean bean = result.get("foop"); assertNotNull(bean); Object ob = bean.value; assertEquals(IntWrapper.class, ob.getClass()); assertEquals(((IntWrapper) ob).i, 13); } public void testSimpleMapMethod() throws Exception { ObjectMapper mapper = new ObjectMapper(); MethodWrapperBeanMap map = new MethodWrapperBeanMap(); map.put("xyz", new MethodWrapperBean(new BooleanValue(true))); String json = mapper.writeValueAsString(map); MethodWrapperBeanMap result = mapper.readValue(json, MethodWrapperBeanMap.class); assertNotNull(result); assertEquals(1, result.size()); MethodWrapperBean bean = result.get("xyz"); assertNotNull(bean); Object ob = bean.value; assertEquals(BooleanValue.class, ob.getClass()); assertEquals(((BooleanValue) ob).b, Boolean.TRUE); } } TestScalars.java000066400000000000000000000116571325620701100354630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.UUID; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class TestScalars extends BaseMapTest { private static class DynamicWrapper { @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) public Object value; @SuppressWarnings("unused") public DynamicWrapper() { } public DynamicWrapper(Object v) { value = v; } } static enum TestEnum { A, B; } private static class AbstractWrapper { @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) public Serializable value; @SuppressWarnings("unused") public AbstractWrapper() { } public AbstractWrapper(Serializable v) { value = v; } } static class ScalarList { @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) public List values = new ArrayList(); public ScalarList() { } public ScalarList add(Object v) { values.add(v); return this; } } /* /********************************************************** /* Unit tests /********************************************************** */ final ObjectMapper MAPPER = new ObjectMapper(); /** * Ensure that per-property dynamic types work, both for "native" types * and others */ public void testScalarsWithTyping() throws Exception { String json; DynamicWrapper result; ObjectMapper m = MAPPER; // first, check "native" types json = m.writeValueAsString(new DynamicWrapper(Integer.valueOf(3))); result = m.readValue(json, DynamicWrapper.class); assertEquals(Integer.valueOf(3), result.value); json = m.writeValueAsString(new DynamicWrapper("abc")); result = m.readValue(json, DynamicWrapper.class); assertEquals("abc", result.value); json = m.writeValueAsString(new DynamicWrapper("abc")); result = m.readValue(json, DynamicWrapper.class); assertEquals("abc", result.value); json = m.writeValueAsString(new DynamicWrapper(Boolean.TRUE)); result = m.readValue(json, DynamicWrapper.class); assertEquals(Boolean.TRUE, result.value); // then verify other scalars json = m.writeValueAsString(new DynamicWrapper(Long.valueOf(7L))); result = m.readValue(json, DynamicWrapper.class); assertEquals(Long.valueOf(7), result.value); json = m.writeValueAsString(new DynamicWrapper(TestEnum.B)); result = m.readValue(json, DynamicWrapper.class); assertEquals(TestEnum.B, result.value); } public void testScalarsViaAbstractType() throws Exception { ObjectMapper m = MAPPER; String json; AbstractWrapper result; // first, check "native" types json = m.writeValueAsString(new AbstractWrapper(Integer.valueOf(3))); result = m.readValue(json, AbstractWrapper.class); assertEquals(Integer.valueOf(3), result.value); json = m.writeValueAsString(new AbstractWrapper("abc")); result = m.readValue(json, AbstractWrapper.class); assertEquals("abc", result.value); json = m.writeValueAsString(new AbstractWrapper("abc")); result = m.readValue(json, AbstractWrapper.class); assertEquals("abc", result.value); json = m.writeValueAsString(new AbstractWrapper(Boolean.TRUE)); result = m.readValue(json, AbstractWrapper.class); assertEquals(Boolean.TRUE, result.value); // then verify other scalars json = m.writeValueAsString(new AbstractWrapper(Long.valueOf(7L))); result = m.readValue(json, AbstractWrapper.class); assertEquals(Long.valueOf(7), result.value); json = m.writeValueAsString(new AbstractWrapper(TestEnum.B)); result = m.readValue(json, AbstractWrapper.class); assertEquals(TestEnum.B, result.value); } // Test inspired by [databind#1104] public void testHeterogenousStringScalars() throws Exception { final UUID NULL_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000"); ScalarList input = new ScalarList() .add("Test") .add(java.lang.Object.class) .add(NULL_UUID) ; String json = MAPPER.writeValueAsString(input); ScalarList result = MAPPER.readValue(json, ScalarList.class); assertNotNull(result.values); assertEquals(3, result.values.size()); assertEquals("Test", result.values.get(0)); assertEquals(Object.class, result.values.get(1)); assertEquals(NULL_UUID, result.values.get(2)); } } TestSubtypes.java000066400000000000000000000324201325620701100357000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.core.Version; import java.util.*; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.exc.InvalidTypeIdException; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.module.SimpleModule; public class TestSubtypes extends com.fasterxml.jackson.databind.BaseMapTest { @JsonTypeInfo(use=JsonTypeInfo.Id.NAME) static abstract class SuperType { } @JsonTypeName("TypeB") static class SubB extends SuperType { public int b = 1; } static class SubC extends SuperType { public int c = 2; } static class SubD extends SuperType { public int d; } // "Empty" bean @JsonTypeInfo(use=JsonTypeInfo.Id.NAME) static abstract class BaseBean { } static class EmptyBean extends BaseBean { } static class EmptyNonFinal { } // Verify combinations static class PropertyBean { @JsonTypeInfo(use=JsonTypeInfo.Id.NAME) public SuperType value; public PropertyBean() { this(null); } public PropertyBean(SuperType v) { value = v; } } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=As.PROPERTY, property="#type", defaultImpl=DefaultImpl.class) static abstract class SuperTypeWithDefault { } static class DefaultImpl extends SuperTypeWithDefault { public int a; } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=As.PROPERTY, property="#type") static abstract class SuperTypeWithoutDefault { } static class DefaultImpl505 extends SuperTypeWithoutDefault { public int a; } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=As.PROPERTY, property="type") @JsonSubTypes({ @JsonSubTypes.Type(ImplX.class), @JsonSubTypes.Type(ImplY.class) }) static abstract class BaseX { } @JsonTypeName("x") static class ImplX extends BaseX { public int x; public ImplX() { } public ImplX(int x) { this.x = x; } } @JsonTypeName("y") static class ImplY extends BaseX { public int y; } // [databind#663] static class AtomicWrapper { public BaseX value; public AtomicWrapper() { } public AtomicWrapper(int x) { value = new ImplX(x); } } // Verifying limits on sub-class ids static class DateWrapper { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY) public java.util.Date value; } static class TheBomb { public int a; public TheBomb() { throw new Error("Ka-boom!"); } } // [databind#1125] static class Issue1125Wrapper { public Base1125 value; public Issue1125Wrapper() { } public Issue1125Wrapper(Base1125 v) { value = v; } } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, defaultImpl=Default1125.class) @JsonSubTypes({ @JsonSubTypes.Type(Interm1125.class) }) static class Base1125 { public int a; } @JsonSubTypes({ @JsonSubTypes.Type(value=Impl1125.class, name="impl") }) static class Interm1125 extends Base1125 { public int b; } static class Impl1125 extends Interm1125 { public int c; public Impl1125() { } public Impl1125(int a0, int b0, int c0) { a = a0; b = b0; c = c0; } } static class Default1125 extends Interm1125 { public int def; Default1125() { } public Default1125(int a0, int b0, int def0) { a = a0; b = b0; def = def0; } } // [databind#1311] @JsonTypeInfo(property = "type", use = JsonTypeInfo.Id.NAME, defaultImpl = Factory1311ImplA.class) interface Factory1311 { } @JsonTypeName("implA") static class Factory1311ImplA implements Factory1311 { } @JsonTypeName("implB") static class Factory1311ImplB implements Factory1311 { } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testPropertyWithSubtypes() throws Exception { ObjectMapper mapper = new ObjectMapper(); // must register subtypes mapper.registerSubtypes(SubB.class, SubC.class, SubD.class); String json = mapper.writeValueAsString(new PropertyBean(new SubC())); PropertyBean result = mapper.readValue(json, PropertyBean.class); assertSame(SubC.class, result.value.getClass()); } // also works via modules public void testSubtypesViaModule() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.registerSubtypes(SubB.class, SubC.class, SubD.class); mapper.registerModule(module); String json = mapper.writeValueAsString(new PropertyBean(new SubC())); PropertyBean result = mapper.readValue(json, PropertyBean.class); assertSame(SubC.class, result.value.getClass()); // and as per [databind#1653]: mapper = new ObjectMapper(); module = new SimpleModule(); List> l = new ArrayList<>(); l.add(SubB.class); l.add(SubC.class); l.add(SubD.class); module.registerSubtypes(l); mapper.registerModule(module); json = mapper.writeValueAsString(new PropertyBean(new SubC())); result = mapper.readValue(json, PropertyBean.class); assertSame(SubC.class, result.value.getClass()); } public void testSerialization() throws Exception { // serialization can detect type name ok without anything extra: SubB bean = new SubB(); assertEquals("{\"@type\":\"TypeB\",\"b\":1}", MAPPER.writeValueAsString(bean)); // but we can override type name here too ObjectMapper mapper = new ObjectMapper(); mapper.registerSubtypes(new NamedType(SubB.class, "typeB")); assertEquals("{\"@type\":\"typeB\",\"b\":1}", mapper.writeValueAsString(bean)); // and default name ought to be simple class name; with context assertEquals("{\"@type\":\"TestSubtypes$SubD\",\"d\":0}", mapper.writeValueAsString(new SubD())); } public void testDeserializationNonNamed() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerSubtypes(SubC.class); // default name should be unqualified class name SuperType bean = mapper.readValue("{\"@type\":\"TestSubtypes$SubC\", \"c\":1}", SuperType.class); assertSame(SubC.class, bean.getClass()); assertEquals(1, ((SubC) bean).c); } public void testDeserializatioNamed() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerSubtypes(SubB.class); mapper.registerSubtypes(new NamedType(SubD.class, "TypeD")); SuperType bean = mapper.readValue("{\"@type\":\"TypeB\", \"b\":13}", SuperType.class); assertSame(SubB.class, bean.getClass()); assertEquals(13, ((SubB) bean).b); // but we can also explicitly register name too bean = mapper.readValue("{\"@type\":\"TypeD\", \"d\":-4}", SuperType.class); assertSame(SubD.class, bean.getClass()); assertEquals(-4, ((SubD) bean).d); } // Trying to reproduce [JACKSON-366] public void testEmptyBean() throws Exception { // First, with annotations ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, true); String json = mapper.writeValueAsString(new EmptyBean()); assertEquals("{\"@type\":\"TestSubtypes$EmptyBean\"}", json); mapper = new ObjectMapper(); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); json = mapper.writeValueAsString(new EmptyBean()); assertEquals("{\"@type\":\"TestSubtypes$EmptyBean\"}", json); // and then with defaults mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); json = mapper.writeValueAsString(new EmptyNonFinal()); assertEquals("[\"com.fasterxml.jackson.databind.jsontype.TestSubtypes$EmptyNonFinal\",{}]", json); } public void testDefaultImpl() throws Exception { // first, test with no type information SuperTypeWithDefault bean = MAPPER.readValue("{\"a\":13}", SuperTypeWithDefault.class); assertEquals(DefaultImpl.class, bean.getClass()); assertEquals(13, ((DefaultImpl) bean).a); // and then with unmapped info bean = MAPPER.readValue("{\"a\":14,\"#type\":\"foobar\"}", SuperTypeWithDefault.class); assertEquals(DefaultImpl.class, bean.getClass()); assertEquals(14, ((DefaultImpl) bean).a); bean = MAPPER.readValue("{\"#type\":\"foobar\",\"a\":15}", SuperTypeWithDefault.class); assertEquals(DefaultImpl.class, bean.getClass()); assertEquals(15, ((DefaultImpl) bean).a); bean = MAPPER.readValue("{\"#type\":\"foobar\"}", SuperTypeWithDefault.class); assertEquals(DefaultImpl.class, bean.getClass()); assertEquals(0, ((DefaultImpl) bean).a); } // [JACKSON-505]: ok to also default to mapping there might be for base type public void testDefaultImplViaModule() throws Exception { final String JSON = "{\"a\":123}"; // first: without registration etc, epic fail: try { MAPPER.readValue(JSON, SuperTypeWithoutDefault.class); fail("Expected an exception"); } catch (InvalidTypeIdException e) { verifyException(e, "missing type id property '#type'"); } // but then succeed when we register default impl ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addAbstractTypeMapping(SuperTypeWithoutDefault.class, DefaultImpl505.class); mapper.registerModule(module); SuperTypeWithoutDefault bean = mapper.readValue(JSON, SuperTypeWithoutDefault.class); assertNotNull(bean); assertEquals(DefaultImpl505.class, bean.getClass()); assertEquals(123, ((DefaultImpl505) bean).a); bean = mapper.readValue("{\"#type\":\"foobar\"}", SuperTypeWithoutDefault.class); assertEquals(DefaultImpl505.class, bean.getClass()); assertEquals(0, ((DefaultImpl505) bean).a); } public void testErrorMessage() throws Exception { ObjectMapper mapper = new ObjectMapper(); try { mapper.readValue("{ \"type\": \"z\"}", BaseX.class); fail("Should have failed"); } catch (JsonMappingException e) { verifyException(e, "known type ids ="); } } public void testViaAtomic() throws Exception { AtomicWrapper input = new AtomicWrapper(3); String json = MAPPER.writeValueAsString(input); AtomicWrapper output = MAPPER.readValue(json, AtomicWrapper.class); assertNotNull(output); assertEquals(ImplX.class, output.value.getClass()); assertEquals(3, ((ImplX) output.value).x); } // Test to verify that base/impl restriction is applied to polymorphic handling // even if class name is used as the id public void testSubclassLimits() throws Exception { try { MAPPER.readValue(aposToQuotes("{'value':['" +TheBomb.class.getName()+"',{'a':13}] }"), DateWrapper.class); fail("Should not pass"); } catch (InvalidTypeIdException e) { verifyException(e, "not a subtype"); verifyException(e, TheBomb.class.getName()); } catch (Exception e) { fail("Should have hit `InvalidTypeIdException`, not `"+e.getClass().getName()+"`: "+e); } } // [databind#1125]: properties from base class too public void testIssue1125NonDefault() throws Exception { String json = MAPPER.writeValueAsString(new Issue1125Wrapper(new Impl1125(1, 2, 3))); Issue1125Wrapper result = MAPPER.readValue(json, Issue1125Wrapper.class); assertNotNull(result.value); assertEquals(Impl1125.class, result.value.getClass()); Impl1125 impl = (Impl1125) result.value; assertEquals(1, impl.a); assertEquals(2, impl.b); assertEquals(3, impl.c); } public void testIssue1125WithDefault() throws Exception { Issue1125Wrapper result = MAPPER.readValue(aposToQuotes("{'value':{'a':3,'def':9,'b':5}}"), Issue1125Wrapper.class); assertNotNull(result.value); assertEquals(Default1125.class, result.value.getClass()); Default1125 impl = (Default1125) result.value; assertEquals(3, impl.a); assertEquals(5, impl.b); assertEquals(9, impl.def); } } TestTypeNames.java000066400000000000000000000137371325620701100360010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Separate tests for verifying that "type name" type id mechanism * works. */ public class TestTypeNames extends BaseMapTest { @SuppressWarnings("serial") static class AnimalMap extends LinkedHashMap { } @JsonTypeInfo(property = "type", include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.NAME) @JsonSubTypes({ @JsonSubTypes.Type(value = A1616.class,name = "A"), @JsonSubTypes.Type(value = B1616.class) }) static abstract class Base1616 { } static class A1616 extends Base1616 { } @JsonTypeName("B") static class B1616 extends Base1616 { } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testBaseTypeId1616() throws Exception { ObjectMapper mapper = new ObjectMapper(); Collection subtypes = new StdSubtypeResolver().collectAndResolveSubtypesByTypeId( mapper.getDeserializationConfig(), // note: `null` is fine here as `AnnotatedMember`: null, mapper.constructType(Base1616.class)); assertEquals(2, subtypes.size()); Set ok = new HashSet<>(Arrays.asList("A", "B")); for (NamedType type : subtypes) { String id = type.getName(); if (!ok.contains(id)) { fail("Unexpected id '"+id+"' (mapping to: "+type.getType()+"), should be one of: "+ok); } } } public void testSerialization() throws Exception { // Note: need to use wrapper array just so that we can define // static type on serialization. If we had root static types, // could use those; but at the moment root type is dynamic assertEquals("[{\"doggy\":{\"name\":\"Spot\",\"ageInYears\":3}}]", MAPPER.writeValueAsString(new Animal[] { new Dog("Spot", 3) })); assertEquals("[{\"MaineCoon\":{\"name\":\"Belzebub\",\"purrs\":true}}]", MAPPER.writeValueAsString(new Animal[] { new MaineCoon("Belzebub", true)})); } public void testRoundTrip() throws Exception { Animal[] input = new Animal[] { new Dog("Odie", 7), null, new MaineCoon("Piru", false), new Persian("Khomeini", true) }; String json = MAPPER.writeValueAsString(input); List output = MAPPER.readValue(json, TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, Animal.class)); assertEquals(input.length, output.size()); for (int i = 0, len = input.length; i < len; ++i) { assertEquals("Entry #"+i+" differs, input = '"+json+"'", input[i], output.get(i)); } } public void testRoundTripMap() throws Exception { AnimalMap input = new AnimalMap(); input.put("venla", new MaineCoon("Venla", true)); input.put("ama", new Dog("Amadeus", 13)); String json = MAPPER.writeValueAsString(input); AnimalMap output = MAPPER.readValue(json, AnimalMap.class); assertNotNull(output); assertEquals(AnimalMap.class, output.getClass()); assertEquals(input.size(), output.size()); // for some reason, straight comparison won't work... for (String name : input.keySet()) { Animal in = input.get(name); Animal out = output.get(name); if (!in.equals(out)) { fail("Animal in input was ["+in+"]; output not matching: ["+out+"]"); } } } } /* /********************************************************** /* Helper types /********************************************************** */ @JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT) @JsonSubTypes({ @Type(value=Dog.class, name="doggy"), @Type(Cat.class) /* defaults to "TestTypedNames$Cat" then */ }) class Animal { public String name; @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; return name.equals(((Animal) o).name); } @Override public String toString() { return getClass().toString() + "('"+name+"')"; } } class Dog extends Animal { public int ageInYears; public Dog() { } public Dog(String n, int y) { name = n; ageInYears = y; } @Override public boolean equals(Object o) { return super.equals(o) && ((Dog) o).ageInYears == ageInYears; } } @JsonSubTypes({ @Type(MaineCoon.class), @Type(Persian.class) }) abstract class Cat extends Animal { public boolean purrs; public Cat() { } public Cat(String n, boolean p) { name = n; purrs = p; } @Override public boolean equals(Object o) { return super.equals(o) && ((Cat) o).purrs == purrs; } @Override public String toString() { return super.toString()+"(purrs: "+purrs+")"; } } /* uses default name ("MaineCoon") since there's no @JsonTypeName, * nor did supertype specify name */ class MaineCoon extends Cat { public MaineCoon() { super(); } public MaineCoon(String n, boolean p) { super(n, p); } } @JsonTypeName("persialaisKissa") class Persian extends Cat { public Persian() { super(); } public Persian(String n, boolean p) { super(n, p); } } TestTypedArrayDeserialization.java000066400000000000000000000105731325620701100412220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.ArrayList; import java.util.LinkedList; import static org.junit.Assert.assertArrayEquals; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.type.TypeFactory; public class TestTypedArrayDeserialization extends BaseMapTest { /* /********************************************************** /* Helper types /********************************************************** */ /** * Let's claim we need type here too (although we won't * really use any sub-classes) */ @SuppressWarnings("serial") @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) static class TypedList extends ArrayList { } @SuppressWarnings("serial") @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) static class TypedListAsProp extends ArrayList { } @SuppressWarnings("serial") @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT) static class TypedListAsWrapper extends LinkedList { } // Mix-in to force wrapper for things like primitive arrays @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT) interface WrapperMixIn { } /* /********************************************************** /* Unit tests, Lists /********************************************************** */ public void testIntList() throws Exception { ObjectMapper m = new ObjectMapper(); // uses WRAPPER_OBJECT inclusion String JSON = "{\""+TypedListAsWrapper.class.getName()+"\":[4,5, 6]}"; JavaType type = TypeFactory.defaultInstance().constructCollectionType(TypedListAsWrapper.class, Integer.class); TypedListAsWrapper result = m.readValue(JSON, type); assertNotNull(result); assertEquals(3, result.size()); assertEquals(Integer.valueOf(4), result.get(0)); assertEquals(Integer.valueOf(5), result.get(1)); assertEquals(Integer.valueOf(6), result.get(2)); } /** * Similar to above, but this time let's request adding type info * as property. That would not work (since there's no JSON Object to * add property in), so it will basically be same as using WRAPPER_ARRAY */ public void testBooleanListAsProp() throws Exception { ObjectMapper m = new ObjectMapper(); // tries to use PROPERTY inclusion; but for ARRAYS (and scalars) will become ARRAY_WRAPPER String JSON = "[\""+TypedListAsProp.class.getName()+"\",[true, false]]"; JavaType type = TypeFactory.defaultInstance().constructCollectionType(TypedListAsProp.class, Boolean.class); TypedListAsProp result = m.readValue(JSON, type); assertNotNull(result); assertEquals(2, result.size()); assertEquals(Boolean.TRUE, result.get(0)); assertEquals(Boolean.FALSE, result.get(1)); } public void testLongListAsWrapper() throws Exception { ObjectMapper m = new ObjectMapper(); // uses OBJECT_ARRAY, works just fine String JSON = "{\""+TypedListAsWrapper.class.getName()+"\":[1, 3]}"; JavaType type = TypeFactory.defaultInstance().constructCollectionType(TypedListAsWrapper.class, Long.class); TypedListAsWrapper result = m.readValue(JSON, type); assertNotNull(result); assertEquals(2, result.size()); assertEquals(Long.class, result.get(0).getClass()); assertEquals(Long.valueOf(1), result.get(0)); assertEquals(Long.class, result.get(1).getClass()); assertEquals(Long.valueOf(3), result.get(1)); } /* /********************************************************** /* Unit tests, primitive arrays /********************************************************** */ public void testLongArray() throws Exception { ObjectMapper m = new ObjectMapper(); // use class name, WRAPPER_OBJECT m.addMixIn(long[].class, WrapperMixIn.class); String JSON = "{\""+long[].class.getName()+"\":[5, 6, 7]}"; long[] value = m.readValue(JSON, long[].class); assertNotNull(value); assertEquals(3, value.length); assertArrayEquals(new long[] { 5L, 6L, 7L} , value); } } TestTypedArraySerialization.java000066400000000000000000000122731325620701100407100ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying that types that serialize as JSON Arrays * get properly serialized with types (esp. for contents, and * gracefully handling Lists themselves too) */ public class TestTypedArraySerialization extends BaseMapTest { /* /********************************************************** /* Helper types /********************************************************** */ /** * Let's claim we need type here too (although we won't * really use any sub-classes) */ @SuppressWarnings("serial") @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) static class TypedList extends ArrayList { } @SuppressWarnings("serial") @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) static class TypedListAsProp extends ArrayList { } @SuppressWarnings("serial") @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT) static class TypedListAsWrapper extends LinkedList { } // Mix-in to force wrapper for things like primitive arrays @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT) interface WrapperMixIn { } // for [JACKSON-341] @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT) @JsonSubTypes({ @JsonSubTypes.Type(B.class) }) interface A { } @JsonTypeName("BB") static class B implements A { public int value = 2; } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY) @JsonTypeName("bean") static class Bean { public int x = 0; } static class BeanListWrapper { @JsonView({Object.class}) public List beans = new ArrayList(); { beans.add(new Bean()); } } /* /********************************************************** /* Unit tests, Lists /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testListWithPolymorphic() throws Exception { BeanListWrapper beans = new BeanListWrapper(); assertEquals("{\"beans\":[{\"@type\":\"bean\",\"x\":0}]}", MAPPER.writeValueAsString(beans)); // Related to [JACKSON-364] ObjectWriter w = MAPPER.writerWithView(Object.class); assertEquals("{\"beans\":[{\"@type\":\"bean\",\"x\":0}]}", w.writeValueAsString(beans)); } public void testIntList() throws Exception { TypedList input = new TypedList(); input.add(5); input.add(13); // uses WRAPPER_ARRAY inclusion: assertEquals("[\""+TypedList.class.getName()+"\",[5,13]]", MAPPER.writeValueAsString(input)); } // Similar to above, but this time let's request adding type info // as property. That would not work (since there's no JSON Object to // add property in), so it should revert to method used with // ARRAY_WRAPPER method. public void testStringListAsProp() throws Exception { TypedListAsProp input = new TypedListAsProp(); input.add("a"); input.add("b"); assertEquals("[\""+TypedListAsProp.class.getName()+"\",[\"a\",\"b\"]]", MAPPER.writeValueAsString(input)); } public void testStringListAsObjectWrapper() throws Exception { TypedListAsWrapper input = new TypedListAsWrapper(); input.add(true); input.add(null); input.add(false); // Can wrap in JSON Object for wrapped style... also, will use // non-qualified class name as type name, since there are no // annotations String expName = "TestTypedArraySerialization$TypedListAsWrapper"; assertEquals("{\""+expName+"\":[true,null,false]}", MAPPER.writeValueAsString(input)); } /* /********************************************************** /* Unit tests, primitive arrays /********************************************************** */ public void testIntArray() throws Exception { ObjectMapper m = new ObjectMapper(); m.addMixIn(int[].class, WrapperMixIn.class); int[] input = new int[] { 1, 2, 3 }; String clsName = int[].class.getName(); assertEquals("{\""+clsName+"\":[1,2,3]}", m.writeValueAsString(input)); } /* /********************************************************** /* Unit tests, generic arrays /********************************************************** */ public void testGenericArray() throws Exception { final A[] input = new A[] { new B() }; final String EXP = "[{\"BB\":{\"value\":2}}]"; // first, with defaults assertEquals(EXP, MAPPER.writeValueAsString(input)); // then with static typing enabled: ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.USE_STATIC_TYPING, true); assertEquals(EXP, m.writeValueAsString(input)); } } TestTypedContainerSerialization.java000066400000000000000000000101031325620701100415420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import org.junit.Assert; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class TestTypedContainerSerialization extends BaseMapTest { @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "object-type") @JsonSubTypes( { @Type(value = Dog.class, name = "doggy"), @Type(value = Cat.class, name = "kitty") }) static abstract class Animal { public String name; protected Animal(String n) { name = n; } } @JsonTypeName("doggie") static class Dog extends Animal { public int boneCount; public Dog() { super(null); } @JsonCreator public Dog(@JsonProperty("name") String name) { super(name); } public void setBoneCount(int i) { boneCount = i; } } @JsonTypeName("kitty") static class Cat extends Animal { public String furColor; public Cat() { super(null); } @JsonCreator public Cat(@JsonProperty("furColor") String c) { super(null); furColor = c; } public void setName(String n) { name = n; } } static class Container1 { Animal animal; public Animal getAnimal() { return animal; } public void setAnimal(Animal animal) { this.animal = animal; } } static class Container2 { @JsonSerialize T animal; public T getAnimal() { return animal; } public void setAnimal(T animal) { this.animal = animal; } } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") static class Issue508A { } static class Issue508B extends Issue508A { } private final static ObjectMapper mapper = new ObjectMapper(); /* /********************************************************** /* Test methods /********************************************************** */ public void testPolymorphicWithContainer() throws Exception { Dog dog = new Dog("medor"); dog.setBoneCount(3); Container1 c1 = new Container1(); c1.setAnimal(dog); String s1 = mapper.writeValueAsString(c1); Assert.assertTrue("polymorphic type info is kept (1)", s1 .indexOf("\"object-type\":\"doggy\"") >= 0); Container2 c2 = new Container2(); c2.setAnimal(dog); String s2 = mapper.writeValueAsString(c2); Assert.assertTrue("polymorphic type info is kept (2)", s2 .indexOf("\"object-type\":\"doggy\"") >= 0); } public void testIssue329() throws Exception { ArrayList animals = new ArrayList(); animals.add(new Dog("Spot")); JavaType rootType = mapper.getTypeFactory().constructParametricType(Iterator.class, Animal.class); String json = mapper.writerFor(rootType).writeValueAsString(animals.iterator()); if (json.indexOf("\"object-type\":\"doggy\"") < 0) { fail("No polymorphic type retained, should be; JSON = '"+json+"'"); } } public void testIssue508() throws Exception { List> l = new ArrayList>(); List l2 = new ArrayList(); l2.add(new Issue508A()); l.add(l2); TypeReference typeRef = new TypeReference>>() {}; String json = mapper.writerFor(typeRef).writeValueAsString(l); List output = mapper.readValue(json, typeRef); assertEquals(1, output.size()); Object ob = output.get(0); assertTrue(ob instanceof List); List list2 = (List) ob; assertEquals(1, list2.size()); ob = list2.get(0); assertSame(Issue508A.class, ob.getClass()); } } TestTypedDeserialization.java000066400000000000000000000174201325620701100402210ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.type.TypeFactory; public class TestTypedDeserialization extends BaseMapTest { /* /********************************************************** /* Helper types /********************************************************** */ /** * Polymorphic base class */ @JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY, property="@classy") static abstract class Animal { public String name; protected Animal(String n) { name = n; } } @JsonTypeName("doggie") static class Dog extends Animal { public int boneCount; @JsonCreator public Dog(@JsonProperty("name") String name) { super(name); } public void setBoneCount(int i) { boneCount = i; } } @JsonTypeName("kitty") static class Cat extends Animal { public String furColor; @JsonCreator public Cat(@JsonProperty("furColor") String c) { super(null); furColor = c; } public void setName(String n) { name = n; } } // for [JACKSON-319] -- allow "empty" beans @JsonTypeName("fishy") static class Fish extends Animal { @JsonCreator public Fish() { super(null); } } static class AnimalContainer { public Animal animal; } // base class with no useful info @JsonTypeInfo(use=Id.CLASS, include=As.WRAPPER_ARRAY) static abstract class DummyBase { protected DummyBase(boolean foo) { } } static class DummyImpl extends DummyBase { public int x; public DummyImpl() { super(true); } } @JsonTypeInfo(use=Id.MINIMAL_CLASS, include=As.WRAPPER_OBJECT) interface TypeWithWrapper { } @JsonTypeInfo(use=Id.CLASS, include=As.WRAPPER_ARRAY) interface TypeWithArray { } static class Issue506DateBean { @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type2") public Date date; } static class Issue506NumberBean { @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type3") @JsonSubTypes({ @Type(Long.class), @Type(Integer.class) }) public Number number; } /* /********************************************************** /* Unit tests /********************************************************** */ /** * First things first, let's ensure we can serialize using * class name, written as main-level property name */ public void testSimpleClassAsProperty() throws Exception { ObjectMapper m = new ObjectMapper(); Animal a = m.readValue(asJSONObjectValueString("@classy", Cat.class.getName(), "furColor", "tabby", "name", "Garfield"), Animal.class); assertNotNull(a); assertEquals(Cat.class, a.getClass()); Cat c = (Cat) a; assertEquals("Garfield", c.name); assertEquals("tabby", c.furColor); } // Test inclusion using wrapper style public void testTypeAsWrapper() throws Exception { ObjectMapper m = new ObjectMapper(); m.addMixIn(Animal.class, TypeWithWrapper.class); String JSON = "{\".TestTypedDeserialization$Dog\" : " +asJSONObjectValueString(m, "name", "Scooby", "boneCount", "6")+" }"; Animal a = m.readValue(JSON, Animal.class); assertTrue(a instanceof Animal); assertEquals(Dog.class, a.getClass()); Dog d = (Dog) a; assertEquals("Scooby", d.name); assertEquals(6, d.boneCount); } // Test inclusion using 2-element array public void testTypeAsArray() throws Exception { ObjectMapper m = new ObjectMapper(); m.addMixIn(Animal.class, TypeWithArray.class); // hmmh. Not good idea to rely on exact output, order may change. But... String JSON = "[\""+Dog.class.getName()+"\", " +asJSONObjectValueString(m, "name", "Martti", "boneCount", "11")+" ]"; Animal a = m.readValue(JSON, Animal.class); assertEquals(Dog.class, a.getClass()); Dog d = (Dog) a; assertEquals("Martti", d.name); assertEquals(11, d.boneCount); } // Use basic Animal as contents of a regular List public void testListAsArray() throws Exception { ObjectMapper m = new ObjectMapper(); // This time using PROPERTY style (default) again String JSON = "[\n" +asJSONObjectValueString(m, "@classy", Cat.class.getName(), "name", "Hello", "furColor", "white") +",\n" // let's shuffle doggy's fields a bit for testing +asJSONObjectValueString(m, "boneCount", Integer.valueOf(1), "@classy", Dog.class.getName(), "name", "Bob" ) +",\n" +asJSONObjectValueString(m, "@classy", Fish.class.getName()) +", null\n]"; JavaType expType = TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, Animal.class); List animals = m.readValue(JSON, expType); assertNotNull(animals); assertEquals(4, animals.size()); Cat c = (Cat) animals.get(0); assertEquals("Hello", c.name); assertEquals("white", c.furColor); Dog d = (Dog) animals.get(1); assertEquals("Bob", d.name); assertEquals(1, d.boneCount); Fish f = (Fish) animals.get(2); assertNotNull(f); assertNull(animals.get(3)); } public void testCagedAnimal() throws Exception { ObjectMapper m = new ObjectMapper(); String jsonCat = asJSONObjectValueString(m, "@classy", Cat.class.getName(), "name", "Nilson", "furColor", "black"); String JSON = "{\"animal\":"+jsonCat+"}"; AnimalContainer cont = m.readValue(JSON, AnimalContainer.class); assertNotNull(cont); Animal a = cont.animal; assertNotNull(a); Cat c = (Cat) a; assertEquals("Nilson", c.name); assertEquals("black", c.furColor); } /** * Test that verifies that there are few limitations on polymorphic * base class. */ public void testAbstractEmptyBaseClass() throws Exception { DummyBase result = new ObjectMapper().readValue( "[\""+DummyImpl.class.getName()+"\",{\"x\":3}]", DummyBase.class); assertNotNull(result); assertEquals(DummyImpl.class, result.getClass()); assertEquals(3, ((DummyImpl) result).x); } // [JACKSON-506], wrt Date public void testIssue506WithDate() throws Exception { Issue506DateBean input = new Issue506DateBean(); input.date = new Date(1234L); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(input); Issue506DateBean output = mapper.readValue(json, Issue506DateBean.class); assertEquals(input.date, output.date); } // [JACKSON-506], wrt Number public void testIssue506WithNumber() throws Exception { Issue506NumberBean input = new Issue506NumberBean(); input.number = Long.valueOf(4567L); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(input); Issue506NumberBean output = mapper.readValue(json, Issue506NumberBean.class); assertEquals(input.number, output.number); } } TestTypedSerialization.java000066400000000000000000000156171325620701100377160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import static com.fasterxml.jackson.annotation.JsonTypeInfo.*; public class TestTypedSerialization extends BaseMapTest { /* /********************************************************** /* Helper types /********************************************************** */ /** * Polymorphic base class */ @JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY) static abstract class Animal { public String name; protected Animal(String n) { name = n; } } @JsonTypeName("doggie") static class Dog extends Animal { public int boneCount; private Dog() { super(null); } public Dog(String name, int b) { super(name); boneCount = b; } } @JsonTypeName("kitty") static class Cat extends Animal { public String furColor; private Cat() { super(null); } public Cat(String name, String c) { super(name); furColor = c; } } public class AnimalWrapper { public Animal animal; public AnimalWrapper(Animal a) { animal = a; } } @JsonTypeInfo(use=Id.MINIMAL_CLASS, include=As.WRAPPER_OBJECT) interface TypeWithWrapper { } @JsonTypeInfo(use=Id.CLASS, include=As.WRAPPER_ARRAY) interface TypeWithArray { } @JsonTypeInfo(use=Id.NAME) @JsonTypeName("empty") public class Empty { } @JsonTypeInfo(include=As.PROPERTY, use=Id.CLASS) public class Super {} public class A extends Super {} public class B extends Super {} /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); /** * First things first, let's ensure we can serialize using * class name, written as main-level property name */ public void testSimpleClassAsProperty() throws Exception { Map result = writeAndMap(MAPPER, new Cat("Beelzebub", "tabby")); assertEquals(3, result.size()); assertEquals("Beelzebub", result.get("name")); assertEquals("tabby", result.get("furColor")); // should we try customized class name? String classProp = Id.CLASS.getDefaultPropertyName(); assertEquals(Cat.class.getName(), result.get(classProp)); } /** * Test inclusion using wrapper style */ public void testTypeAsWrapper() throws Exception { ObjectMapper m = new ObjectMapper(); m.addMixIn(Animal.class, TypeWithWrapper.class); Map result = writeAndMap(m, new Cat("Venla", "black")); // should get a wrapper; keyed by minimal class name ("Cat" here) assertEquals(1, result.size()); // minimal class name is prefixed by dot, and for inner classes it's bit longer Map cat = (Map) result.get(".TestTypedSerialization$Cat"); assertNotNull(cat); assertEquals(2, cat.size()); assertEquals("Venla", cat.get("name")); assertEquals("black", cat.get("furColor")); } /** * Test inclusion using 2-element array */ public void testTypeAsArray() throws Exception { ObjectMapper m = new ObjectMapper(); m.addMixIn(Animal.class, TypeWithArray.class); // hmmh. Not good idea to rely on exact output, order may change. But... Map result = writeAndMap(m, new AnimalWrapper(new Dog("Amadeus", 7))); // First level, wrapper assertEquals(1, result.size()); List l = (List) result.get("animal"); assertNotNull(l); assertEquals(2, l.size()); assertEquals(Dog.class.getName(), l.get(0)); Map doggie = (Map) l.get(1); assertNotNull(doggie); assertEquals(2, doggie.size()); assertEquals("Amadeus", doggie.get("name")); assertEquals(Integer.valueOf(7), doggie.get("boneCount")); } /* !!! 30-Jan-2010, tatus: I am not completely sure below works as it should * Problem is, context of "untyped" map should prevent type information * being added to Animal entries, because Object.class has no type. * If type information is included, it will not be useful for deserialization, * since static type does not carry through (unlike in serialization). * * But it is not quite clear how type information should be pushed through * array types... */ @SuppressWarnings("unchecked") public void testInArray() throws Exception { // ensure we'll use mapper with default configs ObjectMapper m = new ObjectMapper(); // ... so this should NOT be needed... m.disableDefaultTyping(); Animal[] animals = new Animal[] { new Cat("Miuku", "white"), new Dog("Murre", 9) }; Map map = new HashMap(); map.put("a", animals); String json = m.writeValueAsString(map); Map result = m.readValue(json, Map.class); assertEquals(1, result.size()); Object ob = result.get("a"); if (!(ob instanceof List)) { // 03-Feb-2010, tatu: Weird; seems to fail sometimes... fail("Did not map to entry with 'a' as List (but as "+ob.getClass().getName()+"): JSON == '"+json+"'"); } List l = (List)ob; assertNotNull(l); assertEquals(2, l.size()); Map a1 = (Map) l.get(0); assertEquals(3, a1.size()); String classProp = Id.CLASS.getDefaultPropertyName(); assertEquals(Cat.class.getName(), a1.get(classProp)); Map a2 = (Map) l.get(1); assertEquals(3, a2.size()); assertEquals(Dog.class.getName(), a2.get(classProp)); } /** * Simple unit test to verify that serializing "empty" beans is ok */ public void testEmptyBean() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); assertEquals("{\"@type\":\"empty\"}", m.writeValueAsString(new Empty())); } /** * Unit test for [JACKSON-543] */ public void testTypedMaps() throws Exception { ObjectMapper mapper = new ObjectMapper(); Map> map = new HashMap>(); List list = new ArrayList(); list.add(new A()); map.put(1L, list); String json = mapper.writerFor(new TypeReference>>() {}).writeValueAsString(map); assertTrue("JSON does not contain '@class': "+json, json.contains("@class")); } } TestVisibleTypeId.java000066400000000000000000000202261325620701100365770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.*; /** * Tests to verify that Type Id may be exposed during deserialization, */ public class TestVisibleTypeId extends BaseMapTest { // type id as property, exposed @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type", visible=true) @JsonTypeName("BaseType") static class PropertyBean { public int a = 3; protected String type; public void setType(String t) { type = t; } } // as wrapper-array @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_ARRAY, property="type", visible=true) @JsonTypeName("ArrayType") static class WrapperArrayBean { public int a = 1; protected String type; public void setType(String t) { type = t; } } // as wrapper-object @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT, property="type", visible=true) @JsonTypeName("ObjectType") static class WrapperObjectBean { public int a = 2; protected String type; public void setType(String t) { type = t; } } @JsonTypeName("ExternalType") static class ExternalIdBean { public int a = 2; protected String type; public void setType(String t) { type = t; } } // // // [JACKSON-762]: type id from property @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type") static class TypeIdFromFieldProperty { public int a = 3; @JsonTypeId public String type = "SomeType"; } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_ARRAY, property="type") static class TypeIdFromFieldArray { public int a = 3; @JsonTypeId public String type = "SomeType"; } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT, property="type") static class TypeIdFromMethodObject { public int a = 3; @JsonTypeId public String getType() { return "SomeType"; } } static class ExternalIdWrapper2 { @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.EXTERNAL_PROPERTY, property="type", visible=true) public ExternalIdBean2 bean = new ExternalIdBean2(); } static class ExternalIdBean2 { public int a = 2; /* Type id property itself cannot be external, as it is conceptually * part of the bean for which info is written: */ @JsonTypeId public String getType() { return "SomeType"; } } // Invalid definition: multiple type ids static class MultipleIds { @JsonTypeId public String type1 = "type1"; @JsonTypeId public String getType2() { return "type2"; }; } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "name") @JsonSubTypes({ @JsonSubTypes.Type(value=I263Impl.class) }) public static abstract class I263Base { @JsonTypeId public abstract String getName(); } @JsonPropertyOrder({ "age", "name" }) @JsonTypeName("bob") public static class I263Impl extends I263Base { @Override public String getName() { return "bob"; } public int age = 41; } // [databind#408] static class ExternalBeanWithId { protected String _type; @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="type", visible=true) public ValueBean bean; public ExternalBeanWithId() { } public ExternalBeanWithId(int v) { bean = new ValueBean(v); } public void setType(String t) { _type = t; } } @JsonTypeName("vbean") static class ValueBean { public int value; public ValueBean() { } public ValueBean(int v) { value = v; } } /* /********************************************************** /* Unit tests, success /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testVisibleWithProperty() throws Exception { String json = MAPPER.writeValueAsString(new PropertyBean()); // just default behavior: assertEquals("{\"type\":\"BaseType\",\"a\":3}", json); // but then expect to read it back PropertyBean result = MAPPER.readValue(json, PropertyBean.class); assertEquals("BaseType", result.type); // also, should work with order reversed result = MAPPER.readValue("{\"a\":7, \"type\":\"BaseType\"}", PropertyBean.class); assertEquals(7, result.a); assertEquals("BaseType", result.type); } public void testVisibleWithWrapperArray() throws Exception { String json = MAPPER.writeValueAsString(new WrapperArrayBean()); // just default behavior: assertEquals("[\"ArrayType\",{\"a\":1}]", json); // but then expect to read it back WrapperArrayBean result = MAPPER.readValue(json, WrapperArrayBean.class); assertEquals("ArrayType", result.type); assertEquals(1, result.a); } public void testVisibleWithWrapperObject() throws Exception { String json = MAPPER.writeValueAsString(new WrapperObjectBean()); assertEquals("{\"ObjectType\":{\"a\":2}}", json); // but then expect to read it back WrapperObjectBean result = MAPPER.readValue(json, WrapperObjectBean.class); assertEquals("ObjectType", result.type); } public void testTypeIdFromProperty() throws Exception { assertEquals("{\"type\":\"SomeType\",\"a\":3}", MAPPER.writeValueAsString(new TypeIdFromFieldProperty())); } public void testTypeIdFromArray() throws Exception { assertEquals("[\"SomeType\",{\"a\":3}]", MAPPER.writeValueAsString(new TypeIdFromFieldArray())); } public void testTypeIdFromObject() throws Exception { assertEquals("{\"SomeType\":{\"a\":3}}", MAPPER.writeValueAsString(new TypeIdFromMethodObject())); } public void testTypeIdFromExternal() throws Exception { String json = MAPPER.writeValueAsString(new ExternalIdWrapper2()); // Implementation detail: type id written AFTER value, due to constraints assertEquals("{\"bean\":{\"a\":2},\"type\":\"SomeType\"}", json); } public void testIssue263() throws Exception { // first, serialize: assertEquals("{\"name\":\"bob\",\"age\":41}", MAPPER.writeValueAsString(new I263Impl())); // then bring back: I263Base result = MAPPER.readValue("{\"age\":19,\"name\":\"bob\"}", I263Base.class); assertTrue(result instanceof I263Impl); assertEquals(19, ((I263Impl) result).age); } // [databind#408] /* NOTE: Handling changed between 2.4 and 2.5; earlier, type id was 'injected' * inside POJO; but with 2.5 this was fixed so it would remain outside, similar * to how JSON structure is. */ public void testVisibleTypeId408() throws Exception { String json = MAPPER.writeValueAsString(new ExternalBeanWithId(3)); ExternalBeanWithId result = MAPPER.readValue(json, ExternalBeanWithId.class); assertNotNull(result); assertNotNull(result.bean); assertEquals(3, result.bean.value); assertEquals("vbean", result._type); } /* /********************************************************** /* Unit tests, fails /********************************************************** */ public void testInvalidMultipleTypeIds() throws Exception { try { MAPPER.writeValueAsString(new MultipleIds()); fail("Should have failed"); } catch (JsonMappingException e) { verifyException(e, "multiple type ids"); } } } TestWithGenerics.java000066400000000000000000000174171325620701100364660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.BeanSerializerFactory; import com.fasterxml.jackson.databind.ser.ResolvableSerializer; public class TestWithGenerics extends BaseMapTest { @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "object-type") @JsonSubTypes( { @Type(value = Dog.class, name = "doggy") }) static abstract class Animal { public String name; } static class Dog extends Animal { public int boneCount; public Dog(String name, int b) { super(); this.name = name; boneCount = b; } } static class ContainerWithGetter { private T animal; public ContainerWithGetter(T a) { animal = a; } public T getAnimal() { return animal; } } static class ContainerWithField { public T animal; public ContainerWithField(T a) { animal = a; } } static class WrappedContainerWithField { public ContainerWithField animalContainer; } // Beans for [JACKSON-387], [JACKSON-430] @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@classAttr1") static class MyClass { public List> params = new ArrayList>(); } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@classAttr2") static class MyParam{ public T value; public MyParam() { } public MyParam(T v) { value = v; } } static class SomeObject { public String someValue = UUID.randomUUID().toString(); } // Beans for [JACKSON-430] static class CustomJsonSerializer extends JsonSerializer implements ResolvableSerializer { private final JsonSerializer beanSerializer; public CustomJsonSerializer( JsonSerializer beanSerializer ) { this.beanSerializer = beanSerializer; } @Override public void serialize( Object value, JsonGenerator jgen, SerializerProvider provider ) throws IOException, JsonProcessingException { beanSerializer.serialize( value, jgen, provider ); } @Override public Class handledType() { return beanSerializer.handledType(); } @Override public void serializeWithType( Object value, JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer ) throws IOException, JsonProcessingException { beanSerializer.serializeWithType( value, jgen, provider, typeSer ); } @Override public void resolve(SerializerProvider provider) throws JsonMappingException { if (beanSerializer instanceof ResolvableSerializer) { ((ResolvableSerializer) beanSerializer).resolve(provider); } } } @SuppressWarnings("serial") protected static class CustomJsonSerializerFactory extends BeanSerializerFactory { public CustomJsonSerializerFactory() { super(null); } @Override protected JsonSerializer constructBeanSerializer(SerializerProvider prov, BeanDescription beanDesc) throws JsonMappingException { return new CustomJsonSerializer(super.constructBeanSerializer(prov, beanDesc) ); } } // [Issue#543] static class ContainerWithTwoAnimals extends ContainerWithField { public V otherAnimal; public ContainerWithTwoAnimals(U a1, V a2) { super(a1); otherAnimal = a2; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testWrapperWithGetter() throws Exception { Dog dog = new Dog("Fluffy", 3); String json = MAPPER.writeValueAsString(new ContainerWithGetter(dog)); if (json.indexOf("\"object-type\":\"doggy\"") < 0) { fail("polymorphic type not kept, result == "+json+"; should contain 'object-type':'...'"); } } public void testWrapperWithField() throws Exception { Dog dog = new Dog("Fluffy", 3); String json = MAPPER.writeValueAsString(new ContainerWithField(dog)); if (json.indexOf("\"object-type\":\"doggy\"") < 0) { fail("polymorphic type not kept, result == "+json+"; should contain 'object-type':'...'"); } } public void testWrapperWithExplicitType() throws Exception { Dog dog = new Dog("Fluffy", 3); ContainerWithGetter c2 = new ContainerWithGetter(dog); String json = MAPPER.writerFor(MAPPER.getTypeFactory().constructParametricType(ContainerWithGetter.class, Animal.class)).writeValueAsString(c2); if (json.indexOf("\"object-type\":\"doggy\"") < 0) { fail("polymorphic type not kept, result == "+json+"; should contain 'object-type':'...'"); } } public void testJackson387() throws Exception { ObjectMapper om = new ObjectMapper(); om.enableDefaultTyping( ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.As.PROPERTY ); om.setSerializationInclusion(JsonInclude.Include.NON_NULL ); om.enable( SerializationFeature.INDENT_OUTPUT); MyClass mc = new MyClass(); MyParam moc1 = new MyParam(1); MyParam moc2 = new MyParam("valueX"); SomeObject so = new SomeObject(); so.someValue = "xxxxxx"; MyParam moc3 = new MyParam(so); List colist = new ArrayList(); colist.add( new SomeObject() ); colist.add( new SomeObject() ); colist.add( new SomeObject() ); MyParam> moc4 = new MyParam>(colist); mc.params.add( moc1 ); mc.params.add( moc2 ); mc.params.add( moc3 ); mc.params.add( moc4 ); String json = om.writeValueAsString( mc ); MyClass mc2 = om.readValue(json, MyClass.class ); assertNotNull(mc2); assertNotNull(mc2.params); assertEquals(4, mc2.params.size()); } public void testJackson430() throws Exception { ObjectMapper om = new ObjectMapper(); // om.getSerializationConfig().setSerializationInclusion( Inclusion.NON_NULL ); om.setSerializerFactory( new CustomJsonSerializerFactory() ); MyClass mc = new MyClass(); mc.params.add(new MyParam(1)); String str = om.writeValueAsString( mc ); // System.out.println( str ); MyClass mc2 = om.readValue( str, MyClass.class ); assertNotNull(mc2); assertNotNull(mc2.params); assertEquals(1, mc2.params.size()); } // [Issue#543] public void testValueWithMoreGenericParameters() throws Exception { WrappedContainerWithField wrappedContainerWithField = new WrappedContainerWithField(); wrappedContainerWithField.animalContainer = new ContainerWithTwoAnimals(new Dog("d1",1), new Dog("d2",2)); String json = MAPPER.writeValueAsString(wrappedContainerWithField); assertNotNull(json); } } TypeDeserializerTest.java000066400000000000000000000025671325620701100373570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; public class TypeDeserializerTest extends BaseMapTest { public void testUtilMethods() throws Exception { final JsonFactory f = new JsonFactory(); JsonParser p = f.createParser("true"); assertNull(TypeDeserializer.deserializeIfNatural(p, null, Object.class)); p.nextToken(); assertEquals(Boolean.TRUE, TypeDeserializer.deserializeIfNatural(p, null, Object.class)); p.close(); p = f.createParser("false "); p.nextToken(); assertEquals(Boolean.FALSE, TypeDeserializer.deserializeIfNatural(p, null, Object.class)); p.close(); p = f.createParser("1"); p.nextToken(); assertEquals(Integer.valueOf(1), TypeDeserializer.deserializeIfNatural(p, null, Object.class)); p.close(); p = f.createParser("0.5 "); p.nextToken(); assertEquals(Double.valueOf(0.5), TypeDeserializer.deserializeIfNatural(p, null, Object.class)); p.close(); p = f.createParser("\"foo\" [ ] "); p.nextToken(); assertEquals("foo", TypeDeserializer.deserializeIfNatural(p, null, Object.class)); p.nextToken(); assertNull(TypeDeserializer.deserializeIfNatural(p, null, Object.class)); p.close(); } } TypeRefinementForMapTest.java000066400000000000000000000105071325620701100401270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.io.IOException; import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class TypeRefinementForMapTest extends BaseMapTest { interface HasUniqueId { K getId(); } static class Item implements HasUniqueId { public String id; public String property; @Override public String getId() { return id; } } static class Data { public String id; @JsonDeserialize(as = MyHashMap.class) public Map items; // Would work with straight arguments: // public MyHashMap items; } @SuppressWarnings("serial") static class MyHashMap> extends LinkedHashMap { @JsonCreator(mode=JsonCreator.Mode.DELEGATING) public MyHashMap(V[] values) { for (int i = 0; i < values.length; i++) { V v = values[i]; put(v.getId(), v); } } } // for [databind#1384] @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public static final class TestClass { @JsonProperty("mapProperty") @JsonSerialize(keyUsing = CompoundKeySerializer.class) @JsonDeserialize(keyUsing = CompoundKeyDeserializer.class) private final Map mapProperty; @JsonCreator private TestClass(@JsonProperty("mapProperty") Map mapProperty) { this.mapProperty = mapProperty; } } static final class CompoundKey { private String part0; private String part1; public CompoundKey(String part0, String part1) { this.part0 = part0; this.part1 = part1; } public String getPart0() { return part0; } public String getPart1() { return part1; } } static class CompoundKeyDeserializer extends KeyDeserializer { @Override public Object deserializeKey(String s, DeserializationContext deserializationContext) { String[] parts = s.split("\\|"); return new CompoundKey(parts[0], parts[1]); } } static class CompoundKeySerializer extends JsonSerializer { @Override public void serialize(CompoundKey compoundKey, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeFieldName(compoundKey.getPart0() + '|' + compoundKey.getPart1()); } } /* /******************************************************* /* Test methods /******************************************************* */ public void testMapRefinement() throws Exception { String ID1 = "3a6383d4-8123-4c43-8b8d-7cedf3e59404"; String ID2 = "81c3d978-90c4-4b00-8da1-1c39ffcab02c"; String json = aposToQuotes( "{'id':'"+ID1+"','items':[{'id':'"+ID2+"','property':'value'}]}"); ObjectMapper m = new ObjectMapper(); Data data = m.readValue(json, Data.class); assertEquals(ID1, data.id); assertNotNull(data.items); assertEquals(1, data.items.size()); Item value = data.items.get(ID2); assertNotNull(value); assertEquals("value", value.property); } // for [databind#1384] public void testMapKeyRefinement1384() throws Exception { final String TEST_INSTANCE_SERIALIZED = "{\"mapProperty\":[\"java.util.HashMap\",{\"Compound|Key\":\"Value\"}]}"; ObjectMapper mapper = new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); TestClass testInstance = mapper.readValue(TEST_INSTANCE_SERIALIZED, TestClass.class); assertEquals(1, testInstance.mapProperty.size()); Object key = testInstance.mapProperty.keySet().iterator().next(); assertEquals(CompoundKey.class, key.getClass()); String testInstanceSerialized = mapper.writeValueAsString(testInstance); assertEquals(TEST_INSTANCE_SERIALIZED, testInstanceSerialized); } } TypeResolverTest.java000066400000000000000000000030351325620701100365250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; import com.fasterxml.jackson.databind.module.SimpleModule; @SuppressWarnings("rawtypes") public class TypeResolverTest extends BaseMapTest { static class A { private Map map; @JsonCreator public A(@JsonProperty("z") Map map) { this.map = map; } public Map getMap() { return map; } } static class B { int a; public B(@JsonProperty("a") int a) { this.a = a; } } @SuppressWarnings("serial") static class MyMap extends HashMap { } public static void testSubtypeResolution() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver(); resolver.addMapping(Map.class, MyMap.class); SimpleModule basicModule = new SimpleModule(); basicModule.setAbstractTypes(resolver); mapper.registerModule(basicModule); String value = "{\"z\": {\"zz\": {\"a\": 42}}}"; A a = mapper.readValue(value, A.class); Map map = a.getMap(); assertEquals(MyMap.class, map.getClass()); Object ob = map.get("zz"); assertEquals(B.class, ob.getClass()); } } UnknownSubClassTest.java000066400000000000000000000014711325620701100371630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; public class UnknownSubClassTest extends BaseMapTest { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "clazz") abstract static class BaseClass { } static class BaseWrapper { public BaseClass value; } public void testUnknownClassAsSubtype() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); BaseWrapper w = mapper.readValue(aposToQuotes ("{'value':{'clazz':'com.foobar.Nothing'}}'"), BaseWrapper.class); assertNotNull(w); } } WrapperObjectWithObjectIdTest.java000066400000000000000000000047351325620701100411010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontypepackage com.fasterxml.jackson.databind.jsontype; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // Test for [databind#1051], issue with combination of Type and Object ids, // if (but only if) `JsonTypeInfo.As.WRAPPER_OBJECT` used. public class WrapperObjectWithObjectIdTest extends BaseMapTest { @JsonRootName(value = "company") static class Company { public List computers; public Company() { computers = new ArrayList(); } public Company addComputer(Computer computer) { if (computers == null) { computers = new ArrayList(); } computers.add(computer); return this; } } @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id" ) @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "type" ) @JsonSubTypes({ @JsonSubTypes.Type(value = DesktopComputer.class, name = "desktop"), @JsonSubTypes.Type(value = LaptopComputer.class, name = "laptop") }) static class Computer { public String id; } @JsonTypeName("desktop") static class DesktopComputer extends Computer { public String location; protected DesktopComputer() { } public DesktopComputer(String id, String loc) { this.id = id; location = loc; } } @JsonTypeName("laptop") static class LaptopComputer extends Computer { public String vendor; protected LaptopComputer() { } public LaptopComputer(String id, String v) { this.id = id; vendor = v; } } public void testSimple() throws Exception { Company comp = new Company(); comp.addComputer(new DesktopComputer("computer-1", "Bangkok")); comp.addComputer(new DesktopComputer("computer-2", "Pattaya")); comp.addComputer(new LaptopComputer("computer-3", "Apple")); final ObjectMapper mapper = new ObjectMapper(); String json = mapper.writerWithDefaultPrettyPrinter() .writeValueAsString(comp); Company result = mapper.readValue(json, Company.class); assertNotNull(result); assertNotNull(result.computers); assertEquals(3, result.computers.size()); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/000077500000000000000000000000001325620701100332355ustar00rootroot00000000000000ExternalTypeId198Test.java000066400000000000000000000037171325620701100400340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontype/extpackage com.fasterxml.jackson.databind.jsontype.ext; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; public class ExternalTypeId198Test extends BaseMapTest { public enum Attacks { KICK, PUNCH } static class Character { public String name; public Attacks preferredAttack; @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, defaultImpl=Kick.class, include=JsonTypeInfo.As.EXTERNAL_PROPERTY, property="preferredAttack") @JsonSubTypes({ @JsonSubTypes.Type(value=Kick.class, name="KICK"), @JsonSubTypes.Type(value=Punch.class, name="PUNCH") }) public Attack attack; } public static abstract class Attack { public String side; @JsonCreator public Attack(String side) { this.side = side; } } public static class Kick extends Attack { @JsonCreator public Kick(String side) { super(side); } } public static class Punch extends Attack { @JsonCreator public Punch(String side) { super(side); } } final ObjectMapper MAPPER = new ObjectMapper(); public void testFails() throws Exception { String json = "{ \"name\": \"foo\", \"attack\":\"right\" } }"; Character character = MAPPER.readValue(json, Character.class); assertNotNull(character); assertNotNull(character.attack); assertEquals("foo", character.name); } public void testWorks() throws Exception { String json = "{ \"name\": \"foo\", \"preferredAttack\": \"KICK\", \"attack\":\"right\" } }"; Character character = MAPPER.readValue(json, Character.class); assertNotNull(character); assertNotNull(character.attack); assertEquals("foo", character.name); } } ExternalTypeId999Test.java000066400000000000000000000033061325620701100400370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontype/extpackage com.fasterxml.jackson.databind.jsontype.ext; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class ExternalTypeId999Test extends BaseMapTest { public static interface Payload { } @JsonTypeName("foo") public static class FooPayload implements Payload { } @JsonTypeName("bar") public static class BarPayload implements Payload { } public static class Message

{ final String type; @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, visible = true, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(FooPayload.class), @JsonSubTypes.Type(BarPayload.class) }) private final P payload; @JsonCreator public Message(@JsonProperty("type") String type, @JsonProperty("payload") P payload) { this.type = type; this.payload = payload; } } private final ObjectMapper MAPPER = objectMapper(); public void testExternalTypeId() throws Exception { TypeReference type = new TypeReference>() { }; Message msg = MAPPER.readValue(aposToQuotes("{ 'type':'foo', 'payload': {} }"), type); assertNotNull(msg); assertNotNull(msg.payload); assertEquals("foo", msg.type); // and then with different order msg = MAPPER.readValue(aposToQuotes("{'payload': {}, 'type':'foo' }"), type); assertNotNull(msg); assertNotNull(msg.payload); assertEquals("foo", msg.type); } } ExternalTypeIdTest.java000066400000000000000000000450161325620701100375700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontype/extpackage com.fasterxml.jackson.databind.jsontype.ext; import java.math.BigDecimal; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; // Tests for External type id, one that exists at same level as typed Object, // that is, property is not within typed object but a member of its parent. public class ExternalTypeIdTest extends BaseMapTest { static class ExternalBean { @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType") public Object bean; public ExternalBean() { } public ExternalBean(int v) { bean = new ValueBean(v); } } // for [databind#96] static class ExternalBeanWithDefault { @JsonTypeInfo(use=Id.CLASS, include=As.EXTERNAL_PROPERTY, property="extType", defaultImpl=ValueBean.class) public Object bean; public ExternalBeanWithDefault() { } public ExternalBeanWithDefault(int v) { bean = new ValueBean(v); } } static class ExternalBean3 { @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType1") public Object value1; @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType2") public Object value2; public int foo; @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType3") public Object value3; public ExternalBean3() { } public ExternalBean3(int v) { value1 = new ValueBean(v); value2 = new ValueBean(v+1); value3 = new ValueBean(v+2); foo = v; } } static class ExternalBeanWithCreator { @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType") public Object value; public int foo; @JsonCreator public ExternalBeanWithCreator(@JsonProperty("foo") int f) { foo = f; value = new ValueBean(f); } } @JsonTypeName("vbean") static class ValueBean { public int value; public ValueBean() { } public ValueBean(int v) { value = v; } } @JsonTypeName("funk") @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType") static class FunkyExternalBean { public int i = 3; } // [JACKSON-798]: problems with polymorphic types, external prop @JsonSubTypes(value= { @JsonSubTypes.Type(value=Derived1.class, name="d1"), @JsonSubTypes.Type(value=Derived2.class, name="d2") }) interface Base { String getBaseProperty(); } static class Derived1 implements Base { private String derived1Property; private String baseProperty; protected Derived1() { throw new IllegalStateException("wrong constructor called"); } @JsonCreator public Derived1(@JsonProperty("derived1Property") String d1p, @JsonProperty("baseProperty") String bp) { derived1Property = d1p; baseProperty = bp; } @Override @JsonProperty public String getBaseProperty() { return baseProperty; } @JsonProperty public String getDerived1Property() { return derived1Property; } } static class Derived2 implements Base { private String derived2Property; private String baseProperty; protected Derived2() { throw new IllegalStateException("wrong constructor called"); } @JsonCreator public Derived2(@JsonProperty("derived2Property") String d2p, @JsonProperty("baseProperty") String bp) { derived2Property = d2p; baseProperty = bp; } @Override @JsonProperty public String getBaseProperty() { return baseProperty; } @JsonProperty public String getDerived2Property() { return derived2Property; } } static class BaseContainer { protected final Base base; protected final String baseContainerProperty; protected BaseContainer() { throw new IllegalStateException("wrong constructor called"); } @JsonCreator public BaseContainer(@JsonProperty("baseContainerProperty") String bcp, @JsonProperty("base") Base b) { baseContainerProperty = bcp; base = b; } @JsonProperty public String getBaseContainerProperty() { return baseContainerProperty; } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.EXTERNAL_PROPERTY, property="type") @JsonProperty public Base getBase() { return base; } } interface Pet {} static class Dog implements Pet { public String name; } static class House831 { protected String petType; @JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, property = "petType") @JsonSubTypes({@JsonSubTypes.Type(name = "dog", value = Dog.class)}) public Pet pet; public String getPetType() { return petType; } public void setPetType(String petType) { this.petType = petType; } } // for [databind#118] static class ExternalTypeWithNonPOJO { @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, defaultImpl = String.class) @JsonSubTypes({ @JsonSubTypes.Type(value = Date.class, name = "date"), @JsonSubTypes.Type(value = AsValueThingy.class, name = "thingy") }) public Object value; public ExternalTypeWithNonPOJO() { } public ExternalTypeWithNonPOJO(Object o) { value = o; } } // for [databind#119] static class AsValueThingy { public long rawDate; public AsValueThingy(long l) { rawDate = l; } public AsValueThingy() { } @JsonValue public Date serialization() { return new Date(rawDate); } } // [databind#222] static class Issue222Bean { @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", include = JsonTypeInfo.As.EXTERNAL_PROPERTY) public Issue222BeanB value; public String type = "foo"; public Issue222Bean() { } public Issue222Bean(int v) { value = new Issue222BeanB(v); } } @JsonTypeName("222b") // shouldn't actually matter static class Issue222BeanB { public int x; public Issue222BeanB() { } public Issue222BeanB(int value) { x = value; } } // [databind#928] static class Envelope928 { Object _payload; public Envelope928(@JsonProperty("payload") @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.EXTERNAL_PROPERTY, property="class") Object payload) { _payload = payload; } } static class Payload928 { public String something; } enum Type965 { BIG_DECIMAL } static class Wrapper965 { protected Type965 typeEnum; protected Object value; @JsonGetter("type") String getTypeString() { return typeEnum.name(); } @JsonSetter("type") void setTypeString(String type) { this.typeEnum = Type965.valueOf(type); } @JsonGetter(value = "objectValue") Object getValue() { return value; } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(name = "BIG_DECIMAL", value = BigDecimal.class) }) @JsonSetter(value = "objectValue") private void setValue(Object value) { this.value = value; } } /* /********************************************************** /* Unit tests, serialization /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleSerialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerSubtypes(ValueBean.class); // This may look odd, but one implementation nastiness is the fact // that we cannot properly serialize type id before the object, // because call is made after property name (for object) has already // been written out. So we'll write it after... // Deserializer will work either way as it cannot rely on ordering // anyway. assertEquals("{\"bean\":{\"value\":11},\"extType\":\"vbean\"}", mapper.writeValueAsString(new ExternalBean(11))); } // If trying to use with Class, should just become "PROPERTY" instead: public void testImproperExternalIdSerialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); assertEquals("{\"extType\":\"funk\",\"i\":3}", mapper.writeValueAsString(new FunkyExternalBean())); } // for [databind#942] public void testExternalTypeIdWithNull() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerSubtypes(ValueBean.class); ExternalBean b; b = mapper.readValue(aposToQuotes("{'bean':null,'extType':'vbean'}"), ExternalBean.class); assertNotNull(b); b = mapper.readValue(aposToQuotes("{'extType':'vbean','bean':null}"), ExternalBean.class); assertNotNull(b); } /* /********************************************************** /* Unit tests, deserialization /********************************************************** */ public void testSimpleDeserialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerSubtypes(ValueBean.class); ExternalBean result = mapper.readValue("{\"bean\":{\"value\":11},\"extType\":\"vbean\"}", ExternalBean.class); assertNotNull(result); assertNotNull(result.bean); ValueBean vb = (ValueBean) result.bean; assertEquals(11, vb.value); // let's also test with order switched: result = mapper.readValue("{\"extType\":\"vbean\", \"bean\":{\"value\":13}}", ExternalBean.class); assertNotNull(result); assertNotNull(result.bean); vb = (ValueBean) result.bean; assertEquals(13, vb.value); } // Test for verifying that it's ok to have multiple (say, 3) // externally typed things, mixed with other stuff... public void testMultipleTypeIdsDeserialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerSubtypes(ValueBean.class); String json = mapper.writeValueAsString(new ExternalBean3(3)); ExternalBean3 result = mapper.readValue(json, ExternalBean3.class); assertNotNull(result); assertNotNull(result.value1); assertNotNull(result.value2); assertNotNull(result.value3); assertEquals(3, ((ValueBean)result.value1).value); assertEquals(4, ((ValueBean)result.value2).value); assertEquals(5, ((ValueBean)result.value3).value); assertEquals(3, result.foo); } // Also, it should be ok to use @JsonCreator as well... public void testExternalTypeWithCreator() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerSubtypes(ValueBean.class); String json = mapper.writeValueAsString(new ExternalBeanWithCreator(7)); ExternalBeanWithCreator result = mapper.readValue(json, ExternalBeanWithCreator.class); assertNotNull(result); assertNotNull(result.value); assertEquals(7, ((ValueBean)result.value).value); assertEquals(7, result.foo); } // If trying to use with Class, should just become "PROPERTY" instead: public void testImproperExternalIdDeserialization() throws Exception { FunkyExternalBean result = MAPPER.readValue("{\"extType\":\"funk\",\"i\":3}", FunkyExternalBean.class); assertNotNull(result); assertEquals(3, result.i); result = MAPPER.readValue("{\"i\":4,\"extType\":\"funk\"}", FunkyExternalBean.class); assertNotNull(result); assertEquals(4, result.i); } public void testIssue798() throws Exception { Base base = new Derived1("derived1 prop val", "base prop val"); BaseContainer baseContainer = new BaseContainer("bc prop val", base); String generatedJson = MAPPER.writeValueAsString(baseContainer); BaseContainer baseContainer2 = MAPPER.readValue(generatedJson,BaseContainer.class); assertEquals("bc prop val", baseContainer.getBaseContainerProperty()); Base b = baseContainer2.getBase(); assertNotNull(b); if (b.getClass() != Derived1.class) { fail("Should have type Derived1, was "+b.getClass().getName()); } Derived1 derived1 = (Derived1) b; assertEquals("base prop val", derived1.getBaseProperty()); assertEquals("derived1 prop val", derived1.getDerived1Property()); } // There seems to be some problems if type is also visible... public void testIssue831() throws Exception { final String JSON = "{ \"petType\": \"dog\",\n" +"\"pet\": { \"name\": \"Pluto\" }\n}"; House831 result = MAPPER.readValue(JSON, House831.class); assertNotNull(result); assertNotNull(result.pet); assertSame(Dog.class, result.pet.getClass()); assertEquals("dog", result.petType); } // For [databind#118] // Note: String works fine, since no type id will used; other scalar types have issues public void testWithScalar118() throws Exception { ExternalTypeWithNonPOJO input = new ExternalTypeWithNonPOJO(new java.util.Date(123L)); String json = MAPPER.writeValueAsString(input); assertNotNull(json); // and back just to be sure: ExternalTypeWithNonPOJO result = MAPPER.readValue(json, ExternalTypeWithNonPOJO.class); assertNotNull(result.value); assertTrue(result.value instanceof java.util.Date); } // For [databind#118] using "natural" type(s) public void testWithNaturalScalar118() throws Exception { ExternalTypeWithNonPOJO input = new ExternalTypeWithNonPOJO(Integer.valueOf(13)); String json = MAPPER.writeValueAsString(input); assertNotNull(json); // and back just to be sure: ExternalTypeWithNonPOJO result = MAPPER.readValue(json, ExternalTypeWithNonPOJO.class); assertNotNull(result.value); assertTrue(result.value instanceof Integer); // ditto with others types input = new ExternalTypeWithNonPOJO(Boolean.TRUE); json = MAPPER.writeValueAsString(input); assertNotNull(json); result = MAPPER.readValue(json, ExternalTypeWithNonPOJO.class); assertNotNull(result.value); assertTrue(result.value instanceof Boolean); input = new ExternalTypeWithNonPOJO("foobar"); json = MAPPER.writeValueAsString(input); assertNotNull(json); result = MAPPER.readValue(json, ExternalTypeWithNonPOJO.class); assertNotNull(result.value); assertTrue(result.value instanceof String); assertEquals("foobar", result.value); } // For [databind#119]... and bit of [#167] as well public void testWithAsValue() throws Exception { ExternalTypeWithNonPOJO input = new ExternalTypeWithNonPOJO(new AsValueThingy(12345L)); String json = MAPPER.writeValueAsString(input); assertNotNull(json); assertEquals("{\"value\":12345,\"type\":\"thingy\"}", json); // and get it back too: ExternalTypeWithNonPOJO result = MAPPER.readValue(json, ExternalTypeWithNonPOJO.class); assertNotNull(result); assertNotNull(result.value); assertEquals(AsValueThingy.class, result.value.getClass()); assertEquals(12345L, ((AsValueThingy) result.value).rawDate); } // for [databind#222] public void testExternalTypeWithProp222() throws Exception { final ObjectMapper mapper = new ObjectMapper(); Issue222Bean input = new Issue222Bean(13); String json = mapper.writeValueAsString(input); assertEquals("{\"value\":{\"x\":13},\"type\":\"foo\"}", json); } // [databind#928] public void testInverseExternalId928() throws Exception { final String CLASS = Payload928.class.getName(); ObjectMapper mapper = new ObjectMapper(); final String successCase = "{\"payload\":{\"something\":\"test\"},\"class\":\""+CLASS+"\"}"; Envelope928 envelope1 = mapper.readValue(successCase, Envelope928.class); assertNotNull(envelope1); assertEquals(Payload928.class, envelope1._payload.getClass()); // and then re-ordered case that was problematic final String failCase = "{\"class\":\""+CLASS+"\",\"payload\":{\"something\":\"test\"}}"; Envelope928 envelope2 = mapper.readValue(failCase, Envelope928.class); assertNotNull(envelope2); assertEquals(Payload928.class, envelope2._payload.getClass()); } // for [databind#965] public void testBigDecimal965() throws Exception { Wrapper965 w = new Wrapper965(); w.typeEnum = Type965.BIG_DECIMAL; final String NUM_STR = "-10000000000.0000000001"; w.value = new BigDecimal(NUM_STR); String json = MAPPER.writeValueAsString(w); // simple sanity check so serialization is faithful if (!json.contains(NUM_STR)) { fail("JSON content should contain value '"+NUM_STR+"', does not appear to: "+json); } Wrapper965 w2 = MAPPER.readerFor(Wrapper965.class) .with(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) .readValue(json); assertEquals(w.typeEnum, w2.typeEnum); assertTrue(String.format("Expected %s = %s; got back %s = %s", w.value.getClass().getSimpleName(), w.value.toString(), w2.value.getClass().getSimpleName(), w2.value.toString()), w.value.equals(w2.value)); } } ExternalTypeIdTest1288.java000066400000000000000000000510511325620701100401070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontype/extpackage com.fasterxml.jackson.databind.jsontype.ext; import java.util.UUID; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver; import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; @SuppressWarnings("hiding") public class ExternalTypeIdTest1288 extends BaseMapTest { public static class ClassesWithoutBuilder { public static class CreditCardDetails implements PaymentDetails { protected String cardHolderFirstName; protected String cardHolderLastName; protected String number; protected String expiryDate; protected int csc; protected String address; protected String zipCode; protected String city; protected String province; protected String countryCode; protected String description; public void setCardHolderFirstName (String cardHolderFirstName) { this.cardHolderFirstName = cardHolderFirstName; } public void setCardHolderLastName (String cardHolderLastName) { this.cardHolderLastName = cardHolderLastName; } public void setNumber (String number) { this.number = number; } public void setExpiryDate (String expiryDate) { this.expiryDate = expiryDate; } public void setCsc (int csc) { this.csc = csc; } public void setAddress (String address) { this.address = address; } public void setZipCode (String zipCode) { this.zipCode = zipCode; } public void setCity (String city) { this.city = city; } public void setProvince (String province) { this.province = province; } public void setCountryCode (String countryCode) { this.countryCode = countryCode; } public void setDescription (String description) { this.description = description; } } public static class EncryptedCreditCardDetails implements PaymentDetails { protected UUID paymentInstrumentID; protected String name; public void setPaymentInstrumentID (UUID paymentInstrumentID) { this.paymentInstrumentID = paymentInstrumentID; } public void setName (String name) { this.name = name; } } public enum FormOfPayment { INDIVIDUAL_CREDIT_CARD (CreditCardDetails.class), COMPANY_CREDIT_CARD ( CreditCardDetails.class), INSTRUMENTED_CREDIT_CARD (EncryptedCreditCardDetails.class); private final Class clazz; FormOfPayment (final Class clazz) { this.clazz = clazz; } @SuppressWarnings ("unchecked") public Class getDetailsClass () { return (Class) this.clazz; } public static FormOfPayment fromDetailsClass (Class detailsClass) { for (FormOfPayment fop : FormOfPayment.values ()) { if (fop.clazz == detailsClass) { return fop; } } throw new IllegalArgumentException ("not found"); } } public interface PaymentDetails { public interface Builder { PaymentDetails build (); } } public static class PaymentMean { FormOfPayment formOfPayment; PaymentDetails paymentDetails; public void setFormOfPayment (FormOfPayment formOfPayment) { this.formOfPayment = formOfPayment; } @JsonTypeInfo (use = JsonTypeInfo.Id.CUSTOM, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "form_of_payment", visible = true) @JsonTypeIdResolver (PaymentDetailsTypeIdResolver.class) public void setPaymentDetails (PaymentDetails paymentDetails) { this.paymentDetails = paymentDetails; } } public static class PaymentDetailsTypeIdResolver extends TypeIdResolverBase { @SuppressWarnings ("unchecked") @Override public String idFromValue (Object value) { if (! (value instanceof PaymentDetails)) { return null; } return FormOfPayment.fromDetailsClass ((Class) value.getClass ()).name (); } @Override public String idFromValueAndType (Object value, Class suggestedType) { return this.idFromValue (value); } @Override public JavaType typeFromId (DatabindContext context, String id) { return context.getTypeFactory().constructType(FormOfPayment.valueOf(id).getDetailsClass ()); } @Override public String getDescForKnownTypeIds () { return "PaymentDetails"; } @Override public Id getMechanism () { return JsonTypeInfo.Id.CUSTOM; } } } public static class ClassesWithBuilder { @JsonDeserialize (builder = CreditCardDetails.IndividualCreditCardDetailsBuilder.class) public static class CreditCardDetails implements PaymentDetails { @JsonPOJOBuilder (withPrefix = "") public static class CompanyCreditCardDetailsBuilder implements Builder { private String cardHolderFirstName; private String cardHolderLastName; private String number; private String expiryDate; private int csc; private String address; private String zipCode; private String city; private String province; private String countryCode; public CompanyCreditCardDetailsBuilder address (final String a) { address = a; return this; } @Override public CreditCardDetails build() { return new CreditCardDetails (this.cardHolderFirstName, this.cardHolderLastName, this.number, this.expiryDate, this.csc, this.address, this.zipCode, this.city, this.province, this.countryCode, "COMPANY CREDIT CARD"); } public CompanyCreditCardDetailsBuilder cardHolderFirstName(final String cardHolderFirstName) { this.cardHolderFirstName = cardHolderFirstName; return this; } public CompanyCreditCardDetailsBuilder cardHolderLastName (final String cardHolderLastName) { this.cardHolderLastName = cardHolderLastName; return this; } public CompanyCreditCardDetailsBuilder city (final String city) { this.city = city; return this; } public CompanyCreditCardDetailsBuilder countryCode (final String countryCode) { this.countryCode = countryCode; return this; } public CompanyCreditCardDetailsBuilder csc (final int csc) { this.csc = csc; return this; } public CompanyCreditCardDetailsBuilder expiryDate (final String expiryDate) { this.expiryDate = expiryDate; return this; } public CompanyCreditCardDetailsBuilder number (final String number) { this.number = number; return this; } public CompanyCreditCardDetailsBuilder province (final String province) { this.province = province; return this; } public CompanyCreditCardDetailsBuilder zipCode (final String zipCode) { this.zipCode = zipCode; return this; } } @JsonPOJOBuilder (withPrefix = "") public static class IndividualCreditCardDetailsBuilder implements Builder { private String cardHolderFirstName; private String cardHolderLastName; private String number; private String expiryDate; private int csc; private String address; private String zipCode; private String city; private String province; private String countryCode; private String description; public IndividualCreditCardDetailsBuilder address (final String address) { this.address = address; return this; } @Override public CreditCardDetails build () { return new CreditCardDetails (this.cardHolderFirstName, this.cardHolderLastName, this.number, this.expiryDate, this.csc, this.address, this.zipCode, this.city, this.province, this.countryCode, this.description); } public IndividualCreditCardDetailsBuilder cardHolderFirstName (final String cardHolderFirstName) { this.cardHolderFirstName = cardHolderFirstName; return this; } public IndividualCreditCardDetailsBuilder cardHolderLastName (final String cardHolderLastName) { this.cardHolderLastName = cardHolderLastName; return this; } public IndividualCreditCardDetailsBuilder city (final String city) { this.city = city; return this; } public IndividualCreditCardDetailsBuilder countryCode (final String countryCode) { this.countryCode = countryCode; return this; } public IndividualCreditCardDetailsBuilder csc (final int csc) { this.csc = csc; return this; } public IndividualCreditCardDetailsBuilder description (final String description) { this.description = description; return this; } public IndividualCreditCardDetailsBuilder expiryDate (final String expiryDate) { this.expiryDate = expiryDate; return this; } public IndividualCreditCardDetailsBuilder number (final String number) { this.number = number; return this; } public IndividualCreditCardDetailsBuilder province (final String p) { province = p; return this; } public IndividualCreditCardDetailsBuilder zipCode (final String z) { zipCode = z; return this; } } protected final String cardHolderFirstName; protected final String cardHolderLastName; protected final String number; protected final String expiryDate; protected final int csc; protected final String address; protected final String zipCode; protected final String city; protected final String province; protected final String countryCode; protected final String description; public CreditCardDetails (final String cardHolderFirstName, final String cardHolderLastName, final String number, final String expiryDate, final int csc, final String address, final String zipCode, final String city, final String province, final String countryCode, final String description) { super (); this.cardHolderFirstName = cardHolderFirstName; this.cardHolderLastName = cardHolderLastName; this.number = number; this.expiryDate = expiryDate; this.csc = csc; this.address = address; this.zipCode = zipCode; this.city = city; this.province = province; this.countryCode = countryCode; this.description = description; } } @JsonDeserialize (builder = EncryptedCreditCardDetails.InstrumentedCreditCardBuilder.class) public static class EncryptedCreditCardDetails implements PaymentDetails { @JsonPOJOBuilder (withPrefix = "") public static class InstrumentedCreditCardBuilder implements Builder { private UUID paymentInstrumentID; private String name; @Override public EncryptedCreditCardDetails build () { return new EncryptedCreditCardDetails (this.paymentInstrumentID, this.name); } public InstrumentedCreditCardBuilder name (final String name) { this.name = name; return this; } public InstrumentedCreditCardBuilder paymentInstrumentID (final UUID paymentInstrumentID) { this.paymentInstrumentID = paymentInstrumentID; return this; } } protected final UUID paymentInstrumentID; protected final String name; private EncryptedCreditCardDetails (final UUID paymentInstrumentID, final String name) { super (); this.paymentInstrumentID = paymentInstrumentID; this.name = name; } } public enum FormOfPayment { INDIVIDUAL_CREDIT_CARD (CreditCardDetails.IndividualCreditCardDetailsBuilder.class), COMPANY_CREDIT_CARD ( CreditCardDetails.CompanyCreditCardDetailsBuilder.class), INSTRUMENTED_CREDIT_CARD (EncryptedCreditCardDetails.InstrumentedCreditCardBuilder.class); private final Class builderClass; FormOfPayment (final Class builderClass) { this.builderClass = builderClass; } @SuppressWarnings ("unchecked") public Class getDetailsClass () { return (Class) this.builderClass.getEnclosingClass (); } public static FormOfPayment fromDetailsClass (Class detailsClass) { for (FormOfPayment fop : FormOfPayment.values ()) { if (fop.builderClass.getEnclosingClass () == detailsClass) { return fop; } } throw new IllegalArgumentException ("not found"); } } public interface PaymentDetails { public interface Builder { PaymentDetails build (); } } @JsonDeserialize (builder = PaymentMean.Builder.class) public static class PaymentMean { @JsonPOJOBuilder (withPrefix = "") @JsonPropertyOrder ({ "form_of_payment", "payment_details" }) public static class Builder { private FormOfPayment formOfPayment; private PaymentDetails paymentDetails; public PaymentMean build () { return new PaymentMean (this.formOfPayment, this.paymentDetails); } // if you annotate with @JsonIgnore, it works, but the value // disappears in the constructor public Builder formOfPayment (final FormOfPayment val) { this.formOfPayment = val; return this; } @JsonTypeInfo (use = JsonTypeInfo.Id.CUSTOM, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "form_of_payment", visible = true) @JsonTypeIdResolver (PaymentDetailsTypeIdResolver.class) public Builder paymentDetails (final PaymentDetails val) { this.paymentDetails = val; return this; } } public static Builder create() { return new Builder(); } protected final FormOfPayment formOfPayment; protected final PaymentDetails paymentDetails; private PaymentMean (final FormOfPayment formOfPayment, final PaymentDetails paymentDetails) { super (); this.formOfPayment = formOfPayment; this.paymentDetails = paymentDetails; } } public static class PaymentDetailsTypeIdResolver extends TypeIdResolverBase { @SuppressWarnings ("unchecked") @Override public String idFromValue (Object value) { if (! (value instanceof PaymentDetails)) { return null; } return FormOfPayment.fromDetailsClass ((Class) value.getClass ()).name (); } @Override public String idFromValueAndType (Object value, Class suggestedType) { return this.idFromValue (value); } @Override public JavaType typeFromId (DatabindContext context, String id) { return context.getTypeFactory().constructType(FormOfPayment.valueOf (id).getDetailsClass ()); } @Override public String getDescForKnownTypeIds () { return "PaymentDetails"; } @Override public Id getMechanism () { return JsonTypeInfo.Id.CUSTOM; } } } public void testVisibleExternalTypeId1288() throws Exception { // given final String asJson1 = "{\"form_of_payment\":\"INDIVIDUAL_CREDIT_CARD\", \"payment_details\":{\"card_holder_first_name\":\"John\", \"card_holder_last_name\":\"Doe\", \"number\":\"XXXXXXXXXXXXXXXX\", \"expiry_date\":\"MM/YY\"," + "\"csc\":666,\"address\":\"10 boulevard de Sebastopol\",\"zip_code\":\"75001\",\"city\":\"Paris\",\"province\":\"Ile-de-France\",\"country_code\":\"FR\",\"description\":\"John Doe personal credit card\"}}"; final String asJson2 = "{\"form_of_payment\":\"INSTRUMENTED_CREDIT_CARD\",\"payment_details\":{\"payment_instrument_id\":\"00000000-0000-0000-0000-000000000000\", \"name\":\"Mr John Doe encrypted credit card\"}}"; final ObjectMapper objectMapper = new ObjectMapper ().setPropertyNamingStrategy (PropertyNamingStrategy.SNAKE_CASE); ClassesWithoutBuilder.PaymentMean ob1 = objectMapper.readValue (asJson1, ClassesWithoutBuilder.PaymentMean.class); assertNotNull(ob1); ClassesWithBuilder.PaymentMean ob2 = objectMapper.readValue (asJson2, ClassesWithBuilder.PaymentMean.class); assertNotNull(ob2); } } JsonValueExtTypeIdTest.java000066400000000000000000000054331325620701100403740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontype/extpackage com.fasterxml.jackson.databind.jsontype.ext; import java.io.*; import java.math.BigDecimal; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; @SuppressWarnings("serial") public class JsonValueExtTypeIdTest extends BaseMapTest { // The following is required for the testDecimalMetadata test case. That case fails. @JsonTypeName(value = "decimalValue") public static class DecimalValue { private BigDecimal value; public DecimalValue() { value = new BigDecimal("111.1"); } @JsonValue public BigDecimal getValue(){ return value; } } @JsonPropertyOrder({"key","value"}) public static class DecimalEntry { public DecimalEntry() {} public String getKey() { return "num"; } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.EXTERNAL_PROPERTY) public DecimalValue getValue(){ return new DecimalValue(); } } public static class DecimalMetadata { @JsonProperty("metadata") public List getMetadata() { return new ArrayList() { {add(new DecimalEntry());} }; } } // The following succeeds. It's included for comparison @JsonTypeName(value = "doubleValue") public static class DoubleValue { private Double value; public DoubleValue() { value = 1234.25; } @JsonValue public Double getValue() { return value; } } @JsonPropertyOrder({"key","value"}) public static class DoubleEntry { public DoubleEntry(){} public String getKey(){ return "num"; } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.EXTERNAL_PROPERTY) public DoubleValue getValue(){ return new DoubleValue(); } } public static class DoubleMetadata { @JsonProperty("metadata") public List getMetadata() { return new ArrayList() { {add(new DoubleEntry());} }; } } final ObjectMapper MAPPER = new ObjectMapper(); public void testDoubleMetadata() throws IOException { DoubleMetadata doub = new DoubleMetadata(); String expected = "{\"metadata\":[{\"key\":\"num\",\"value\":1234.25,\"@type\":\"doubleValue\"}]}"; String json = MAPPER.writeValueAsString(doub); assertEquals("Serialized json not equivalent", expected, json); } public void testDecimalMetadata() throws IOException{ DecimalMetadata dec = new DecimalMetadata(); String expected = "{\"metadata\":[{\"key\":\"num\",\"value\":111.1,\"@type\":\"decimalValue\"}]}"; String json = MAPPER.writeValueAsString(dec); assertEquals("Serialized json not equivalent", expected, json); } } MultipleExternalIds291Test.java000066400000000000000000000060171325620701100410570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontype/extpackage com.fasterxml.jackson.databind.jsontype.ext; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.*; public class MultipleExternalIds291Test extends BaseMapTest { // For [Issue#291] interface F1 {} static class A implements F1 { public String a; } static class B implements F1 { public String b; } static interface F2 {} static class C implements F2 { public String c; } static class D implements F2{ public String d; } static class Container { @JsonTypeInfo(use = Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY) @JsonSubTypes({ @JsonSubTypes.Type(value = A.class, name = "1"), @JsonSubTypes.Type(value = B.class, name = "2")}) public F1 field1; @JsonTypeInfo(use = Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY) @JsonSubTypes({ @JsonSubTypes.Type(value = C.class, name = "1"), @JsonSubTypes.Type(value = D.class, name = "2")}) public F2 field2; } static class ContainerWithExtra extends Container { public String type; } /* /********************************************************** /* Test methods /********************************************************** */ final ObjectMapper MAPPER = objectMapper(); // [databind#291] public void testMultipleValuesSingleExtId() throws Exception { // first with ext-id before values _testMultipleValuesSingleExtId( "{'type' : '1',\n" +"'field1' : { 'a' : 'AAA' },\n" +"'field2' : { 'c' : 'CCC' }\n" +"}" ); // then after _testMultipleValuesSingleExtId( "{\n" +"'field1' : { 'a' : 'AAA' },\n" +"'field2' : { 'c' : 'CCC' },\n" +"'type' : '1'\n" +"}" ); // and then in-between _testMultipleValuesSingleExtId( "{\n" +"'field1' : { 'a' : 'AAA' },\n" +"'type' : '1',\n" +"'field2' : { 'c' : 'CCC' }\n" +"}" ); } public void _testMultipleValuesSingleExtId(String json) throws Exception { json = aposToQuotes(json); // First, with base class, no type id field separately { Container c = MAPPER.readValue(json, Container.class); assertNotNull(c); assertTrue(c.field1 instanceof A); assertEquals("AAA", ((A) c.field1).a); assertTrue(c.field2 instanceof C); assertEquals("CCC", ((C) c.field2).c); } // then with sub-class that does have similarly named property { ContainerWithExtra c = MAPPER.readValue(json, ContainerWithExtra.class); assertNotNull(c); assertEquals("1", c.type); assertTrue(c.field1 instanceof A); assertEquals("AAA", ((A) c.field1).a); assertTrue(c.field2 instanceof C); assertEquals("CCC", ((C) c.field2).c); } } } TestSubtypesExternalPropertyMissingProperty.java000066400000000000000000000215031325620701100450470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/jsontype/extpackage com.fasterxml.jackson.databind.jsontype.ext; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.*; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; // for [databind#1341] public class TestSubtypesExternalPropertyMissingProperty { @Rule public ExpectedException thrown = ExpectedException.none(); /** * Base class - external property for Fruit subclasses. */ static class Box { public String type; @JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, property = "type") public Fruit fruit; public Box() { } public Box(String type, Fruit fruit) { this.type = type; this.fruit = fruit; } } /** * Base class that requires the property to be present. */ static class ReqBox { public String type; @JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, property = "type") @JsonProperty(required = true) public Fruit fruit; public ReqBox() { } public ReqBox(String type, Fruit fruit) { this.type = type; this.fruit = fruit; } } @JsonSubTypes({ @Type(value = Apple.class, name = "apple"), @Type(value = Orange.class, name = "orange") }) static abstract class Fruit { public String name; public Fruit() { } protected Fruit(String n) { name = n; } } static class Apple extends Fruit { public int seedCount; public Apple() { } public Apple(String name, int b) { super(name); seedCount = b; } } static class Orange extends Fruit { public String color; public Orange() { } public Orange(String name, String c) { super(name); color = c; } } private final ObjectMapper MAPPER = new ObjectMapper(); /* /********************************************************** /* Mock data /********************************************************** */ private static final Orange orange = new Orange("Orange", "orange"); private static final Box orangeBox = new Box("orange", orange); private static final String orangeBoxJson = "{\"type\":\"orange\",\"fruit\":{\"name\":\"Orange\",\"color\":\"orange\"}}"; private static final String orangeBoxNullJson = "{\"type\":\"orange\",\"fruit\":null}}"; private static final String orangeBoxEmptyJson = "{\"type\":\"orange\",\"fruit\":{}}}"; private static final String orangeBoxMissingJson = "{\"type\":\"orange\"}}"; private static final Apple apple = new Apple("Apple", 16); private static Box appleBox = new Box("apple", apple); private static final String appleBoxJson = "{\"type\":\"apple\",\"fruit\":{\"name\":\"Apple\",\"seedCount\":16}}"; private static final String appleBoxNullJson = "{\"type\":\"apple\",\"fruit\":null}"; private static final String appleBoxEmptyJson = "{\"type\":\"apple\",\"fruit\":{}}"; private static final String appleBoxMissingJson = "{\"type\":\"apple\"}"; /* /********************************************************** /* Unit tests /********************************************************** */ /** * Deserialization tests for external type id property present */ @Test public void testDeserializationPresent() throws Exception { MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY); checkOrangeBox(); checkAppleBox(); MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY); checkOrangeBox(); checkAppleBox(); } /** * Deserialization tests for external type id property null */ @Test public void testDeserializationNull() throws Exception { MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY); checkOrangeBoxNull(orangeBoxNullJson); checkAppleBoxNull(appleBoxNullJson); MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY); checkOrangeBoxNull(orangeBoxNullJson); checkAppleBoxNull(appleBoxNullJson); } /** * Deserialization tests for external type id property empty */ @Test public void testDeserializationEmpty() throws Exception { MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY); checkOrangeBoxEmpty(orangeBoxEmptyJson); checkAppleBoxEmpty(appleBoxEmptyJson); MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY); checkOrangeBoxEmpty(orangeBoxEmptyJson); checkAppleBoxEmpty(appleBoxEmptyJson); } /** * Deserialization tests for external type id property missing */ @Test public void testDeserializationMissing() throws Exception { MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY); checkOrangeBoxNull(orangeBoxMissingJson); checkAppleBoxNull(appleBoxMissingJson); MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY); checkBoxJsonMappingException(orangeBoxMissingJson); checkBoxJsonMappingException(appleBoxMissingJson); } /** * Deserialization tests for external type id required property missing */ @Test public void testDeserializationMissingRequired() throws Exception { MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY); checkReqBoxJsonMappingException(orangeBoxMissingJson); checkReqBoxJsonMappingException(appleBoxMissingJson); MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY); checkReqBoxJsonMappingException(orangeBoxMissingJson); checkReqBoxJsonMappingException(appleBoxMissingJson); } private void checkOrangeBox() throws Exception { Box deserOrangeBox = MAPPER.readValue(orangeBoxJson, Box.class); assertEquals(orangeBox.type, deserOrangeBox.type); Fruit deserOrange = deserOrangeBox.fruit; assertSame(Orange.class, deserOrange.getClass()); assertEquals(orange.name, deserOrange.name); assertEquals(orange.color, ((Orange) deserOrange).color); } private void checkAppleBox() throws Exception { Box deserAppleBox = MAPPER.readValue(appleBoxJson, Box.class); assertEquals(appleBox.type, deserAppleBox.type); Fruit deserApple = deserAppleBox.fruit; assertSame(Apple.class, deserApple.getClass()); assertEquals(apple.name, deserApple.name); assertEquals(apple.seedCount, ((Apple) deserApple).seedCount); } private void checkOrangeBoxEmpty(String json) throws Exception { Box deserOrangeBox = MAPPER.readValue(json, Box.class); assertEquals(orangeBox.type, deserOrangeBox.type); Fruit deserOrange = deserOrangeBox.fruit; assertSame(Orange.class, deserOrange.getClass()); assertNull(deserOrange.name); assertNull(((Orange) deserOrange).color); } private void checkAppleBoxEmpty(String json) throws Exception { Box deserAppleBox = MAPPER.readValue(json, Box.class); assertEquals(appleBox.type, deserAppleBox.type); Fruit deserApple = deserAppleBox.fruit; assertSame(Apple.class, deserApple.getClass()); assertNull(deserApple.name); assertEquals(0, ((Apple) deserApple).seedCount); } private void checkOrangeBoxNull(String json) throws Exception { Box deserOrangeBox = MAPPER.readValue(json, Box.class); assertEquals(orangeBox.type, deserOrangeBox.type); assertNull(deserOrangeBox.fruit); } private void checkAppleBoxNull(String json) throws Exception { Box deserAppleBox = MAPPER.readValue(json, Box.class); assertEquals(appleBox.type, deserAppleBox.type); assertNull(deserAppleBox.fruit); } private void checkBoxJsonMappingException(String json) throws Exception { thrown.expect(JsonMappingException.class); thrown.expectMessage("Missing property 'fruit' for external type id 'type'"); MAPPER.readValue(json, Box.class); } private void checkReqBoxJsonMappingException(String json) throws Exception { thrown.expect(JsonMappingException.class); thrown.expectMessage("Missing property 'fruit' for external type id 'type'"); MAPPER.readValue(json, ReqBox.class); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/misc/000077500000000000000000000000001325620701100315155ustar00rootroot00000000000000AccessFixTest.java000066400000000000000000000026431325620701100350160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/miscpackage com.fasterxml.jackson.databind.misc; import java.io.IOException; import java.security.Permission; import com.fasterxml.jackson.databind.*; // Test(s) to verify that forced access works as expected public class AccessFixTest extends BaseMapTest { static class CauseBlockingSecurityManager extends SecurityManager { @Override public void checkPermission(Permission perm) throws SecurityException { if ("suppressAccessChecks".equals(perm.getName())) { throw new SecurityException("Cannot force permission: "+perm); } } } // [databind#877]: avoid forcing access to `cause` field of `Throwable` // as it is never actually used (always call `initCause()` instead) public void testCauseOfThrowableIgnoral() throws Exception { final SecurityManager origSecMan = System.getSecurityManager(); ObjectMapper mapper = new ObjectMapper(); mapper.disable(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS); try { System.setSecurityManager(new CauseBlockingSecurityManager()); _testCauseOfThrowableIgnoral(mapper); } finally { System.setSecurityManager(origSecMan); } } private void _testCauseOfThrowableIgnoral(ObjectMapper mapper) throws Exception { IOException e = mapper.readValue("{}", IOException.class); assertNotNull(e); } } BeanPropertyMapTest.java000066400000000000000000000030701325620701100362110ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/miscpackage com.fasterxml.jackson.databind.misc; import java.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap; import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader; import com.fasterxml.jackson.databind.deser.impl.ObjectIdValueProperty; import com.fasterxml.jackson.databind.type.TypeFactory; // for [databind#884] public class BeanPropertyMapTest extends BaseMapTest { protected final static JavaType BOGUS_TYPE = TypeFactory.unknownType(); @SuppressWarnings("serial") static class MyObjectIdReader extends ObjectIdReader { public MyObjectIdReader(String name) { super(BOGUS_TYPE, new PropertyName(name), null, null, null, null); } } // Highly specialized test in which we get couple of hash collisions for // small (16) hash map public void testArrayOutOfBounds884() throws Exception { List props = new ArrayList(); PropertyMetadata md = PropertyMetadata.STD_REQUIRED; props.add(new ObjectIdValueProperty(new MyObjectIdReader("pk"), md)); props.add(new ObjectIdValueProperty(new MyObjectIdReader("firstName"), md)); BeanPropertyMap propMap = new BeanPropertyMap(false, props, new HashMap>()); propMap = propMap.withProperty(new ObjectIdValueProperty(new MyObjectIdReader("@id"), md)); assertNotNull(propMap); } } CaseInsensitive1854Test.java000066400000000000000000000034251325620701100365630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/miscpackage com.fasterxml.jackson.databind.misc; import java.util.List; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class CaseInsensitive1854Test extends BaseMapTest { static class Obj1854 { private final int id; // 17-Dec-2017, tatu: One of following would work around the bug [databind#1854] // @JsonProperty("Items") // @JsonIgnore private final List items; public Obj1854(int id, List items) { this.id = id; this.items = items; } @JsonCreator public static Obj1854 fromJson(@JsonProperty("ID") int id, @JsonProperty("Items") List items) { return new Obj1854(id, items); } public int getId() { return id; } public List getItems() { return items; } } static class ChildObj { private final String childId; private ChildObj(String id) { this.childId = id; } @JsonCreator public static ChildObj fromJson(@JsonProperty("ChildID") String cid) { return new ChildObj(cid); } public String getId() { return childId; } } public void testIssue1854() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); final String DOC = aposToQuotes("{'ID': 1, 'Items': [ { 'ChildID': 10 } ]}"); Obj1854 result = mapper.readValue(DOC, Obj1854.class); assertNotNull(result); assertEquals(1, result.getId()); assertNotNull(result.getItems()); assertEquals(1, result.getItems().size()); } } CaseInsensitiveDeserTest.java000066400000000000000000000106421325620701100372230ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/miscpackage com.fasterxml.jackson.databind.misc; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; public class CaseInsensitiveDeserTest extends BaseMapTest { // [databind#1036] static class BaseResponse { public int errorCode; public String debugMessage; } static class Issue476Bean { public Issue476Type value1, value2; } static class Issue476Type { public String name, value; } // [databind#1232]: allow per-property case-insensitivity static class Role { public String ID; public String Name; } static class CaseInsensitiveRoleWrapper { @JsonFormat(with={ JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES }) public Role role; } // [databind#1438] static class InsensitiveCreator { int v; @JsonCreator public InsensitiveCreator(@JsonProperty("value") int v0) { v = v0; } } /* /******************************************************** /* Test methods /******************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); private final ObjectMapper INSENSITIVE_MAPPER = new ObjectMapper(); { INSENSITIVE_MAPPER.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); } // [databind#566] public void testCaseInsensitiveDeserialization() throws Exception { final String JSON = "{\"Value1\" : {\"nAme\" : \"fruit\", \"vALUe\" : \"apple\"}, \"valUE2\" : {\"NAME\" : \"color\", \"value\" : \"red\"}}"; // first, verify default settings which do not accept improper case ObjectMapper mapper = new ObjectMapper(); assertFalse(mapper.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); try { mapper.readValue(JSON, Issue476Bean.class); fail("Should not accept improper case properties by default"); } catch (JsonProcessingException e) { verifyException(e, "Unrecognized field"); assertValidLocation(e.getLocation()); } // Definitely not OK to enable dynamically - the BeanPropertyMap (which is the consumer of this particular feature) gets cached. ObjectReader r = INSENSITIVE_MAPPER.readerFor(Issue476Bean.class); Issue476Bean result = r.readValue(JSON); assertEquals(result.value1.name, "fruit"); assertEquals(result.value1.value, "apple"); } // [databind#1036] public void testCaseInsensitive1036() throws Exception { final String json = "{\"ErrorCode\":2,\"DebugMessage\":\"Signature not valid!\"}"; // final String json = "{\"errorCode\":2,\"debugMessage\":\"Signature not valid!\"}"; BaseResponse response = INSENSITIVE_MAPPER.readValue(json, BaseResponse.class); assertEquals(2, response.errorCode); assertEquals("Signature not valid!", response.debugMessage); } // [databind#1232]: allow per-property case-insensitivity public void testCaseInsensitiveWithFormat() throws Exception { CaseInsensitiveRoleWrapper w = MAPPER.readValue (aposToQuotes("{'role':{'id':'12','name':'Foo'}}"), CaseInsensitiveRoleWrapper.class); assertNotNull(w); assertEquals("12", w.role.ID); assertEquals("Foo", w.role.Name); } // [databind#1438] public void testCreatorWithInsensitive() throws Exception { final String json = aposToQuotes("{'VALUE':3}"); InsensitiveCreator bean = INSENSITIVE_MAPPER.readValue(json, InsensitiveCreator.class); assertEquals(3, bean.v); } // And allow config overrides too public void testCaseInsensitiveWithClassFormat() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(Role.class) .setFormat(JsonFormat.Value.empty() .withFeature(JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); Role role = mapper.readValue (aposToQuotes("{'id':'12','name':'Foo'}"), Role.class); assertNotNull(role); assertEquals("12", role.ID); assertEquals("Foo", role.Name); } } RaceCondition738Test.java000066400000000000000000000054571325620701100361370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/miscpackage com.fasterxml.jackson.databind.misc; import java.util.*; import java.util.concurrent.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public class RaceCondition738Test extends BaseMapTest { static abstract class AbstractHasSubTypes implements HasSubTypes { } static class TypeOne extends AbstractHasSubTypes { private final String id; public TypeOne(String id) { this.id = id; } @JsonProperty public String getId() { return id; } @Override public String getType() { return TypeOne.class.getSimpleName(); } } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) @JsonSubTypes({ @JsonSubTypes.Type(value = TypeOne.class, name = "one") }) public interface HasSubTypes { String getType(); } static class Wrapper { private final HasSubTypes hasSubTypes; private Wrapper(HasSubTypes hasSubTypes) { this.hasSubTypes = hasSubTypes; } @JsonProperty public HasSubTypes getHasSubTypes() { return hasSubTypes; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testRepeatedly() throws Exception { final int COUNT = 2000; for (int i = 0; i < COUNT; i++) { runOnce(i, COUNT); } } void runOnce(int round, int max) throws Exception { final ObjectMapper mapper = newObjectMapper(); Callable writeJson = new Callable() { @Override public String call() throws Exception { Wrapper wrapper = new Wrapper(new TypeOne("test")); return mapper.writeValueAsString(wrapper); } }; int numThreads = 4; ExecutorService executor = Executors.newFixedThreadPool(numThreads); List> jsonFutures = new ArrayList>(); for (int i = 0; i < numThreads; i++) { jsonFutures.add(executor.submit(writeJson)); } executor.shutdown(); executor.awaitTermination(5, TimeUnit.SECONDS); for (Future jsonFuture : jsonFutures) { String json = jsonFuture.get(); JsonNode tree = mapper.readTree(json); JsonNode wrapped = tree.get("hasSubTypes"); if (!wrapped.has("one")) { throw new IllegalStateException("Round #"+round+"/"+max+" ; missing property 'one', source: "+json); } } } } TestBlocking.java000066400000000000000000000023671325620701100347010ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/miscpackage com.fasterxml.jackson.databind.misc; import java.io.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; /** * Unit test mostly written to cover issue [JACKSON-81]; unintended blocking * after data binding. */ public class TestBlocking extends BaseMapTest { /** * This is an indirect test that should trigger problems if (and only if) * underlying parser is advanced beyond the only element array. * Basically, although content is invalid, this should be encountered * quite yet. */ public void testEagerAdvance() throws IOException { ObjectMapper mapper = new ObjectMapper(); JsonParser jp = createParserUsingReader("[ 1 "); assertToken(JsonToken.START_ARRAY, jp.nextToken()); assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); // And then try to map just a single entry: shouldn't fail: Integer I = mapper.readValue(jp, Integer.class); assertEquals(Integer.valueOf(1), I); // and should fail only now: try { jp.nextToken(); } catch (IOException ioe) { verifyException(ioe, "Unexpected end-of-input: expected close marker for ARRAY"); } jp.close(); } } TestJSONP.java000066400000000000000000000035441325620701100340400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/miscpackage com.fasterxml.jackson.databind.misc; import java.util.Arrays; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.util.JSONPObject; import com.fasterxml.jackson.databind.util.JSONWrappedObject; public class TestJSONP extends BaseMapTest { static class Base { public String a; } static class Impl extends Base { public String b; public Impl(String a, String b) { this.a = a; this.b = b; } } private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleScalars() throws Exception { assertEquals("callback(\"abc\")", MAPPER.writeValueAsString(new JSONPObject("callback", "abc"))); assertEquals("calc(123)", MAPPER.writeValueAsString(new JSONPObject("calc", Integer.valueOf(123)))); assertEquals("dummy(null)", MAPPER.writeValueAsString(new JSONPObject("dummy", null))); } public void testSimpleBean() throws Exception { assertEquals("xxx({\"a\":\"123\",\"b\":\"456\"})", MAPPER.writeValueAsString(new JSONPObject("xxx", new Impl("123", "456")))); } /** * Test to ensure that it is possible to force a static type for wrapped * value. */ public void testWithType() throws Exception { Object ob = new Impl("abc", "def"); JavaType type = MAPPER.constructType(Base.class); assertEquals("do({\"a\":\"abc\"})", MAPPER.writeValueAsString(new JSONPObject("do", ob, type))); } public void testGeneralWrapping() throws Exception { JSONWrappedObject input = new JSONWrappedObject("/*Foo*/", "\n// the end", Arrays.asList()); assertEquals("/*Foo*/[]\n// the end", MAPPER.writeValueAsString(input)); } } ThreadSafety1759Test.java000066400000000000000000000050361325620701100360560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/miscpackage com.fasterxml.jackson.databind.misc; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import com.fasterxml.jackson.databind.*; public class ThreadSafety1759Test extends BaseMapTest { /* /********************************************************** /* Test methods /********************************************************** */ public void testCalendarForDeser() throws Exception { final ObjectMapper mapper = newObjectMapper(); final int numThreads = 4; final int COUNT = 3000; final AtomicInteger counter = new AtomicInteger(); // IMPORTANT! Use different timestamp for every thread List> calls = new ArrayList>(); for (int thread = 1; thread <= numThreads; ++thread) { final String json = quote(String.format("2017-01-%02dT16:30:49Z", thread)); final long timestamp = mapper.readValue(json, Date.class).getTime(); calls.add(createCallable(thread, mapper, json, timestamp, COUNT, counter)); } ExecutorService executor = Executors.newFixedThreadPool(numThreads); List> results = new ArrayList<>(); for (Callable c : calls) { results.add(executor.submit(c)); } executor.shutdown(); for (Future f : results) { Throwable t = f.get(5, TimeUnit.SECONDS); if (t != null) { fail("Exception during processing: "+t.getMessage()); } } assertEquals(numThreads * COUNT, counter.get()); } private Callable createCallable(final int threadId, final ObjectMapper mapper, final String json, final long timestamp, final int count, final AtomicInteger counter) { return new Callable() { @Override public Throwable call() throws IOException { for (int i = 0; i < count; ++i) { Date dt = mapper.readValue(json, Date.class); if (dt.getTime() != timestamp) { return new IllegalArgumentException("Wrong timestamp (thread id "+threadId+", input: "+json+": should get "+timestamp+", got "+dt.getTime()); } counter.addAndGet(1); } return null; } }; } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/mixins/000077500000000000000000000000001325620701100320715ustar00rootroot00000000000000MixinsWithBundlesTest.java000066400000000000000000000020661325620701100371410ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/mixinspackage com.fasterxml.jackson.databind.mixins; import java.lang.annotation.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // for [databind#771] public class MixinsWithBundlesTest extends BaseMapTest { @Target(value={ ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD }) @Retention(value=RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonProperty("bar") public @interface ExposeStuff { } public abstract class FooMixin { @ExposeStuff public abstract String getStuff(); } public static class Foo { private String stuff; Foo(String stuff) { this.stuff = stuff; } public String getStuff() { return stuff; } } public void testMixinWithBundles() throws Exception { ObjectMapper mapper = new ObjectMapper().addMixIn(Foo.class, FooMixin.class); String result = mapper.writeValueAsString(new Foo("result")); assertEquals("{\"bar\":\"result\"}", result); } } TestMixinDeserForClass.java000066400000000000000000000060421325620701100372230ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/mixinspackage com.fasterxml.jackson.databind.mixins; import java.io.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.databind.*; public class TestMixinDeserForClass extends BaseMapTest { /* /********************************************************** /* Helper bean classes /********************************************************** */ static class BaseClass { /* property that is always found; but has lower priority than * setter method if both found */ @JsonProperty public String a; // setter that may or may not be auto-detected public void setA(String v) { a = "XXX"+v; } } @JsonAutoDetect(setterVisibility=Visibility.ANY, fieldVisibility=Visibility.ANY) static class LeafClass extends BaseClass { } @JsonAutoDetect(setterVisibility=Visibility.NONE, fieldVisibility=Visibility.NONE) interface MixIn { } /* /********************************************************** /* Unit tests /********************************************************** */ public void testClassMixInsTopLevel() throws IOException { ObjectMapper m = new ObjectMapper(); // First: test default behavior: should use setter LeafClass result = m.readValue("{\"a\":\"value\"}", LeafClass.class); assertEquals("XXXvalue", result.a); /* Then with leaf-level mix-in; without (method) auto-detect, should * use field */ m = new ObjectMapper(); m.addMixIn(LeafClass.class, MixIn.class); result = m.readValue("{\"a\":\"value\"}", LeafClass.class); assertEquals("value", result.a); } /* and then a test for mid-level mixin; should have no effect * when deserializing leaf (but will if deserializing base class) */ public void testClassMixInsMidLevel() throws IOException { ObjectMapper m = new ObjectMapper(); m.addMixIn(BaseClass.class, MixIn.class); { BaseClass result = m.readValue("{\"a\":\"value\"}", BaseClass.class); assertEquals("value", result.a); } // whereas with leaf class, reverts to default { LeafClass result = m.readValue("{\"a\":\"value\"}", LeafClass.class); assertEquals("XXXvalue", result.a); } } /* Also: when mix-in attached to Object.class, will work, if * visible (similar to mid-level, basically) */ public void testClassMixInsForObjectClass() throws IOException { ObjectMapper m = new ObjectMapper(); m.addMixIn(Object.class, MixIn.class); // will be seen for BaseClass { BaseClass result = m.readValue("{\"a\":\"\"}", BaseClass.class); assertEquals("", result.a); } // but LeafClass still overrides { LeafClass result = m.readValue("{\"a\":\"\"}", LeafClass.class); assertEquals("XXX", result.a); } } } TestMixinDeserForCreators.java000066400000000000000000000063701325620701100377440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/mixinspackage com.fasterxml.jackson.databind.mixins; import java.io.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestMixinDeserForCreators extends BaseMapTest { /* /********************************************************** /* Helper bean classes /********************************************************** */ static class BaseClass { protected String _a; public BaseClass(String a) { _a = a+"..."; } private BaseClass(String value, boolean dummy) { _a = value; } public static BaseClass myFactory(String a) { return new BaseClass(a+"X", true); } } static class BaseClassWithPrivateCtor { protected String _a; private BaseClassWithPrivateCtor(String a) { _a = a+"..."; } } /** * Mix-in class that will effectively suppresses String constructor, * and marks a non-auto-detectable static method as factory method * as a creator. *

* Note that method implementations are not used for anything; but * we have to a class: interface won't do, as they can't have * constructors or static methods. */ static class MixIn { @JsonIgnore protected MixIn(String s) { } @JsonCreator static BaseClass myFactory(String a) { return null; } } static class MixInForPrivate { @JsonCreator MixInForPrivate(String s) { } } static class StringWrapper { String _value; private StringWrapper(String s, boolean foo) { _value = s; } @SuppressWarnings("unused") private static StringWrapper create(String str) { return new StringWrapper(str, false); } } abstract static class StringWrapperMixIn { @JsonCreator static StringWrapper create(String str) { return null; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testForConstructor() throws IOException { ObjectMapper m = new ObjectMapper(); m.addMixIn(BaseClassWithPrivateCtor.class, MixInForPrivate.class); BaseClassWithPrivateCtor result = m.readValue("\"?\"", BaseClassWithPrivateCtor.class); assertEquals("?...", result._a); } public void testForFactoryAndCtor() throws IOException { ObjectMapper m = new ObjectMapper(); BaseClass result; // First: test default behavior: should use constructor result = m.readValue("\"string\"", BaseClass.class); assertEquals("string...", result._a); // Then with simple mix-in: should change to use the factory method m = new ObjectMapper(); m.addMixIn(BaseClass.class, MixIn.class); result = m.readValue("\"string\"", BaseClass.class); assertEquals("stringX", result._a); } public void testFactoryMixIn() throws IOException { ObjectMapper m = new ObjectMapper(); m.addMixIn(StringWrapper.class, StringWrapperMixIn.class); StringWrapper result = m.readValue("\"a\"", StringWrapper.class); assertEquals("a", result._value); } } TestMixinDeserForMethods.java000066400000000000000000000027271325620701100375670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/mixinspackage com.fasterxml.jackson.databind.mixins; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestMixinDeserForMethods extends BaseMapTest { /* /********************************************************** /* Helper bean classes /********************************************************** */ static class BaseClass { protected HashMap values = new HashMap(); public BaseClass() { } protected void addValue(String key, Object value) { values.put(key, value); } } interface MixIn { @JsonAnySetter void addValue(String key, Object value); } /* /********************************************************** /* Unit tests /********************************************************** */ /** * Unit test that verifies that we can mix in @JsonAnySetter * annotation, as expected. */ public void testWithAnySetter() throws IOException { ObjectMapper m = new ObjectMapper(); m.addMixIn(BaseClass.class, MixIn.class); BaseClass result = m.readValue("{ \"a\" : 3, \"b\" : true }", BaseClass.class); assertNotNull(result); assertEquals(2, result.values.size()); assertEquals(Integer.valueOf(3), result.values.get("a")); assertEquals(Boolean.TRUE, result.values.get("b")); } } TestMixinInheritance.java000066400000000000000000000041371325620701100367600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/mixinspackage com.fasterxml.jackson.databind.mixins; import java.io.IOException; import java.util.Map; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class TestMixinInheritance extends BaseMapTest { static class Beano { public int ido = 42; public String nameo = "Bob"; } static class BeanoMixinSuper { @JsonProperty("name") public String nameo; } static class BeanoMixinSub extends BeanoMixinSuper { @JsonProperty("id") public int ido; } static class Beano2 { public int getIdo() { return 13; } public String getNameo() { return "Bill"; } } static abstract class BeanoMixinSuper2 extends Beano2 { @Override @JsonProperty("name") public abstract String getNameo(); } static abstract class BeanoMixinSub2 extends BeanoMixinSuper2 { @Override @JsonProperty("id") public abstract int getIdo(); } /* /********************************************************** /* Unit tests /********************************************************** */ public void testMixinFieldInheritance() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(Beano.class, BeanoMixinSub.class); Map result; result = writeAndMap(mapper, new Beano()); assertEquals(2, result.size()); if (!result.containsKey("id") || !result.containsKey("name")) { fail("Should have both 'id' and 'name', but content = "+result); } } public void testMixinMethodInheritance() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(Beano2.class, BeanoMixinSub2.class); Map result; result = writeAndMap(mapper, new Beano2()); assertEquals(2, result.size()); assertTrue(result.containsKey("id")); assertTrue(result.containsKey("name")); } } TestMixinSerForClass.java000066400000000000000000000076571325620701100367270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/mixinspackage com.fasterxml.jackson.databind.mixins; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.databind.*; public class TestMixinSerForClass extends BaseMapTest { @JsonInclude(JsonInclude.Include.ALWAYS) static class BaseClass { protected String _a, _b; protected String _c = "c"; protected BaseClass() { } public BaseClass(String a) { _a = a; } // will be auto-detectable unless disabled: public String getA() { return _a; } @JsonProperty public String getB() { return _b; } @JsonProperty public String getC() { return _c; } } @JsonInclude(JsonInclude.Include.NON_DEFAULT) static class LeafClass extends BaseClass { public LeafClass() { super(null); } public LeafClass(String a) { super(a); } } /** * This interface only exists to add "mix-in annotations": that is, any * annotations it has can be virtually added to mask annotations * of other classes */ @JsonInclude(JsonInclude.Include.NON_NULL) interface MixIn { } // test disabling of autodetect... @JsonAutoDetect(getterVisibility=Visibility.NONE, fieldVisibility=Visibility.NONE) interface MixInAutoDetect { } // [databind#245] @JsonFilter(PortletRenderExecutionEventFilterMixIn.FILTER_NAME) private interface PortletRenderExecutionEventFilterMixIn { static final String FILTER_NAME = "PortletRenderExecutionEventFilter"; } /* /********************************************************** /( Unit tests /********************************************************** */ public void testClassMixInsTopLevel() throws IOException { ObjectMapper mapper = new ObjectMapper(); Map result; // first: with no mix-ins: result = writeAndMap(mapper, new LeafClass("abc")); assertEquals(1, result.size()); assertEquals("abc", result.get("a")); // then with top-level override mapper = new ObjectMapper(); mapper.addMixIn(LeafClass.class, MixIn.class); result = writeAndMap(mapper, new LeafClass("abc")); assertEquals(2, result.size()); assertEquals("abc", result.get("a")); assertEquals("c", result.get("c")); // mid-level override; should not have any effect mapper = new ObjectMapper(); mapper.addMixIn(BaseClass.class, MixIn.class); result = writeAndMap(mapper, new LeafClass("abc")); assertEquals(1, result.size()); assertEquals("abc", result.get("a")); } public void testClassMixInsMidLevel() throws IOException { ObjectMapper mapper = new ObjectMapper(); Map result; LeafClass bean = new LeafClass("xyz"); bean._c = "c2"; // with no mix-ins first... result = writeAndMap(mapper, bean); assertEquals(2, result.size()); assertEquals("xyz", result.get("a")); assertEquals("c2", result.get("c")); // then with working mid-level override, which effectively suppresses 'a' mapper = new ObjectMapper(); mapper.addMixIn(BaseClass.class, MixInAutoDetect.class); result = writeAndMap(mapper, bean); assertEquals(1, result.size()); assertEquals("c2", result.get("c")); // and related to [databind#245], apply mix-ins to a copy of ObjectMapper ObjectMapper mapper2 = new ObjectMapper(); result = writeAndMap(mapper2, bean); assertEquals(2, result.size()); ObjectMapper mapper3 = mapper2.copy(); mapper3.addMixIn(BaseClass.class, MixInAutoDetect.class); result = writeAndMap(mapper3, bean); assertEquals(1, result.size()); assertEquals("c2", result.get("c")); } } TestMixinSerForFields.java000066400000000000000000000050211325620701100370470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/mixinspackage com.fasterxml.jackson.databind.mixins; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestMixinSerForFields extends BaseMapTest { /* /********************************************************** /* Helper bean classes /********************************************************** */ static class BaseClass { public String a; protected String b; public BaseClass(String a, String b) { this.a = a; this.b = b; } } static class SubClass extends BaseClass { public SubClass(String a, String b) { super(a, b); } } abstract class MixIn { // Let's add 'b' as "banana" @JsonProperty("banana") public String b; } abstract class MixIn2 { // Let's remove 'a' @JsonIgnore public String a; // also: add a dummy field that is NOT to match anything @JsonProperty public String xyz; } /* /********************************************************** /* Unit tests /********************************************************** */ public void testFieldMixInsTopLevel() throws IOException { ObjectMapper mapper = new ObjectMapper(); Map result; BaseClass bean = new BaseClass("1", "2"); // first: with no mix-ins: result = writeAndMap(mapper, bean); assertEquals(1, result.size()); assertEquals("1", result.get("a")); // and then with simple mix-in mapper = new ObjectMapper(); mapper.addMixIn(BaseClass.class, MixIn.class); result = writeAndMap(mapper, bean); assertEquals(2, result.size()); assertEquals("1", result.get("a")); assertEquals("2", result.get("banana")); } public void testMultipleFieldMixIns() throws IOException { ObjectMapper mapper = new ObjectMapper(); // ordering here shouldn't matter really... HashMap,Class> mixins = new HashMap,Class>(); mixins.put(SubClass.class, MixIn.class); mixins.put(BaseClass.class, MixIn2.class); mapper.setMixIns(mixins); Map result; result = writeAndMap(mapper, new SubClass("1", "2")); assertEquals(1, result.size()); // 'a' should be suppressed; 'b' mapped to 'banana' assertEquals("2", result.get("banana")); } } TestMixinSerForMethods.java000066400000000000000000000120301325620701100372420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/mixinspackage com.fasterxml.jackson.databind.mixins; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.ClassIntrospector; import com.fasterxml.jackson.databind.introspect.ClassIntrospector.MixInResolver; public class TestMixinSerForMethods extends BaseMapTest { /* /********************************************************** /* Helper bean classes /********************************************************** */ // base class: just one visible property ('b') @SuppressWarnings("unused") static class BaseClass { private String a; private String b; protected BaseClass() { } public BaseClass(String a, String b) { this.a = a; this.b = b; } @JsonProperty("b") public String takeB() { return b; } } /* extends, just for fun; and to show possible benefit of being * able to declare that a method is overridden (compile-time check * that our intended mix-in override will match a method) */ abstract static class MixIn extends BaseClass { // let's make 'a' visible @JsonProperty String a; @Override @JsonProperty("b2") public abstract String takeB(); // also: just for fun; add a "red herring"... unmatched method @JsonProperty abstract String getFoobar(); } static class LeafClass extends BaseClass { public LeafClass(String a, String b) { super(a, b); } @Override @JsonIgnore public String takeB() { return null; } } static class EmptyBean { } static class SimpleBean extends EmptyBean { int x() { return 42; } } /** * This mix-in is to be attached to EmptyBean, but really modify * methods that its subclass, SimpleBean, has. */ abstract class MixInForSimple { // This should apply to sub-class @JsonProperty("x") abstract int x(); // and this matches nothing, should be ignored @JsonProperty("notreally") public int xxx() { return 3; } // nor this public abstract int getIt(); } /* /********************************************************** /* Unit tests /********************************************************** */ /** * Unit test for verifying that leaf-level mix-ins work ok; * that is, any annotations added properly override all annotations * that masked methods (fields etc) have. */ public void testLeafMixin() throws IOException { ObjectMapper mapper = new ObjectMapper(); Map result; BaseClass bean = new BaseClass("a1", "b2"); // first: with no mix-ins: result = writeAndMap(mapper, bean); assertEquals(1, result.size()); assertEquals("b2", result.get("b")); // then with leaf-level mix-in mapper = new ObjectMapper(); mapper.addMixIn(BaseClass.class, MixIn.class); result = writeAndMap(mapper, bean); assertEquals(2, result.size()); assertEquals("b2", result.get("b2")); assertEquals("a1", result.get("a")); } /** * Unit test for verifying that having a mix-in "between" classes * (overriding annotations of a base class, but being overridden * further by a sub-class) works as expected */ public void testIntermediateMixin() throws IOException { ObjectMapper mapper = new ObjectMapper(); Map result; LeafClass bean = new LeafClass("XXX", "b2"); mapper.addMixIn(BaseClass.class, MixIn.class); result = writeAndMap(mapper, bean); assertEquals(1, result.size()); assertEquals("XXX", result.get("a")); } /** * Another intermediate mix-in, to verify that annotations * properly "trickle up" */ public void testIntermediateMixin2() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(EmptyBean.class, MixInForSimple.class); Map result = writeAndMap(mapper, new SimpleBean()); assertEquals(1, result.size()); assertEquals(Integer.valueOf(42), result.get("x")); } // [databind#688] public void testCustomResolver() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.setMixInResolver(new ClassIntrospector.MixInResolver() { @Override public Class findMixInClassFor(Class target) { if (target == EmptyBean.class) { return MixInForSimple.class; } return null; } @Override public MixInResolver copy() { return this; } }); Map result = writeAndMap(mapper, new SimpleBean()); assertEquals(1, result.size()); assertEquals(Integer.valueOf(42), result.get("x")); } } TestMixinSerWithViews.java000066400000000000000000000127561325620701100371400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/mixinspackage com.fasterxml.jackson.databind.mixins; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestMixinSerWithViews extends BaseMapTest { /* /********************************************************** /* Helper bean classes /********************************************************** */ static class SimpleTestData { private String name = "shown"; private String nameHidden = "hidden"; public String getName() { return name; } public String getNameHidden( ) { return nameHidden; } public void setName( String name ) { this.name = name; } public void setNameHidden( String nameHidden ) { this.nameHidden = nameHidden; } } static class ComplexTestData { String nameNull = null; String nameComplex = "complexValue"; String nameComplexHidden = "nameComplexHiddenValue"; SimpleTestData testData = new SimpleTestData( ); SimpleTestData[] testDataArray = new SimpleTestData[] { new SimpleTestData( ), null }; public String getNameNull() { return nameNull; } public void setNameNull( String nameNull ) { this.nameNull = nameNull; } public String getNameComplex() { return nameComplex; } public void setNameComplex( String nameComplex ) { this.nameComplex = nameComplex; } public String getNameComplexHidden() { return nameComplexHidden; } public void setNameComplexHidden( String nameComplexHidden ) { this.nameComplexHidden = nameComplexHidden; } public SimpleTestData getTestData() { return testData; } public void setTestData( SimpleTestData testData ) { this.testData = testData; } public SimpleTestData[] getTestDataArray() { return testDataArray; } public void setTestDataArray( SimpleTestData[] testDataArray ) { this.testDataArray = testDataArray; } } public interface TestDataJAXBMixin { @JsonView( Views.View.class ) String getName( ); } public interface TestComplexDataJAXBMixin { @JsonView( Views.View.class ) String getNameNull(); @JsonView( Views.View.class ) String getNameComplex(); @JsonView( Views.View.class ) String getNameComplexHidden(); @JsonView( Views.View.class ) SimpleTestData getTestData(); @JsonView( Views.View.class ) SimpleTestData[] getTestDataArray( ); } static class Views { static class View { } } public class A { private String name; private int age; private String surname; public A(String name, int age, String surname) { super(); this.name = name; this.age = age; this.surname = surname; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } } public interface AView { } public abstract class AMixInAnnotation { @JsonProperty("name") @JsonView(AView.class) abstract String getName(); @JsonProperty("age") @JsonView(AView.class) abstract int getAge(); } /* /********************************************************** /* Tests /********************************************************** */ public void testDataBindingUsage( ) throws Exception { ObjectMapper objectMapper = createObjectMapper(); ObjectWriter objectWriter = objectMapper.writerWithView(Views.View.class).withDefaultPrettyPrinter(); Object object = new ComplexTestData(); String json = objectWriter.writeValueAsString(object); assertTrue( json.indexOf( "nameHidden" ) == -1 ); assertTrue( json.indexOf( "\"name\" : \"shown\"" ) > 0 ); } public void testIssue560() throws Exception { ObjectMapper mapper = new ObjectMapper(); A a = new A("myname", 29, "mysurname"); // Property SerializationConfig.SerializationFeature.DEFAULT_VIEW_INCLUSION set to false mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, Boolean.FALSE); mapper.addMixIn(A.class, AMixInAnnotation.class); String json = mapper.writerWithView(AView.class).writeValueAsString(a); assertTrue(json.indexOf("\"name\"") > 0); } /* /********************************************************** /* Helper methods /********************************************************** */ private ObjectMapper createObjectMapper( ) { ObjectMapper objectMapper = new ObjectMapper( ); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false ); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL ); objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false ); Map, Class> sourceMixins = new HashMap, Class>( ); sourceMixins.put( SimpleTestData.class, TestDataJAXBMixin.class ); sourceMixins.put( ComplexTestData.class, TestComplexDataJAXBMixin.class ); objectMapper.setMixIns(sourceMixins); return objectMapper; } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/module/000077500000000000000000000000001325620701100320475ustar00rootroot00000000000000SimpleModuleArgCheckTest.java000066400000000000000000000123161325620701100374650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.util.Collections; import java.util.List; import java.util.Map; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.NamedType; public class SimpleModuleArgCheckTest extends BaseMapTest { /* /********************************************************** /* Unit tests for invalid deserializers /********************************************************** */ public void testInvalidForDeserializers() throws Exception { SimpleModule mod = new SimpleModule("test", Version.unknownVersion(), (Map,JsonDeserializer>) null); try { mod.addDeserializer(String.class, null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as deserializer"); } try { mod.addKeyDeserializer(String.class, null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as key deserializer"); } } /* /********************************************************** /* Unit tests for invalid serializers /********************************************************** */ public void testInvalidForSerializers() throws Exception { SimpleModule mod = new SimpleModule("test", Version.unknownVersion(), (List>) null); try { mod.addSerializer(String.class, null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as serializer"); } try { mod.addSerializer((JsonSerializer) null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as serializer"); } try { mod.addKeySerializer(String.class, null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as key serializer"); } } /* /********************************************************** /* Unit tests for invalid misc other /********************************************************** */ public void testInvalidAbstractTypeMapping() throws Exception { // just for funsies let's use more esoteric constructor Map,JsonDeserializer> desers = Collections.emptyMap(); List> sers = Collections.emptyList(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion(), desers, sers); try { mod.addAbstractTypeMapping(null, String.class); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as abstract type to map"); } try { mod.addAbstractTypeMapping(String.class, null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as concrete type to map to"); } } public void testInvalidSubtypeMappings() throws Exception { SimpleModule mod = new SimpleModule("test", Version.unknownVersion(), null, null); try { mod.registerSubtypes(String.class, null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as subtype to register"); } try { mod.registerSubtypes(new NamedType(Integer.class), (NamedType) null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as subtype to register"); } } public void testInvalidValueInstantiator() throws Exception { SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); try { mod.addValueInstantiator(null, null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as class to register value instantiator for"); } try { mod.addValueInstantiator(CharSequence.class, null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as value instantiator"); } } public void testInvalidMixIn() throws Exception { SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); try { mod.setMixInAnnotation(null, String.class); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as target type"); } try { mod.setMixInAnnotation(String.class, null); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot pass `null` as mixin class"); } } } SimpleModuleTest.java000066400000000000000000000276251325620701100361060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.io.IOException; import java.lang.reflect.Type; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleDeserializers; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.module.SimpleSerializers; import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; @SuppressWarnings("serial") public class SimpleModuleTest extends BaseMapTest { /** * Trivial bean that requires custom serializer and deserializer */ final static class CustomBean { protected String str; protected int num; public CustomBean(String s, int i) { str = s; num = i; } } static enum SimpleEnum { A, B; } // Extend SerializerBase to get access to declared handledType static class CustomBeanSerializer extends StdSerializer { public CustomBeanSerializer() { super(CustomBean.class); } @Override public void serialize(CustomBean value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { // We will write it as a String, with '|' as delimiter jgen.writeString(value.str + "|" + value.num); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { return null; } } static class CustomBeanDeserializer extends JsonDeserializer { @Override public CustomBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { String text = jp.getText(); int ix = text.indexOf('|'); if (ix < 0) { throw new IOException("Failed to parse String value of \""+text+"\""); } String str = text.substring(0, ix); int num = Integer.parseInt(text.substring(ix+1)); return new CustomBean(str, num); } } static class SimpleEnumSerializer extends StdSerializer { public SimpleEnumSerializer() { super(SimpleEnum.class); } @Override public void serialize(SimpleEnum value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString(value.name().toLowerCase()); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { return null; } } static class SimpleEnumDeserializer extends JsonDeserializer { @Override public SimpleEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return SimpleEnum.valueOf(jp.getText().toUpperCase()); } } interface Base { public String getText(); } static class Impl1 implements Base { @Override public String getText() { return "1"; } } static class Impl2 extends Impl1 { @Override public String getText() { return "2"; } } static class BaseSerializer extends StdScalarSerializer { public BaseSerializer() { super(Base.class); } @Override public void serialize(Base value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeString("Base:"+value.getText()); } } static class MixableBean { public int a = 1; public int b = 2; public int c = 3; } @JsonPropertyOrder({"c", "a", "b"}) static class MixInForOrder { } protected static class MySimpleSerializers extends SimpleSerializers { } protected static class MySimpleDeserializers extends SimpleDeserializers { } /** * Test module which uses custom 'serializers' and 'deserializers' container; used * to trigger type problems. */ protected static class MySimpleModule extends SimpleModule { public MySimpleModule(String name, Version version) { super(name, version); _deserializers = new MySimpleDeserializers(); _serializers = new MySimpleSerializers(); } } protected static class ContextVerifierModule extends com.fasterxml.jackson.databind.Module { @Override public String getModuleName() { return "x"; } @Override public Version version() { return Version.unknownVersion(); } @Override public void setupModule(SetupContext context) { ObjectCodec c = context.getOwner(); assertNotNull(c); assertTrue(c instanceof ObjectMapper); ObjectMapper m = context.getOwner(); assertNotNull(m); } } static class TestModule626 extends SimpleModule { final Class mixin, target; public TestModule626(Class t, Class m) { super("Test"); target = t; mixin = m; } @Override public void setupModule(SetupContext context) { context.setMixInAnnotations(target, mixin); } } /* /********************************************************** /* Unit tests; first, verifying need for custom handlers /********************************************************** */ /** * Basic test to ensure we do not have functioning default * serializers for custom types used in tests. */ public void testWithoutModule() { ObjectMapper mapper = new ObjectMapper(); // first: serialization failure: try { mapper.writeValueAsString(new CustomBean("foo", 3)); fail("Should have caused an exception"); } catch (IOException e) { verifyException(e, "No serializer found"); } // then deserialization try { mapper.readValue("{\"str\":\"ab\",\"num\":2}", CustomBean.class); fail("Should have caused an exception"); } catch (IOException e) { verifyException(e, "Cannot construct"); verifyException(e, "no creators"); } } /* /********************************************************** /* Unit tests; simple serializers /********************************************************** */ public void testSimpleBeanSerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); mod.addSerializer(new CustomBeanSerializer()); mapper.registerModule(mod); assertEquals(quote("abcde|5"), mapper.writeValueAsString(new CustomBean("abcde", 5))); } public void testSimpleEnumSerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); mod.addSerializer(new SimpleEnumSerializer()); // for fun, call "multi-module" registration mapper.registerModules(mod); assertEquals(quote("b"), mapper.writeValueAsString(SimpleEnum.B)); } public void testSimpleInterfaceSerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); mod.addSerializer(new BaseSerializer()); // and another variant here too List mods = Arrays.asList(mod); mapper.registerModules(mods); assertEquals(quote("Base:1"), mapper.writeValueAsString(new Impl1())); assertEquals(quote("Base:2"), mapper.writeValueAsString(new Impl2())); } /* /********************************************************** /* Unit tests; simple deserializers /********************************************************** */ public void testSimpleBeanDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); mod.addDeserializer(CustomBean.class, new CustomBeanDeserializer()); mapper.registerModule(mod); CustomBean bean = mapper.readValue(quote("xyz|3"), CustomBean.class); assertEquals("xyz", bean.str); assertEquals(3, bean.num); } public void testSimpleEnumDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); mod.addDeserializer(SimpleEnum.class, new SimpleEnumDeserializer()); mapper.registerModule(mod); SimpleEnum result = mapper.readValue(quote("a"), SimpleEnum.class); assertSame(SimpleEnum.A, result); } public void testMultipleModules() throws Exception { MySimpleModule mod1 = new MySimpleModule("test1", Version.unknownVersion()); SimpleModule mod2 = new SimpleModule("test2", Version.unknownVersion()); mod1.addSerializer(SimpleEnum.class, new SimpleEnumSerializer()); mod1.addDeserializer(CustomBean.class, new CustomBeanDeserializer()); Map,JsonDeserializer> desers = new HashMap<>(); desers.put(SimpleEnum.class, new SimpleEnumDeserializer()); mod2.setDeserializers(new SimpleDeserializers(desers)); mod2.addSerializer(CustomBean.class, new CustomBeanSerializer()); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(mod1); mapper.registerModule(mod2); assertEquals(quote("b"), mapper.writeValueAsString(SimpleEnum.B)); SimpleEnum result = mapper.readValue(quote("a"), SimpleEnum.class); assertSame(SimpleEnum.A, result); // also let's try it with different order of registration, just in case mapper = new ObjectMapper(); mapper.registerModule(mod2); mapper.registerModule(mod1); assertEquals(quote("b"), mapper.writeValueAsString(SimpleEnum.B)); result = mapper.readValue(quote("a"), SimpleEnum.class); assertSame(SimpleEnum.A, result); } /* /********************************************************** /* Unit tests; other /********************************************************** */ public void testMixIns() throws Exception { SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.setMixInAnnotation(MixableBean.class, MixInForOrder.class); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(module); Map props = this.writeAndMap(mapper, new MixableBean()); assertEquals(3, props.size()); assertEquals(Integer.valueOf(3), props.get("c")); assertEquals(Integer.valueOf(1), props.get("a")); assertEquals(Integer.valueOf(2), props.get("b")); } public void testAccessToMapper() throws Exception { ContextVerifierModule module = new ContextVerifierModule(); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(module); } // [databind#626] public void testMixIns626() throws Exception { ObjectMapper mapper = new ObjectMapper(); // no real annotations, but nominally add ones from 'String' to 'Object', just for testing mapper.registerModule(new TestModule626(Object.class, String.class)); Class found = mapper.findMixInClassFor(Object.class); assertEquals(String.class, found); } public void testAutoDiscovery() throws Exception { List mods = ObjectMapper.findModules(); assertEquals(0, mods.size()); } } TestAbstractTypes.java000066400000000000000000000077221325620701100362730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.util.*; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; public class TestAbstractTypes extends BaseMapTest { static class MyString implements CharSequence { protected String value; public MyString(String s) { value = s; } @Override public char charAt(int index) { return value.charAt(index); } @Override public int length() { return value.length(); } @Override public CharSequence subSequence(int arg0, int arg1) { return this; } } public interface Abstract { public int getValue(); } public static class AbstractImpl implements Abstract { @Override public int getValue() { return 3; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testCollectionDefaulting() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); // let's ensure we get hierarchic mapping mod.addAbstractTypeMapping(Collection.class, List.class); mod.addAbstractTypeMapping(List.class, LinkedList.class); mapper.registerModule(mod); Collection result = mapper.readValue("[]", Collection.class); assertEquals(LinkedList.class, result.getClass()); } public void testMapDefaultingBasic() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); // default is HashMap, so: mod.addAbstractTypeMapping(Map.class, TreeMap.class); mapper.registerModule(mod); Map result = mapper.readValue("{}", Map.class); assertEquals(TreeMap.class, result.getClass()); } // [databind#700] public void testDefaultingRecursive() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); // defaults: LinkedHashMap, ArrayList mod.addAbstractTypeMapping(Map.class, TreeMap.class); mod.addAbstractTypeMapping(List.class, LinkedList.class); mapper.registerModule(mod); Object result; result = mapper.readValue("[ {} ]", Object.class); assertEquals(LinkedList.class, result.getClass()); Object v = ((List) result).get(0); assertNotNull(v); assertEquals(TreeMap.class, v.getClass()); result = mapper.readValue("{ \"x\": [ 3 ] }", Object.class); assertEquals(TreeMap.class, result.getClass()); Map map = (Map) result; assertEquals(1, map.size()); v = map.get("x"); assertNotNull(v); assertEquals(LinkedList.class, v.getClass()); assertEquals(1, ((List) v).size()); } public void testInterfaceDefaulting() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); // let's ensure we get hierarchic mapping mod.addAbstractTypeMapping(CharSequence.class, MyString.class); mapper.registerModule(mod); Object result = mapper.readValue(quote("abc"), CharSequence.class); assertEquals(MyString.class, result.getClass()); assertEquals("abc", ((MyString) result).value); // and ditto for POJOs mod = new SimpleModule(); mod.addAbstractTypeMapping(Abstract.class, AbstractImpl.class); mapper = new ObjectMapper() .registerModule(mod); Abstract a = mapper.readValue("{}", Abstract.class); assertNotNull(a); } } TestCustomEnumKeyDeserializer.java000066400000000000000000000235141325620701100406130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.io.File; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import com.fasterxml.jackson.databind.node.ObjectNode; @SuppressWarnings("serial") public class TestCustomEnumKeyDeserializer extends BaseMapTest { @JsonSerialize(using = TestEnumSerializer.class, keyUsing = TestEnumKeySerializer.class) @JsonDeserialize(using = TestEnumDeserializer.class, keyUsing = TestEnumKeyDeserializer.class) public enum TestEnumMixin { } enum KeyEnum { replacements, rootDirectory, licenseString } enum TestEnum { RED("red"), GREEN("green"); private final String code; TestEnum(String code) { this.code = code; } public static TestEnum lookup(String lower) { for (TestEnum item : values()) { if (item.code().equals(lower)) { return item; } } throw new IllegalArgumentException("Invalid code " + lower); } public String code() { return code; } } static class TestEnumSerializer extends JsonSerializer { @Override public void serialize(TestEnum languageCode, JsonGenerator g, SerializerProvider serializerProvider) throws IOException { g.writeString(languageCode.code()); } @Override public Class handledType() { return TestEnum.class; } } static class TestEnumKeyDeserializer extends KeyDeserializer { @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { try { return TestEnum.lookup(key); } catch (IllegalArgumentException e) { return ctxt.handleWeirdKey(TestEnum.class, key, "Unknown code"); } } } static class TestEnumDeserializer extends StdDeserializer { public TestEnumDeserializer() { super(TestEnum.class); } @Override public TestEnum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String code = p.getText(); try { return TestEnum.lookup(code); } catch (IllegalArgumentException e) { throw InvalidFormatException.from(p, "Undefined ISO-639 language code", code, TestEnum.class); } } } static class TestEnumKeySerializer extends JsonSerializer { @Override public void serialize(TestEnum test, JsonGenerator g, SerializerProvider serializerProvider) throws IOException { g.writeFieldName(test.code()); } @Override public Class handledType() { return TestEnum.class; } } static class Bean { private File rootDirectory; private String licenseString; private Map> replacements; public File getRootDirectory() { return rootDirectory; } public void setRootDirectory(File rootDirectory) { this.rootDirectory = rootDirectory; } public String getLicenseString() { return licenseString; } public void setLicenseString(String licenseString) { this.licenseString = licenseString; } public Map> getReplacements() { return replacements; } public void setReplacements(Map> replacements) { this.replacements = replacements; } } static class TestEnumModule extends SimpleModule { public TestEnumModule() { super(Version.unknownVersion()); } @Override public void setupModule(SetupContext context) { context.setMixInAnnotations(TestEnum.class, TestEnumMixin.class); SimpleSerializers keySerializers = new SimpleSerializers(); keySerializers.addSerializer(new TestEnumKeySerializer()); context.addKeySerializers(keySerializers); } } // for [databind#1441] enum SuperTypeEnum { FOO; } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type", defaultImpl = SuperType.class) static class SuperType { public Map someMap; } /* /********************************************************** /* Test methods /********************************************************** */ // Test passing with the fix public void testWithEnumKeys() throws Exception { ObjectMapper plainObjectMapper = new ObjectMapper(); JsonNode tree = plainObjectMapper.readTree(aposToQuotes("{'red' : [ 'a', 'b']}")); ObjectMapper fancyObjectMapper = new ObjectMapper().registerModule(new TestEnumModule()); // this line is might throw with Jackson 2.6.2. Map> map = fancyObjectMapper.convertValue(tree, new TypeReference>>() { } ); assertNotNull(map); } // and another still failing // NOTE: temporarily named as non-test to ignore it; JsonIgnore doesn't work for some reason // public void testWithTree749() throws Exception public void withTree749() throws Exception { ObjectMapper mapper = new ObjectMapper().registerModule(new TestEnumModule()); Map inputMap = new LinkedHashMap(); Map> replacements = new LinkedHashMap>(); Map reps = new LinkedHashMap(); reps.put("1", "one"); replacements.put(TestEnum.GREEN, reps); inputMap.put(KeyEnum.replacements, replacements); JsonNode tree = mapper.valueToTree(inputMap); ObjectNode ob = (ObjectNode) tree; JsonNode inner = ob.get("replacements"); String firstFieldName = inner.fieldNames().next(); assertEquals("green", firstFieldName); } // [databind#1441] public void testCustomEnumKeySerializerWithPolymorphic() throws IOException { SimpleModule simpleModule = new SimpleModule(); simpleModule.addDeserializer(SuperTypeEnum.class, new JsonDeserializer() { @Override public SuperTypeEnum deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException { return SuperTypeEnum.valueOf(p.getText()); } }); ObjectMapper mapper = new ObjectMapper() .registerModule(simpleModule); SuperType superType = mapper.readValue("{\"someMap\": {\"FOO\": \"bar\"}}", SuperType.class); assertEquals("Deserialized someMap.FOO should equal bar", "bar", superType.someMap.get(SuperTypeEnum.FOO)); } // [databind#1445] @SuppressWarnings({ "unchecked", "rawtypes" }) public void testCustomEnumValueAndKeyViaModifier() throws IOException { SimpleModule module = new SimpleModule(); module.setDeserializerModifier(new BeanDeserializerModifier() { @Override public JsonDeserializer modifyEnumDeserializer(DeserializationConfig config, final JavaType type, BeanDescription beanDesc, final JsonDeserializer deserializer) { return new JsonDeserializer() { @Override public Enum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Class rawClass = (Class>) type.getRawClass(); final String str = p.getValueAsString().toLowerCase(); return KeyEnum.valueOf(rawClass, str); } }; } @Override public KeyDeserializer modifyKeyDeserializer(DeserializationConfig config, final JavaType type, KeyDeserializer deserializer) { if (!type.isEnumType()) { return deserializer; } return new KeyDeserializer() { @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { Class rawClass = (Class>) type.getRawClass(); return Enum.valueOf(rawClass, key.toLowerCase()); } }; } }); ObjectMapper mapper = new ObjectMapper() .registerModule(module); // First, enum value as is KeyEnum key = mapper.readValue(quote(KeyEnum.replacements.name().toUpperCase()), KeyEnum.class); assertSame(KeyEnum.replacements, key); // and then as key EnumMap map = mapper.readValue( aposToQuotes("{'REPlaceMENTS':'foobar'}"), new TypeReference>() { }); assertEquals(1, map.size()); assertSame(KeyEnum.replacements, map.keySet().iterator().next()); } } TestDuplicateRegistration.java000066400000000000000000000033401325620701100400000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; public class TestDuplicateRegistration extends BaseMapTest { static class MyModule extends com.fasterxml.jackson.databind.Module { public int regCount; public MyModule() { super(); } @Override public String getModuleName() { return "TestModule"; } @Override public Version version() { return Version.unknownVersion(); } @Override public void setupModule(SetupContext context) { ++regCount; } } public void testDuplicateRegistration() throws Exception { // by default, duplicate registration should be prevented ObjectMapper mapper = new ObjectMapper(); assertTrue(mapper.isEnabled(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS)); MyModule module = new MyModule(); mapper.registerModule(module); mapper.registerModule(module); mapper.registerModule(module); assertEquals(1, module.regCount); // but may be allowed by changing setting mapper.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS); mapper.registerModule(module); assertEquals(2, module.regCount); // and ditto for a new instance ObjectMapper mapper2 = new ObjectMapper(); mapper2.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS); MyModule module2 = new MyModule(); mapper.registerModule(module2); mapper.registerModule(module2); mapper.registerModule(module2); assertEquals(3, module2.regCount); } } TestKeyDeserializers.java000066400000000000000000000024751325620701100367610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.util.Map; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class TestKeyDeserializers extends BaseMapTest { static class FooKeyDeserializer extends KeyDeserializer { @Override public Foo deserializeKey(String key, DeserializationContext ctxt) { return new Foo(key); } } static class Foo { public String value; public Foo(String v) { value = v; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testKeyDeserializers() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); mod.addKeyDeserializer(Foo.class, new FooKeyDeserializer()); mapper.registerModule(mod); Map map = mapper.readValue("{\"a\":3}", new TypeReference>() {} ); assertNotNull(map); assertEquals(1, map.size()); Foo foo = map.keySet().iterator().next(); assertEquals("a", foo.value); } } TestTypeModifierNameResolution.java000066400000000000000000000031371325620701100407640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.type.TypeBindings; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.type.TypeModifier; import java.lang.reflect.Type; public class TestTypeModifierNameResolution extends BaseMapTest { interface MyType { String getData(); void setData(String data); } static class MyTypeImpl implements MyType { private String data; @Override public String getData() { return data; } @Override public void setData(String data) { this.data = data; } } static class CustomTypeModifier extends TypeModifier { @Override public JavaType modifyType(JavaType type, Type jdkType, TypeBindings context, TypeFactory typeFactory) { if (type.getRawClass().equals(MyTypeImpl.class)) { return typeFactory.constructType(MyType.class); } return type; } } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT) public interface Mixin { } // Expect that the TypeModifier kicks in when the type id is written. public void testTypeModiferNameResolution() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new CustomTypeModifier())); mapper.addMixIn(MyType.class, Mixin.class); MyType obj = new MyTypeImpl(); obj.setData("something"); String s = mapper.writer().writeValueAsString(obj); assertTrue(s.startsWith("{\"TestTypeModifierNameResolution$MyType\":")); } }TestTypeModifiers.java000066400000000000000000000266161325620701100362710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/modulepackage com.fasterxml.jackson.databind.module; import java.io.IOException; import java.lang.reflect.Type; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.module.SimpleDeserializers; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.Serializers; import com.fasterxml.jackson.databind.type.*; @SuppressWarnings("serial") public class TestTypeModifiers extends BaseMapTest { /* /********************************************************** /* Helper classes /********************************************************** */ static class ModifierModule extends SimpleModule { public ModifierModule() { super("test", Version.unknownVersion()); } @Override public void setupModule(SetupContext context) { context.addSerializers(new Serializers.Base() { @Override public JsonSerializer findMapLikeSerializer(SerializationConfig config, MapLikeType type, BeanDescription beanDesc, JsonSerializer keySerializer, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { if (MapMarker.class.isAssignableFrom(type.getRawClass())) { return new MyMapSerializer(keySerializer, elementValueSerializer); } return null; } @Override public JsonSerializer findCollectionLikeSerializer(SerializationConfig config, CollectionLikeType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { if (CollectionMarker.class.isAssignableFrom(type.getRawClass())) { return new MyCollectionSerializer(); } return null; } }); context.addDeserializers(new SimpleDeserializers() { @Override public JsonDeserializer findCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { if (CollectionMarker.class.isAssignableFrom(type.getRawClass())) { return new MyCollectionDeserializer(); } return null; } @Override public JsonDeserializer findMapLikeDeserializer(MapLikeType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { if (MapMarker.class.isAssignableFrom(type.getRawClass())) { return new MyMapDeserializer(); } return null; } }); } } static class XxxSerializer extends JsonSerializer { @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeString("xxx:"+value); } } interface MapMarker { public K getKey(); public V getValue(); } interface CollectionMarker { public V getValue(); } @JsonSerialize(contentUsing=XxxSerializer.class) static class MyMapLikeType implements MapMarker { public String key; public int value; public MyMapLikeType() { } public MyMapLikeType(String k, int v) { key = k; value = v; } @Override public String getKey() { return key; } @Override public Integer getValue() { return value; } } static class MyCollectionLikeType implements CollectionMarker { public int value; public MyCollectionLikeType() { } public MyCollectionLikeType(int v) { value = v; } @Override public Integer getValue() { return value; } } static class MyMapSerializer extends JsonSerializer> { protected final JsonSerializer _keySerializer; protected final JsonSerializer _valueSerializer; public MyMapSerializer(JsonSerializer keySer, JsonSerializer valueSer) { _keySerializer = keySer; _valueSerializer = valueSer; } @Override public void serialize(MapMarker value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeStartObject(); if (_keySerializer == null) { jgen.writeFieldName((String) value.getKey()); } else { _keySerializer.serialize(value.getKey(), jgen, provider); } if (_valueSerializer == null) { jgen.writeNumber(((Number) value.getValue()).intValue()); } else { _valueSerializer.serialize(value.getValue(), jgen, provider); } jgen.writeEndObject(); } } static class MyMapDeserializer extends JsonDeserializer> { @Override public MapMarker deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { if (jp.getCurrentToken() != JsonToken.START_OBJECT) throw new IOException("Wrong token: "+jp.getCurrentToken()); if (jp.nextToken() != JsonToken.FIELD_NAME) throw new IOException("Wrong token: "+jp.getCurrentToken()); String key = jp.getCurrentName(); if (jp.nextToken() != JsonToken.VALUE_NUMBER_INT) throw new IOException("Wrong token: "+jp.getCurrentToken()); int value = jp.getIntValue(); if (jp.nextToken() != JsonToken.END_OBJECT) throw new IOException("Wrong token: "+jp.getCurrentToken()); return new MyMapLikeType(key, value); } } static class MyCollectionSerializer extends JsonSerializer { @Override public void serialize(MyCollectionLikeType value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeStartArray(); jgen.writeNumber(value.value); jgen.writeEndArray(); } } static class MyCollectionDeserializer extends JsonDeserializer { @Override public MyCollectionLikeType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { if (jp.getCurrentToken() != JsonToken.START_ARRAY) throw new IOException("Wrong token: "+jp.getCurrentToken()); if (jp.nextToken() != JsonToken.VALUE_NUMBER_INT) throw new IOException("Wrong token: "+jp.getCurrentToken()); int value = jp.getIntValue(); if (jp.nextToken() != JsonToken.END_ARRAY) throw new IOException("Wrong token: "+jp.getCurrentToken()); return new MyCollectionLikeType(value); } } static class MyTypeModifier extends TypeModifier { @Override public JavaType modifyType(JavaType type, Type jdkType, TypeBindings bindings, TypeFactory typeFactory) { if (!type.isContainerType()) { // not 100% required, minor optimization Class raw = type.getRawClass(); if (raw == MapMarker.class) { return MapLikeType.upgradeFrom(type, type.containedType(0), type.containedType(1)); } if (raw == CollectionMarker.class) { return CollectionLikeType.upgradeFrom(type, type.containedType(0)); } } return type; } } /* /********************************************************** /* Unit tests /********************************************************** */ /** * Basic test for ensuring that we can get "xxx-like" types recognized. */ public void testMapLikeTypeConstruction() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); JavaType type = mapper.constructType(MyMapLikeType.class); assertTrue(type.isMapLikeType()); // also, must have resolved type info JavaType param = ((MapLikeType) type).getKeyType(); assertNotNull(param); assertSame(String.class, param.getRawClass()); param = ((MapLikeType) type).getContentType(); assertNotNull(param); assertSame(Integer.class, param.getRawClass()); } public void testCollectionLikeTypeConstruction() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); JavaType type = mapper.constructType(MyCollectionLikeType.class); assertTrue(type.isCollectionLikeType()); JavaType param = ((CollectionLikeType) type).getContentType(); assertNotNull(param); assertSame(Integer.class, param.getRawClass()); } public void testCollectionLikeSerialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); mapper.registerModule(new ModifierModule()); assertEquals("[19]", mapper.writeValueAsString(new MyCollectionLikeType(19))); } public void testMapLikeSerialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); mapper.registerModule(new ModifierModule()); // Due to custom serializer, should get: assertEquals("{\"x\":\"xxx:3\"}", mapper.writeValueAsString(new MyMapLikeType("x", 3))); } public void testCollectionLikeDeserialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); mapper.registerModule(new ModifierModule()); // !!! TBI MyMapLikeType result = mapper.readValue("{\"a\":13}", MyMapLikeType.class); assertEquals("a", result.getKey()); assertEquals(Integer.valueOf(13), result.getValue()); } public void testMapLikeDeserialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); mapper.registerModule(new ModifierModule()); // !!! TBI MyCollectionLikeType result = mapper.readValue("[-37]", MyCollectionLikeType.class); assertEquals(Integer.valueOf(-37), result.getValue()); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/node/000077500000000000000000000000001325620701100315075ustar00rootroot00000000000000ArrayNodeTest.java000066400000000000000000000251461325620701100350270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.TextNode; import com.fasterxml.jackson.databind.node.TreeTraversingParser; /** * Additional tests for {@link ArrayNode} container class. */ public class ArrayNodeTest extends BaseMapTest { public void testDirectCreation() throws IOException { ArrayNode n = new ArrayNode(JsonNodeFactory.instance); assertStandardEquals(n); assertFalse(n.elements().hasNext()); assertFalse(n.fieldNames().hasNext()); TextNode text = TextNode.valueOf("x"); n.add(text); assertEquals(1, n.size()); assertFalse(0 == n.hashCode()); assertTrue(n.elements().hasNext()); // no field names for arrays assertFalse(n.fieldNames().hasNext()); assertNull(n.get("x")); // not used with arrays assertTrue(n.path("x").isMissingNode()); assertSame(text, n.get(0)); // single element, so: assertFalse(n.has("field")); assertFalse(n.hasNonNull("field")); assertTrue(n.has(0)); assertTrue(n.hasNonNull(0)); assertFalse(n.has(1)); assertFalse(n.hasNonNull(1)); // add null node too n.add((JsonNode) null); assertEquals(2, n.size()); assertTrue(n.get(1).isNull()); assertTrue(n.has(1)); assertFalse(n.hasNonNull(1)); // change to text n.set(1, text); assertSame(text, n.get(1)); n.set(0, null); assertTrue(n.get(0).isNull()); // and finally, clear it all ArrayNode n2 = new ArrayNode(JsonNodeFactory.instance); n2.add("foobar"); assertFalse(n.equals(n2)); n.addAll(n2); assertEquals(3, n.size()); assertFalse(n.get(0).isTextual()); assertNotNull(n.remove(0)); assertEquals(2, n.size()); assertTrue(n.get(0).isTextual()); assertNull(n.remove(-1)); assertNull(n.remove(100)); assertEquals(2, n.size()); ArrayList nodes = new ArrayList(); nodes.add(text); n.addAll(nodes); assertEquals(3, n.size()); assertNull(n.get(10000)); assertNull(n.remove(-4)); TextNode text2 = TextNode.valueOf("b"); n.insert(0, text2); assertEquals(4, n.size()); assertSame(text2, n.get(0)); assertNotNull(n.addArray()); assertEquals(5, n.size()); n.addPOJO("foo"); assertEquals(6, n.size()); // Try serializing it for fun, too... JsonGenerator g = objectMapper().getFactory().createGenerator(new StringWriter()); n.serialize(g, null); g.close(); n.removeAll(); assertEquals(0, n.size()); } public void testDirectCreation2() throws IOException { JsonNodeFactory f = objectMapper().getNodeFactory(); ArrayList list = new ArrayList<>(); list.add(f.booleanNode(true)); list.add(f.textNode("foo")); ArrayNode n = new ArrayNode(f, list); assertEquals(2, n.size()); assertTrue(n.get(0).isBoolean()); assertTrue(n.get(1).isTextual()); // also, should fail with invalid set attempt try { n.set(2, f.nullNode()); fail("Should not pass"); } catch (IndexOutOfBoundsException e) { verifyException(e, "illegal index"); } n.insert(1, (String) null); assertEquals(3, n.size()); assertTrue(n.get(0).isBoolean()); assertTrue(n.get(1).isNull()); assertTrue(n.get(2).isTextual()); n.removeAll(); n.insert(0, (JsonNode) null); assertEquals(1, n.size()); assertTrue(n.get(0).isNull()); } public void testArrayViaMapper() throws Exception { final String JSON = "[[[-0.027512,51.503221],[-0.008497,51.503221],[-0.008497,51.509744],[-0.027512,51.509744]]]"; JsonNode n = objectMapper().readTree(JSON); assertNotNull(n); assertTrue(n.isArray()); ArrayNode an = (ArrayNode) n; assertEquals(1, an.size()); ArrayNode an2 = (ArrayNode) n.get(0); assertTrue(an2.isArray()); assertEquals(4, an2.size()); } public void testAdds() { ArrayNode n = new ArrayNode(JsonNodeFactory.instance); assertNotNull(n.addArray()); assertNotNull(n.addObject()); n.addPOJO("foobar"); n.add(1); n.add(1L); n.add(0.5); n.add(0.5f); n.add(new BigDecimal("0.2")); n.add(BigInteger.TEN); assertEquals(9, n.size()); assertNotNull(n.insertArray(0)); assertNotNull(n.insertObject(0)); n.insertPOJO(2, "xxx"); assertEquals(12, n.size()); n.insert(0, BigInteger.ONE); n.insert(0, new BigDecimal("0.1")); assertEquals(14, n.size()); } public void testNullAdds() { JsonNodeFactory f = objectMapper().getNodeFactory(); ArrayNode array = f.arrayNode(14); array.add((BigDecimal) null); array.add((BigInteger) null); array.add((Boolean) null); array.add((byte[]) null); array.add((Double) null); array.add((Float) null); array.add((Integer) null); array.add((JsonNode) null); array.add((Long) null); array.add((String) null); assertEquals(10, array.size()); for (JsonNode node : array) { assertTrue(node.isNull()); } } public void testNullInserts() { JsonNodeFactory f = objectMapper().getNodeFactory(); ArrayNode array = f.arrayNode(3); array.insert(0, (BigDecimal) null); array.insert(0, (BigInteger) null); array.insert(0, (Boolean) null); // Offsets out of the range are fine; negative become 0; // super big just add at the end array.insert(-56, (byte[]) null); array.insert(0, (Double) null); array.insert(200, (Float) null); array.insert(0, (Integer) null); array.insert(1, (JsonNode) null); array.insert(array.size(), (Long) null); array.insert(1, (String) null); assertEquals(10, array.size()); for (JsonNode node : array) { assertTrue(node.isNull()); } } public void testNullChecking() { ArrayNode a1 = JsonNodeFactory.instance.arrayNode(); ArrayNode a2 = JsonNodeFactory.instance.arrayNode(); // used to throw NPE before fix: a1.addAll(a2); assertEquals(0, a1.size()); assertEquals(0, a2.size()); a2.addAll(a1); assertEquals(0, a1.size()); assertEquals(0, a2.size()); } public void testNullChecking2() { ObjectMapper mapper = new ObjectMapper(); ArrayNode src = mapper.createArrayNode(); ArrayNode dest = mapper.createArrayNode(); src.add("element"); dest.addAll(src); } public void testParser() throws Exception { ArrayNode n = new ArrayNode(JsonNodeFactory.instance); n.add(123); TreeTraversingParser p = new TreeTraversingParser(n, null); p.setCodec(null); assertNull(p.getCodec()); assertNotNull(p.getParsingContext()); assertNotNull(p.getTokenLocation()); assertNotNull(p.getCurrentLocation()); assertNull(p.getEmbeddedObject()); assertNull(p.currentNode()); //assertNull(p.getNumberType()); assertToken(JsonToken.START_ARRAY, p.nextToken()); p.skipChildren(); assertToken(JsonToken.END_ARRAY, p.getCurrentToken()); p.close(); p = new TreeTraversingParser(n, null); p.nextToken(); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(JsonParser.NumberType.INT, p.getNumberType()); p.close(); } public void testArrayNodeEquality() { ArrayNode n1 = new ArrayNode(null); ArrayNode n2 = new ArrayNode(null); assertTrue(n1.equals(n2)); assertTrue(n2.equals(n1)); n1.add(TextNode.valueOf("Test")); assertFalse(n1.equals(n2)); assertFalse(n2.equals(n1)); n2.add(TextNode.valueOf("Test")); assertTrue(n1.equals(n2)); assertTrue(n2.equals(n1)); } public void testSimpleArray() throws Exception { ArrayNode result = objectMapper().createArrayNode(); assertTrue(result.isArray()); assertType(result, ArrayNode.class); assertFalse(result.isObject()); assertFalse(result.isNumber()); assertFalse(result.isNull()); assertFalse(result.isTextual()); // and let's add stuff... result.add(false); result.insertNull(0); // should be equal to itself no matter what assertEquals(result, result); assertFalse(result.equals(null)); // but not to null // plus see that we can access stuff assertEquals(NullNode.instance, result.path(0)); assertEquals(NullNode.instance, result.get(0)); assertEquals(BooleanNode.FALSE, result.path(1)); assertEquals(BooleanNode.FALSE, result.get(1)); assertEquals(2, result.size()); assertNull(result.get(-1)); assertNull(result.get(2)); JsonNode missing = result.path(2); assertTrue(missing.isMissingNode()); assertTrue(result.path(-100).isMissingNode()); // then construct and compare ArrayNode array2 = objectMapper().createArrayNode(); array2.addNull(); array2.add(false); assertEquals(result, array2); // plus remove entries JsonNode rm1 = array2.remove(0); assertEquals(NullNode.instance, rm1); assertEquals(1, array2.size()); assertEquals(BooleanNode.FALSE, array2.get(0)); assertFalse(result.equals(array2)); JsonNode rm2 = array2.remove(0); assertEquals(BooleanNode.FALSE, rm2); assertEquals(0, array2.size()); } public void testSimpleMismatch() throws Exception { ObjectMapper mapper = objectMapper(); try { mapper.readValue(" 123 ", ArrayNode.class); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "out of VALUE_NUMBER_INT token"); } } } JsonNodeFactoryTest.java000066400000000000000000000017061325620701100362060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.databind.*; public class JsonNodeFactoryTest extends NodeTestBase { private final ObjectMapper MAPPER = objectMapper(); public void testSimpleCreation() { JsonNodeFactory f = MAPPER.getNodeFactory(); JsonNode n; n = f.numberNode((byte) 4); assertTrue(n.isInt()); assertEquals(4, n.intValue()); assertTrue(f.numberNode((Byte) null).isNull()); assertTrue(f.numberNode((Short) null).isNull()); assertTrue(f.numberNode((Integer) null).isNull()); assertTrue(f.numberNode((Long) null).isNull()); assertTrue(f.numberNode((Float) null).isNull()); assertTrue(f.numberNode((Double) null).isNull()); assertTrue(f.numberNode((BigDecimal) null).isNull()); assertTrue(f.numberNode((BigInteger) null).isNull()); } } NodeTestBase.java000066400000000000000000000016751325620701100346240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.BaseMapTest; abstract class NodeTestBase extends BaseMapTest { protected void assertNodeNumbersForNonNumeric(JsonNode n) { assertFalse(n.isNumber()); assertEquals(0, n.asInt()); assertEquals(-42, n.asInt(-42)); assertEquals(0, n.asLong()); assertEquals(12345678901L, n.asLong(12345678901L)); assertEquals(0.0, n.asDouble()); assertEquals(-19.25, n.asDouble(-19.25)); } protected void assertNodeNumbers(JsonNode n, int expInt, double expDouble) { assertEquals(expInt, n.asInt()); assertEquals(expInt, n.asInt(-42)); assertEquals((long) expInt, n.asLong()); assertEquals((long) expInt, n.asLong(19L)); assertEquals(expDouble, n.asDouble()); assertEquals(expDouble, n.asDouble(-19.25)); } } NotANumberConversionTest.java000066400000000000000000000024561325620701100372220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.math.BigDecimal; import com.fasterxml.jackson.databind.*; public class NotANumberConversionTest extends BaseMapTest { private final ObjectMapper m = new ObjectMapper(); { m.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS); } public void testBigDecimalWithNaN() throws Exception { JsonNode tree = m.valueToTree(new DoubleWrapper(Double.NaN)); assertNotNull(tree); String json = m.writeValueAsString(tree); assertNotNull(json); tree = m.valueToTree(new DoubleWrapper(Double.NEGATIVE_INFINITY)); assertNotNull(tree); json = m.writeValueAsString(tree); assertNotNull(json); tree = m.valueToTree(new DoubleWrapper(Double.POSITIVE_INFINITY)); assertNotNull(tree); json = m.writeValueAsString(tree); assertNotNull(json); } // for [databind#1315]: no accidental coercion to DoubleNode public void testBigDecimalWithoutNaN() throws Exception { BigDecimal input = new BigDecimal(Double.MIN_VALUE).divide(new BigDecimal(10L)); JsonNode tree = m.readTree(input.toString()); assertTrue(tree.isBigDecimal()); BigDecimal output = tree.decimalValue(); assertEquals(input, output); } } NumberNodesTest.java000066400000000000000000000404471325620701100353650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.*; /** * Basic tests for {@link JsonNode} implementations that * contain numeric values. */ public class NumberNodesTest extends NodeTestBase { private final ObjectMapper MAPPER = objectMapper(); public void testShort() { ShortNode n = ShortNode.valueOf((short) 1); assertStandardEquals(n); assertTrue(0 != n.hashCode()); assertEquals(JsonToken.VALUE_NUMBER_INT, n.asToken()); assertEquals(JsonParser.NumberType.INT, n.numberType()); // should be SHORT assertEquals(1, n.intValue()); assertEquals(1L, n.longValue()); assertEquals(BigDecimal.ONE, n.decimalValue()); assertEquals(BigInteger.ONE, n.bigIntegerValue()); assertEquals("1", n.asText()); assertNodeNumbers(n, 1, 1.0); assertTrue(ShortNode.valueOf((short) 0).canConvertToInt()); assertTrue(ShortNode.valueOf(Short.MAX_VALUE).canConvertToInt()); assertTrue(ShortNode.valueOf(Short.MIN_VALUE).canConvertToInt()); assertTrue(ShortNode.valueOf((short) 0).canConvertToLong()); assertTrue(ShortNode.valueOf(Short.MAX_VALUE).canConvertToLong()); assertTrue(ShortNode.valueOf(Short.MIN_VALUE).canConvertToLong()); } public void testIntViaMapper() throws Exception { int value = -90184; JsonNode result = MAPPER.readTree(String.valueOf(value)); assertTrue(result.isNumber()); assertTrue(result.isIntegralNumber()); assertTrue(result.isInt()); assertType(result, IntNode.class); assertFalse(result.isLong()); assertFalse(result.isFloatingPointNumber()); assertFalse(result.isDouble()); assertFalse(result.isNull()); assertFalse(result.isTextual()); assertFalse(result.isMissingNode()); assertEquals(value, result.numberValue().intValue()); assertEquals(value, result.intValue()); assertEquals(String.valueOf(value), result.asText()); assertEquals((double) value, result.doubleValue()); assertEquals((long) value, result.longValue()); // also, equality should work ok assertEquals(result, IntNode.valueOf(value)); } public void testInt() { IntNode n = IntNode.valueOf(1); assertStandardEquals(n); assertTrue(0 != n.hashCode()); assertEquals(JsonToken.VALUE_NUMBER_INT, n.asToken()); assertEquals(JsonParser.NumberType.INT, n.numberType()); assertEquals(1, n.intValue()); assertEquals(1L, n.longValue()); assertEquals(BigDecimal.ONE, n.decimalValue()); assertEquals(BigInteger.ONE, n.bigIntegerValue()); assertEquals("1", n.asText()); // 2.4 assertEquals("1", n.asText("foo")); assertNodeNumbers(n, 1, 1.0); assertTrue(IntNode.valueOf(0).canConvertToInt()); assertTrue(IntNode.valueOf(Integer.MAX_VALUE).canConvertToInt()); assertTrue(IntNode.valueOf(Integer.MIN_VALUE).canConvertToInt()); assertTrue(IntNode.valueOf(0).canConvertToLong()); assertTrue(IntNode.valueOf(Integer.MAX_VALUE).canConvertToLong()); assertTrue(IntNode.valueOf(Integer.MIN_VALUE).canConvertToLong()); } public void testLong() { LongNode n = LongNode.valueOf(1L); assertStandardEquals(n); assertTrue(0 != n.hashCode()); assertEquals(JsonToken.VALUE_NUMBER_INT, n.asToken()); assertEquals(JsonParser.NumberType.LONG, n.numberType()); assertEquals(1, n.intValue()); assertEquals(1L, n.longValue()); assertEquals(BigDecimal.ONE, n.decimalValue()); assertEquals(BigInteger.ONE, n.bigIntegerValue()); assertEquals("1", n.asText()); assertNodeNumbers(n, 1, 1.0); // ok if contains small enough value assertTrue(LongNode.valueOf(0).canConvertToInt()); assertTrue(LongNode.valueOf(Integer.MAX_VALUE).canConvertToInt()); assertTrue(LongNode.valueOf(Integer.MIN_VALUE).canConvertToInt()); // but not in other cases assertFalse(LongNode.valueOf(1L + Integer.MAX_VALUE).canConvertToInt()); assertFalse(LongNode.valueOf(-1L + Integer.MIN_VALUE).canConvertToInt()); assertTrue(LongNode.valueOf(0L).canConvertToLong()); assertTrue(LongNode.valueOf(Long.MAX_VALUE).canConvertToLong()); assertTrue(LongNode.valueOf(Long.MIN_VALUE).canConvertToLong()); } public void testLongViaMapper() throws Exception { // need to use something being 32-bit value space long value = 12345678L << 32; JsonNode result = MAPPER.readTree(String.valueOf(value)); assertTrue(result.isNumber()); assertTrue(result.isIntegralNumber()); assertTrue(result.isLong()); assertType(result, LongNode.class); assertFalse(result.isInt()); assertFalse(result.isFloatingPointNumber()); assertFalse(result.isDouble()); assertFalse(result.isNull()); assertFalse(result.isTextual()); assertFalse(result.isMissingNode()); assertEquals(value, result.numberValue().longValue()); assertEquals(value, result.longValue()); assertEquals(String.valueOf(value), result.asText()); assertEquals((double) value, result.doubleValue()); // also, equality should work ok assertEquals(result, LongNode.valueOf(value)); } public void testDouble() throws Exception { DoubleNode n = DoubleNode.valueOf(0.25); assertStandardEquals(n); assertTrue(0 != n.hashCode()); assertEquals(JsonToken.VALUE_NUMBER_FLOAT, n.asToken()); assertEquals(JsonParser.NumberType.DOUBLE, n.numberType()); assertEquals(0, n.intValue()); assertEquals(0.25, n.doubleValue()); assertNotNull(n.decimalValue()); assertEquals(BigInteger.ZERO, n.bigIntegerValue()); assertEquals("0.25", n.asText()); assertNodeNumbers(DoubleNode.valueOf(4.5), 4, 4.5); assertTrue(DoubleNode.valueOf(0).canConvertToInt()); assertTrue(DoubleNode.valueOf(Integer.MAX_VALUE).canConvertToInt()); assertTrue(DoubleNode.valueOf(Integer.MIN_VALUE).canConvertToInt()); assertFalse(DoubleNode.valueOf(1L + Integer.MAX_VALUE).canConvertToInt()); assertFalse(DoubleNode.valueOf(-1L + Integer.MIN_VALUE).canConvertToInt()); assertTrue(DoubleNode.valueOf(0L).canConvertToLong()); assertTrue(DoubleNode.valueOf(Long.MAX_VALUE).canConvertToLong()); assertTrue(DoubleNode.valueOf(Long.MIN_VALUE).canConvertToLong()); JsonNode num = objectMapper().readTree(" -0.0"); assertTrue(num.isDouble()); n = (DoubleNode) num; assertEquals(-0.0, n.doubleValue()); assertEquals("-0.0", String.valueOf(n.doubleValue())); } public void testDoubleViaMapper() throws Exception { double value = 3.04; JsonNode result = MAPPER.readTree(String.valueOf(value)); assertTrue(result.isNumber()); assertFalse(result.isNull()); assertType(result, DoubleNode.class); assertTrue(result.isFloatingPointNumber()); assertTrue(result.isDouble()); assertFalse(result.isInt()); assertFalse(result.isLong()); assertFalse(result.isIntegralNumber()); assertFalse(result.isTextual()); assertFalse(result.isMissingNode()); assertEquals(value, result.doubleValue()); assertEquals(value, result.numberValue().doubleValue()); assertEquals((int) value, result.intValue()); assertEquals((long) value, result.longValue()); assertEquals(String.valueOf(value), result.asText()); // also, equality should work ok assertEquals(result, DoubleNode.valueOf(value)); } // @since 2.2 public void testFloat() { FloatNode n = FloatNode.valueOf(0.45f); assertStandardEquals(n); assertTrue(0 != n.hashCode()); assertEquals(JsonToken.VALUE_NUMBER_FLOAT, n.asToken()); assertEquals(JsonParser.NumberType.FLOAT, n.numberType()); assertEquals(0, n.intValue()); // NOTE: conversion to double NOT as simple as with exact numbers like 0.25: assertEquals(0.45f, n.floatValue()); assertEquals("0.45", n.asText()); // so; as double we'll get more complex number; however, should round-trip // to something that gets printed the same way. But not exact value, alas, hence: assertEquals("0.45", String.valueOf((float) n.doubleValue())); assertNotNull(n.decimalValue()); // possibly surprisingly, however, this will produce same output: assertEquals(BigInteger.ZERO, n.bigIntegerValue()); assertEquals("0.45", n.asText()); // 1.6: assertNodeNumbers(FloatNode.valueOf(4.5f), 4, 4.5f); assertTrue(FloatNode.valueOf(0).canConvertToInt()); assertTrue(FloatNode.valueOf(Integer.MAX_VALUE).canConvertToInt()); assertTrue(FloatNode.valueOf(Integer.MIN_VALUE).canConvertToInt()); // rounding errors if we just add/sub 1... so: assertFalse(FloatNode.valueOf(1000L + Integer.MAX_VALUE).canConvertToInt()); assertFalse(FloatNode.valueOf(-1000L + Integer.MIN_VALUE).canConvertToInt()); assertTrue(FloatNode.valueOf(0L).canConvertToLong()); assertTrue(FloatNode.valueOf(Integer.MAX_VALUE).canConvertToLong()); assertTrue(FloatNode.valueOf(Integer.MIN_VALUE).canConvertToLong()); } public void testDecimalNode() throws Exception { DecimalNode n = DecimalNode.valueOf(BigDecimal.ONE); assertStandardEquals(n); assertTrue(n.equals(new DecimalNode(BigDecimal.ONE))); assertEquals(JsonToken.VALUE_NUMBER_FLOAT, n.asToken()); assertEquals(JsonParser.NumberType.BIG_DECIMAL, n.numberType()); assertTrue(n.isNumber()); assertFalse(n.isIntegralNumber()); assertFalse(n.isArray()); assertTrue(n.isBigDecimal()); assertEquals(BigDecimal.ONE, n.numberValue()); assertEquals(1, n.intValue()); assertEquals(1L, n.longValue()); assertEquals(BigDecimal.ONE, n.decimalValue()); assertEquals("1", n.asText()); assertNodeNumbers(n, 1, 1.0); assertTrue(DecimalNode.valueOf(BigDecimal.ZERO).canConvertToInt()); assertTrue(DecimalNode.valueOf(BigDecimal.valueOf(Integer.MAX_VALUE)).canConvertToInt()); assertTrue(DecimalNode.valueOf(BigDecimal.valueOf(Integer.MIN_VALUE)).canConvertToInt()); assertFalse(DecimalNode.valueOf(BigDecimal.valueOf(1L + Integer.MAX_VALUE)).canConvertToInt()); assertFalse(DecimalNode.valueOf(BigDecimal.valueOf(-1L + Integer.MIN_VALUE)).canConvertToInt()); assertTrue(DecimalNode.valueOf(BigDecimal.ZERO).canConvertToLong()); assertTrue(DecimalNode.valueOf(BigDecimal.valueOf(Long.MAX_VALUE)).canConvertToLong()); assertTrue(DecimalNode.valueOf(BigDecimal.valueOf(Long.MIN_VALUE)).canConvertToLong()); // no "natural" way to get it, must construct BigDecimal value = new BigDecimal("0.1"); JsonNode result = DecimalNode.valueOf(value); assertFalse(result.isObject()); assertTrue(result.isNumber()); assertFalse(result.isIntegralNumber()); assertFalse(result.isLong()); assertType(result, DecimalNode.class); assertFalse(result.isInt()); assertTrue(result.isFloatingPointNumber()); assertTrue(result.isBigDecimal()); assertFalse(result.isDouble()); assertFalse(result.isNull()); assertFalse(result.isTextual()); assertFalse(result.isMissingNode()); assertEquals(value, result.numberValue()); assertEquals(value.toString(), result.asText()); // also, equality should work ok assertEquals(result, DecimalNode.valueOf(value)); } public void testDecimalNodeEqualsHashCode() { // We want DecimalNodes with equivalent _numeric_ values to be equal; // this is not the case for BigDecimal where "1.0" and "1" are not // equal! BigDecimal b1 = BigDecimal.ONE; BigDecimal b2 = new BigDecimal("1.0"); BigDecimal b3 = new BigDecimal("0.01e2"); BigDecimal b4 = new BigDecimal("1000e-3"); DecimalNode node1 = new DecimalNode(b1); DecimalNode node2 = new DecimalNode(b2); DecimalNode node3 = new DecimalNode(b3); DecimalNode node4 = new DecimalNode(b4); assertEquals(node1.hashCode(), node2.hashCode()); assertEquals(node2.hashCode(), node3.hashCode()); assertEquals(node3.hashCode(), node4.hashCode()); assertEquals(node1, node2); assertEquals(node2, node1); assertEquals(node2, node3); assertEquals(node3, node4); } public void testBigIntegerNode() throws Exception { BigIntegerNode n = BigIntegerNode.valueOf(BigInteger.ONE); assertStandardEquals(n); assertTrue(n.equals(new BigIntegerNode(BigInteger.ONE))); assertEquals(JsonToken.VALUE_NUMBER_INT, n.asToken()); assertEquals(JsonParser.NumberType.BIG_INTEGER, n.numberType()); assertTrue(n.isNumber()); assertTrue(n.isIntegralNumber()); assertTrue(n.isBigInteger()); assertEquals(BigInteger.ONE, n.numberValue()); assertEquals(1, n.intValue()); assertEquals(1L, n.longValue()); assertEquals(BigInteger.ONE, n.bigIntegerValue()); assertEquals("1", n.asText()); assertNodeNumbers(n, 1, 1.0); BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE); n = BigIntegerNode.valueOf(maxLong); assertEquals(Long.MAX_VALUE, n.longValue()); ObjectMapper mapper = new ObjectMapper(); JsonNode n2 = mapper.readTree(maxLong.toString()); assertEquals(Long.MAX_VALUE, n2.longValue()); // then over long limit: BigInteger beyondLong = maxLong.shiftLeft(2); // 4x max long n2 = mapper.readTree(beyondLong.toString()); assertEquals(beyondLong, n2.bigIntegerValue()); assertTrue(BigIntegerNode.valueOf(BigInteger.ZERO).canConvertToInt()); assertTrue(BigIntegerNode.valueOf(BigInteger.valueOf(Integer.MAX_VALUE)).canConvertToInt()); assertTrue(BigIntegerNode.valueOf(BigInteger.valueOf(Integer.MIN_VALUE)).canConvertToInt()); assertFalse(BigIntegerNode.valueOf(BigInteger.valueOf(1L + Integer.MAX_VALUE)).canConvertToInt()); assertFalse(BigIntegerNode.valueOf(BigInteger.valueOf(-1L + Integer.MIN_VALUE)).canConvertToInt()); assertTrue(BigIntegerNode.valueOf(BigInteger.ZERO).canConvertToLong()); assertTrue(BigIntegerNode.valueOf(BigInteger.valueOf(Long.MAX_VALUE)).canConvertToLong()); assertTrue(BigIntegerNode.valueOf(BigInteger.valueOf(Long.MIN_VALUE)).canConvertToLong()); } public void testBigDecimalAsPlain() throws Exception { ObjectMapper mapper = new ObjectMapper() .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) .enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN); final String INPUT = "{\"x\":1e2}"; final JsonNode node = mapper.readTree(INPUT); String result = mapper.writeValueAsString(node); assertEquals("{\"x\":100}", result); // also via ObjectWriter: assertEquals("{\"x\":100}", mapper.writer().writeValueAsString(node)); // and once more for [core#175]: BigDecimal bigDecimal = new BigDecimal(100); JsonNode tree = mapper.valueToTree(bigDecimal); assertEquals("100", mapper.writeValueAsString(tree)); } // Related to [databind#333] public void testCanonicalNumbers() throws Exception { JsonNodeFactory f = new JsonNodeFactory(); NumericNode n = f.numberNode(123); assertTrue(n.isInt()); n = f.numberNode(1L + Integer.MAX_VALUE); assertFalse(n.isInt()); assertTrue(n.isLong()); // 19-May-2015, tatu: Actually, no, coercion should not happen by default. // But it should be possible to change it if necessary. // but "too small" number will be 'int'... n = f.numberNode(123L); assertTrue(n.isLong()); } } ObjectNodeTest.java000066400000000000000000000340251325620701100351530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.exc.MismatchedInputException; /** * Additional tests for {@link ObjectNode} container class. */ public class ObjectNodeTest extends BaseMapTest { @JsonDeserialize(as = DataImpl.class) public interface Data { } public static class DataImpl implements Data { protected JsonNode root; @JsonCreator public DataImpl(JsonNode n) { root = n; } @JsonValue public JsonNode value() { return root; } /* public Wrapper(ObjectNode n) { root = n; } @JsonValue public ObjectNode value() { return root; } */ } static class ObNodeWrapper { @JsonInclude(JsonInclude.Include.NON_EMPTY) public ObjectNode node; public ObNodeWrapper(ObjectNode n) { node = n; } } // [databind#941] static class MyValue { private final ObjectNode object; @JsonCreator public MyValue(ObjectNode object) { this.object = object; } @JsonValue public ObjectNode getObject() { return object; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testSimpleObject() throws Exception { String JSON = "{ \"key\" : 1, \"b\" : \"x\" }"; JsonNode root = MAPPER.readTree(JSON); // basic properties first: assertFalse(root.isValueNode()); assertTrue(root.isContainerNode()); assertFalse(root.isArray()); assertTrue(root.isObject()); assertEquals(2, root.size()); Iterator it = root.iterator(); assertNotNull(it); assertTrue(it.hasNext()); JsonNode n = it.next(); assertNotNull(n); assertEquals(IntNode.valueOf(1), n); assertTrue(it.hasNext()); n = it.next(); assertNotNull(n); assertEquals(TextNode.valueOf("x"), n); assertFalse(it.hasNext()); // Ok, then, let's traverse via extended interface ObjectNode obNode = (ObjectNode) root; Iterator> fit = obNode.fields(); // we also know that LinkedHashMap is used, i.e. order preserved assertTrue(fit.hasNext()); Map.Entry en = fit.next(); assertEquals("key", en.getKey()); assertEquals(IntNode.valueOf(1), en.getValue()); assertTrue(fit.hasNext()); en = fit.next(); assertEquals("b", en.getKey()); assertEquals(TextNode.valueOf("x"), en.getValue()); // Plus: we should be able to modify the node via iterator too: fit.remove(); assertEquals(1, obNode.size()); assertEquals(IntNode.valueOf(1), root.get("key")); assertNull(root.get("b")); } // for [databind#346] public void testEmptyNodeAsValue() throws Exception { Data w = MAPPER.readValue("{}", Data.class); assertNotNull(w); } public void testBasics() { ObjectNode n = new ObjectNode(JsonNodeFactory.instance); assertStandardEquals(n); assertFalse(n.elements().hasNext()); assertFalse(n.fields().hasNext()); assertFalse(n.fieldNames().hasNext()); assertNull(n.get("a")); assertTrue(n.path("a").isMissingNode()); TextNode text = TextNode.valueOf("x"); assertSame(n, n.set("a", text)); assertEquals(1, n.size()); assertTrue(n.elements().hasNext()); assertTrue(n.fields().hasNext()); assertTrue(n.fieldNames().hasNext()); assertSame(text, n.get("a")); assertSame(text, n.path("a")); assertNull(n.get("b")); assertNull(n.get(0)); // not used with objects assertFalse(n.has(0)); assertFalse(n.hasNonNull(0)); assertTrue(n.has("a")); assertTrue(n.hasNonNull("a")); assertFalse(n.has("b")); assertFalse(n.hasNonNull("b")); ObjectNode n2 = new ObjectNode(JsonNodeFactory.instance); n2.put("b", 13); assertFalse(n.equals(n2)); n.setAll(n2); assertEquals(2, n.size()); n.set("null", (JsonNode)null); assertEquals(3, n.size()); // may be non-intuitive, but explicit nulls do exist in tree: assertTrue(n.has("null")); assertFalse(n.hasNonNull("null")); // should replace, not add n.put("null", "notReallNull"); assertEquals(3, n.size()); assertNotNull(n.remove("null")); assertEquals(2, n.size()); Map nodes = new HashMap(); nodes.put("d", text); n.setAll(nodes); assertEquals(3, n.size()); n.removeAll(); assertEquals(0, n.size()); } public void testBigNumbers() { ObjectNode n = new ObjectNode(JsonNodeFactory.instance); assertStandardEquals(n); BigInteger I = BigInteger.valueOf(3); BigDecimal DEC = new BigDecimal("0.1"); n.put("a", DEC); n.put("b", I); assertEquals(2, n.size()); assertTrue(n.path("a").isBigDecimal()); assertEquals(DEC, n.get("a").decimalValue()); assertTrue(n.path("b").isBigInteger()); assertEquals(I, n.get("b").bigIntegerValue()); } /** * Verify null handling */ public void testNullChecking() { ObjectNode o1 = JsonNodeFactory.instance.objectNode(); ObjectNode o2 = JsonNodeFactory.instance.objectNode(); // used to throw NPE before fix: o1.setAll(o2); assertEquals(0, o1.size()); assertEquals(0, o2.size()); // also: nulls should be converted to NullNodes... o1.set("x", null); JsonNode n = o1.get("x"); assertNotNull(n); assertSame(n, NullNode.instance); o1.put("str", (String) null); n = o1.get("str"); assertNotNull(n); assertSame(n, NullNode.instance); o1.put("d", (BigDecimal) null); n = o1.get("d"); assertNotNull(n); assertSame(n, NullNode.instance); o1.put("3", (BigInteger) null); n = o1.get("3"); assertNotNull(3); assertSame(n, NullNode.instance); assertEquals(4, o1.size()); } /** * Another test to verify [JACKSON-227]... */ public void testNullChecking2() { ObjectNode src = MAPPER.createObjectNode(); ObjectNode dest = MAPPER.createObjectNode(); src.put("a", "b"); dest.setAll(src); } public void testRemove() { ObjectNode ob = MAPPER.createObjectNode(); ob.put("a", "a"); ob.put("b", "b"); ob.put("c", "c"); assertEquals(3, ob.size()); assertSame(ob, ob.without(Arrays.asList("a", "c"))); assertEquals(1, ob.size()); assertEquals("b", ob.get("b").textValue()); } public void testRetain() { ObjectNode ob = MAPPER.createObjectNode(); ob.put("a", "a"); ob.put("b", "b"); ob.put("c", "c"); assertEquals(3, ob.size()); assertSame(ob, ob.retain("a", "c")); assertEquals(2, ob.size()); assertEquals("a", ob.get("a").textValue()); assertNull(ob.get("b")); assertEquals("c", ob.get("c").textValue()); } public void testValidWith() throws Exception { ObjectNode root = MAPPER.createObjectNode(); assertEquals("{}", MAPPER.writeValueAsString(root)); JsonNode child = root.with("prop"); assertTrue(child instanceof ObjectNode); assertEquals("{\"prop\":{}}", MAPPER.writeValueAsString(root)); } public void testValidWithArray() throws Exception { ObjectNode root = MAPPER.createObjectNode(); assertEquals("{}", MAPPER.writeValueAsString(root)); JsonNode child = root.withArray("arr"); assertTrue(child instanceof ArrayNode); assertEquals("{\"arr\":[]}", MAPPER.writeValueAsString(root)); } public void testInvalidWith() throws Exception { JsonNode root = MAPPER.createArrayNode(); try { // should not work for non-ObjectNode nodes: root.with("prop"); fail("Expected exception"); } catch (UnsupportedOperationException e) { verifyException(e, "not of type ObjectNode"); } // also: should fail of we already have non-object property ObjectNode root2 = MAPPER.createObjectNode(); root2.put("prop", 13); try { // should not work for non-ObjectNode nodes: root2.with("prop"); fail("Expected exception"); } catch (UnsupportedOperationException e) { verifyException(e, "has value that is not"); } } public void testInvalidWithArray() throws Exception { JsonNode root = MAPPER.createArrayNode(); try { // should not work for non-ObjectNode nodes: root.withArray("prop"); fail("Expected exception"); } catch (UnsupportedOperationException e) { verifyException(e, "not of type ObjectNode"); } // also: should fail of we already have non-Array property ObjectNode root2 = MAPPER.createObjectNode(); root2.put("prop", 13); try { // should not work for non-ObjectNode nodes: root2.withArray("prop"); fail("Expected exception"); } catch (UnsupportedOperationException e) { verifyException(e, "has value that is not"); } } // [Issue#93] public void testSetAll() throws Exception { ObjectNode root = MAPPER.createObjectNode(); assertEquals(0, root.size()); HashMap map = new HashMap(); map.put("a", root.numberNode(1)); root.setAll(map); assertEquals(1, root.size()); assertTrue(root.has("a")); assertFalse(root.has("b")); map.put("b", root.numberNode(2)); root.setAll(map); assertEquals(2, root.size()); assertTrue(root.has("a")); assertTrue(root.has("b")); assertEquals(2, root.path("b").intValue()); // Then with ObjectNodes... ObjectNode root2 = MAPPER.createObjectNode(); root2.setAll(root); assertEquals(2, root.size()); assertEquals(2, root2.size()); root2.setAll(root); assertEquals(2, root.size()); assertEquals(2, root2.size()); ObjectNode root3 = MAPPER.createObjectNode(); root3.put("a", 2); root3.put("c", 3); assertEquals(2, root3.path("a").intValue()); root3.setAll(root2); assertEquals(3, root3.size()); assertEquals(1, root3.path("a").intValue()); } // [databind#237] (databind): support DeserializationFeature#FAIL_ON_READING_DUP_TREE_KEY public void testFailOnDupKeys() throws Exception { final String DUP_JSON = "{ \"a\":1, \"a\":2 }"; // first: verify defaults: ObjectMapper mapper = new ObjectMapper(); assertFalse(mapper.isEnabled(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY)); ObjectNode root = (ObjectNode) mapper.readTree(DUP_JSON); assertEquals(2, root.path("a").asInt()); // and then enable checks: try { mapper.reader(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY).readTree(DUP_JSON); fail("Should have thrown exception!"); } catch (JsonMappingException e) { verifyException(e, "duplicate field 'a'"); } } public void testEqualityWrtOrder() throws Exception { ObjectNode ob1 = MAPPER.createObjectNode(); ObjectNode ob2 = MAPPER.createObjectNode(); // same contents, different insertion order; should not matter ob1.put("a", 1); ob1.put("b", 2); ob1.put("c", 3); ob2.put("b", 2); ob2.put("c", 3); ob2.put("a", 1); assertTrue(ob1.equals(ob2)); assertTrue(ob2.equals(ob1)); } public void testSimplePath() throws Exception { JsonNode root = MAPPER.readTree("{ \"results\" : { \"a\" : 3 } }"); assertTrue(root.isObject()); JsonNode rnode = root.path("results"); assertNotNull(rnode); assertTrue(rnode.isObject()); assertEquals(3, rnode.path("a").intValue()); } public void testNonEmptySerialization() throws Exception { ObNodeWrapper w = new ObNodeWrapper(MAPPER.createObjectNode() .put("a", 3)); assertEquals("{\"node\":{\"a\":3}}", MAPPER.writeValueAsString(w)); w = new ObNodeWrapper(MAPPER.createObjectNode()); assertEquals("{}", MAPPER.writeValueAsString(w)); } public void testIssue941() throws Exception { ObjectNode object = MAPPER.createObjectNode(); String json = MAPPER.writeValueAsString(object); // System.out.println("json: "+json); ObjectNode de1 = MAPPER.readValue(json, ObjectNode.class); // this works // System.out.println("Deserialized to ObjectNode: "+de1); assertNotNull(de1); MyValue de2 = MAPPER.readValue(json, MyValue.class); // but this throws exception // System.out.println("Deserialized to MyValue: "+de2); assertNotNull(de2); } public void testSimpleMismatch() throws Exception { ObjectMapper mapper = objectMapper(); try { mapper.readValue("[ 1, 2, 3 ]", ObjectNode.class); fail("Should not pass"); } catch (MismatchedInputException e) { verifyException(e, "out of START_ARRAY token"); } } } TestConversions.java000066400000000000000000000251221325620701100354450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import java.math.BigDecimal; import java.util.*; import static org.junit.Assert.*; import org.junit.Assert; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Unit tests for verifying functionality of {@link JsonNode} methods that * convert values to other types */ public class TestConversions extends BaseMapTest { static class Root { public Leaf leaf; } static class Leaf { public int value; public Leaf() { } public Leaf(int v) { value = v; } } @JsonDeserialize(using = LeafDeserializer.class) public static class LeafMixIn { } // for [databind#467] @JsonSerialize(using=Issue467Serializer.class) static class Issue467Bean { public int i; public Issue467Bean(int i0) { i = i0; } public Issue467Bean() { this(0); } } @JsonSerialize(using=Issue467TreeSerializer.class) static class Issue467Tree { } static class Issue467Serializer extends JsonSerializer { @Override public void serialize(Issue467Bean value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeObject(new Issue467TmpBean(value.i)); } } static class Issue467TreeSerializer extends JsonSerializer { @Override public void serialize(Issue467Tree value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeTree(BooleanNode.TRUE); } } static class Issue467TmpBean { public int x; public Issue467TmpBean(int i) { x = i; } } static class Issue709Bean { public byte[] data; } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="_class") static class LongContainer1940 { public Long longObj; } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testAsInt() throws Exception { assertEquals(9, IntNode.valueOf(9).asInt()); assertEquals(7, LongNode.valueOf(7L).asInt()); assertEquals(13, new TextNode("13").asInt()); assertEquals(0, new TextNode("foobar").asInt()); assertEquals(27, new TextNode("foobar").asInt(27)); assertEquals(1, BooleanNode.TRUE.asInt()); } public void testAsBoolean() throws Exception { assertEquals(false, BooleanNode.FALSE.asBoolean()); assertEquals(true, BooleanNode.TRUE.asBoolean()); assertEquals(false, IntNode.valueOf(0).asBoolean()); assertEquals(true, IntNode.valueOf(1).asBoolean()); assertEquals(false, LongNode.valueOf(0).asBoolean()); assertEquals(true, LongNode.valueOf(-34L).asBoolean()); assertEquals(true, new TextNode("true").asBoolean()); assertEquals(false, new TextNode("false").asBoolean()); assertEquals(false, new TextNode("barf").asBoolean()); assertEquals(true, new TextNode("barf").asBoolean(true)); assertEquals(true, new POJONode(Boolean.TRUE).asBoolean()); } // Deserializer to trigger the problem described in [JACKSON-554] public static class LeafDeserializer extends JsonDeserializer { @Override public Leaf deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { JsonNode tree = (JsonNode) jp.readValueAsTree(); Leaf leaf = new Leaf(); leaf.value = tree.get("value").intValue(); return leaf; } } public void testTreeToValue() throws Exception { String JSON = "{\"leaf\":{\"value\":13}}"; ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(Leaf.class, LeafMixIn.class); JsonNode root = mapper.readTree(JSON); // Ok, try converting to bean using two mechanisms Root r1 = mapper.treeToValue(root, Root.class); assertNotNull(r1); assertEquals(13, r1.leaf.value); } // [databind#1208]: should coerce POJOs at least at root level public void testTreeToValueWithPOJO() throws Exception { Calendar c = Calendar.getInstance(); c.setTime(new java.util.Date(0)); ValueNode pojoNode = MAPPER.getNodeFactory().pojoNode(c); Calendar result = MAPPER.treeToValue(pojoNode, Calendar.class); assertNotNull(result); assertEquals(result.getTimeInMillis(), c.getTimeInMillis()); } public void testBase64Text() throws Exception { // let's actually iterate over sets of encoding modes, lengths final int[] LENS = { 1, 2, 3, 4, 7, 9, 32, 33, 34, 35 }; final Base64Variant[] VARIANTS = { Base64Variants.MIME, Base64Variants.MIME_NO_LINEFEEDS, Base64Variants.MODIFIED_FOR_URL, Base64Variants.PEM }; for (int len : LENS) { byte[] input = new byte[len]; for (int i = 0; i < input.length; ++i) { input[i] = (byte) i; } for (Base64Variant variant : VARIANTS) { TextNode n = new TextNode(variant.encode(input)); byte[] data = null; try { data = n.getBinaryValue(variant); } catch (Exception e) { throw new IOException("Failed (variant "+variant+", data length "+len+"): "+e.getMessage()); } assertNotNull(data); assertArrayEquals(data, input); } } } /** * Simple test to verify that byte[] values can be handled properly when * converting, as long as there is metadata (from POJO definitions). */ public void testIssue709() throws Exception { byte[] inputData = new byte[] { 1, 2, 3 }; ObjectNode node = MAPPER.createObjectNode(); node.put("data", inputData); Issue709Bean result = MAPPER.treeToValue(node, Issue709Bean.class); String json = MAPPER.writeValueAsString(node); Issue709Bean resultFromString = MAPPER.readValue(json, Issue709Bean.class); Issue709Bean resultFromConvert = MAPPER.convertValue(node, Issue709Bean.class); // all methods should work equally well: Assert.assertArrayEquals(inputData, resultFromString.data); Assert.assertArrayEquals(inputData, resultFromConvert.data); Assert.assertArrayEquals(inputData, result.data); } public void testEmbeddedByteArray() throws Exception { TokenBuffer buf = new TokenBuffer(MAPPER, false); buf.writeObject(new byte[3]); JsonNode node = MAPPER.readTree(buf.asParser()); buf.close(); assertTrue(node.isBinary()); byte[] data = node.binaryValue(); assertNotNull(data); assertEquals(3, data.length); } // [databind#232] public void testBigDecimalAsPlainStringTreeConversion() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN); Map map = new HashMap(); String PI_STR = "3.00000000"; map.put("pi", new BigDecimal(PI_STR)); JsonNode tree = mapper.valueToTree(map); assertNotNull(tree); assertEquals(1, tree.size()); assertTrue(tree.has("pi")); } static class CustomSerializedPojo implements JsonSerializable { private final ObjectNode node = JsonNodeFactory.instance.objectNode(); public void setFoo(final String foo) { node.put("foo", foo); } @Override public void serialize(final JsonGenerator jgen, final SerializerProvider provider) throws IOException { jgen.writeTree(node); } @Override public void serializeWithType(JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException { WritableTypeId typeIdDef = new WritableTypeId(this, JsonToken.START_OBJECT); typeSer.writeTypePrefix(g, typeIdDef); serialize(g, provider); typeSer.writeTypePrefix(g, typeIdDef); } } // [databind#433] public void testBeanToTree() throws Exception { final CustomSerializedPojo pojo = new CustomSerializedPojo(); pojo.setFoo("bar"); final JsonNode node = MAPPER.valueToTree(pojo); assertEquals(JsonNodeType.OBJECT, node.getNodeType()); } // [databind#467] public void testConversionOfPojos() throws Exception { final Issue467Bean input = new Issue467Bean(13); final String EXP = "{\"x\":13}"; // first, sanity check String json = MAPPER.writeValueAsString(input); assertEquals(EXP, json); // then via conversions: should become JSON Object JsonNode tree = MAPPER.valueToTree(input); assertTrue("Expected Object, got "+tree.getNodeType(), tree.isObject()); assertEquals(EXP, MAPPER.writeValueAsString(tree)); } // [databind#467] public void testConversionOfTrees() throws Exception { final Issue467Tree input = new Issue467Tree(); final String EXP = "true"; // first, sanity check String json = MAPPER.writeValueAsString(input); assertEquals(EXP, json); // then via conversions: should become JSON Object JsonNode tree = MAPPER.valueToTree(input); assertTrue("Expected Object, got "+tree.getNodeType(), tree.isBoolean()); assertEquals(EXP, MAPPER.writeValueAsString(tree)); } // [databind#1940]: losing of precision due to coercion public void testBufferedLongViaCoercion() throws Exception { long EXP = 1519348261000L; JsonNode tree = MAPPER.readTree("{\"longObj\": "+EXP+".0, \"_class\": \""+LongContainer1940.class.getName()+"\"}"); LongContainer1940 obj = MAPPER.treeToValue(tree, LongContainer1940.class); assertEquals(Long.valueOf(EXP), obj.longObj); } } TestDeepCopy.java000066400000000000000000000047301325620701100346470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; /** * Simple tests to verify that [JACKSON-707] is implemented correctly. */ public class TestDeepCopy extends BaseMapTest { private final ObjectMapper mapper = new ObjectMapper(); public void testWithObjectSimple() { ObjectNode root = mapper.createObjectNode(); root.put("a", 3); assertEquals(1, root.size()); ObjectNode copy = root.deepCopy(); assertEquals(1, copy.size()); // adding to root won't change copy: root.put("b", 7); assertEquals(2, root.size()); assertEquals(1, copy.size()); // nor vice versa copy.put("c", 3); assertEquals(2, root.size()); assertEquals(2, copy.size()); } public void testWithArraySimple() { ArrayNode root = mapper.createArrayNode(); root.add("a"); assertEquals(1, root.size()); ArrayNode copy = root.deepCopy(); assertEquals(1, copy.size()); // adding to root won't change copy: root.add( 7); assertEquals(2, root.size()); assertEquals(1, copy.size()); // nor vice versa copy.add(3); assertEquals(2, root.size()); assertEquals(2, copy.size()); } public void testWithNested() { ObjectNode root = mapper.createObjectNode(); ObjectNode leafObject = root.putObject("ob"); ArrayNode leafArray = root.putArray("arr"); assertEquals(2, root.size()); leafObject.put("a", 3); assertEquals(1, leafObject.size()); leafArray.add(true); assertEquals(1, leafArray.size()); ObjectNode copy = root.deepCopy(); assertNotSame(copy, root); assertEquals(2, copy.size()); // should be detached, once again leafObject.put("x", 9); assertEquals(2, leafObject.size()); assertEquals(1, copy.get("ob").size()); leafArray.add("foobar"); assertEquals(2, leafArray.size()); assertEquals(1, copy.get("arr").size()); // nor vice versa ((ObjectNode) copy.get("ob")).put("c", 3); assertEquals(2, leafObject.size()); assertEquals(2, copy.get("ob").size()); ((ArrayNode) copy.get("arr")).add(13); assertEquals(2, leafArray.size()); assertEquals(2, copy.get("arr").size()); } } TestEndOfInputHandling.java000066400000000000000000000014401325620701100366120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; public class TestEndOfInputHandling extends BaseMapTest { public void testErrorHandling() throws IOException { ObjectMapper mapper = new ObjectMapper(); String json = "{\"A\":{\"B\":\n"; JsonParser parser = mapper.getFactory().createParser(json); parser.setCodec(new ObjectMapper()); try { parser.readValueAsTree(); } catch(JsonParseException e) { verifyException(e, "Unexpected end-of-input"); } parser.close(); try { mapper.readTree(json); } catch(JsonParseException e) { verifyException(e, "Unexpected end-of-input"); } } } TestFindMethods.java000066400000000000000000000045351325620701100353460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.util.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; public class TestFindMethods extends BaseMapTest { public void testNonMatching() throws Exception { JsonNode root = _buildTree(); assertNull(root.findValue("boogaboo")); assertNull(root.findParent("boogaboo")); JsonNode n = root.findPath("boogaboo"); assertNotNull(n); assertTrue(n.isMissingNode()); assertTrue(root.findValues("boogaboo").isEmpty()); assertTrue(root.findParents("boogaboo").isEmpty()); } public void testMatchingSingle() throws Exception { JsonNode root = _buildTree(); JsonNode node = root.findValue("b"); assertNotNull(node); assertEquals(3, node.intValue()); node = root.findParent("b"); assertNotNull(node); assertTrue(node.isObject()); assertEquals(1, ((ObjectNode) node).size()); assertEquals(3, node.path("b").intValue()); } public void testMatchingMultiple() throws Exception { JsonNode root = _buildTree(); List nodes = root.findValues("value"); assertEquals(2, nodes.size()); // here we count on nodes being returned in order; true with Jackson: assertEquals(3, nodes.get(0).intValue()); assertEquals(42, nodes.get(1).intValue()); nodes = root.findParents("value"); assertEquals(2, nodes.size()); // should only return JSON Object nodes: assertTrue(nodes.get(0).isObject()); assertTrue(nodes.get(1).isObject()); assertEquals(3, nodes.get(0).path("value").intValue()); assertEquals(42, nodes.get(1).path("value").intValue()); // and finally, convenience conversion method List values = root.findValuesAsText("value"); assertEquals(2, values.size()); assertEquals("3", values.get(0)); assertEquals("42", values.get(1)); } private JsonNode _buildTree() throws Exception { final String SAMPLE = "{ \"a\" : { \"value\" : 3 }," +"\"array\" : [ { \"b\" : 3 }, {\"value\" : 42}, { \"other\" : true } ]" +"}"; return objectMapper().readTree(SAMPLE); } } TestJsonNode.java000066400000000000000000000151501325620701100346540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.util.Comparator; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.util.RawValue; /** * Basic tests for {@link JsonNode} base class and some features * of implementation classes */ public class TestJsonNode extends NodeTestBase { private final ObjectMapper MAPPER = objectMapper(); public void testBoolean() throws Exception { BooleanNode f = BooleanNode.getFalse(); assertNotNull(f); assertTrue(f.isBoolean()); assertSame(f, BooleanNode.valueOf(false)); assertStandardEquals(f); assertFalse(f.booleanValue()); assertFalse(f.asBoolean()); assertEquals("false", f.asText()); assertEquals(JsonToken.VALUE_FALSE, f.asToken()); // and ditto for true BooleanNode t = BooleanNode.getTrue(); assertNotNull(t); assertTrue(t.isBoolean()); assertSame(t, BooleanNode.valueOf(true)); assertStandardEquals(t); assertTrue(t.booleanValue()); assertTrue(t.asBoolean()); assertEquals("true", t.asText()); assertEquals(JsonToken.VALUE_TRUE, t.asToken()); assertNodeNumbers(f, 0, 0.0); assertNodeNumbers(t, 1, 1.0); JsonNode result = objectMapper().readTree("true\n"); assertFalse(result.isNull()); assertFalse(result.isNumber()); assertFalse(result.isTextual()); assertTrue(result.isBoolean()); assertType(result, BooleanNode.class); assertTrue(result.booleanValue()); assertEquals("true", result.asText()); assertFalse(result.isMissingNode()); // also, equality should work ok assertEquals(result, BooleanNode.valueOf(true)); assertEquals(result, BooleanNode.getTrue()); } public void testBinary() throws Exception { assertNull(BinaryNode.valueOf(null)); assertNull(BinaryNode.valueOf(null, 0, 0)); BinaryNode empty = BinaryNode.valueOf(new byte[1], 0, 0); assertSame(BinaryNode.EMPTY_BINARY_NODE, empty); assertStandardEquals(empty); byte[] data = new byte[3]; data[1] = (byte) 3; BinaryNode n = BinaryNode.valueOf(data, 1, 1); data[2] = (byte) 3; BinaryNode n2 = BinaryNode.valueOf(data, 2, 1); assertTrue(n.equals(n2)); assertEquals("\"Aw==\"", n.toString()); assertEquals("AAMD", new BinaryNode(data).asText()); assertNodeNumbersForNonNumeric(n); } public void testPOJO() { POJONode n = new POJONode("x"); // not really a pojo but that's ok assertStandardEquals(n); assertEquals(n, new POJONode("x")); assertEquals("x", n.asText()); // not sure if this is what it'll remain as but: assertEquals("x", n.toString()); assertEquals(new POJONode(null), new POJONode(null)); // default; non-numeric assertNodeNumbersForNonNumeric(n); // but if wrapping actual number, use it assertNodeNumbers(new POJONode(Integer.valueOf(123)), 123, 123.0); } // [databind#743] public void testRawValue() throws Exception { ObjectNode root = MAPPER.createObjectNode(); root.putRawValue("a", new RawValue(new SerializedString("[1, 2, 3]"))); assertEquals("{\"a\":[1, 2, 3]}", MAPPER.writeValueAsString(root)); } // [databind#790] public void testCustomComparators() throws Exception { ObjectNode nestedObject1 = MAPPER.createObjectNode(); nestedObject1.put("value", 6); ArrayNode nestedArray1 = MAPPER.createArrayNode(); nestedArray1.add(7); ObjectNode root1 = MAPPER.createObjectNode(); root1.put("value", 5); root1.set("nested_object", nestedObject1); root1.set("nested_array", nestedArray1); ObjectNode nestedObject2 = MAPPER.createObjectNode(); nestedObject2.put("value", 6.9); ArrayNode nestedArray2 = MAPPER.createArrayNode(); nestedArray2.add(7.0); ObjectNode root2 = MAPPER.createObjectNode(); root2.put("value", 5.0); root2.set("nested_object", nestedObject2); root2.set("nested_array", nestedArray2); // default equals(): not strictly equal assertFalse(root1.equals(root2)); assertFalse(root2.equals(root1)); assertTrue(root1.equals(root1)); assertTrue(root2.equals(root2)); assertTrue(nestedArray1.equals(nestedArray1)); assertFalse(nestedArray1.equals(nestedArray2)); assertFalse(nestedArray2.equals(nestedArray1)); // but. Custom comparator can make all the difference Comparator cmp = new Comparator() { @Override public int compare(JsonNode o1, JsonNode o2) { if (o1 instanceof ContainerNode || o2 instanceof ContainerNode) { fail("container nodes should be traversed, comparator should not be invoked"); } if (o1.equals(o2)) { return 0; } if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)) { int d1 = ((NumericNode) o1).asInt(); int d2 = ((NumericNode) o2).asInt(); if (d1 == d2) { // strictly equals because it's integral value return 0; } if (d1 < d2) { return -1; } return 1; } return 0; } }; assertTrue(root1.equals(cmp, root2)); assertTrue(root2.equals(cmp, root1)); assertTrue(root1.equals(cmp, root1)); assertTrue(root2.equals(cmp, root2)); ArrayNode array3 = MAPPER.createArrayNode(); array3.add(123); assertFalse(root2.equals(cmp, nestedArray1)); assertTrue(nestedArray1.equals(cmp, nestedArray1)); assertFalse(nestedArray1.equals(cmp, root2)); assertFalse(nestedArray1.equals(cmp, array3)); } // [databind#793] public void testArrayWithDefaultTyping() throws Exception { ObjectMapper mapper = new ObjectMapper() .enableDefaultTyping(); JsonNode array = mapper.readTree("[ 1, 2 ]"); assertTrue(array.isArray()); assertEquals(2, array.size()); JsonNode obj = mapper.readTree("{ \"a\" : 2 }"); assertTrue(obj.isObject()); assertEquals(1, obj.size()); assertEquals(2, obj.path("a").asInt()); } } TestJsonPointer.java000066400000000000000000000033461325620701100354130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.databind.*; public class TestJsonPointer extends BaseMapTest { public void testIt() throws Exception { final JsonNode SAMPLE_ROOT = objectMapper().readTree(SAMPLE_DOC_JSON_SPEC); // first: "empty" pointer points to context node: assertSame(SAMPLE_ROOT, SAMPLE_ROOT.at(JsonPointer.compile(""))); // then simple reference assertTrue(SAMPLE_ROOT.at(JsonPointer.compile("/Image")).isObject()); JsonNode n = SAMPLE_ROOT.at(JsonPointer.compile("/Image/Width")); assertTrue(n.isNumber()); assertEquals(SAMPLE_SPEC_VALUE_WIDTH, n.asInt()); // ok also with implicit compile() for pointer: assertEquals(SAMPLE_SPEC_VALUE_HEIGHT, SAMPLE_ROOT.at("/Image/Height").asInt()); assertEquals(SAMPLE_SPEC_VALUE_TN_ID3, SAMPLE_ROOT.at(JsonPointer.compile("/Image/IDs/2")).asInt()); // and then check that "missing" paths are ok too but assertTrue(SAMPLE_ROOT.at("/Image/Depth").isMissingNode()); assertTrue(SAMPLE_ROOT.at("/Image/1").isMissingNode()); } // To help verify [Core#133]; should be fine with "big numbers" as property keys public void testLongNumbers() throws Exception { // First, with small int key JsonNode root = objectMapper().readTree("{\"123\" : 456}"); JsonNode jn2 = root.at("/123"); assertEquals(456, jn2.asInt()); // and then with above int-32: root = objectMapper().readTree("{\"35361706045\" : 1234}"); jn2 = root.at("/35361706045"); assertEquals(1234, jn2.asInt()); } } TestMissingNode.java000066400000000000000000000057171325620701100353640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.StringReader; import java.util.Iterator; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.JsonNode; public class TestMissingNode extends NodeTestBase { public void testMissing() { MissingNode n = MissingNode.getInstance(); assertTrue(n.isMissingNode()); assertEquals(JsonToken.NOT_AVAILABLE, n.asToken()); assertEquals("", n.asText()); assertStandardEquals(n); assertEquals("", n.toString()); assertNodeNumbersForNonNumeric(n); assertTrue(n.asBoolean(true)); assertEquals(4, n.asInt(4)); assertEquals(5L, n.asLong(5)); assertEquals(0.25, n.asDouble(0.25)); assertEquals("foo", n.asText("foo")); } /** * Let's also verify behavior of "MissingNode" -- one needs to be able * to traverse such bogus nodes with appropriate methods. */ @SuppressWarnings("unused") public void testMissingViaMapper() throws Exception { String JSON = "[ { }, [ ] ]"; JsonNode result = objectMapper().readTree(new StringReader(JSON)); assertTrue(result.isContainerNode()); assertTrue(result.isArray()); assertEquals(2, result.size()); int count = 0; for (JsonNode node : result) { ++count; } assertEquals(2, count); Iterator it = result.iterator(); JsonNode onode = it.next(); assertTrue(onode.isContainerNode()); assertTrue(onode.isObject()); assertEquals(0, onode.size()); assertFalse(onode.isMissingNode()); // real node assertNull(onode.textValue()); // how about dereferencing? assertNull(onode.get(0)); JsonNode dummyNode = onode.path(0); assertNotNull(dummyNode); assertTrue(dummyNode.isMissingNode()); assertNull(dummyNode.get(3)); assertNull(dummyNode.get("whatever")); JsonNode dummyNode2 = dummyNode.path(98); assertNotNull(dummyNode2); assertTrue(dummyNode2.isMissingNode()); JsonNode dummyNode3 = dummyNode.path("field"); assertNotNull(dummyNode3); assertTrue(dummyNode3.isMissingNode()); // and same for the array node JsonNode anode = it.next(); assertTrue(anode.isContainerNode()); assertTrue(anode.isArray()); assertFalse(anode.isMissingNode()); // real node assertEquals(0, anode.size()); assertNull(anode.get(0)); dummyNode = anode.path(0); assertNotNull(dummyNode); assertTrue(dummyNode.isMissingNode()); assertNull(dummyNode.get(0)); assertNull(dummyNode.get("myfield")); dummyNode2 = dummyNode.path(98); assertNotNull(dummyNode2); assertTrue(dummyNode2.isMissingNode()); dummyNode3 = dummyNode.path("f"); assertNotNull(dummyNode3); assertTrue(dummyNode3.isMissingNode()); } } TestNullNode.java000066400000000000000000000057751325620701100346710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.StringWriter; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public class TestNullNode extends NodeTestBase { final static class CovarianceBean { ObjectNode _object; ArrayNode _array; public void setObject(ObjectNode n) { _object = n; } public void setArray(ArrayNode n) { _array = n; } } public void testBasicsWithNullNode() throws Exception { // Let's use something that doesn't add much beyond JsonNode base NullNode n = NullNode.instance; // basic properties assertFalse(n.isContainerNode()); assertFalse(n.isBigDecimal()); assertFalse(n.isBigInteger()); assertFalse(n.isBinary()); assertFalse(n.isBoolean()); assertFalse(n.isPojo()); assertFalse(n.isMissingNode()); // fallback accessors assertFalse(n.booleanValue()); assertNull(n.numberValue()); assertEquals(0, n.intValue()); assertEquals(0L, n.longValue()); assertEquals(BigDecimal.ZERO, n.decimalValue()); assertEquals(BigInteger.ZERO, n.bigIntegerValue()); assertEquals(0, n.size()); assertFalse(n.elements().hasNext()); assertFalse(n.fieldNames().hasNext()); // path is never null; but does point to missing node assertNotNull(n.path("xyz")); assertTrue(n.path("xyz").isMissingNode()); assertFalse(n.has("field")); assertFalse(n.has(3)); assertNodeNumbersForNonNumeric(n); // 2.4 assertEquals("foo", n.asText("foo")); } public void testNullHandling() throws Exception { // First, a stand-alone null JsonNode n = objectReader().readTree("null"); assertNotNull(n); assertTrue(n.isNull()); assertFalse(n.isNumber()); assertFalse(n.isTextual()); assertEquals("null", n.asText()); assertEquals(n, NullNode.instance); n = objectMapper().readTree("null"); assertNotNull(n); assertTrue(n.isNull()); // Then object property ObjectNode root = (ObjectNode) objectReader().readTree("{\"x\":null}"); assertEquals(1, root.size()); n = root.get("x"); assertNotNull(n); assertTrue(n.isNull()); } public void testNullSerialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); StringWriter sw = new StringWriter(); mapper.writeValue(sw, NullNode.instance); assertEquals("null", sw.toString()); } public void testNullHandlingCovariance() throws Exception { String JSON = "{\"object\" : null, \"array\" : null }"; CovarianceBean bean = objectMapper().readValue(JSON, CovarianceBean.class); ObjectNode on = bean._object; assertNull(on); ArrayNode an = bean._array; assertNull(an); } } TestTreeDeserialization.java000066400000000000000000000033321325620701100371020ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; /** * This unit test suite tries to verify that JsonNode-based trees * can be deserialized as expected. */ public class TestTreeDeserialization extends BaseMapTest { final static class Bean { int _x; JsonNode _node; public void setX(int x) { _x = x; } public void setNode(JsonNode n) { _node = n; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testObjectNodeEquality() { ObjectNode n1 = new ObjectNode(null); ObjectNode n2 = new ObjectNode(null); assertTrue(n1.equals(n2)); assertTrue(n2.equals(n1)); n1.set("x", TextNode.valueOf("Test")); assertFalse(n1.equals(n2)); assertFalse(n2.equals(n1)); n2.set("x", TextNode.valueOf("Test")); assertTrue(n1.equals(n2)); assertTrue(n2.equals(n1)); } public void testReadFromString() throws Exception { String json = "{\"field\":\"{\\\"name\\\":\\\"John Smith\\\"}\"}"; ObjectMapper mapper = new ObjectMapper(); JsonNode jNode = mapper.readValue(json, JsonNode.class); String generated = mapper.writeValueAsString( jNode); //back slashes are gone JsonNode out = mapper.readValue( generated, JsonNode.class ); //crashes here assertTrue(out.isObject()); assertEquals(1, out.size()); String value = out.path("field").asText(); assertNotNull(value); } } TestTreeMapperSerializer.java000066400000000000000000000164261325620701100372420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import static org.junit.Assert.*; import java.io.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; /** * This unit test suite tries to verify that the trees ObjectMapper * constructs can be serialized properly. */ public class TestTreeMapperSerializer extends NodeTestBase { final static String FIELD1 = "first"; final static String FIELD2 = "Second?"; final static String FIELD3 = "foo'n \"bar\""; final static String FIELD4 = "4"; final static String TEXT1 = "Some text & \"stuff\""; final static String TEXT2 = "Some more text:\twith\nlinefeeds and all!"; final static double DOUBLE_VALUE = 9.25; public void testFromArray() throws Exception { ObjectMapper mapper = new ObjectMapper(); ArrayNode root = mapper.createArrayNode(); root.add(TEXT1); root.add(3); ObjectNode obj = root.addObject(); obj.put(FIELD1, true); obj.putArray(FIELD2); root.add(false); /* Ok, ready... let's serialize using one of two alternate * methods: first preferred (using generator) * (there are 2 variants here too) */ for (int i = 0; i < 2; ++i) { StringWriter sw = new StringWriter(); if (i == 0) { JsonGenerator gen = new JsonFactory().createGenerator(sw); root.serialize(gen, null); gen.close(); } else { mapper.writeValue(sw, root); } verifyFromArray(sw.toString()); } // And then convenient but less efficient alternative: verifyFromArray(root.toString()); } public void testFromMap() throws Exception { ObjectMapper mapper = new ObjectMapper(); ObjectNode root = mapper.createObjectNode(); root.put(FIELD4, TEXT2); root.put(FIELD3, -1); root.putArray(FIELD2); root.put(FIELD1, DOUBLE_VALUE); /* Let's serialize using one of two alternate methods: * first preferred (using generator) * (there are 2 variants here too) */ for (int i = 0; i < 2; ++i) { StringWriter sw = new StringWriter(); if (i == 0) { JsonGenerator gen = new JsonFactory().createGenerator(sw); root.serialize(gen, null); gen.close(); } else { mapper.writeValue(sw, root); } verifyFromMap(sw.toString()); } // And then convenient but less efficient alternative: verifyFromMap(root.toString()); } /** * Unit test to check for regression of [JACKSON-18]. */ public void testSmallNumbers() throws Exception { ObjectMapper mapper = new ObjectMapper(); ArrayNode root = mapper.createArrayNode(); for (int i = -20; i <= 20; ++i) { JsonNode n = root.numberNode(i); root.add(n); // Hmmh. Not sure why toString() won't be triggered otherwise... assertEquals(String.valueOf(i), n.toString()); } // Loop over 2 different serialization methods for (int type = 0; type < 2; ++type) { StringWriter sw = new StringWriter(); if (type == 0) { JsonGenerator gen = new JsonFactory().createGenerator(sw); root.serialize(gen, null); gen.close(); } else { mapper.writeValue(sw, root); } String doc = sw.toString(); JsonParser p = new JsonFactory().createParser(new StringReader(doc)); assertEquals(JsonToken.START_ARRAY, p.nextToken()); for (int i = -20; i <= 20; ++i) { assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(i, p.getIntValue()); assertEquals(""+i, p.getText()); } assertEquals(JsonToken.END_ARRAY, p.nextToken()); p.close(); } } public void testBinary() throws Exception { ObjectMapper mapper = new ObjectMapper(); final int LENGTH = 13045; byte[] data = new byte[LENGTH]; for (int i = 0; i < LENGTH; ++i) { data[i] = (byte) i; } StringWriter sw = new StringWriter(); mapper.writeValue(sw, BinaryNode.valueOf(data)); JsonParser p = new JsonFactory().createParser(sw.toString()); // note: can't determine it's binary from json alone: assertToken(JsonToken.VALUE_STRING, p.nextToken()); assertArrayEquals(data, p.getBinaryValue()); p.close(); } /* /////////////////////////////////////////////////////////////// // Internal methods /////////////////////////////////////////////////////////////// */ private void verifyFromArray(String input) throws Exception { JsonParser p = new JsonFactory().createParser(new StringReader(input)); assertEquals(JsonToken.START_ARRAY, p.nextToken()); assertEquals(JsonToken.VALUE_STRING, p.nextToken()); assertEquals(TEXT1, getAndVerifyText(p)); assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(3, p.getIntValue()); assertEquals(JsonToken.START_OBJECT, p.nextToken()); assertEquals(JsonToken.FIELD_NAME, p.nextToken()); assertEquals(FIELD1, getAndVerifyText(p)); assertEquals(JsonToken.VALUE_TRUE, p.nextToken()); assertEquals(JsonToken.FIELD_NAME, p.nextToken()); assertEquals(FIELD2, getAndVerifyText(p)); assertEquals(JsonToken.START_ARRAY, p.nextToken()); assertEquals(JsonToken.END_ARRAY, p.nextToken()); assertEquals(JsonToken.END_OBJECT, p.nextToken()); assertEquals(JsonToken.VALUE_FALSE, p.nextToken()); assertEquals(JsonToken.END_ARRAY, p.nextToken()); assertNull(p.nextToken()); p.close(); } private void verifyFromMap(String input) throws Exception { JsonParser p = new JsonFactory().createParser(input); assertEquals(JsonToken.START_OBJECT, p.nextToken()); assertEquals(JsonToken.FIELD_NAME, p.nextToken()); assertEquals(FIELD4, getAndVerifyText(p)); assertEquals(JsonToken.VALUE_STRING, p.nextToken()); assertEquals(TEXT2, getAndVerifyText(p)); assertEquals(JsonToken.FIELD_NAME, p.nextToken()); assertEquals(FIELD3, getAndVerifyText(p)); assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(-1, p.getIntValue()); assertEquals(JsonToken.FIELD_NAME, p.nextToken()); assertEquals(FIELD2, getAndVerifyText(p)); assertEquals(JsonToken.START_ARRAY, p.nextToken()); assertEquals(JsonToken.END_ARRAY, p.nextToken()); assertEquals(JsonToken.FIELD_NAME, p.nextToken()); assertEquals(FIELD1, getAndVerifyText(p)); assertEquals(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); assertEquals(DOUBLE_VALUE, p.getDoubleValue(), 0); assertEquals(JsonToken.END_OBJECT, p.nextToken()); assertNull(p.nextToken()); p.close(); } } TestTreeTraversingParser.java000066400000000000000000000224401325620701100372560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.util.*; import static org.junit.Assert.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import com.fasterxml.jackson.databind.node.BinaryNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.POJONode; import com.fasterxml.jackson.databind.node.TextNode; public class TestTreeTraversingParser extends BaseMapTest { static class Person { public String name; public int magicNumber; public List kids; } @JsonIgnoreProperties(ignoreUnknown=true) public static class Jackson370Bean { public Inner inner; } public static class Inner { public String value; } /* /********************************************************** /* Test methods /********************************************************** */ public void testSimple() throws Exception { // For convenience, parse tree from JSON first final String JSON = "{ \"a\" : 123, \"list\" : [ 12.25, null, true, { }, [ ] ] }"; ObjectMapper m = new ObjectMapper(); JsonNode tree = m.readTree(JSON); JsonParser p = tree.traverse(); assertNull(p.getCurrentToken()); assertNull(p.getCurrentName()); assertToken(JsonToken.START_OBJECT, p.nextToken()); assertNull(p.getCurrentName()); assertEquals("Expected START_OBJECT", JsonToken.START_OBJECT.asString(), p.getText()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); assertEquals("a", p.getCurrentName()); assertEquals("a", p.getText()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals("a", p.getCurrentName()); assertEquals(123, p.getIntValue()); assertEquals("123", p.getText()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); assertEquals("list", p.getCurrentName()); assertEquals("list", p.getText()); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertEquals("list", p.getCurrentName()); assertEquals(JsonToken.START_ARRAY.asString(), p.getText()); assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); assertNull(p.getCurrentName()); assertEquals(12.25, p.getDoubleValue(), 0); assertEquals("12.25", p.getText()); assertToken(JsonToken.VALUE_NULL, p.nextToken()); assertNull(p.getCurrentName()); assertEquals(JsonToken.VALUE_NULL.asString(), p.getText()); assertToken(JsonToken.VALUE_TRUE, p.nextToken()); assertNull(p.getCurrentName()); assertTrue(p.getBooleanValue()); assertEquals(JsonToken.VALUE_TRUE.asString(), p.getText()); assertToken(JsonToken.START_OBJECT, p.nextToken()); assertNull(p.getCurrentName()); assertToken(JsonToken.END_OBJECT, p.nextToken()); assertNull(p.getCurrentName()); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertNull(p.getCurrentName()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertNull(p.getCurrentName()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertToken(JsonToken.END_OBJECT, p.nextToken()); assertNull(p.getCurrentName()); assertNull(p.nextToken()); p.close(); assertTrue(p.isClosed()); } public void testArray() throws Exception { // For convenience, parse tree from JSON first ObjectMapper m = new ObjectMapper(); JsonParser p = m.readTree("[]").traverse(); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); p.close(); p = m.readTree("[[]]").traverse(); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); p.close(); p = m.readTree("[[ 12.1 ]]").traverse(); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); p.close(); } public void testNested() throws Exception { // For convenience, parse tree from JSON first final String JSON = "{\"coordinates\":[[[-3,\n1],[179.859681,51.175092]]]}" ; ObjectMapper m = new ObjectMapper(); JsonNode tree = m.readTree(JSON); JsonParser p = tree.traverse(); assertToken(JsonToken.START_OBJECT, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertToken(JsonToken.END_OBJECT, p.nextToken()); p.close(); } /** * Unit test that verifies that we can (re)parse sample document * from JSON specification. */ public void testSpecDoc() throws Exception { ObjectMapper m = new ObjectMapper(); JsonNode tree = m.readTree(SAMPLE_DOC_JSON_SPEC); JsonParser p = tree.traverse(); verifyJsonSpecSampleDoc(p, true); p.close(); } public void testBinaryPojo() throws Exception { byte[] inputBinary = new byte[] { 1, 2, 100 }; POJONode n = new POJONode(inputBinary); JsonParser p = n.traverse(); assertNull(p.getCurrentToken()); assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); byte[] data = p.getBinaryValue(); assertNotNull(data); assertArrayEquals(inputBinary, data); Object pojo = p.getEmbeddedObject(); assertSame(data, pojo); p.close(); } public void testBinaryNode() throws Exception { byte[] inputBinary = new byte[] { 0, -5 }; BinaryNode n = new BinaryNode(inputBinary); JsonParser p = n.traverse(); assertNull(p.getCurrentToken()); // exposed as POJO... not as VALUE_STRING assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); byte[] data = p.getBinaryValue(); assertNotNull(data); assertArrayEquals(inputBinary, data); // but as importantly, can be viewed as base64 encoded thing: assertEquals("APs=", p.getText()); assertNull(p.nextToken()); p.close(); } public void testTextAsBinary() throws Exception { TextNode n = new TextNode(" APs=\n"); JsonParser p = n.traverse(); assertNull(p.getCurrentToken()); assertToken(JsonToken.VALUE_STRING, p.nextToken()); byte[] data = p.getBinaryValue(); assertNotNull(data); assertArrayEquals(new byte[] { 0, -5 }, data); assertNull(p.nextToken()); p.close(); assertTrue(p.isClosed()); // Also: let's verify we get an exception for garbage... n = new TextNode("?!??"); p = n.traverse(); assertToken(JsonToken.VALUE_STRING, p.nextToken()); try { p.getBinaryValue(); } catch (InvalidFormatException e) { verifyException(e, "Illegal character"); } p.close(); } /** * Very simple test case to verify that tree-to-POJO * conversion works ok */ public void testDataBind() throws Exception { ObjectMapper m = new ObjectMapper(); JsonNode tree = m.readTree ("{ \"name\" : \"Tatu\", \n" +"\"magicNumber\" : 42," +"\"kids\" : [ \"Leo\", \"Lila\", \"Leia\" ] \n" +"}"); Person tatu = m.treeToValue(tree, Person.class); assertNotNull(tatu); assertEquals(42, tatu.magicNumber); assertEquals("Tatu", tatu.name); assertNotNull(tatu.kids); assertEquals(3, tatu.kids.size()); assertEquals("Leo", tatu.kids.get(0)); assertEquals("Lila", tatu.kids.get(1)); assertEquals("Leia", tatu.kids.get(2)); } // [JACKSON-370] public void testSkipChildrenWrt370() throws Exception { ObjectMapper o = new ObjectMapper(); ObjectNode n = o.createObjectNode(); n.putObject("inner").put("value", "test"); n.putObject("unknown").putNull("inner"); Jackson370Bean obj = o.readValue(n.traverse(), Jackson370Bean.class); assertNotNull(obj.inner); assertEquals("test", obj.inner.value); } } TestTreeWithType.java000066400000000000000000000104111325620701100355250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; public class TestTreeWithType extends BaseMapTest { public static class Foo { public String bar; public Foo() { } public Foo(String bar) { this.bar = bar; } } // [databind#353] public class SavedCookie { public String name, value; public SavedCookie() { } public SavedCookie(String n, String v) { name = n; value = v; } } public class SavedCookieDeserializer extends JsonDeserializer { @Override public SavedCookie deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException { ObjectCodec oc = jsonParser.getCodec(); JsonNode node = oc.readTree(jsonParser); return new SavedCookie(node.path("name").textValue(), node.path("value").textValue()); } @Override public SavedCookie deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException, JsonProcessingException { return (SavedCookie) typeDeserializer.deserializeTypedFromObject(jp, ctxt); } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testValueAsStringWithoutDefaultTyping() throws Exception { Foo foo = new Foo("baz"); String json = MAPPER.writeValueAsString(foo); JsonNode jsonNode = MAPPER.readTree(json); assertEquals(jsonNode.get("bar").textValue(), foo.bar); } public void testValueAsStringWithDefaultTyping() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); Foo foo = new Foo("baz"); String json = mapper.writeValueAsString(foo); JsonNode jsonNode = mapper.readTree(json); assertEquals(jsonNode.get("bar").textValue(), foo.bar); } public void testReadTreeWithDefaultTyping() throws Exception { final String CLASS = Foo.class.getName(); final ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); String json = "{\"@class\":\""+CLASS+"\",\"bar\":\"baz\"}"; JsonNode jsonNode = mapper.readTree(json); assertEquals(jsonNode.get("bar").textValue(), "baz"); } public void testValueToTreeWithoutDefaultTyping() throws Exception { Foo foo = new Foo("baz"); JsonNode jsonNode = MAPPER.valueToTree(foo); assertEquals(jsonNode.get("bar").textValue(), foo.bar); } public void testValueToTreeWithDefaultTyping() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); Foo foo = new Foo("baz"); JsonNode jsonNode = mapper.valueToTree(foo); assertEquals(jsonNode.get("bar").textValue(), foo.bar); } public void testIssue353() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, "@class"); SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null, "TEST", "TEST")); testModule.addDeserializer(SavedCookie.class, new SavedCookieDeserializer()); mapper.registerModule(testModule); SavedCookie savedCookie = new SavedCookie("key", "v"); String json = mapper.writeValueAsString(savedCookie); SavedCookie out = mapper.readerFor(SavedCookie.class).readValue(json); assertEquals("key", out.name); assertEquals("v", out.value); } } TextNodeTest.java000066400000000000000000000020711325620701100346650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; public class TextNodeTest extends NodeTestBase { public void testText() { assertNull(TextNode.valueOf(null)); TextNode empty = TextNode.valueOf(""); assertStandardEquals(empty); assertSame(TextNode.EMPTY_STRING_NODE, empty); assertNodeNumbers(TextNode.valueOf("-3"), -3, -3.0); assertNodeNumbers(TextNode.valueOf("17.75"), 17, 17.75); long value = 127353264013893L; TextNode n = TextNode.valueOf(String.valueOf(value)); assertEquals(value, n.asLong()); // and then with non-numeric input n = TextNode.valueOf("foobar"); assertNodeNumbersForNonNumeric(n); assertEquals("foobar", n.asText("barf")); assertEquals("", empty.asText("xyz")); assertTrue(TextNode.valueOf("true").asBoolean(true)); assertTrue(TextNode.valueOf("true").asBoolean(false)); assertFalse(TextNode.valueOf("false").asBoolean(true)); assertFalse(TextNode.valueOf("false").asBoolean(false)); } } TreeReadViaMapperTest.java000066400000000000000000000145041325620701100364370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/nodepackage com.fasterxml.jackson.databind.node; import java.io.*; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.node.TestTreeDeserialization.Bean; /** * This unit test suite tries to verify that ObjectMapper * can properly parse JSON and bind contents into appropriate * JsonNode instances. */ public class TreeReadViaMapperTest extends BaseMapTest { public void testSimple() throws Exception { final String JSON = SAMPLE_DOC_JSON_SPEC; for (int type = 0; type < 2; ++type) { JsonNode result; if (type == 0) { result = objectMapper().readTree(new StringReader(JSON)); } else { result = objectMapper().readTree(JSON); } assertType(result, ObjectNode.class); assertEquals(1, result.size()); assertTrue(result.isObject()); ObjectNode main = (ObjectNode) result; assertEquals("Image", main.fieldNames().next()); JsonNode ob = main.elements().next(); assertType(ob, ObjectNode.class); ObjectNode imageMap = (ObjectNode) ob; assertEquals(5, imageMap.size()); ob = imageMap.get("Width"); assertTrue(ob.isIntegralNumber()); assertFalse(ob.isFloatingPointNumber()); assertEquals(SAMPLE_SPEC_VALUE_WIDTH, ob.intValue()); ob = imageMap.get("Height"); assertTrue(ob.isIntegralNumber()); assertEquals(SAMPLE_SPEC_VALUE_HEIGHT, ob.intValue()); ob = imageMap.get("Title"); assertTrue(ob.isTextual()); assertEquals(SAMPLE_SPEC_VALUE_TITLE, ob.textValue()); ob = imageMap.get("Thumbnail"); assertType(ob, ObjectNode.class); ObjectNode tn = (ObjectNode) ob; ob = tn.get("Url"); assertTrue(ob.isTextual()); assertEquals(SAMPLE_SPEC_VALUE_TN_URL, ob.textValue()); ob = tn.get("Height"); assertTrue(ob.isIntegralNumber()); assertEquals(SAMPLE_SPEC_VALUE_TN_HEIGHT, ob.intValue()); ob = tn.get("Width"); assertTrue(ob.isTextual()); assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, ob.textValue()); ob = imageMap.get("IDs"); assertTrue(ob.isArray()); ArrayNode idList = (ArrayNode) ob; assertEquals(4, idList.size()); assertEquals(4, calcLength(idList.elements())); assertEquals(4, calcLength(idList.iterator())); { int[] values = new int[] { SAMPLE_SPEC_VALUE_TN_ID1, SAMPLE_SPEC_VALUE_TN_ID2, SAMPLE_SPEC_VALUE_TN_ID3, SAMPLE_SPEC_VALUE_TN_ID4 }; for (int i = 0; i < values.length; ++i) { assertEquals(values[i], idList.get(i).intValue()); } int i = 0; for (JsonNode n : idList) { assertEquals(values[i], n.intValue()); ++i; } } } } public void testMixed() throws IOException { ObjectMapper om = new ObjectMapper(); String JSON = "{\"node\" : { \"a\" : 3 }, \"x\" : 9 }"; Bean bean = om.readValue(JSON, Bean.class); assertEquals(9, bean._x); JsonNode n = bean._node; assertNotNull(n); assertEquals(1, n.size()); ObjectNode on = (ObjectNode) n; assertEquals(3, on.get("a").intValue()); } /** * Type mappers should be able to gracefully deal with end of * input. */ public void testEOF() throws Exception { String JSON = "{ \"key\": [ { \"a\" : { \"name\": \"foo\", \"type\": 1\n" +"}, \"type\": 3, \"url\": \"http://www.google.com\" } ],\n" +"\"name\": \"xyz\", \"type\": 1, \"url\" : null }\n " ; JsonFactory jf = new JsonFactory(); JsonParser p = jf.createParser(new StringReader(JSON)); JsonNode result = objectMapper().readTree(p); assertTrue(result.isObject()); assertEquals(4, result.size()); assertNull(objectMapper().readTree(p)); p.close(); } public void testMultiple() throws Exception { String JSON = "12 \"string\" [ 1, 2, 3 ]"; JsonFactory jf = new JsonFactory(); JsonParser p = jf.createParser(new StringReader(JSON)); final ObjectMapper mapper = objectMapper(); JsonNode result = mapper.readTree(p); assertTrue(result.isIntegralNumber()); assertTrue(result.isInt()); assertFalse(result.isTextual()); assertEquals(12, result.intValue()); result = mapper.readTree(p); assertTrue(result.isTextual()); assertFalse(result.isIntegralNumber()); assertFalse(result.isInt()); assertEquals("string", result.textValue()); result = mapper.readTree(p); assertTrue(result.isArray()); assertEquals(3, result.size()); assertNull(mapper.readTree(p)); p.close(); } // [databind#1406] public void testNullFromEOFViaMapper() throws Exception { final ObjectMapper mapper = objectMapper(); assertNull(mapper.readTree(new StringReader(""))); assertNull(mapper.readTree(new ByteArrayInputStream(new byte[0]))); } // [databind#1406] public void testNullFromEOFViaObjectReader() throws Exception { final ObjectMapper mapper = objectMapper(); assertNull(mapper.readTree(new StringReader(""))); assertNull(mapper.readTree(new ByteArrayInputStream(new byte[0]))); assertNull(mapper.readerFor(JsonNode.class) .readTree(new StringReader(""))); assertNull(mapper.readerFor(JsonNode.class) .readTree(new ByteArrayInputStream(new byte[0]))); } /* /********************************************** /* Helper methods /********************************************** */ private int calcLength(Iterator it) { int count = 0; while (it.hasNext()) { it.next(); ++count; } return count; } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectid/000077500000000000000000000000001325620701100323455ustar00rootroot00000000000000AlwaysAsReferenceFirstTest.java000066400000000000000000000043141325620701100403460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class AlwaysAsReferenceFirstTest extends BaseMapTest { // [databind#1255] @JsonPropertyOrder({ "bar1", "bar2" }) static class Foo { @JsonIdentityReference(alwaysAsId = true) public Bar bar1; @JsonIdentityReference public Bar bar2; } @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) static class Bar { public int value = 3; } // [databind#1607] @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id") static class Value1607 { public int value; public Value1607() { this(0); } public Value1607(int v) { value = v; } } @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id") @JsonIdentityReference(alwaysAsId=true) static class Value1607ViaClass { public int value; public Value1607ViaClass() { this(0); } public Value1607ViaClass(int v) { value = v; } } @JsonPropertyOrder(alphabetic=true) static class ReallyAlwaysContainer { public Value1607ViaClass alwaysClass = new Value1607ViaClass(13); @JsonIdentityReference(alwaysAsId=true) public Value1607 alwaysProp = new Value1607(13); } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); // [databind#1255] public void testIssue1255() throws Exception { Foo mo = new Foo(); mo.bar1 = new Bar(); mo.bar2 = mo.bar1; String json = MAPPER.writeValueAsString(mo); Foo result = MAPPER.readValue(json, Foo.class); assertNotNull(result); } // [databind#1607] public void testIssue1607() throws Exception { String json = MAPPER.writeValueAsString(new ReallyAlwaysContainer()); assertEquals(aposToQuotes("{'alwaysClass':1,'alwaysProp':2}"), json); } } JSOGDeserialize622Test.java000066400000000000000000000161441325620701100371540ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.io.IOException; /** * Unit test(s) for [databind#622], supporting non-scalar-Object-ids, * to support things like JSOG. */ public class JSOGDeserialize622Test extends BaseMapTest { /** the key of the property that holds the ref */ public static final String REF_KEY = "@ref"; /** * JSON input */ private static final String EXP_EXAMPLE_JSOG = aposToQuotes( "{'@id':'1','foo':66,'next':{'"+REF_KEY+"':'1'}}"); /** * Customer IdGenerator */ static class JSOGGenerator extends ObjectIdGenerator { private static final long serialVersionUID = 1L; protected transient int _nextValue; protected final Class _scope; protected JSOGGenerator() { this(null, -1); } protected JSOGGenerator(Class scope, int nextValue) { _scope = scope; _nextValue = nextValue; } @Override public Class getScope() { return _scope; } @Override public boolean canUseFor(ObjectIdGenerator gen) { return (gen.getClass() == getClass()) && (gen.getScope() == _scope); } @Override public ObjectIdGenerator forScope(Class scope) { return (_scope == scope) ? this : new JSOGGenerator(scope, _nextValue); } @Override public ObjectIdGenerator newForSerialization(Object context) { return new JSOGGenerator(_scope, 1); } @Override public com.fasterxml.jackson.annotation.ObjectIdGenerator.IdKey key(Object key) { return new IdKey(getClass(), _scope, key); } // important: otherwise won't get proper handling @Override public boolean maySerializeAsObject() { return true; } // ditto: needed for handling Object-valued Object references @Override public boolean isValidReferencePropertyName(String name, Object parser) { return REF_KEY.equals(name); } @Override public JSOGRef generateId(Object forPojo) { int id = _nextValue; ++_nextValue; return new JSOGRef(id); } } /** * The reference deserializer */ static class JSOGRefDeserializer extends JsonDeserializer { @Override public JSOGRef deserialize(JsonParser p, DeserializationContext ctx) throws IOException { JsonNode node = p.readValueAsTree(); if (node.isTextual()) { return new JSOGRef(node.asInt()); } JsonNode n = node.get(REF_KEY); if (n == null) { throw new JsonMappingException(p, "Could not find key '"+REF_KEY +"' from ("+node.getClass().getName()+"): "+node); } return new JSOGRef(n.asInt()); } } /** * The reference object */ @JsonDeserialize(using=JSOGRefDeserializer.class) static class JSOGRef { @JsonProperty(REF_KEY) public int ref; public JSOGRef() { } public JSOGRef(int val) { ref = val; } @Override public String toString() { return "[JSOGRef#"+ref+"]"; } @Override public int hashCode() { return ref; } @Override public boolean equals(Object other) { return (other instanceof JSOGRef) && ((JSOGRef) other).ref == this.ref; } } /** * Example class using JSOGGenerator */ @JsonIdentityInfo(generator=JSOGGenerator.class, property="@id") public static class IdentifiableExampleJSOG { public int foo; public IdentifiableExampleJSOG next; protected IdentifiableExampleJSOG() { } public IdentifiableExampleJSOG(int v) { foo = v; } } public static class JSOGWrapper { public int value; @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) public Object jsog; JSOGWrapper() { } public JSOGWrapper(int v) { value = v; } } // For [databind#669] @JsonIdentityInfo(generator=JSOGGenerator.class) @JsonTypeInfo(use=Id.CLASS, include= As.PROPERTY, property="@class") public static class Inner { public String bar; protected Inner() {} public Inner(String bar) { this.bar = bar; } } public static class SubInner extends Inner { public String extra; protected SubInner() {} public SubInner(String bar, String extra) { super(bar); this.extra = extra; } } @JsonIdentityInfo(generator=JSOGGenerator.class) public static class Outer { public String foo; public Inner inner1; public Inner inner2; } /* /********************************************************************** /* Test methods /********************************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); // Basic for [databind#622] public void testStructJSOGRef() throws Exception { IdentifiableExampleJSOG result = MAPPER.readValue(EXP_EXAMPLE_JSOG, IdentifiableExampleJSOG.class); assertEquals(66, result.foo); assertSame(result, result.next); } // polymorphic alternative for [databind#622] public void testPolymorphicRoundTrip() throws Exception { JSOGWrapper w = new JSOGWrapper(15); // create a nice little loop IdentifiableExampleJSOG ex = new IdentifiableExampleJSOG(123); ex.next = ex; w.jsog = ex; String json = MAPPER.writeValueAsString(w); JSOGWrapper out = MAPPER.readValue(json, JSOGWrapper.class); assertNotNull(out); assertEquals(15, out.value); assertTrue(out.jsog instanceof IdentifiableExampleJSOG); IdentifiableExampleJSOG jsog = (IdentifiableExampleJSOG) out.jsog; assertEquals(123, jsog.foo); assertSame(jsog, jsog.next); } // polymorphic alternative for [databind#669] public void testAlterativePolymorphicRoundTrip669() throws Exception { Outer outer = new Outer(); outer.foo = "foo"; outer.inner1 = outer.inner2 = new SubInner("bar", "extra"); String jsog = MAPPER.writeValueAsString(outer); Outer back = MAPPER.readValue(jsog, Outer.class); assertSame(back.inner1, back.inner2); } } ObjectId687Test.java000066400000000000000000000072421325620701100357260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class ObjectId687Test extends BaseMapTest { // for [databind#687] @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="label") static class ReferredWithCreator { public String label; @JsonCreator ReferredWithCreator(@JsonProperty("label")String label) { this.label = label; } } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="label") static class ReferringToObjWithCreator { public String label = "test1"; public List refs = new ArrayList(); public void addRef(ReferredWithCreator r) { refs.add(r); } } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="label") static class EnclosingForRefsWithCreator { public String label = "enclosing1"; public ReferredWithCreator baseRef; public ReferringToObjWithCreator nextRef; } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="label") static class ReferredWithNoCreator { public String label = "label2"; } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="label") static class ReferringToObjWithNoCreator { public String label = "test2"; public List refs = new ArrayList(); public void addRef(ReferredWithNoCreator r) { refs.add(r); } } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="label") static class EnclosingForRefWithNoCreator { public String label = "enclosing2"; public ReferredWithNoCreator baseRef; public ReferringToObjWithNoCreator nextRef; } /* /***************************************************** /* Test methods /***************************************************** */ private final ObjectMapper MAPPER = objectMapper(); // for [databind#687] public void testSerializeDeserializeWithCreator() throws IOException { ReferredWithCreator base = new ReferredWithCreator("label1"); ReferringToObjWithCreator r = new ReferringToObjWithCreator(); r.addRef(base); EnclosingForRefsWithCreator e = new EnclosingForRefsWithCreator(); e.baseRef = base; e.nextRef = r; String json = MAPPER.writeValueAsString(e); EnclosingForRefsWithCreator result = MAPPER.readValue(json, EnclosingForRefsWithCreator.class); assertNotNull(result); assertEquals(result.label, e.label); // also, compare by re-serializing: assertEquals(json, MAPPER.writeValueAsString(result)); } public void testSerializeDeserializeNoCreator() throws IOException { ReferredWithNoCreator base = new ReferredWithNoCreator(); ReferringToObjWithNoCreator r = new ReferringToObjWithNoCreator(); r.addRef(base); EnclosingForRefWithNoCreator e = new EnclosingForRefWithNoCreator(); e.baseRef = base; e.nextRef = r; String json = MAPPER.writeValueAsString(e); EnclosingForRefWithNoCreator result = MAPPER.readValue(json, EnclosingForRefWithNoCreator.class); assertNotNull(result); assertEquals(result.label, e.label); // also, compare by re-serializing: assertEquals(json, MAPPER.writeValueAsString(result)); } } ObjectId825BTest.java000066400000000000000000000126201325620701100360160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import java.util.ArrayList; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; @SuppressWarnings("serial") public class ObjectId825BTest extends BaseMapTest { static abstract class AbstractAct extends AbstractEntity { protected java.util.ArrayList outTr; public java.util.ArrayList getOutTr() { return this.outTr; } public void setOutTr(java.util.ArrayList outTr) { this.outTr = outTr; } } static abstract class AbstractCond extends AbstractAct { } static abstract class AbstractData extends AbstractSym { } static abstract class AbstractDec extends AbstractAct { protected java.util.ArrayList dec; public java.util.ArrayList getDec() { return this.dec; } public void setDec(java.util.ArrayList dec) { this.dec = dec; } } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="oidString") @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") static abstract class AbstractEntity implements java.io.Serializable { public String oidString; protected AbstractEntity() { } public String getOidString() { return oidString; } public void setOidString(String oidString) { this.oidString = oidString; } } static abstract class AbstractSym extends AbstractEntity { } static class Ch extends AbstractEntity { protected java.util.ArrayList act; public java.util.ArrayList getAct() { return this.act; } public void setAct(java.util.ArrayList act) { this.act = act; } } static class CTC extends AbstractEntity { protected java.util.ArrayList var; public CTC() { } public java.util.ArrayList getVar() { if (var == null) { var = new ArrayList(); } return new ArrayList(var); } public void setVar(java.util.ArrayList var) { this.var = var; } } static class CTD extends AbstractDec { } static class CTV extends AbstractEntity { protected Ch ch; protected java.util.ArrayList locV; public Ch getCh() { return this.ch; } public void setCh(Ch ch) { this.ch = ch; } public java.util.ArrayList getLocV() { return this.locV; } public void setLocV(java.util.ArrayList locV) { this.locV = locV; } } static class Dec extends AbstractCond { } static class Ti extends AbstractAct { protected AbstractData timer; public AbstractData getTimer() { return this.timer; } public void setTimer(AbstractData timer) { this.timer = timer; } } static class Tr extends AbstractEntity { protected AbstractAct target; public AbstractAct getTarget() { return this.target; } public void setTarget(AbstractAct target) { this.target = target; } } static class V extends AbstractData { private static final long serialVersionUID = 1L; } public void testFull825() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); String INPUT = aposToQuotes( "{\n"+ " '@class': '_PKG_CTC',\n"+ " 'var': [{\n"+ " 'ch': {\n"+ " '@class': '_PKG_Ch',\n"+ " 'act': [{\n"+ " '@class': '_PKG_CTD',\n"+ " 'oidString': 'oid1',\n"+ " 'dec': [{\n"+ " '@class': '_PKG_Dec',\n"+ " 'oidString': 'oid2',\n"+ " 'outTr': [{\n"+ " '@class': '_PKG_Tr',\n"+ " 'target': {\n"+ " '@class': '_PKG_Ti',\n"+ " 'oidString': 'oid3',\n"+ " 'timer': 'problemoid',\n"+ " 'outTr': [{\n"+ " '@class': '_PKG_Tr',\n"+ " 'target': {\n"+ " '@class': '_PKG_Ti',\n"+ " 'oidString': 'oid4',\n"+ " 'timer': {\n"+ " '@class': '_PKG_V',\n"+ " 'oidString': 'problemoid'\n"+ " }\n"+ " }\n"+ " }]\n"+ " }\n"+ " }]\n"+ " }]\n"+ " }],\n"+ " 'oidString': 'oid5'\n"+ " },\n"+ " '@class': '_PKG_CTV',\n"+ " 'oidString': 'oid6',\n"+ " 'locV': ['problemoid']\n"+ " }],\n"+ " 'oidString': 'oid7'\n"+ "}\n" ); // also replace package final String newPkg = getClass().getName() + "\\$"; INPUT = INPUT.replaceAll("_PKG_", newPkg); CTC result = mapper.readValue(INPUT, CTC.class); assertNotNull(result); } } ObjectId825Test.java000066400000000000000000000027201325620701100357140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class ObjectId825Test extends BaseMapTest { @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="oidString") public static class AbstractEntity { public String oidString; } public static class TestA extends AbstractEntity { public TestAbst testAbst; public TestD d; } static class TestAbst extends AbstractEntity { } static class TestC extends TestAbst { public TestD d; } static class TestD extends AbstractEntity { } private final ObjectMapper DEF_TYPING_MAPPER = new ObjectMapper(); { DEF_TYPING_MAPPER.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); } public void testDeserialize() throws Exception { TestA a = new TestA(); a.oidString = "oidA"; TestC c = new TestC(); c.oidString = "oidC"; a.testAbst = c; TestD d = new TestD(); d.oidString = "oidD"; c.d = d; a.d = d; String json = DEF_TYPING_MAPPER.writeValueAsString(a); // System.out.println("JSON: " + json); TestA testADeserialized = DEF_TYPING_MAPPER.readValue(json, TestA.class); assertNotNull(testADeserialized); assertNotNull(testADeserialized.d); assertEquals("oidD", testADeserialized.d.oidString); } } ObjectIdReordering1388Test.java000066400000000000000000000063251325620701100400270ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class ObjectIdReordering1388Test extends BaseMapTest { @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) public static class NamedThing { private final UUID id; private final String name; @JsonCreator public NamedThing(@JsonProperty("id") UUID id, @JsonProperty("name") String name) { this.id = id; this.name = name; } public UUID getId() { return id; } public String getName() { return name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; NamedThing that = (NamedThing) o; return that.id.equals(id) && that.name.equals(name); } @Override public int hashCode() { return name.hashCode(); } } public void testDeserializationFinalClassJSOG() throws Exception { final ObjectMapper mapper = new ObjectMapper(); final UUID id = UUID.fromString("a59aa02c-fe3c-43f8-9b5a-5fe01878a818"); final NamedThing thing = new NamedThing(id, "Hello"); final TypeReference namedThingListType = new TypeReference>() { }; { final String jsog = mapper.writeValueAsString(Arrays.asList(thing, thing, thing)); final List list = mapper.readValue(jsog, namedThingListType); _assertAllSame(list); // this is the jsog representation of the list of 3 of the same item assertTrue(jsog.equals("[{\"@id\":1,\"id\":\"a59aa02c-fe3c-43f8-9b5a-5fe01878a818\",\"name\":\"Hello\"},1,1]")); } // now move it around it have forward references // this works { final String json = "[1,1,{\"@id\":1,\"id\":\"a59aa02c-fe3c-43f8-9b5a-5fe01878a818\",\"name\":\"Hello\"}]"; final List forward = mapper.readValue(json, namedThingListType); _assertAllSame(forward); } // next, move @id to between properties { final String json = aposToQuotes("[{'id':'a59aa02c-fe3c-43f8-9b5a-5fe01878a818','@id':1,'name':'Hello'}, 1, 1]"); final List forward = mapper.readValue(json, namedThingListType); _assertAllSame(forward); } // and last, move @id to be not the first key in the object { final String json = aposToQuotes("[{'id':'a59aa02c-fe3c-43f8-9b5a-5fe01878a818','name':'Hello','@id':1}, 1, 1]"); final List forward = mapper.readValue(json, namedThingListType); _assertAllSame(forward); } } private void _assertAllSame(List entries) { Object first = entries.get(0); for (int i = 0, end = entries.size(); i < end; ++i) { if (first != entries.get(i)) { fail("Mismatch: entry #"+i+" not same as #0"); } } } } ObjectWithCreator1261Test.java000066400000000000000000000066061325620701100376750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class ObjectWithCreator1261Test extends BaseMapTest { static class Answer { public SortedMap parents; public Answer() { parents = new TreeMap(); } } @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id") static class Parent { public Map children; @JsonIdentityReference(alwaysAsId = true) public Child favoriteChild; public String name; protected Parent() { } public Parent(String name, boolean ignored) { children = new TreeMap(); this.name = name; } } @JsonInclude(JsonInclude.Include.NON_NULL) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id") static class Child { public String name; @JsonIdentityReference(alwaysAsId = true) public Parent parent; @JsonIdentityReference(alwaysAsId = true) public List parentAsList; public String someNullProperty; protected Child() { } @JsonCreator public Child(@JsonProperty("name") String name, @JsonProperty("someNullProperty") String someNullProperty) { this.name = name; this.someNullProperty = someNullProperty; } public Child(String n) { name = n; } } public void testObjectIds1261() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.INDENT_OUTPUT); mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); Answer initialAnswer = createInitialAnswer(); String initialAnswerString = mapper.writeValueAsString(initialAnswer); // System.out.println("Initial answer:\n"+initialAnswerString); JsonNode tree = mapper.readTree(initialAnswerString); Answer deserializedAnswer = mapper.readValue(initialAnswerString, Answer.class); String reserializedAnswerString = mapper .writeValueAsString(deserializedAnswer); JsonNode newTree = mapper.readTree(reserializedAnswerString); if (!tree.equals(newTree)) { fail("Original and recovered Json are different. Recovered = \n" + reserializedAnswerString + "\n"); } } private Answer createInitialAnswer() { Answer answer = new Answer(); String child1Name = "child1"; String child2Name = "child2"; String parent1Name = "parent1"; String parent2Name = "parent2"; Parent parent1 = new Parent(parent1Name, false); answer.parents.put(parent1Name, parent1); Child child1 = new Child(child1Name); child1.parent = parent1; child1.parentAsList = Collections.singletonList(parent1); Child child2 = new Child(child2Name); Parent parent2 = new Parent(parent2Name, false); child2.parent = parent2; child2.parentAsList = Collections.singletonList(parent2); parent1.children.put(child1Name, child1); parent1.children.put(child2Name, child2); answer.parents.put(parent2Name, parent2); return answer; } } PolymorphicWithObjectId1551Test.java000066400000000000000000000071101325620701100410510ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; public class PolymorphicWithObjectId1551Test extends BaseMapTest { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") static abstract class Vehicle { public String vehicleId; } static class Car extends Vehicle { public int numberOfDoors; } static class VehicleOwnerViaProp { @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "vehicleId") @JsonIdentityReference(alwaysAsId = false) public Vehicle ownedVehicle; } static class VehicleOwnerBroken { @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "bogus") @JsonIdentityReference(alwaysAsId = false) public Vehicle ownedVehicle; } public void testWithAbstractUsingProp() throws Exception { Car c = new Car(); c.vehicleId = "123"; c.numberOfDoors = 2; // both owners own the same vehicle (car sharing ;-)) VehicleOwnerViaProp v1 = new VehicleOwnerViaProp(); v1.ownedVehicle = c; VehicleOwnerViaProp v2 = new VehicleOwnerViaProp(); v2.ownedVehicle = c; ObjectMapper objectMapper = new ObjectMapper(); String serialized = objectMapper.writer() .writeValueAsString(new VehicleOwnerViaProp[] { v1, v2 }); // 02-May-2017, tatu: Not possible to support as of Jackson 2.8 at least, so: VehicleOwnerViaProp[] deserialized = objectMapper.readValue(serialized, VehicleOwnerViaProp[].class); assertEquals(2, deserialized.length); assertSame(deserialized[0].ownedVehicle, deserialized[1].ownedVehicle); } public void testFailingAbstractUsingProp() throws Exception { Car c = new Car(); c.vehicleId = "123"; c.numberOfDoors = 2; // both owners own the same vehicle (car sharing ;-)) VehicleOwnerBroken v1 = new VehicleOwnerBroken(); v1.ownedVehicle = c; VehicleOwnerBroken v2 = new VehicleOwnerBroken(); v2.ownedVehicle = c; ObjectMapper objectMapper = new ObjectMapper(); try { objectMapper.writer() .writeValueAsString(new VehicleOwnerBroken[] { v1, v2 }); } catch (InvalidDefinitionException e) { // on serialization, reported for different type assertEquals(Car.class, e.getType().getRawClass()); verifyException(e, "Invalid Object Id definition"); verifyException(e, "cannot find property with name 'bogus'"); } // and same for deser final String JSON = aposToQuotes( "[{'ownedVehicle':{'@class':'com.fasterxml.jackson.failing.PolymorphicWithObjectId1551Test$Car','vehicleId':'123'," +"'numberOfDoors':2}},{'ownedVehicle':'123'}]" ); try { objectMapper.readValue(JSON, VehicleOwnerBroken[].class); fail("Should not pass"); } catch (InvalidDefinitionException e) { assertEquals(Vehicle.class, e.getType().getRawClass()); verifyException(e, "Invalid Object Id definition"); verifyException(e, "cannot find property with name 'bogus'"); } } } ReferentialWithObjectIdTest.java000066400000000000000000000036071325620701100404770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.*; public class ReferentialWithObjectIdTest extends BaseMapTest { public static class EmployeeList { public AtomicReference first; } @JsonIdentityInfo(property="id", generator=ObjectIdGenerators.PropertyGenerator.class) public static class Employee { public int id; public String name; public AtomicReference next; public Employee next(Employee n) { next = new AtomicReference(n); return this; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testAtomicWithObjectId() throws Exception { Employee first = new Employee(); first.id = 1; first.name = "Alice"; Employee second = new Employee(); second.id = 2; second.name = "Bob"; first.next(second); second.next(first); EmployeeList input = new EmployeeList(); input.first = new AtomicReference(first); String json = MAPPER.writeValueAsString(input); // and back EmployeeList result = MAPPER.readValue(json, EmployeeList.class); Employee firstB = result.first.get(); assertNotNull(firstB); assertEquals("Alice", firstB.name); Employee secondB = firstB.next.get(); assertNotNull(secondB); assertEquals("Bob", secondB.name); assertNotNull(secondB.next.get()); assertSame(firstB, secondB.next.get()); } } TestAbstractWithObjectId.java000066400000000000000000000040751325620701100400020ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import java.util.*; public class TestAbstractWithObjectId extends BaseMapTest { interface BaseInterface { } @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id") static class BaseInterfaceImpl implements BaseInterface { @JsonProperty private List myInstances = new ArrayList(); void addInstance(BaseInterfaceImpl instance) { myInstances.add(instance); } } static class ListWrapper { @JsonProperty private List myList = new ArrayList(); void add(T t) { myList.add(t); } int size() { return myList.size(); } } public void testIssue877() throws Exception { // make two instances BaseInterfaceImpl one = new BaseInterfaceImpl(); BaseInterfaceImpl two = new BaseInterfaceImpl(); // add them to each other's list to show identify info being used one.addInstance(two); two.addInstance(one); // make a typed version of the list and add the 2 instances to it ListWrapper myList = new ListWrapper(); myList.add(one); myList.add(two); // make an object mapper that will add class info in so deserialisation works ObjectMapper om = new ObjectMapper(); om.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, "@class"); // write and print the JSON String json = om.writerWithDefaultPrettyPrinter().writeValueAsString(myList); ListWrapper result; result = om.readValue(json, new TypeReference>() { }); assertNotNull(result); // see what we get back assertEquals(2, result.size()); } } TestObjectId.java000066400000000000000000000134421325620701100354600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestObjectId extends BaseMapTest { @JsonPropertyOrder({"a", "b"}) static class Wrapper { public ColumnMetadata a, b; } @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") static class ColumnMetadata { private final String name; private final String type; private final String comment; @JsonCreator public ColumnMetadata( @JsonProperty("name") String name, @JsonProperty("type") String type, @JsonProperty("comment") String comment ) { this.name = name; this.type = type; this.comment = comment; } @JsonProperty("name") public String getName() { return name; } @JsonProperty("type") public String getType() { return type; } @JsonProperty("comment") public String getComment() { return comment; } } /* Problem in which always-as-id reference may prevent initial * serialization of a POJO. */ static class Company { public List employees; public void add(Employee e) { if (employees == null) { employees = new ArrayList(); } employees.add(e); } } @JsonIdentityInfo(property="id", generator=ObjectIdGenerators.PropertyGenerator.class) public static class Employee { public int id; public String name; @JsonIdentityReference(alwaysAsId=true) public Employee manager; @JsonIdentityReference(alwaysAsId=true) public List reports; public Employee() { } public Employee(int id, String name, Employee manager) { this.id = id; this.name = name; this.manager = manager; reports = new ArrayList(); } public Employee addReport(Employee e) { reports.add(e); return this; } } @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") public static class BaseEntity { } public static class Foo extends BaseEntity { public BaseEntity ref; } public static class Bar extends BaseEntity { public Foo next; } // for [databind#1083] @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = JsonMapSchema.class) @JsonSubTypes({ @JsonSubTypes.Type(value = JsonMapSchema.class, name = "map"), @JsonSubTypes.Type(value = JsonJdbcSchema.class, name = "jdbc") }) public static abstract class JsonSchema { public String name; } static class JsonMapSchema extends JsonSchema { } static class JsonJdbcSchema extends JsonSchema { } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testColumnMetadata() throws Exception { ColumnMetadata col = new ColumnMetadata("Billy", "employee", "comment"); Wrapper w = new Wrapper(); w.a = col; w.b = col; String json = MAPPER.writeValueAsString(w); Wrapper deserialized = MAPPER.readValue(json, Wrapper.class); assertNotNull(deserialized); assertNotNull(deserialized.a); assertNotNull(deserialized.b); assertEquals("Billy", deserialized.a.getName()); assertEquals("employee", deserialized.a.getType()); assertEquals("comment", deserialized.a.getComment()); assertSame(deserialized.a, deserialized.b); } // For [databind#188] public void testMixedRefsIssue188() throws Exception { Company comp = new Company(); Employee e1 = new Employee(1, "First", null); Employee e2 = new Employee(2, "Second", e1); e1.addReport(e2); comp.add(e1); comp.add(e2); String json = MAPPER.writeValueAsString(comp); assertEquals("{\"employees\":[" +"{\"id\":1,\"name\":\"First\",\"manager\":null,\"reports\":[2]}," +"{\"id\":2,\"name\":\"Second\",\"manager\":1,\"reports\":[]}" +"]}", json); } public void testObjectAndTypeId() throws Exception { final ObjectMapper mapper = new ObjectMapper(); Bar inputRoot = new Bar(); Foo inputChild = new Foo(); inputRoot.next = inputChild; inputChild.ref = inputRoot; String json = mapper.writerWithDefaultPrettyPrinter() .writeValueAsString(inputRoot); BaseEntity resultRoot = mapper.readValue(json, BaseEntity.class); assertNotNull(resultRoot); assertTrue(resultRoot instanceof Bar); Bar first = (Bar) resultRoot; assertNotNull(first.next); assertTrue(first.next instanceof Foo); Foo second = (Foo) first.next; assertNotNull(second.ref); assertSame(first, second.ref); } public static class JsonRoot { public final List schemas = new ArrayList(); } public void testWithFieldsInBaseClass1083() throws Exception { final String json = aposToQuotes("{'schemas': [{\n" + " 'name': 'FoodMart'\n" + "}]}\n"); MAPPER.readValue(json, JsonRoot.class); } } TestObjectIdDeserialization.java000066400000000000000000000426341325620701100405340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.ObjectIdGenerator.IdKey; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.annotation.ObjectIdResolver; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.cfg.ContextAttributes; import com.fasterxml.jackson.databind.deser.UnresolvedForwardReference; import com.fasterxml.jackson.databind.deser.UnresolvedId; import com.fasterxml.jackson.databind.objectid.TestObjectId.Company; import com.fasterxml.jackson.databind.objectid.TestObjectId.Employee; /** * Unit test to verify handling of Object Id deserialization */ public class TestObjectIdDeserialization extends BaseMapTest { private static final String POOL_KEY = "POOL"; // // Classes for external id use @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id") static class Identifiable { public int value; public Identifiable next; public Identifiable() { this(0); } public Identifiable(int v) { value = v; } } @JsonIdentityInfo(generator=ObjectIdGenerators.UUIDGenerator.class, property="#") static class UUIDNode { public int value; public UUIDNode parent; public UUIDNode first; public UUIDNode second; public UUIDNode() { this(0); } public UUIDNode(int v) { value = v; } } // // Classes for external id from property annotations: static class IdWrapper { @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") public ValueNode node; public IdWrapper() { } public IdWrapper(int v) { node = new ValueNode(v); } } static class ValueNode { public int value; public IdWrapper next; public ValueNode() { this(0); } public ValueNode(int v) { value = v; } } // // Classes for external id use @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="customId") static class IdentifiableCustom { public int value; public int customId; public IdentifiableCustom next; public IdentifiableCustom() { this(-1, 0); } public IdentifiableCustom(int i, int v) { customId = i; value = v; } } static class IdWrapperExt { @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="customId") public ValueNodeExt node; public IdWrapperExt() { } public IdWrapperExt(int v) { node = new ValueNodeExt(v); } } static class ValueNodeExt { public int value; protected int customId; public IdWrapperExt next; public ValueNodeExt() { this(0); } public ValueNodeExt(int v) { value = v; } public void setCustomId(int i) { customId = i; } } static class MappedCompany { public Map employees; } @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) static class AnySetterObjectId { protected Map values = new HashMap(); @JsonAnySetter public void anySet(String field, AnySetterObjectId value) { // Ensure that it is never called with null because of unresolved reference. assertNotNull(value); values.put(field, value); } } static class CustomResolutionWrapper { public List data; } @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", resolver = PoolResolver.class) @JsonIdentityReference(alwaysAsId = true) // #524 static class WithCustomResolution { public int id; public int data; public WithCustomResolution(int id, int data) { this.id = id; this.data = data; } } public static class PoolResolver implements ObjectIdResolver { private Map _pool; public PoolResolver() {} public PoolResolver(Map pool){ _pool = pool; } @Override public void bindItem(IdKey id, Object pojo){ } @Override public Object resolveId(IdKey id){ return _pool.get(id.key); } @Override public boolean canUseFor(ObjectIdResolver resolverType) { return resolverType.getClass() == getClass() && _pool != null && !_pool.isEmpty(); } @Override public ObjectIdResolver newForDeserialization(Object c) { DeserializationContext context = (DeserializationContext)c; @SuppressWarnings("unchecked") Map pool = (Map)context.getAttribute(POOL_KEY); return new PoolResolver(pool); } } /* /***************************************************** /* Unit tests, external id deserialization /***************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); private final static String EXP_SIMPLE_INT_CLASS = "{\"id\":1,\"value\":13,\"next\":1}"; public void testSimpleDeserializationClass() throws Exception { // then bring back... Identifiable result = MAPPER.readValue(EXP_SIMPLE_INT_CLASS, Identifiable.class); assertEquals(13, result.value); assertSame(result, result.next); } // Should be ok NOT to have Object id, as well public void testMissingObjectId() throws Exception { Identifiable result = MAPPER.readValue(aposToQuotes("{'value':28, 'next':{'value':29}}"), Identifiable.class); assertNotNull(result); assertEquals(28, result.value); assertNotNull(result.next); assertEquals(29, result.next.value); } public void testSimpleUUIDForClassRoundTrip() throws Exception { UUIDNode root = new UUIDNode(1); UUIDNode child1 = new UUIDNode(2); UUIDNode child2 = new UUIDNode(3); root.first = child1; root.second = child2; child1.parent = root; child2.parent = root; child1.first = child2; String json = MAPPER.writeValueAsString(root); // and should come back the same too... UUIDNode result = MAPPER.readValue(json, UUIDNode.class); assertEquals(1, result.value); UUIDNode result2 = result.first; UUIDNode result3 = result.second; assertNotNull(result2); assertNotNull(result3); assertEquals(2, result2.value); assertEquals(3, result3.value); assertSame(result, result2.parent); assertSame(result, result3.parent); assertSame(result3, result2.first); } // Bit more complex, due to extra wrapping etc: private final static String EXP_SIMPLE_INT_PROP = "{\"node\":{\"@id\":1,\"value\":7,\"next\":{\"node\":1}}}"; public void testSimpleDeserializationProperty() throws Exception { IdWrapper result = MAPPER.readValue(EXP_SIMPLE_INT_PROP, IdWrapper.class); assertEquals(7, result.node.value); assertSame(result.node, result.node.next.node); } // Another test to ensure ordering is not required (i.e. can do front references) public void testSimpleDeserWithForwardRefs() throws Exception { IdWrapper result = MAPPER.readValue("{\"node\":{\"value\":7,\"next\":{\"node\":1}, \"@id\":1}}" ,IdWrapper.class); assertEquals(7, result.node.value); assertSame(result.node, result.node.next.node); } public void testForwardReference() throws Exception { String json = "{\"employees\":[" + "{\"id\":1,\"name\":\"First\",\"manager\":2,\"reports\":[]}," + "{\"id\":2,\"name\":\"Second\",\"manager\":null,\"reports\":[1]}" + "]}"; Company company = MAPPER.readValue(json, Company.class); assertEquals(2, company.employees.size()); Employee firstEmployee = company.employees.get(0); Employee secondEmployee = company.employees.get(1); assertEquals(1, firstEmployee.id); assertEquals(2, secondEmployee.id); assertEquals(secondEmployee, firstEmployee.manager); // Ensure that forward reference was properly resolved. assertEquals(firstEmployee, secondEmployee.reports.get(0)); // And that back reference is also properly resolved. } public void testForwardReferenceInCollection() throws Exception { String json = "{\"employees\":[" + "{\"id\":1,\"name\":\"First\",\"manager\":null,\"reports\":[2]}," + "{\"id\":2,\"name\":\"Second\",\"manager\":1,\"reports\":[]}" + "]}"; Company company = MAPPER.readValue(json, Company.class); assertEquals(2, company.employees.size()); Employee firstEmployee = company.employees.get(0); Employee secondEmployee = company.employees.get(1); assertEmployees(firstEmployee, secondEmployee); } public void testForwardReferenceInMap() throws Exception { String json = "{\"employees\":{" + "\"1\":{\"id\":1,\"name\":\"First\",\"manager\":null,\"reports\":[2]}," + "\"2\": 2," + "\"3\":{\"id\":2,\"name\":\"Second\",\"manager\":1,\"reports\":[]}" + "}}"; MappedCompany company = MAPPER.readValue(json, MappedCompany.class); assertEquals(3, company.employees.size()); Employee firstEmployee = company.employees.get(1); Employee secondEmployee = company.employees.get(3); assertEmployees(firstEmployee, secondEmployee); } private void assertEmployees(Employee firstEmployee, Employee secondEmployee) { assertEquals(1, firstEmployee.id); assertEquals(2, secondEmployee.id); assertEquals(1, firstEmployee.reports.size()); assertSame(secondEmployee, firstEmployee.reports.get(0)); // Ensure that forward reference was properly resolved and in order. assertSame(firstEmployee, secondEmployee.manager); // And that back reference is also properly resolved. } public void testForwardReferenceAnySetterCombo() throws Exception { String json = "{\"@id\":1, \"foo\":2, \"bar\":{\"@id\":2, \"foo\":1}}"; AnySetterObjectId value = MAPPER.readValue(json, AnySetterObjectId.class); assertSame(value.values.get("bar"), value.values.get("foo")); } public void testUnresolvedForwardReference() throws Exception { String json = "{\"employees\":[" + "{\"id\":1,\"name\":\"First\",\"manager\":null,\"reports\":[3]}," + "{\"id\":2,\"name\":\"Second\",\"manager\":3,\"reports\":[]}" + "]}"; try { MAPPER.readValue(json, Company.class); fail("Should have thrown."); } catch (UnresolvedForwardReference exception) { // Expected List unresolvedIds = exception.getUnresolvedIds(); assertEquals(2, unresolvedIds.size()); UnresolvedId firstUnresolvedId = unresolvedIds.get(0); assertEquals(3, firstUnresolvedId.getId()); assertEquals(Employee.class, firstUnresolvedId.getType()); UnresolvedId secondUnresolvedId = unresolvedIds.get(1); assertEquals(firstUnresolvedId.getId(), secondUnresolvedId.getId()); assertEquals(Employee.class, secondUnresolvedId.getType()); } } // [databind#299]: Allow unresolved ids to become nulls public void testUnresolvableAsNull() throws Exception { IdWrapper w = MAPPER.readerFor(IdWrapper.class) .without(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS) .readValue(aposToQuotes("{'node':123}")); assertNotNull(w); assertNull(w.node); } public void testKeepCollectionOrdering() throws Exception { String json = "{\"employees\":[2,1," + "{\"id\":1,\"name\":\"First\",\"manager\":null,\"reports\":[2]}," + "{\"id\":2,\"name\":\"Second\",\"manager\":1,\"reports\":[]}" + "]}"; Company company = MAPPER.readValue(json, Company.class); assertEquals(4, company.employees.size()); // Deser must keep object ordering. Employee firstEmployee = company.employees.get(1); Employee secondEmployee = company.employees.get(0); assertSame(firstEmployee, company.employees.get(2)); assertSame(secondEmployee, company.employees.get(3)); assertEmployees(firstEmployee, secondEmployee); } public void testKeepMapOrdering() throws Exception { String json = "{\"employees\":{" + "\"1\":2, \"2\":1," + "\"3\":{\"id\":1,\"name\":\"First\",\"manager\":null,\"reports\":[2]}," + "\"4\":{\"id\":2,\"name\":\"Second\",\"manager\":1,\"reports\":[]}" + "}}"; MappedCompany company = MAPPER.readValue(json, MappedCompany.class); assertEquals(4, company.employees.size()); Employee firstEmployee = company.employees.get(2); Employee secondEmployee = company.employees.get(1); assertEmployees(firstEmployee, secondEmployee); // Deser must keep object ordering. Not sure if it's really important for maps, // but since default map is LinkedHashMap might as well ensure it does... Iterator> iterator = company.employees.entrySet().iterator(); assertSame(secondEmployee, iterator.next().getValue()); assertSame(firstEmployee, iterator.next().getValue()); assertSame(firstEmployee, iterator.next().getValue()); assertSame(secondEmployee, iterator.next().getValue()); } /* /***************************************************** /* Unit tests, custom (property-based) id deserialization /***************************************************** */ private final static String EXP_CUSTOM_VIA_CLASS = "{\"customId\":123,\"value\":-900,\"next\":123}"; public void testCustomDeserializationClass() throws Exception { // then bring back... IdentifiableCustom result = MAPPER.readValue(EXP_CUSTOM_VIA_CLASS, IdentifiableCustom.class); assertEquals(-900, result.value); assertSame(result, result.next); } private final static String EXP_CUSTOM_VIA_PROP = "{\"node\":{\"customId\":3,\"value\":99,\"next\":{\"node\":3}}}"; public void testCustomDeserializationProperty() throws Exception { // then bring back... IdWrapperExt result = MAPPER.readValue(EXP_CUSTOM_VIA_PROP, IdWrapperExt.class); assertEquals(99, result.node.value); assertSame(result.node, result.node.next.node); assertEquals(3, result.node.customId); } /* /***************************************************** /* Unit tests, custom id resolver /***************************************************** */ public void testCustomPoolResolver() throws Exception { Map pool = new HashMap(); pool.put(1, new WithCustomResolution(1, 1)); pool.put(2, new WithCustomResolution(2, 2)); pool.put(3, new WithCustomResolution(3, 3)); pool.put(4, new WithCustomResolution(4, 4)); pool.put(5, new WithCustomResolution(5, 5)); ContextAttributes attrs = MAPPER.getDeserializationConfig().getAttributes().withSharedAttribute(POOL_KEY, pool); String content = "{\"data\":[1,2,3,4,5]}"; CustomResolutionWrapper wrapper = MAPPER.readerFor(CustomResolutionWrapper.class).with(attrs).readValue(content); assertFalse(wrapper.data.isEmpty()); for (WithCustomResolution ob : wrapper.data) { assertSame(pool.get(ob.id), ob); } } /* /***************************************************** /* Unit tests, missing/null Object id [databind#742] /***************************************************** */ /* private final static String EXP_SIMPLE_INT_CLASS = "{\"id\":1,\"value\":13,\"next\":1}"; @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id") static class Identifiable { public int value; public Identifiable next; } */ public void testNullObjectId() throws Exception { // Ok, so missing Object Id is ok, but so is null. Identifiable value = MAPPER.readValue (aposToQuotes("{'value':3, 'next':null, 'id':null}"), Identifiable.class); assertNotNull(value); assertEquals(3, value.value); } } TestObjectIdSerialization.java000066400000000000000000000246131325620701100402200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.*; /** * Unit test to verify handling of Object Id deserialization */ public class TestObjectIdSerialization extends BaseMapTest { @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id") static class Identifiable { public int value; public Identifiable next; public Identifiable() { this(0); } public Identifiable(int v) { value = v; } } @JsonIdentityInfo(generator=ObjectIdGenerators.StringIdGenerator.class, property="id") static class StringIdentifiable { public int value; public StringIdentifiable next; public StringIdentifiable() { this(0); } public StringIdentifiable(int v) { value = v; } } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="customId") static class IdentifiableWithProp { public int value; // Property that contains Object Id to use public int customId; public IdentifiableWithProp next; public IdentifiableWithProp() { this(0, 0); } public IdentifiableWithProp(int id, int value) { this.customId = id; this.value = value; } } // For property reference, need another class: static class IdWrapper { @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") public ValueNode node; public IdWrapper() { } public IdWrapper(int v) { node = new ValueNode(v); } } static class ValueNode { public int value; public IdWrapper next; public ValueNode() { this(0); } public ValueNode(int v) { value = v; } } // Similarly for property-ref via property: protected static class IdWrapperCustom { @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id") public ValueNodeCustom node; public IdWrapperCustom() { } public IdWrapperCustom(int id, int value) { node = new ValueNodeCustom(id, value); } } protected static class ValueNodeCustom { public int value; private int id; public IdWrapperCustom next; public int getId() { return id; } public ValueNodeCustom() { this(0, 0); } public ValueNodeCustom(int id, int value) { this.id = id; this.value = value; } } @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id") static class AlwaysAsId { public int value; public AlwaysAsId() { this(0); } public AlwaysAsId(int v) { value = v; } } // For [https://github.com/FasterXML/jackson-annotations/issues/4] @JsonPropertyOrder(alphabetic=true) static class AlwaysContainer { @JsonIdentityReference(alwaysAsId=true) public AlwaysAsId a = new AlwaysAsId(13); @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id") @JsonIdentityReference(alwaysAsId=true) public Value b = new Value(); } static class Value { public int x = 3; } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id") static class TreeNode { public int id; public String name; @JsonIdentityReference(alwaysAsId=true) public TreeNode parent; // children serialized with ids if need be public TreeNode child; public TreeNode() { } public TreeNode(TreeNode p, int id, String name) { parent = p; this.id = id; this.name = name; } } // // Let's also have one 'broken' test // no "id" property @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id") static class Broken { public int value; public int customId; } // [databind#370] @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") public static class EmptyObject { } //for [databind#1150] @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id") static class IdentifiableStringId { public String id; public int value; public Identifiable next; public IdentifiableStringId() { this(0); } public IdentifiableStringId(int v) { value = v; } } /* /***************************************************** /* Unit tests, external id serialization /***************************************************** */ private final static String EXP_SIMPLE_INT_CLASS = "{\"id\":1,\"value\":13,\"next\":1}"; private final ObjectMapper MAPPER = objectMapper(); public void testSimpleSerializationClass() throws Exception { Identifiable src = new Identifiable(13); src.next = src; // First, serialize: String json = MAPPER.writeValueAsString(src); assertEquals(EXP_SIMPLE_INT_CLASS, json); // and ensure that state is cleared in-between as well: json = MAPPER.writeValueAsString(src); assertEquals(EXP_SIMPLE_INT_CLASS, json); } // Bit more complex, due to extra wrapping etc: private final static String EXP_SIMPLE_INT_PROP = "{\"node\":{\"@id\":1,\"value\":7,\"next\":{\"node\":1}}}"; public void testSimpleSerializationProperty() throws Exception { IdWrapper src = new IdWrapper(7); src.node.next = src; // First, serialize: String json = MAPPER.writeValueAsString(src); assertEquals(EXP_SIMPLE_INT_PROP, json); // and second time too, for a good measure json = MAPPER.writeValueAsString(src); assertEquals(EXP_SIMPLE_INT_PROP, json); } // [databind#370] public void testEmptyObjectWithId() throws Exception { final ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(new EmptyObject()); assertEquals(aposToQuotes("{'@id':1}"), json); } public void testSerializeWithOpaqueStringId() throws Exception { StringIdentifiable ob1 = new StringIdentifiable(12); StringIdentifiable ob2 = new StringIdentifiable(34); ob1.next = ob2; ob2.next = ob1; // first just verify we get some output String json = MAPPER.writeValueAsString(ob1); assertNotNull(json); // then get them back StringIdentifiable output = MAPPER.readValue(json, StringIdentifiable.class); assertNotNull(output); assertEquals(12, output.value); assertNotNull(output.next); assertEquals(34, output.next.value); assertSame(output.next.next, output); String json2 = aposToQuotes("{'id':'foobar','value':3, 'next':{'id':'barf','value':5,'next':'foobar'}}"); output = MAPPER.readValue(json2, StringIdentifiable.class); assertNotNull(output); assertEquals(3, output.value); assertNotNull(output.next); assertEquals(5, output.next.value); assertSame(output.next.next, output); } /* /***************************************************** /* Unit tests, custom (property) id serialization /***************************************************** */ private final static String EXP_CUSTOM_PROP = "{\"customId\":123,\"value\":-19,\"next\":123}"; // Test for verifying that custom public void testCustomPropertyForClass() throws Exception { IdentifiableWithProp src = new IdentifiableWithProp(123, -19); src.next = src; // First, serialize: String json = MAPPER.writeValueAsString(src); assertEquals(EXP_CUSTOM_PROP, json); // and ensure that state is cleared in-between as well: json = MAPPER.writeValueAsString(src); assertEquals(EXP_CUSTOM_PROP, json); } private final static String EXP_CUSTOM_PROP_VIA_REF = "{\"node\":{\"id\":123,\"value\":7,\"next\":{\"node\":123}}}"; // Test for verifying that custom public void testCustomPropertyViaProperty() throws Exception { IdWrapperCustom src = new IdWrapperCustom(123, 7); src.node.next = src; // First, serialize: String json = MAPPER.writeValueAsString(src); assertEquals(EXP_CUSTOM_PROP_VIA_REF, json); // and second time too, for a good measure json = MAPPER.writeValueAsString(src); assertEquals(EXP_CUSTOM_PROP_VIA_REF, json); } public void testAlwaysAsId() throws Exception { String json = MAPPER.writeValueAsString(new AlwaysContainer()); assertEquals("{\"a\":1,\"b\":2}", json); } public void testAlwaysIdForTree() throws Exception { TreeNode root = new TreeNode(null, 1, "root"); TreeNode leaf = new TreeNode(root, 2, "leaf"); root.child = leaf; String json = MAPPER.writeValueAsString(root); // System.out.println(json); assertEquals("{\"id\":1,\"name\":\"root\",\"parent\":null,\"child\":" +"{\"id\":2,\"name\":\"leaf\",\"parent\":1,\"child\":null}}", json); } //for [databind#1150] public void testNullStringPropertyId() throws Exception { IdentifiableStringId value = MAPPER.readValue (aposToQuotes("{'value':3, 'next':null, 'id':null}"), IdentifiableStringId.class); assertNotNull(value); assertEquals(3, value.value); } /* /***************************************************** /* Unit tests, error handling /***************************************************** */ public void testInvalidProp() throws Exception { try { MAPPER.writeValueAsString(new Broken()); fail("Should have thrown an exception"); } catch (JsonMappingException e) { verifyException(e, "cannot find property with name 'id'"); } } } TestObjectIdWithEquals.java000066400000000000000000000103651325620701100374700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import java.net.URI; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class TestObjectIdWithEquals extends BaseMapTest { @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Foo.class) static class Foo { public int id; public List bars = new ArrayList(); public List otherBars = new ArrayList(); public Foo() { } public Foo(int i) { id = i; } } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Bar.class) static class Bar { public int id; public Bar() { } public Bar(int i) { id = i; } @Override public int hashCode() { return id; } @Override public boolean equals(Object obj) { if (!(obj instanceof Bar)) { return false; } return ((Bar) obj).id == id; } } // for [databind#1002] @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "uri") static class Element { public URI uri; public String name; @Override public boolean equals(Object object) { if (object == this) { return true; } else if (object == null || !(object instanceof Element)) { return false; } else { Element element = (Element) object; if (element.uri.toString().equalsIgnoreCase(this.uri.toString())) { return true; } } return false; } @Override public int hashCode() { return uri.hashCode(); } } /* /****************************************************** /* Test methods /****************************************************** */ public void testSimpleEquals() throws Exception { ObjectMapper mapper = new ObjectMapper(); // Verify default state too assertFalse(mapper.isEnabled(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID)); mapper.enable(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID); Foo foo = new Foo(1); Bar bar1 = new Bar(1); Bar bar2 = new Bar(2); // this is another bar which is supposed to be "equal" to bar1 // due to the same ID and // Bar class' equals() method will return true. Bar anotherBar1 = new Bar(1); foo.bars.add(bar1); foo.bars.add(bar2); // this anotherBar1 object will confuse the serializer. foo.otherBars.add(anotherBar1); foo.otherBars.add(bar2); String json = mapper.writeValueAsString(foo); assertEquals("{\"id\":1,\"bars\":[{\"id\":1},{\"id\":2}],\"otherBars\":[1,2]}", json); Foo foo2 = mapper.readValue(json, Foo.class); assertNotNull(foo2); assertEquals(foo.id, foo2.id); } public void testEqualObjectIdsExternal() throws Exception { Element element = new Element(); element.uri = URI.create("URI"); element.name = "Element1"; Element element2 = new Element(); element2.uri = URI.create("URI"); element2.name = "Element2"; // 12-Nov-2015, tatu: array works fine regardless of Type Erasure, but if using List, // must provide additional piece of type info // Element[] input = new Element[] { element, element2 }; List input = Arrays.asList(element, element2); ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID); // String json = mapper.writeValueAsString(input); String json = mapper.writerFor(new TypeReference>() { }) .writeValueAsString(input); Element[] output = mapper.readValue(json, Element[].class); assertNotNull(output); assertEquals(2, output.length); } } TestObjectIdWithInjectables538.java000066400000000000000000000030311325620701100407110ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestObjectIdWithInjectables538 extends BaseMapTest { @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) public static class A { public B b; public A(@JacksonInject("i1") String injected) { } } @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) public static class B { public A a; @JsonCreator public B(@JacksonInject("i2") String injected) { } } /* /***************************************************** /* Test methods /***************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testWithInjectables538() throws Exception { A a = new A("a"); B b = new B("b"); a.b = b; b.a = a; String json = MAPPER.writeValueAsString(a); InjectableValues.Std inject = new InjectableValues.Std(); inject.addValue("i1", "e1"); inject.addValue("i2", "e2"); A output = null; try { output = MAPPER.reader(inject).forType(A.class).readValue(json); } catch (Exception e) { throw new IllegalStateException("Failed to deserialize from JSON '"+json+"'", e); } assertNotNull(output); assertNotNull(output.b); assertSame(output, output.b.a); } } TestObjectIdWithPolymorphic.java000066400000000000000000000110461325620701100405400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/objectidpackage com.fasterxml.jackson.databind.objectid; import java.util.*; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; public class TestObjectIdWithPolymorphic extends BaseMapTest { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id") static abstract class Base { public int value; public Base next; public Base() { this(0); } public Base(int v) { value = v; } } static class Impl extends Base { public int extra; public Impl() { this(0, 0); } public Impl(int v, int e) { super(v); extra = e; } } // [JACKSON-811] types @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id") public static class Base811 { public int id; public Base811 owner; protected Base811() {} public Base811(Process owner) { this.owner = owner; if (owner == null) { id = 0; } else { id = ++owner.childIdCounter; owner.children.add(this); } } } public static class Process extends Base811 { protected int childIdCounter = 0; protected List children = new ArrayList(); public Process() { super(null); } } public static abstract class Activity extends Base811 { protected Activity parent; public Activity(Process owner, Activity parent) { super(owner); this.parent = parent; } protected Activity() { super(); } } public static class Scope extends Activity { public final List faultHandlers = new ArrayList(); public Scope(Process owner, Activity parent) { super(owner, parent); } protected Scope() { super(); } } public static class FaultHandler extends Base811 { public final List catchBlocks = new ArrayList(); public FaultHandler(Process owner) { super(owner); } protected FaultHandler() {} } public static class Catch extends Scope { public Catch(Process owner, Activity parent) { super(owner, parent); } protected Catch() {}; } /* /***************************************************** /* Unit tests for polymorphic type handling /***************************************************** */ private final ObjectMapper mapper = new ObjectMapper(); public void testPolymorphicRoundtrip() throws Exception { // create simple 2 node loop: Impl in1 = new Impl(123, 456); in1.next = new Impl(111, 222); in1.next.next = in1; String json = mapper.writeValueAsString(in1); // then bring back... Base result0 = mapper.readValue(json, Base.class); assertNotNull(result0); assertSame(Impl.class, result0.getClass()); Impl result = (Impl) result0; assertEquals(123, result.value); assertEquals(456, result.extra); Impl result2 = (Impl) result.next; assertEquals(111, result2.value); assertEquals(222, result2.extra); assertSame(result, result2.next); } public void testIssue811() throws Exception { ObjectMapper om = new ObjectMapper(); om.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX); om.enable(SerializationFeature.INDENT_OUTPUT); om.enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, "@class"); Process p = new Process(); Scope s = new Scope(p, null); FaultHandler fh = new FaultHandler(p); Catch c = new Catch(p, s); fh.catchBlocks.add(c); s.faultHandlers.add(fh); String json = om.writeValueAsString(p); Process restored = om.readValue(json, Process.class); assertNotNull(restored); assertEquals(0, p.id); assertEquals(3, p.children.size()); assertSame(p, p.children.get(0).owner); assertSame(p, p.children.get(1).owner); assertSame(p, p.children.get(2).owner); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/seq/000077500000000000000000000000001325620701100313525ustar00rootroot00000000000000PolyMapWriter827Test.java000066400000000000000000000033051325620701100360160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/seqpackage com.fasterxml.jackson.databind.seq; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.junit.Assert; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; // for [databind#827] public class PolyMapWriter827Test extends BaseMapTest { static class CustomKey { String a; int b; @Override public String toString() { return "BAD-KEY"; } } public class CustomKeySerializer extends JsonSerializer { @Override public void serialize(CustomKey key, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { jsonGenerator.writeFieldName(key.a + "," + key.b); } } public void testPolyCustomKeySerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); mapper.registerModule(new SimpleModule("keySerializerModule") .addKeySerializer(CustomKey.class, new CustomKeySerializer())); Map map = new HashMap(); CustomKey key = new CustomKey(); key.a = "foo"; key.b = 1; map.put(key, "bar"); final ObjectWriter writer = mapper.writerFor(new TypeReference>() { }); String json = writer.writeValueAsString(map); Assert.assertEquals("[\"java.util.HashMap\",{\"foo,1\":\"bar\"}]", json); } } ReadRecoveryTest.java000066400000000000000000000060711325620701100353740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/seqpackage com.fasterxml.jackson.databind.seq; import com.fasterxml.jackson.databind.*; /** * Tests to verify aspects of error recover for reading using * iterator. */ public class ReadRecoveryTest extends BaseMapTest { static class Bean { public int a, b; @Override public String toString() { return "{Bean, a="+a+", b="+b+"}"; } } /* /********************************************************** /* Unit tests; root-level value sequences via Mapper /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testRootBeans() throws Exception { final String JSON = aposToQuotes("{'a':3} {'x':5}"); MappingIterator it = MAPPER.readerFor(Bean.class).readValues(JSON); // First one should be fine assertTrue(it.hasNextValue()); Bean bean = it.nextValue(); assertEquals(3, bean.a); // but second one not try { bean = it.nextValue(); fail("Should not have succeeded"); } catch (JsonMappingException e) { verifyException(e, "Unrecognized field \"x\""); } // 21-May-2015, tatu: With [databind#734], recovery, we now know there's no more data! assertFalse(it.hasNextValue()); it.close(); } // for [databind#734] // Simple test for verifying that basic recover works for a case of // unknown structured value public void testSimpleRootRecovery() throws Exception { final String JSON = aposToQuotes("{'a':3}{'a':27,'foo':[1,2],'b':{'x':3}} {'a':1,'b':2} "); MappingIterator it = MAPPER.readerFor(Bean.class).readValues(JSON); Bean bean = it.nextValue(); assertNotNull(bean); assertEquals(3, bean.a); // second one problematic try { it.nextValue(); } catch (JsonMappingException e) { verifyException(e, "Unrecognized field \"foo\""); } // but should recover nicely bean = it.nextValue(); assertNotNull(bean); assertEquals(1, bean.a); assertEquals(2, bean.b); assertFalse(it.hasNextValue()); it.close(); } // Similar to "raw" root-level Object sequence, but in array public void testSimpleArrayRecovery() throws Exception { final String JSON = aposToQuotes("[{'a':3},{'a':27,'foo':[1,2],'b':{'x':3}} ,{'a':1,'b':2} ]"); MappingIterator it = MAPPER.readerFor(Bean.class).readValues(JSON); Bean bean = it.nextValue(); assertNotNull(bean); assertEquals(3, bean.a); // second one problematic try { it.nextValue(); } catch (JsonMappingException e) { verifyException(e, "Unrecognized field \"foo\""); } // but should recover nicely bean = it.nextValue(); assertNotNull(bean); assertEquals(1, bean.a); assertEquals(2, bean.b); assertFalse(it.hasNextValue()); it.close(); } } ReadValuesTest.java000066400000000000000000000261251325620701100350370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/seqpackage com.fasterxml.jackson.databind.seq; import java.io.*; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; @SuppressWarnings("resource") public class ReadValuesTest extends BaseMapTest { static class Bean { public int a; @Override public boolean equals(Object o) { if (o == null || o.getClass() != getClass()) return false; Bean other = (Bean) o; return other.a == this.a; } @Override public int hashCode() { return a; } } /* /********************************************************** /* Unit tests; root-level value sequences via Mapper /********************************************************** */ private enum Source { STRING, INPUT_STREAM, READER, BYTE_ARRAY, BYTE_ARRAY_OFFSET ; } private final ObjectMapper MAPPER = new ObjectMapper(); public void testRootBeans() throws Exception { for (Source src : Source.values()) { _testRootBeans(src); } } private MappingIterator _iterator(ObjectReader r, String json, Source srcType) throws IOException { switch (srcType) { case BYTE_ARRAY: return r.readValues(json.getBytes("UTF-8")); case BYTE_ARRAY_OFFSET: { ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write(0); out.write(0); out.write(0); out.write(json.getBytes("UTF-8")); out.write(0); out.write(0); out.write(0); byte[] b = out.toByteArray(); return r.readValues(b, 3, b.length-6); } case INPUT_STREAM: return r.readValues(new ByteArrayInputStream(json.getBytes("UTF-8"))); case READER: return r.readValues(new StringReader(json)); case STRING: default: return r.readValues(json); } } private void _testRootBeans(Source srcType) throws Exception { final String JSON = "{\"a\":3}{\"a\":27} "; MappingIterator it = _iterator(MAPPER.readerFor(Bean.class), JSON, srcType); assertNotNull(it.getCurrentLocation()); assertTrue(it.hasNext()); Bean b = it.next(); assertEquals(3, b.a); assertTrue(it.hasNext()); b = it.next(); assertEquals(27, b.a); assertFalse(it.hasNext()); it.close(); // Also, test 'readAll()' it = _iterator(MAPPER.readerFor(Bean.class), JSON, srcType); List all = it.readAll(); assertEquals(2, all.size()); it.close(); it = _iterator(MAPPER.readerFor(Bean.class), "{\"a\":3}{\"a\":3}", srcType); Set set = it.readAll(new HashSet()); assertEquals(HashSet.class, set.getClass()); assertEquals(1, set.size()); assertEquals(3, set.iterator().next().a); it.close(); } public void testRootBeansInArray() throws Exception { final String JSON = "[{\"a\":6}, {\"a\":-7}]"; MappingIterator it = MAPPER.readerFor(Bean.class).readValues(JSON); assertNotNull(it.getCurrentLocation()); assertTrue(it.hasNext()); Bean b = it.next(); assertEquals(6, b.a); assertTrue(it.hasNext()); b = it.next(); assertEquals(-7, b.a); assertFalse(it.hasNext()); it.close(); // Also, test 'readAll()' it = MAPPER.readerFor(Bean.class).readValues(JSON); List all = it.readAll(); assertEquals(2, all.size()); it.close(); it = MAPPER.readerFor(Bean.class).readValues("[{\"a\":4},{\"a\":4}]"); Set set = it.readAll(new HashSet()); assertEquals(HashSet.class, set.getClass()); assertEquals(1, set.size()); assertEquals(4, set.iterator().next().a); } public void testRootMaps() throws Exception { final String JSON = "{\"a\":3}{\"a\":27} "; Iterator> it = MAPPER.readerFor(Map.class).readValues(JSON); assertNotNull(((MappingIterator) it).getCurrentLocation()); assertTrue(it.hasNext()); Map map = it.next(); assertEquals(1, map.size()); assertEquals(Integer.valueOf(3), map.get("a")); assertTrue(it.hasNext()); assertNotNull(((MappingIterator) it).getCurrentLocation()); map = it.next(); assertEquals(1, map.size()); assertEquals(Integer.valueOf(27), map.get("a")); assertFalse(it.hasNext()); } /* /********************************************************** /* Unit tests; root-level value sequences via JsonParser /********************************************************** */ public void testRootBeansWithParser() throws Exception { final String JSON = "{\"a\":3}{\"a\":27} "; JsonParser jp = MAPPER.getFactory().createParser(JSON); Iterator it = jp.readValuesAs(Bean.class); assertTrue(it.hasNext()); Bean b = it.next(); assertEquals(3, b.a); assertTrue(it.hasNext()); b = it.next(); assertEquals(27, b.a); assertFalse(it.hasNext()); } public void testRootArraysWithParser() throws Exception { final String JSON = "[1][3]"; JsonParser jp = MAPPER.getFactory().createParser(JSON); // NOTE: We must point JsonParser to the first element; if we tried to // use "managed" accessor, it would try to advance past START_ARRAY. assertToken(JsonToken.START_ARRAY, jp.nextToken()); Iterator it = MAPPER.readerFor(int[].class).readValues(jp); assertTrue(it.hasNext()); int[] array = it.next(); assertEquals(1, array.length); assertEquals(1, array[0]); assertTrue(it.hasNext()); array = it.next(); assertEquals(1, array.length); assertEquals(3, array[0]); assertFalse(it.hasNext()); } public void testHasNextWithEndArray() throws Exception { final String JSON = "[1,3]"; JsonParser jp = MAPPER.getFactory().createParser(JSON); // NOTE: We must point JsonParser to the first element; if we tried to // use "managed" accessor, it would try to advance past START_ARRAY. assertToken(JsonToken.START_ARRAY, jp.nextToken()); jp.nextToken(); Iterator it = MAPPER.readerFor(Integer.class).readValues(jp); assertTrue(it.hasNext()); int value = it.next(); assertEquals(1, value); assertTrue(it.hasNext()); value = it.next(); assertEquals(3, value); assertFalse(it.hasNext()); assertFalse(it.hasNext()); } public void testHasNextWithEndArrayManagedParser() throws Exception { final String JSON = "[1,3]"; Iterator it = MAPPER.readerFor(Integer.class).readValues(JSON); assertTrue(it.hasNext()); int value = it.next(); assertEquals(1, value); assertTrue(it.hasNext()); value = it.next(); assertEquals(3, value); assertFalse(it.hasNext()); assertFalse(it.hasNext()); } /* /********************************************************** /* Unit tests; non-root arrays /********************************************************** */ public void testNonRootBeans() throws Exception { final String JSON = "{\"leaf\":[{\"a\":3},{\"a\":27}]}"; JsonParser jp = MAPPER.getFactory().createParser(JSON); assertToken(JsonToken.START_OBJECT, jp.nextToken()); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); assertToken(JsonToken.START_ARRAY, jp.nextToken()); // can either advance to first START_OBJECT, or clear current token; // explicitly passed JsonParser MUST point to the first token of // the first element assertToken(JsonToken.START_OBJECT, jp.nextToken()); Iterator it = MAPPER.readerFor(Bean.class).readValues(jp); assertTrue(it.hasNext()); Bean b = it.next(); assertEquals(3, b.a); assertTrue(it.hasNext()); b = it.next(); assertEquals(27, b.a); assertFalse(it.hasNext()); jp.close(); } public void testNonRootMapsWithParser() throws Exception { final String JSON = "[{\"a\":3},{\"a\":27}]"; JsonParser jp = MAPPER.getFactory().createParser(JSON); assertToken(JsonToken.START_ARRAY, jp.nextToken()); // can either advance to first START_OBJECT, or clear current token; // explicitly passed JsonParser MUST point to the first token of // the first element jp.clearCurrentToken(); Iterator> it = MAPPER.readerFor(Map.class).readValues(jp); assertTrue(it.hasNext()); Map map = it.next(); assertEquals(1, map.size()); assertEquals(Integer.valueOf(3), map.get("a")); assertTrue(it.hasNext()); map = it.next(); assertEquals(1, map.size()); assertEquals(Integer.valueOf(27), map.get("a")); assertFalse(it.hasNext()); jp.close(); } public void testNonRootMapsWithObjectReader() throws Exception { String JSON = "[{ \"hi\": \"ho\", \"neighbor\": \"Joe\" },\n" +"{\"boy\": \"howdy\", \"huh\": \"what\"}]"; final MappingIterator> iterator = MAPPER .reader() .forType(new TypeReference>(){}) .readValues(JSON); Map map; assertTrue(iterator.hasNext()); map = iterator.nextValue(); assertEquals(2, map.size()); assertTrue(iterator.hasNext()); map = iterator.nextValue(); assertEquals(2, map.size()); assertFalse(iterator.hasNext()); } public void testNonRootArraysUsingParser() throws Exception { final String JSON = "[[1],[3]]"; JsonParser p = MAPPER.getFactory().createParser(JSON); assertToken(JsonToken.START_ARRAY, p.nextToken()); // Important: as of 2.1, START_ARRAY can only be skipped if the // target type is NOT a Collection or array Java type. // So we have to explicitly skip it in this particular case. assertToken(JsonToken.START_ARRAY, p.nextToken()); Iterator it = MAPPER.readValues(p, int[].class); assertTrue(it.hasNext()); int[] array = it.next(); assertEquals(1, array.length); assertEquals(1, array[0]); assertTrue(it.hasNext()); array = it.next(); assertEquals(1, array.length); assertEquals(3, array[0]); assertFalse(it.hasNext()); p.close(); } } SequenceWriterTest.java000066400000000000000000000164211325620701100357470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/seqpackage com.fasterxml.jackson.databind.seq; import java.io.Closeable; import java.io.IOException; import java.io.StringWriter; import java.util.*; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.databind.*; public class SequenceWriterTest extends BaseMapTest { static class Bean { public int a; public Bean(int value) { a = value; } @Override public boolean equals(Object o) { if (o == null || o.getClass() != getClass()) return false; Bean other = (Bean) o; return other.a == this.a; } @Override public int hashCode() { return a; } } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") static class PolyBase { } @JsonTypeName("A") static class ImplA extends PolyBase { public int value; public ImplA(int v) { value = v; } } @JsonTypeName("B") static class ImplB extends PolyBase { public int b; public ImplB(int v) { b = v; } } static class BareBase { public int a = 1; } @JsonPropertyOrder({ "a", "b" }) static class BareBaseExt extends BareBase { public int b = 2; } static class BareBaseCloseable extends BareBase implements Closeable { public int c = 3; boolean closed = false; @Override public void close() throws IOException { closed = true; } } static class CloseableValue implements Closeable { public int x; public boolean closed; @Override public void close() throws IOException { closed = true; } } /* /********************************************************** /* Test methods, simple writes /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); private final ObjectWriter WRITER = MAPPER.writer() .withRootValueSeparator("\n"); public void testSimpleNonArray() throws Exception { StringWriter strw = new StringWriter(); SequenceWriter w = WRITER .forType(Bean.class) .writeValues(strw); w.write(new Bean(13)) .write(new Bean(-6)) .writeAll(new Bean[] { new Bean(3), new Bean(1) }) .writeAll(Arrays.asList(new Bean(5), new Bean(7))) ; w.close(); assertEquals(aposToQuotes("{'a':13}\n{'a':-6}\n{'a':3}\n{'a':1}\n{'a':5}\n{'a':7}"), strw.toString()); strw = new StringWriter(); JsonGenerator gen = WRITER.getFactory().createGenerator(strw); w = WRITER .withRootValueSeparator(new SerializedString("/")) .writeValues(gen); w.write(new Bean(1)) .write(new Bean(2)); w.close(); gen.close(); assertEquals(aposToQuotes("{'a':1}/{'a':2}"), strw.toString()); } public void testSimpleArray() throws Exception { StringWriter strw = new StringWriter(); SequenceWriter w = WRITER.writeValuesAsArray(strw); w.write(new Bean(1)) .write(new Bean(2)) .writeAll(new Bean[] { new Bean(-7), new Bean(2) }); w.close(); assertEquals(aposToQuotes("[{'a':1},{'a':2},{'a':-7},{'a':2}]"), strw.toString()); strw = new StringWriter(); JsonGenerator gen = WRITER.getFactory().createGenerator(strw); w = WRITER.writeValuesAsArray(gen); Collection bean = Collections.singleton(new Bean(3)); w.write(new Bean(1)) .write(null) .writeAll((Iterable) bean); w.close(); gen.close(); assertEquals(aposToQuotes("[{'a':1},null,{'a':3}]"), strw.toString()); } /* /********************************************************** /* Test methods, polymorphic writes /********************************************************** */ @SuppressWarnings("resource") public void testPolymorphicNonArrayWithoutType() throws Exception { StringWriter strw = new StringWriter(); SequenceWriter w = WRITER .writeValues(strw); w.write(new ImplA(3)) .write(new ImplA(4)) .close(); assertEquals(aposToQuotes("{'type':'A','value':3}\n{'type':'A','value':4}"), strw.toString()); } @SuppressWarnings("resource") public void testPolymorphicArrayWithoutType() throws Exception { StringWriter strw = new StringWriter(); SequenceWriter w = WRITER .writeValuesAsArray(strw); w.write(new ImplA(-1)) .write(new ImplA(6)) .close(); assertEquals(aposToQuotes("[{'type':'A','value':-1},{'type':'A','value':6}]"), strw.toString()); } public void testPolymorphicArrayWithType() throws Exception { StringWriter strw = new StringWriter(); SequenceWriter w = WRITER .forType(PolyBase.class) .writeValuesAsArray(strw); w.write(new ImplA(-1)) .write(new ImplB(3)) .write(new ImplA(7)); w.flush(); w.close(); assertEquals(aposToQuotes("[{'type':'A','value':-1},{'type':'B','b':3},{'type':'A','value':7}]"), strw.toString()); } @SuppressWarnings("resource") public void testSimpleCloseable() throws Exception { ObjectWriter w = MAPPER.writer() .with(SerializationFeature.CLOSE_CLOSEABLE); CloseableValue input = new CloseableValue(); assertFalse(input.closed); StringWriter out = new StringWriter(); SequenceWriter seq = w.writeValues(out); input = new CloseableValue(); assertFalse(input.closed); seq.write(input); assertTrue(input.closed); seq.close(); input.close(); assertEquals(aposToQuotes("{'x':0,'closed':false}"), out.toString()); } public void testWithExplicitType() throws Exception { ObjectWriter w = MAPPER.writer() // just for fun (and higher coverage): .without(SerializationFeature.FLUSH_AFTER_WRITE_VALUE) .with(SerializationFeature.CLOSE_CLOSEABLE); StringWriter out = new StringWriter(); SequenceWriter seq = w.writeValues(out); // first full, as-is seq.write(new BareBaseExt()); // but then just base type (no 'b' field) seq.write(new BareBaseExt(), MAPPER.constructType(BareBase.class)); // one more. And note! Check for Closeable is for _value_, not type // so it's fine to expect closing here BareBaseCloseable cl = new BareBaseCloseable(); seq.write(cl, MAPPER.constructType(BareBase.class)); assertTrue(cl.closed); cl.close(); seq.close(); seq.flush(); assertEquals(aposToQuotes("{'a':1,'b':2} {'a':1} {'a':1}"), out.toString()); } } TestInnerClassReaderFor.java000066400000000000000000000020011325620701100366220ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/seqpackage com.fasterxml.jackson.databind.seq; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.BaseMapTest; import java.io.IOException; public class TestInnerClassReaderFor extends BaseMapTest { class X { private String value; X(String value) { this.value = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } class Y extends X { Y(@JsonProperty("value") String value) { super(value); } } public void testReaderFor() throws IOException { X x = new X("dummy"); objectMapper().readerForUpdating(x).readValue("{\"value\": \"updatedX\"}"); assertEquals(x.getValue(), "updatedX"); Y y = new Y("dummy"); objectMapper().readerForUpdating(y).readValue("{\"value\": \"updatedY\"}"); assertEquals(y.getValue(), "updatedY"); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/000077500000000000000000000000001325620701100313535ustar00rootroot00000000000000AnyGetterTest.java000066400000000000000000000140311325620701100347000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; public class AnyGetterTest extends BaseMapTest { static class Bean { final static Map extra = new HashMap(); static { extra.put("a", Boolean.TRUE); } public int getX() { return 3; } @JsonAnyGetter public Map getExtra() { return extra; } } static class AnyOnlyBean { @JsonAnyGetter public Map any() { HashMap map = new HashMap(); map.put("a", 3); return map; } } // For [databind#1376]: allow disabling any-getter static class NotEvenAnyBean extends AnyOnlyBean { @JsonAnyGetter(enabled=false) @Override public Map any() { throw new RuntimeException("Should not get called!)"); } public int getValue() { return 42; } } static class MapAsAny { protected Map stuff = new LinkedHashMap(); @JsonAnyGetter public Map any() { return stuff; } public void add(String key, Object value) { stuff.put(key, value); } } static class Issue705Bean { protected Map stuff; public Issue705Bean(String key, String value) { stuff = new LinkedHashMap(); stuff.put(key, value); } @JsonSerialize(using = Issue705Serializer.class) // @JsonSerialize(converter = MyConverter.class) @JsonAnyGetter public Map getParameters(){ return stuff; } } @SuppressWarnings("serial") static class Issue705Serializer extends StdSerializer { public Issue705Serializer() { super(Map.class, false); } @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { StringBuilder sb = new StringBuilder(); for (Map.Entry entry : ((Map) value).entrySet()) { sb.append('[').append(entry.getKey()).append('/').append(entry.getValue()).append(']'); } jgen.writeStringField("stuff", sb.toString()); } } // [databind#1124] static class Bean1124 { protected Map additionalProperties; public void addAdditionalProperty(String key, String value) { if (additionalProperties == null) { additionalProperties = new HashMap(); } additionalProperties.put(key,value); } public void setAdditionalProperties(Map additionalProperties) { this.additionalProperties = additionalProperties; } @JsonAnyGetter @JsonSerialize(contentUsing=MyUCSerializer.class) public Map getAdditionalProperties() { return additionalProperties; } } // [databind#1124] @SuppressWarnings("serial") static class MyUCSerializer extends StdScalarSerializer { public MyUCSerializer() { super(String.class); } @Override public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeString(value.toUpperCase()); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleAnyBean() throws Exception { String json = MAPPER.writeValueAsString(new Bean()); Map map = MAPPER.readValue(json, Map.class); assertEquals(2, map.size()); assertEquals(Integer.valueOf(3), map.get("x")); assertEquals(Boolean.TRUE, map.get("a")); } public void testAnyOnly() throws Exception { ObjectMapper m; // First, with normal fail settings: m = new ObjectMapper(); m.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, true); String json = serializeAsString(m, new AnyOnlyBean()); assertEquals("{\"a\":3}", json); // then without fail m = new ObjectMapper(); m.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); json = serializeAsString(m, new AnyOnlyBean()); assertEquals("{\"a\":3}", json); } public void testAnyDisabling() throws Exception { String json = MAPPER.writeValueAsString(new NotEvenAnyBean()); assertEquals(aposToQuotes("{'value':42}"), json); } // Trying to repro [databind#577] public void testAnyWithNull() throws Exception { MapAsAny input = new MapAsAny(); input.add("bar", null); assertEquals(aposToQuotes("{'bar':null}"), MAPPER.writeValueAsString(input)); } public void testIssue705() throws Exception { Issue705Bean input = new Issue705Bean("key", "value"); String json = MAPPER.writeValueAsString(input); assertEquals("{\"stuff\":\"[key/value]\"}", json); } // [databind#1124] public void testAnyGetterWithValueSerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); Bean1124 input = new Bean1124(); input.addAdditionalProperty("key", "value"); String json = mapper.writeValueAsString(input); assertEquals("{\"key\":\"VALUE\"}", json); } } BeanSerializerModifier1612Test.java000066400000000000000000000045361325620701100376770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.BeanSerializerBuilder; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; public class BeanSerializerModifier1612Test extends BaseMapTest { @JsonPropertyOrder({ "a", "b", "c" }) static class Bean1612 { public Integer a; public Integer b; public Double c; public Bean1612(Integer a, Integer b, Double c) { this.a = a; this.b = b; this.c = c; } } static class Modifier1612 extends BeanSerializerModifier { @Override public BeanSerializerBuilder updateBuilder(SerializationConfig config, BeanDescription beanDesc, BeanSerializerBuilder builder) { List filtered = new ArrayList(2); List properties = builder.getProperties(); //Make the filtered properties list bigger builder.setFilteredProperties(new BeanPropertyWriter[] {properties.get(0), properties.get(1), properties.get(2)}); //The props will be shorter filtered.add(properties.get(1)); filtered.add(properties.get(2)); builder.setProperties(filtered); return builder; } } /* /********************************************************** /* Construction and setter methods /********************************************************** */ public void testIssue1612() throws Exception { SimpleModule mod = new SimpleModule(); mod.setSerializerModifier(new Modifier1612()); ObjectMapper objectMapper = new ObjectMapper() .registerModule(mod); try { objectMapper.writeValueAsString(new Bean1612(0, 1, 2d)); fail("Should not pass"); } catch (InvalidDefinitionException e) { verifyException(e, "Failed to construct BeanSerializer"); verifyException(e, Bean1612.class.getName()); } } } BeanSerializerModifierTest.java000066400000000000000000000326741325620701100373710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedField; import com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.BeanSerializer; import com.fasterxml.jackson.databind.ser.BeanSerializerBuilder; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.databind.type.ArrayType; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.MapType; /** * Unit tests for verifying that it is possible to configure * construction of {@link BeanSerializer} instances. */ @SuppressWarnings("serial") public class BeanSerializerModifierTest extends BaseMapTest { static class SerializerModifierModule extends SimpleModule { protected BeanSerializerModifier modifier; public SerializerModifierModule(BeanSerializerModifier modifier) { super("test", Version.unknownVersion()); this.modifier = modifier; } @Override public void setupModule(SetupContext context) { super.setupModule(context); if (modifier != null) { context.addBeanSerializerModifier(modifier); } } } @JsonPropertyOrder({"b", "a"}) static class Bean { public String b = "b"; public String a = "a"; } static class RemovingModifier extends BeanSerializerModifier { private final String _removedProperty; public RemovingModifier(String remove) { _removedProperty = remove; } @Override public List changeProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) { Iterator it = beanProperties.iterator(); while (it.hasNext()) { BeanPropertyWriter bpw = it.next(); if (bpw.getName().equals(_removedProperty)) { it.remove(); } } return beanProperties; } } static class ReorderingModifier extends BeanSerializerModifier { @Override public List orderProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) { TreeMap props = new TreeMap(); for (BeanPropertyWriter bpw : beanProperties) { props.put(bpw.getName(), bpw); } return new ArrayList(props.values()); } } static class ReplacingModifier extends BeanSerializerModifier { private final JsonSerializer _serializer; public ReplacingModifier(JsonSerializer s) { _serializer = s; } @Override public JsonSerializer modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer serializer) { return _serializer; } } static class BuilderModifier extends BeanSerializerModifier { private final JsonSerializer _serializer; public BuilderModifier(JsonSerializer ser) { _serializer = ser; } @Override public BeanSerializerBuilder updateBuilder(SerializationConfig config, BeanDescription beanDesc, BeanSerializerBuilder builder) { return new BogusSerializerBuilder(builder, _serializer); } } static class BogusSerializerBuilder extends BeanSerializerBuilder { private final JsonSerializer _serializer; public BogusSerializerBuilder(BeanSerializerBuilder src, JsonSerializer ser) { super(src); _serializer = ser; } @Override public JsonSerializer build() { return _serializer; } } static class BogusBeanSerializer extends JsonSerializer { private final int _value; public BogusBeanSerializer(int v) { _value = v; } @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeNumber(_value); } } static class EmptyBean { @JsonIgnore public String name = "foo"; } static class EmptyBeanModifier extends BeanSerializerModifier { @Override public List changeProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) { JavaType strType = config.constructType(String.class); // we need a valid BeanPropertyDefinition; this will do (just need name to match) POJOPropertyBuilder prop = new POJOPropertyBuilder(config, null, true, new PropertyName("bogus")); try { AnnotatedField f = new AnnotatedField(null, EmptyBean.class.getDeclaredField("name"), null); beanProperties.add(new BeanPropertyWriter(prop, f, null, strType, null, null, strType, false, null, null)); } catch (NoSuchFieldException e) { throw new IllegalStateException(e.getMessage()); } return beanProperties; } } // [Issue#539]: use post-modifier static class EmptyBeanModifier539 extends BeanSerializerModifier { @Override public List changeProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) { return beanProperties; } @Override public JsonSerializer modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer serializer) { return new BogusBeanSerializer(42); } } // [databind#120], arrays, collections, maps static class ArraySerializerModifier extends BeanSerializerModifier { @Override public JsonSerializer modifyArraySerializer(SerializationConfig config, ArrayType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return new StdSerializer(Object.class) { @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeNumber(123); } }; } } static class CollectionSerializerModifier extends BeanSerializerModifier { @Override public JsonSerializer modifyCollectionSerializer(SerializationConfig config, CollectionType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return new StdSerializer(Object.class) { @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeNumber(123); } }; } } static class MapSerializerModifier extends BeanSerializerModifier { @Override public JsonSerializer modifyMapSerializer(SerializationConfig config, MapType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return new StdSerializer(Object.class) { @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeNumber(123); } }; } } static class EnumSerializerModifier extends BeanSerializerModifier { @Override public JsonSerializer modifyEnumSerializer(SerializationConfig config, JavaType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return new StdSerializer(Object.class) { @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeNumber(123); } }; } } static class KeySerializerModifier extends BeanSerializerModifier { @Override public JsonSerializer modifyKeySerializer(SerializationConfig config, JavaType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return new StdSerializer(Object.class) { @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeFieldName("foo"); } }; } } /* /******************************************************** /* Unit tests: success /******************************************************** */ public void testPropertyRemoval() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SerializerModifierModule(new RemovingModifier("a"))); Bean bean = new Bean(); assertEquals("{\"b\":\"b\"}", mapper.writeValueAsString(bean)); } public void testPropertyReorder() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SerializerModifierModule(new ReorderingModifier())); Bean bean = new Bean(); assertEquals("{\"a\":\"a\",\"b\":\"b\"}", mapper.writeValueAsString(bean)); } public void testBuilderReplacement() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SerializerModifierModule(new BuilderModifier(new BogusBeanSerializer(17)))); Bean bean = new Bean(); assertEquals("17", mapper.writeValueAsString(bean)); } public void testSerializerReplacement() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SerializerModifierModule(new ReplacingModifier(new BogusBeanSerializer(123)))); Bean bean = new Bean(); assertEquals("123", mapper.writeValueAsString(bean)); } // for [JACKSON-670] public void testEmptyBean() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test", Version.unknownVersion()) { @Override public void setupModule(SetupContext context) { super.setupModule(context); context.addBeanSerializerModifier(new EmptyBeanModifier()); } }); String json = mapper.writeValueAsString(new EmptyBean()); assertEquals("{\"bogus\":\"foo\"}", json); } public void testEmptyBean539() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test", Version.unknownVersion()) { @Override public void setupModule(SetupContext context) { super.setupModule(context); context.addBeanSerializerModifier(new EmptyBeanModifier539()); } }); String json = mapper.writeValueAsString(new EmptyBean()); assertEquals("42", json); } // [databind#121] public void testModifyArraySerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setSerializerModifier(new ArraySerializerModifier())); assertEquals("123", mapper.writeValueAsString(new Integer[] { 1, 2 })); } public void testModifyCollectionSerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setSerializerModifier(new CollectionSerializerModifier())); assertEquals("123", mapper.writeValueAsString(new ArrayList())); } public void testModifyMapSerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setSerializerModifier(new MapSerializerModifier())); assertEquals("123", mapper.writeValueAsString(new HashMap())); } public void testModifyEnumSerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setSerializerModifier(new EnumSerializerModifier())); assertEquals("123", mapper.writeValueAsString(ABC.C)); } public void testModifyKeySerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule("test") .setSerializerModifier(new KeySerializerModifier())); Map map = new HashMap(); map.put("x", 3); assertEquals("{\"foo\":3}", mapper.writeValueAsString(map)); } } FieldSerializationTest.java000066400000000000000000000151211325620701100365600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * Unit tests for verifying that field-backed properties can also be serialized * (since version 1.1) as well as getter-accessible properties. */ public class FieldSerializationTest extends BaseMapTest { /* /********************************************************** /* Annotated helper classes /********************************************************** */ static class SimpleFieldBean { public int x, y; // not auto-detectable, not public int z; // ignored, not detectable either @JsonIgnore public int a; } static class SimpleFieldBean2 { @JsonSerialize String[] values; // note: this annotation should not matter for serialization: @JsonDeserialize int dummy; } static class TransientBean { public int a; // transients should not be included public transient int b; // or statics public static int c; } @JsonAutoDetect(setterVisibility=Visibility.PUBLIC_ONLY, fieldVisibility=Visibility.NONE) public class NoAutoDetectBean { // not auto-detectable any more public int x; @JsonProperty("z") public int _z; } /** * Let's test invalid bean too: can't have 2 logical properties * with same name. *

* 21-Feb-2010, tatus: That is, not within same class. * As per [JACKSON-226] it is acceptable to "override" * field definitions in sub-classes. */ public static class DupFieldBean { @JsonProperty("foo") public int _z; @JsonSerialize private int foo; } public static class DupFieldBean2 { public int z; @JsonProperty("z") public int _z; } @SuppressWarnings("hiding") public static class OkDupFieldBean extends SimpleFieldBean { @JsonProperty("x") protected int myX; public int y; public OkDupFieldBean(int x, int y) { this.myX = x; this.y = y; } } /** * It is ok to have a method-based and field-based property * introspectable: only one should be serialized, and since * methods have precedence, it should be the method one. */ public static class FieldAndMethodBean { @JsonProperty public int z; @JsonProperty("z") public int getZ() { return z+1; } } @JsonInclude(JsonInclude.Include.NON_EMPTY) public class Item240 { @JsonProperty private String id; // only include annotation to ensure it won't override settings @JsonSerialize(typing=JsonSerialize.Typing.STATIC) private String state; public Item240(String id, String state) { this.id = id; this.state = state; } } /* /********************************************************** /* Main tests, success /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleAutoDetect() throws Exception { SimpleFieldBean bean = new SimpleFieldBean(); // let's set x, leave y as is bean.x = 13; Map result = writeAndMap(MAPPER, bean); assertEquals(2, result.size()); assertEquals(Integer.valueOf(13), result.get("x")); assertEquals(Integer.valueOf(0), result.get("y")); } @SuppressWarnings("unchecked") public void testSimpleAnnotation() throws Exception { SimpleFieldBean2 bean = new SimpleFieldBean2(); bean.values = new String[] { "a", "b" }; Map result = writeAndMap(MAPPER, bean); assertEquals(1, result.size()); List values = (List) result.get("values"); assertEquals(2, values.size()); assertEquals("a", values.get(0)); assertEquals("b", values.get(1)); } public void testTransientAndStatic() throws Exception { TransientBean bean = new TransientBean(); Map result = writeAndMap(MAPPER, bean); assertEquals(1, result.size()); assertEquals(Integer.valueOf(0), result.get("a")); } public void testNoAutoDetect() throws Exception { NoAutoDetectBean bean = new NoAutoDetectBean(); bean._z = -4; Map result = writeAndMap(MAPPER, bean); assertEquals(1, result.size()); assertEquals(Integer.valueOf(-4), result.get("z")); } /** * Unit test that verifies that if both a field and a getter * method exist for a logical property (which is allowed), * getter has precendence over field. */ public void testMethodPrecedence() throws Exception { FieldAndMethodBean bean = new FieldAndMethodBean(); bean.z = 9; assertEquals(10, bean.getZ()); assertEquals("{\"z\":10}", MAPPER.writeValueAsString(bean)); } /** * Testing [JACKSON-226]: it is ok to have "field override", * as long as there are no intra-class conflicts. */ public void testOkDupFields() throws Exception { OkDupFieldBean bean = new OkDupFieldBean(1, 2); Map json = writeAndMap(MAPPER, bean); assertEquals(2, json.size()); assertEquals(Integer.valueOf(1), json.get("x")); assertEquals(Integer.valueOf(2), json.get("y")); } public void testIssue240() throws Exception { Item240 bean = new Item240("a12", null); assertEquals(MAPPER.writeValueAsString(bean), "{\"id\":\"a12\"}"); } /* /********************************************************** /* Main tests, failure cases /********************************************************** */ public void testFailureDueToDups() throws Exception { try { writeAndMap(MAPPER, new DupFieldBean()); } catch (JsonMappingException e) { verifyException(e, "Multiple fields representing"); } } public void testFailureDueToDupField() throws Exception { try { writeAndMap(MAPPER, new DupFieldBean2()); } catch (JsonMappingException e) { verifyException(e, "Multiple fields representing"); } } } JsonValueTest.java000066400000000000000000000205731325620701100347140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; /** * This unit test suite tests functioning of {@link JsonValue} * annotation with bean serialization. */ @SuppressWarnings("serial") public class JsonValueTest extends BaseMapTest { static class ValueClass { final T _value; public ValueClass(T v) { _value = v; } @JsonValue T value() { return _value; } } static class FieldValueClass { @JsonValue(true) final T _value; public FieldValueClass(T v) { _value = v; } } /** * Another test class to check that it is also possible to * force specific serializer to use with @JsonValue annotated * method. Difference is between Integer serialization, and * conversion to a Json String. */ final static class ToStringValueClass extends ValueClass { public ToStringValueClass(T value) { super(value); } // Also, need to use this annotation to help @JsonSerialize(using=ToStringSerializer.class) @Override @JsonValue T value() { return super.value(); } } final static class ToStringValueClass2 extends ValueClass { public ToStringValueClass2(String value) { super(value); } // Simple as well, but let's ensure that other getters won't matter... @JsonProperty int getFoobar() { return 4; } public String[] getSomethingElse() { return new String[] { "1", "a" }; } } static class ValueBase { public String a = "a"; } static class ValueType extends ValueBase { public String b = "b"; } // Finally, let's also test static vs dynamic type static class ValueWrapper { @JsonValue public ValueBase getX() { return new ValueType(); } } static class MapBean { @JsonValue public Map toMap() { HashMap map = new HashMap(); map.put("a", "1"); return map; } } static class MapFieldBean { @JsonValue Map stuff = new HashMap<>(); { stuff.put("b", "2"); } } static class MapAsNumber extends HashMap { @JsonValue public int value() { return 42; } } static class ListAsNumber extends ArrayList { @JsonValue public int value() { return 13; } } // Just to ensure it's possible to disable annotation (usually // via mix-ins, but here directly) @JsonPropertyOrder({ "x", "y" }) static class DisabledJsonValue { @JsonValue(false) public int x = 1; @JsonValue(false) public int getY() { return 2; } } static class IntExtBean { public List values = new ArrayList(); public void add(int v) { values.add(new Internal(v)); } } static class Internal { public int value; public Internal(int v) { value = v; } @JsonValue public External asExternal() { return new External(this); } } static class External { public int i; External(Internal e) { i = e.value; } } // [databind#167] @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "boingo") @JsonSubTypes(value = {@JsonSubTypes.Type(name = "boopsy", value = AdditionInterfaceImpl.class) }) static interface AdditionInterface { public int add(int in); } public static class AdditionInterfaceImpl implements AdditionInterface { private final int toAdd; @JsonCreator public AdditionInterfaceImpl(@JsonProperty("toAdd") int toAdd) { this.toAdd = toAdd; } @JsonProperty public int getToAdd() { return toAdd; } @Override public int add(int in) { return in + toAdd; } } static class Bean838 { @JsonValue public String value() { return "value"; } } static class Bean838Serializer extends StdScalarSerializer { public Bean838Serializer() { super(Bean838.class); } @Override public void serialize(Bean838 value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeNumber(42); } } /* /********************************************************* /* Test cases /********************************************************* */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleMethodJsonValue() throws Exception { assertEquals("\"abc\"", MAPPER.writeValueAsString(new ValueClass("abc"))); assertEquals("null", MAPPER.writeValueAsString(new ValueClass(null))); } public void testSimpleFieldJsonValue() throws Exception { assertEquals("\"abc\"", MAPPER.writeValueAsString(new FieldValueClass("abc"))); assertEquals("null", MAPPER.writeValueAsString(new FieldValueClass(null))); } public void testJsonValueWithUseSerializer() throws Exception { String result = serializeAsString(MAPPER, new ToStringValueClass(Integer.valueOf(123))); assertEquals("\"123\"", result); } /** * Test for verifying that additional getters won't confuse serializer. */ public void testMixedJsonValue() throws Exception { String result = serializeAsString(MAPPER, new ToStringValueClass2("xyz")); assertEquals("\"xyz\"", result); } public void testDisabling() throws Exception { assertEquals(aposToQuotes("{'x':1,'y':2}"), MAPPER.writeValueAsString(new DisabledJsonValue())); } public void testValueWithStaticType() throws Exception { // Ok; first, with dynamic type: assertEquals("{\"a\":\"a\",\"b\":\"b\"}", MAPPER.writeValueAsString(new ValueWrapper())); // then static ObjectMapper staticMapper = new ObjectMapper(); staticMapper.configure(MapperFeature.USE_STATIC_TYPING, true); assertEquals("{\"a\":\"a\"}", staticMapper.writeValueAsString(new ValueWrapper())); } public void testMapWithJsonValue() throws Exception { // First via method assertEquals("{\"a\":\"1\"}", MAPPER.writeValueAsString(new MapBean())); // then field assertEquals("{\"b\":\"2\"}", MAPPER.writeValueAsString(new MapFieldBean())); } public void testWithMap() throws Exception { assertEquals("42", MAPPER.writeValueAsString(new MapAsNumber())); } public void testWithList() throws Exception { assertEquals("13", MAPPER.writeValueAsString(new ListAsNumber())); } public void testInList() throws Exception { IntExtBean bean = new IntExtBean(); bean.add(1); bean.add(2); String json = MAPPER.writeValueAsString(bean); assertEquals(json, "{\"values\":[{\"i\":1},{\"i\":2}]}"); } // [databind#167] public void testPolymorphicSerdeWithDelegate() throws Exception { AdditionInterface adder = new AdditionInterfaceImpl(1); assertEquals(2, adder.add(1)); String json = MAPPER.writeValueAsString(adder); assertEquals("{\"boingo\":\"boopsy\",\"toAdd\":1}", json); assertEquals(2, MAPPER.readValue(json, AdditionInterface.class).add(1)); } public void testJsonValueWithCustomOverride() throws Exception { final Bean838 INPUT = new Bean838(); // by default, @JsonValue should be used assertEquals(quote("value"), MAPPER.writeValueAsString(INPUT)); // but custom serializer should override it ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new SimpleModule() .addSerializer(Bean838.class, new Bean838Serializer()) ); assertEquals("42", mapper.writeValueAsString(INPUT)); } } RawValueTest.java000066400000000000000000000060771325620701100345370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.util.RawValue; /** * This unit test suite tests functioning of {@link JsonRawValue} * annotation with bean serialization. */ public class RawValueTest extends com.fasterxml.jackson.databind.BaseMapTest { /* /********************************************************* /* Helper bean classes /********************************************************* */ /// Class for testing {@link JsonRawValue} annotations with getters returning String @JsonPropertyOrder(alphabetic=true) final static class ClassGetter { protected final T _value; protected ClassGetter(T value) { _value = value;} public T getNonRaw() { return _value; } @JsonProperty("raw") @JsonRawValue public T foobar() { return _value; } @JsonProperty @JsonRawValue protected T value() { return _value; } } // [databind#348] static class RawWrapped { @JsonRawValue private final String json; public RawWrapped(String str) { json = str; } } /* /********************************************************* /* Test cases /********************************************************* */ private final ObjectMapper MAPPER = objectMapper(); public void testSimpleStringGetter() throws Exception { String value = "abc"; String result = MAPPER.writeValueAsString(new ClassGetter(value)); String expected = String.format("{\"nonRaw\":\"%s\",\"raw\":%s,\"value\":%s}", value, value, value); assertEquals(expected, result); } public void testSimpleNonStringGetter() throws Exception { int value = 123; String result = MAPPER.writeValueAsString(new ClassGetter(value)); String expected = String.format("{\"nonRaw\":%d,\"raw\":%d,\"value\":%d}", value, value, value); assertEquals(expected, result); } public void testNullStringGetter() throws Exception { String result = MAPPER.writeValueAsString(new ClassGetter(null)); String expected = "{\"nonRaw\":null,\"raw\":null,\"value\":null}"; assertEquals(expected, result); } public void testWithValueToTree() throws Exception { JsonNode w = MAPPER.valueToTree(new RawWrapped("{ }")); assertNotNull(w); assertEquals("{\"json\":{ }}", MAPPER.writeValueAsString(w)); } // for [databind#743] public void testRawFromMapToTree() throws Exception { RawValue myType = new RawValue("Jackson"); Map object = new HashMap(); object.put("key", myType); JsonNode jsonNode = MAPPER.valueToTree(object); String json = MAPPER.writeValueAsString(jsonNode); assertEquals("{\"key\":Jackson}", json); } } SerializationFeaturesTest.java000066400000000000000000000142661325620701100373240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.*; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; /** * Unit tests for checking handling of some of {@link MapperFeature}s * and {@link SerializationFeature}s for serialization. */ public class SerializationFeaturesTest extends BaseMapTest { static class CloseableBean implements Closeable { public int a = 3; protected boolean wasClosed = false; @Override public void close() throws IOException { wasClosed = true; } } private static class StringListBean { @SuppressWarnings("unused") public Collection values; public StringListBean(Collection v) { values = v; } } /* /********************************************************** /* Test methods /********************************************************** */ // Test for [JACKSON-282] @SuppressWarnings("resource") public void testCloseCloseable() throws IOException { ObjectMapper m = new ObjectMapper(); // default should be disabled: CloseableBean bean = new CloseableBean(); m.writeValueAsString(bean); assertFalse(bean.wasClosed); // but can enable it: m.configure(SerializationFeature.CLOSE_CLOSEABLE, true); bean = new CloseableBean(); m.writeValueAsString(bean); assertTrue(bean.wasClosed); // also: let's ensure that ObjectWriter won't interfere with it bean = new CloseableBean(); m.writerFor(CloseableBean.class).writeValueAsString(bean); assertTrue(bean.wasClosed); } // Test for [JACKSON-289] public void testCharArrays() throws IOException { char[] chars = new char[] { 'a','b','c' }; ObjectMapper m = new ObjectMapper(); // default: serialize as Strings assertEquals(quote("abc"), m.writeValueAsString(chars)); // new feature: serialize as JSON array: m.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS, true); assertEquals("[\"a\",\"b\",\"c\"]", m.writeValueAsString(chars)); } // Test for [JACKSON-401] public void testFlushingAutomatic() throws IOException { ObjectMapper mapper = new ObjectMapper(); assertTrue(mapper.getSerializationConfig().isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)); // default is to flush after writeValue() StringWriter sw = new StringWriter(); JsonGenerator g = mapper.getFactory().createGenerator(sw); mapper.writeValue(g, Integer.valueOf(13)); assertEquals("13", sw.toString()); g.close(); // ditto with ObjectWriter sw = new StringWriter(); g = mapper.getFactory().createGenerator(sw); ObjectWriter ow = mapper.writer(); ow.writeValue(g, Integer.valueOf(99)); assertEquals("99", sw.toString()); g.close(); } public void testFlushingNotAutomatic() throws IOException { // but should not occur if configured otherwise ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, false); StringWriter sw = new StringWriter(); JsonGenerator g = mapper.getFactory().createGenerator(sw); mapper.writeValue(g, Integer.valueOf(13)); // no flushing now: assertEquals("", sw.toString()); // except when actually flushing g.flush(); assertEquals("13", sw.toString()); g.close(); // Also, same should happen with ObjectWriter sw = new StringWriter(); g = mapper.getFactory().createGenerator(sw); ObjectWriter ow = mapper.writer(); ow.writeValue(g, Integer.valueOf(99)); assertEquals("", sw.toString()); // except when actually flushing g.flush(); assertEquals("99", sw.toString()); g.close(); } public void testSingleElementCollections() throws IOException { final ObjectWriter writer = objectWriter().with(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); // Lists: ArrayList strs = new ArrayList(); strs.add("xyz"); assertEquals(quote("xyz"), writer.writeValueAsString(strs)); ArrayList ints = new ArrayList(); ints.add(13); assertEquals("13", writer.writeValueAsString(ints)); // other Collections, like Sets: HashSet longs = new HashSet(); longs.add(42L); assertEquals("42", writer.writeValueAsString(longs)); // [databind#180] final String EXP_STRINGS = "{\"values\":\"foo\"}"; assertEquals(EXP_STRINGS, writer.writeValueAsString(new StringListBean(Collections.singletonList("foo")))); final Set SET = new HashSet(); SET.add("foo"); assertEquals(EXP_STRINGS, writer.writeValueAsString(new StringListBean(SET))); // arrays: assertEquals("true", writer.writeValueAsString(new boolean[] { true })); assertEquals("[true,false]", writer.writeValueAsString(new boolean[] { true, false })); assertEquals("true", writer.writeValueAsString(new Boolean[] { Boolean.TRUE })); assertEquals("3", writer.writeValueAsString(new short[] { 3 })); assertEquals("[3,2]", writer.writeValueAsString(new short[] { 3, 2 })); assertEquals("3", writer.writeValueAsString(new int[] { 3 })); assertEquals("[3,2]", writer.writeValueAsString(new int[] { 3, 2 })); assertEquals("1", writer.writeValueAsString(new long[] { 1L })); assertEquals("[-1,4]", writer.writeValueAsString(new long[] { -1L, 4L })); assertEquals("0.5", writer.writeValueAsString(new double[] { 0.5 })); assertEquals("[0.5,2.5]", writer.writeValueAsString(new double[] { 0.5, 2.5 })); assertEquals("0.5", writer.writeValueAsString(new float[] { 0.5f })); assertEquals("[0.5,2.5]", writer.writeValueAsString(new float[] { 0.5f, 2.5f })); assertEquals(quote("foo"), writer.writeValueAsString(new String[] { "foo" })); } } TestAnnotationInheritance.java000066400000000000000000000054761325620701100372770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * This unit test suite tests use of Annotations for * bean serialization. */ public class TestAnnotationInheritance extends BaseMapTest { /* /********************************************************** /* Annotated helper classes /********************************************************** */ /// Base class for testing {@link JsonProperty} annotations static class BasePojo { @JsonProperty public int width() { return 3; } @JsonProperty public int length() { return 7; } } /** * It should also be possible to specify annotations on interfaces, * to be implemented by classes. This should not only work when interface * is used (which may be the case for de-serialization) but also * when implementing class is used and overrides methods. In latter * case overriding methods should still "inherit" annotations -- this * is not something JVM runtime provides, but Jackson class * instrospector does. */ interface PojoInterface { @JsonProperty int width(); @JsonProperty int length(); } /** * Sub-class for testing that inheritance is handled properly * wrt annotations. */ static class PojoSubclass extends BasePojo { /** * Should still be recognized as a Getter here. */ @Override public int width() { return 9; } } static class PojoImpl implements PojoInterface { // Both should be recognized as getters here @Override public int width() { return 1; } @Override public int length() { return 2; } public int getFoobar() { return 5; } } /* /********************************************************** /* Main tests /********************************************************** */ public void testSimpleGetterInheritance() throws Exception { ObjectMapper m = new ObjectMapper(); Map result = writeAndMap(m, new PojoSubclass()); assertEquals(2, result.size()); assertEquals(Integer.valueOf(7), result.get("length")); assertEquals(Integer.valueOf(9), result.get("width")); } public void testSimpleGetterInterfaceImpl() throws Exception { ObjectMapper m = new ObjectMapper(); Map result = writeAndMap(m, new PojoImpl()); // should get 2 from interface, and one more from impl itself assertEquals(3, result.size()); assertEquals(Integer.valueOf(5), result.get("foobar")); assertEquals(Integer.valueOf(1), result.get("width")); assertEquals(Integer.valueOf(2), result.get("length")); } } TestAnnotations.java000066400000000000000000000200471325620701100352770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * This unit test suite tests use of Annotations for * bean serialization. */ public class TestAnnotations extends BaseMapTest { /* /********************************************************** /* Helper classes /********************************************************** */ /// Class for testing {@link JsonProperty} annotations with getters final static class SizeClassGetter { @JsonProperty public int size() { return 3; } @JsonProperty("length") public int foobar() { return -17; } // note: need not be public since there's annotation @JsonProperty protected int value() { return 0; } // dummy method; not a getter signature protected int getNotReally(int arg) { return 0; } } // And additional testing to cover [JACKSON-64] final static class SizeClassGetter2 { // Should still be considered property "x" @JsonProperty protected int getX() { return 3; } } // and some support for testing [JACKSON-120] final static class SizeClassGetter3 { // Should be considered property "y" even tho non-public @JsonSerialize protected int getY() { return 8; } } /** * Class for testing {@link JsonSerializer} annotation * for class itself. */ @JsonSerialize(using=BogusSerializer.class) final static class ClassSerializer { } /** * Class for testing an active {@link JsonSerialize#using} annotation * for a method */ final static class ClassMethodSerializer { private int _x; public ClassMethodSerializer(int x) { _x = x; } @JsonSerialize(using=StringSerializer.class) public int getX() { return _x; } } /** * Class for testing an inactive (one that will not have any effect) * {@link JsonSerialize} annotation for a method */ final static class InactiveClassMethodSerializer { private int _x; public InactiveClassMethodSerializer(int x) { _x = x; } // Basically, has no effect, hence gets serialized as number @JsonSerialize(using=JsonSerializer.None.class) public int getX() { return _x; } } /** * Class for verifying that getter information is inherited * as expected via normal class inheritance */ static class BaseBean { public int getX() { return 1; } @JsonProperty("y") private int getY() { return 2; } } static class SubClassBean extends BaseBean { public int getZ() { return 3; } } // For [JACKSON-666] ("SerializationFeature of the Beast!") @JsonPropertyOrder(alphabetic=true) static class GettersWithoutSetters { public int d = 0; @JsonCreator public GettersWithoutSetters(@JsonProperty("a") int a) { } // included, since there is a constructor property public int getA() { return 3; } // not included, as there's nothing matching public int getB() { return 4; } // include as there is setter public int getC() { return 5; } public void setC(int v) { } // and included, as there is a field public int getD() { return 6; } } // [JACKSON-806]: override 'need-setter' with explicit annotation static class GettersWithoutSetters2 { @JsonProperty public int getA() { return 123; } } /* /********************************************************** /* Other helper classes /********************************************************** */ public final static class BogusSerializer extends JsonSerializer { @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { jgen.writeBoolean(true); } } private final static class StringSerializer extends JsonSerializer { @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { jgen.writeString("X"+value+"X"); } } /* /********************************************************** /* Main tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleGetter() throws Exception { Map result = writeAndMap(MAPPER, new SizeClassGetter()); assertEquals(3, result.size()); assertEquals(Integer.valueOf(3), result.get("size")); assertEquals(Integer.valueOf(-17), result.get("length")); assertEquals(Integer.valueOf(0), result.get("value")); } public void testSimpleGetter2() throws Exception { Map result = writeAndMap(MAPPER, new SizeClassGetter2()); assertEquals(1, result.size()); assertEquals(Integer.valueOf(3), result.get("x")); } // testing [JACKSON-120], implied getter public void testSimpleGetter3() throws Exception { Map result = writeAndMap(MAPPER, new SizeClassGetter3()); assertEquals(1, result.size()); assertEquals(Integer.valueOf(8), result.get("y")); } /** * Let's also verify that inherited super-class getters are used * as expected */ public void testGetterInheritance() throws Exception { Map result = writeAndMap(MAPPER, new SubClassBean()); assertEquals(3, result.size()); assertEquals(Integer.valueOf(1), result.get("x")); assertEquals(Integer.valueOf(2), result.get("y")); assertEquals(Integer.valueOf(3), result.get("z")); } /** * Unit test to verify that {@link JsonSerialize#using} annotation works * when applied to a class */ public void testClassSerializer() throws Exception { StringWriter sw = new StringWriter(); MAPPER.writeValue(sw, new ClassSerializer()); assertEquals("true", sw.toString()); } /** * Unit test to verify that @JsonSerializer annotation works * when applied to a Method */ public void testActiveMethodSerializer() throws Exception { StringWriter sw = new StringWriter(); MAPPER.writeValue(sw, new ClassMethodSerializer(13)); /* Here we will get wrapped as an object, since we have * full object, just override a single property */ assertEquals("{\"x\":\"X13X\"}", sw.toString()); } public void testInactiveMethodSerializer() throws Exception { String json = MAPPER.writeValueAsString(new InactiveClassMethodSerializer(8)); /* Here we will get wrapped as an object, since we have * full object, just override a single property */ assertEquals("{\"x\":8}", json); } public void testGettersWithoutSetters() throws Exception { ObjectMapper m = new ObjectMapper(); GettersWithoutSetters bean = new GettersWithoutSetters(123); assertFalse(m.isEnabled(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS)); // by default, all 4 found: assertEquals("{\"a\":3,\"b\":4,\"c\":5,\"d\":6}", m.writeValueAsString(bean)); // but 3 if we require mutator: m = new ObjectMapper(); m.enable(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS); assertEquals("{\"a\":3,\"c\":5,\"d\":6}", m.writeValueAsString(bean)); } public void testGettersWithoutSettersOverride() throws Exception { GettersWithoutSetters2 bean = new GettersWithoutSetters2(); ObjectMapper m = new ObjectMapper(); m.enable(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS); assertEquals("{\"a\":123}", m.writeValueAsString(bean)); } } TestArraySerialization.java000066400000000000000000000067011325620701100366170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; public class TestArraySerialization extends BaseMapTest { private final ObjectMapper MAPPER = objectMapper(); public void testLongStringArray() throws Exception { final int SIZE = 40000; StringBuilder sb = new StringBuilder(SIZE*2); for (int i = 0; i < SIZE; ++i) { sb.append((char) i); } String str = sb.toString(); byte[] data = MAPPER.writeValueAsBytes(new String[] { "abc", str, null, str }); JsonParser jp = MAPPER.getFactory().createParser(data); assertToken(JsonToken.START_ARRAY, jp.nextToken()); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals("abc", jp.getText()); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); String actual = jp.getText(); assertEquals(str.length(), actual.length()); assertEquals(str, actual); assertToken(JsonToken.VALUE_NULL, jp.nextToken()); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(str, jp.getText()); assertToken(JsonToken.END_ARRAY, jp.nextToken()); assertNull(jp.nextToken()); jp.close(); } public void testIntArray() throws Exception { String json = MAPPER.writeValueAsString(new int[] { 1, 2, 3, -7 }); assertEquals("[1,2,3,-7]", json); } public void testBigIntArray() throws Exception { final int SIZE = 99999; int[] ints = new int[SIZE]; for (int i = 0; i < ints.length; ++i) { ints[i] = i; } // Let's try couple of times, to ensure that state is handled // correctly by ObjectMapper (wrt buffer recycling used // with 'writeAsBytes()') JsonFactory f = MAPPER.getFactory(); for (int round = 0; round < 3; ++round) { byte[] data = MAPPER.writeValueAsBytes(ints); JsonParser jp = f.createParser(data); assertToken(JsonToken.START_ARRAY, jp.nextToken()); for (int i = 0; i < SIZE; ++i) { assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertEquals(i, jp.getIntValue()); } assertToken(JsonToken.END_ARRAY, jp.nextToken()); jp.close(); } } public void testLongArray() throws Exception { String json = MAPPER.writeValueAsString(new long[] { Long.MIN_VALUE, 0, Long.MAX_VALUE }); assertEquals("["+Long.MIN_VALUE+",0,"+Long.MAX_VALUE+"]", json); } public void testStringArray() throws Exception { assertEquals("[\"a\",\"\\\"foo\\\"\",null]", MAPPER.writeValueAsString(new String[] { "a", "\"foo\"", null })); assertEquals("[]", MAPPER.writeValueAsString(new String[] { })); } public void testDoubleArray() throws Exception { String json = MAPPER.writeValueAsString(new double[] { 1.01, 2.0, -7, Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY }); assertEquals("[1.01,2.0,-7.0,\"NaN\",\"-Infinity\",\"Infinity\"]", json); } public void testFloatArray() throws Exception { String json = MAPPER.writeValueAsString(new float[] { 1.01f, 2.0f, -7f, Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY }); assertEquals("[1.01,2.0,-7.0,\"NaN\",\"-Infinity\",\"Infinity\"]", json); } } TestAutoDetect.java000066400000000000000000000101031325620701100350330ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.VisibilityChecker; /** * Unit tests for checking extended auto-detect configuration, * in context of serialization */ public class TestAutoDetect extends BaseMapTest { static class FieldBean { public String p1 = "public"; protected String p2 = "protected"; @SuppressWarnings("unused") private String p3 = "private"; } @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC) static class ProtFieldBean extends FieldBean { } static class MethodBean { public String getA() { return "a"; } protected String getB() { return "b"; } @SuppressWarnings("unused") private String getC() { return "c"; } } @JsonAutoDetect(getterVisibility=JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC) static class ProtMethodBean extends MethodBean { } /* /********************************************************* /* Test methods /********************************************************* */ public void testDefaults() throws Exception { ObjectMapper m = new ObjectMapper(); // by default, only public fields and getters are detected assertEquals("{\"p1\":\"public\"}", m.writeValueAsString(new FieldBean())); assertEquals("{\"a\":\"a\"}", m.writeValueAsString(new MethodBean())); } public void testProtectedViaAnnotations() throws Exception { ObjectMapper m = new ObjectMapper(); Map result = writeAndMap(m, new ProtFieldBean()); assertEquals(2, result.size()); assertEquals("public", result.get("p1")); assertEquals("protected", result.get("p2")); assertNull(result.get("p3")); result = writeAndMap(m, new ProtMethodBean()); assertEquals(2, result.size()); assertEquals("a", result.get("a")); assertEquals("b", result.get("b")); assertNull(result.get("c")); } public void testPrivateUsingGlobals() throws Exception { ObjectMapper m = new ObjectMapper(); VisibilityChecker vc = m.getVisibilityChecker(); vc = vc.withFieldVisibility(JsonAutoDetect.Visibility.ANY); m.setVisibility(vc); Map result = writeAndMap(m, new FieldBean()); assertEquals(3, result.size()); assertEquals("public", result.get("p1")); assertEquals("protected", result.get("p2")); assertEquals("private", result.get("p3")); m = new ObjectMapper(); vc = m.getVisibilityChecker(); vc = vc.withGetterVisibility(JsonAutoDetect.Visibility.ANY); m.setVisibility(vc); result = writeAndMap(m, new MethodBean()); assertEquals(3, result.size()); assertEquals("a", result.get("a")); assertEquals("b", result.get("b")); assertEquals("c", result.get("c")); } // [JACKSON-621] public void testBasicSetup() throws Exception { ObjectMapper m = new ObjectMapper(); VisibilityChecker vc = m.getVisibilityChecker(); vc = vc.with(JsonAutoDetect.Visibility.ANY); m.setVisibility(vc); Map result = writeAndMap(m, new FieldBean()); assertEquals(3, result.size()); assertEquals("public", result.get("p1")); assertEquals("protected", result.get("p2")); assertEquals("private", result.get("p3")); } // [JACKSON-595] public void testMapperShortcutMethods() throws Exception { ObjectMapper m = new ObjectMapper(); m.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); Map result = writeAndMap(m, new FieldBean()); assertEquals(3, result.size()); assertEquals("public", result.get("p1")); assertEquals("protected", result.get("p2")); assertEquals("private", result.get("p3")); } } TestConfig.java000066400000000000000000000177651325620701100342240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.StringWriter; import java.text.SimpleDateFormat; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.introspect.ClassIntrospector; /** * Unit tests for checking handling of SerializationConfig. */ public class TestConfig extends BaseMapTest { /* /********************************************************** /* Helper beans /********************************************************** */ @JsonInclude(JsonInclude.Include.NON_DEFAULT) @JsonSerialize(typing=JsonSerialize.Typing.STATIC) final static class Config { } final static class ConfigNone { } static class AnnoBean { public int getX() { return 1; } @JsonProperty("y") private int getY() { return 2; } } static class Indentable { public int a = 3; } public static class SimpleBean { public int x = 1; } /* /********************************************************** /* Main tests /********************************************************** */ final static ObjectMapper MAPPER = new ObjectMapper(); /* Test to verify that we don't overflow number of features; if we * hit the limit, need to change implementation -- this test just * gives low-water mark */ public void testEnumIndexes() { int max = 0; for (SerializationFeature f : SerializationFeature.values()) { max = Math.max(max, f.ordinal()); } if (max >= 31) { // 31 is actually ok; 32 not fail("Max number of SerializationFeature enums reached: "+max); } } public void testDefaults() { SerializationConfig cfg = MAPPER.getSerializationConfig(); // First, defaults: assertTrue(cfg.isEnabled(MapperFeature.USE_ANNOTATIONS)); assertTrue(cfg.isEnabled(MapperFeature.AUTO_DETECT_GETTERS)); assertTrue(cfg.isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)); assertTrue(cfg.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)); assertFalse(cfg.isEnabled(SerializationFeature.INDENT_OUTPUT)); assertFalse(cfg.isEnabled(MapperFeature.USE_STATIC_TYPING)); // since 1.3: assertTrue(cfg.isEnabled(MapperFeature.AUTO_DETECT_IS_GETTERS)); // since 1.4 assertTrue(cfg.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)); // since 1.5 assertTrue(cfg.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION)); } public void testOverrideIntrospectors() { SerializationConfig cfg = MAPPER.getSerializationConfig(); // and finally, ensure we could override introspectors cfg = cfg.with((ClassIntrospector) null); // no way to verify tho cfg = cfg.with((AnnotationIntrospector) null); assertNull(cfg.getAnnotationIntrospector()); } public void testMisc() { ObjectMapper m = new ObjectMapper(); m.setDateFormat(null); // just to execute the code path assertNotNull(m.getSerializationConfig().toString()); // ditto } public void testIndentation() throws Exception { Map map = new HashMap(); map.put("a", Integer.valueOf(2)); String result = MAPPER.writer().with(SerializationFeature.INDENT_OUTPUT) .writeValueAsString(map); // 02-Jun-2009, tatu: not really a clean way but... String lf = getLF(); assertEquals("{"+lf+" \"a\" : 2"+lf+"}", result); } public void testAnnotationsDisabled() throws Exception { // first: verify that annotation introspection is enabled by default assertTrue(MAPPER.isEnabled(MapperFeature.USE_ANNOTATIONS)); Map result = writeAndMap(MAPPER, new AnnoBean()); assertEquals(2, result.size()); ObjectMapper m2 = new ObjectMapper(); m2.configure(MapperFeature.USE_ANNOTATIONS, false); result = writeAndMap(m2, new AnnoBean()); assertEquals(1, result.size()); } /** * Test for verifying working of [JACKSON-191] */ public void testProviderConfig() throws Exception { ObjectMapper mapper = new ObjectMapper(); DefaultSerializerProvider prov = (DefaultSerializerProvider) mapper.getSerializerProvider(); assertEquals(0, prov.cachedSerializersCount()); // and then should get one constructed for: Map result = this.writeAndMap(mapper, new AnnoBean()); assertEquals(2, result.size()); assertEquals(Integer.valueOf(1), result.get("x")); assertEquals(Integer.valueOf(2), result.get("y")); /* Note: it is 2 because we'll also get serializer for basic 'int', not * just AnnoBean */ /* 12-Jan-2010, tatus: Actually, probably more, if and when we typing * aspects are considered (depending on what is cached) */ int count = prov.cachedSerializersCount(); if (count < 2) { fail("Should have at least 2 cached serializers, got "+count); } prov.flushCachedSerializers(); assertEquals(0, prov.cachedSerializersCount()); } // Test for [Issue#12] public void testIndentWithPassedGenerator() throws Exception { Indentable input = new Indentable(); assertEquals("{\"a\":3}", MAPPER.writeValueAsString(input)); String LF = getLF(); String INDENTED = "{"+LF+" \"a\" : 3"+LF+"}"; final ObjectWriter indentWriter = MAPPER.writer().with(SerializationFeature.INDENT_OUTPUT); assertEquals(INDENTED, indentWriter.writeValueAsString(input)); // [Issue#12] StringWriter sw = new StringWriter(); JsonGenerator jgen = MAPPER.getFactory().createGenerator(sw); indentWriter.writeValue(jgen, input); jgen.close(); assertEquals(INDENTED, sw.toString()); // and also with ObjectMapper itself sw = new StringWriter(); ObjectMapper m2 = new ObjectMapper(); m2.enable(SerializationFeature.INDENT_OUTPUT); jgen = m2.getFactory().createGenerator(sw); m2.writeValue(jgen, input); jgen.close(); assertEquals(INDENTED, sw.toString()); } public void testNoAccessOverrides() throws Exception { ObjectMapper m = new ObjectMapper(); m.disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS); assertEquals("{\"x\":1}", m.writeValueAsString(new SimpleBean())); } public void testDateFormatConfig() throws Exception { ObjectMapper mapper = new ObjectMapper(); TimeZone tz1 = TimeZone.getTimeZone("America/Los_Angeles"); TimeZone tz2 = TimeZone.getTimeZone("Central Standard Time"); // sanity checks assertEquals(tz1, tz1); assertEquals(tz2, tz2); if (tz1.equals(tz2)) { fail(); } mapper.setTimeZone(tz1); assertEquals(tz1, mapper.getSerializationConfig().getTimeZone()); assertEquals(tz1, mapper.getDeserializationConfig().getTimeZone()); // also better stick via reader/writer as well assertEquals(tz1, mapper.writer().getConfig().getTimeZone()); assertEquals(tz1, mapper.reader().getConfig().getTimeZone()); SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); f.setTimeZone(tz2); mapper.setDateFormat(f); // should not change the timezone tho assertEquals(tz1, mapper.getSerializationConfig().getTimeZone()); assertEquals(tz1, mapper.getDeserializationConfig().getTimeZone()); assertEquals(tz1, mapper.writer().getConfig().getTimeZone()); assertEquals(tz1, mapper.reader().getConfig().getTimeZone()); } private final static String getLF() { return System.getProperty("line.separator"); } } TestCustomSerializers.java000066400000000000000000000206061325620701100364720ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.io.StringWriter; import java.util.*; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Element; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.CharacterEscapes; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.CollectionSerializer; import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer; import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; import com.fasterxml.jackson.databind.util.StdConverter; /** * Tests for verifying various issues with custom serializers. */ @SuppressWarnings("serial") public class TestCustomSerializers extends BaseMapTest { static class ElementSerializer extends JsonSerializer { @Override public void serialize(Element value, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException { gen.writeString("element"); } } @JsonSerialize(using = ElementSerializer.class) public static class ElementMixin {} public static class Immutable { protected int x() { return 3; } protected int y() { return 7; } } /** * Trivial simple custom escape definition set. */ static class CustomEscapes extends CharacterEscapes { private final int[] _asciiEscapes; public CustomEscapes() { _asciiEscapes = standardAsciiEscapesForJSON(); _asciiEscapes['a'] = 'A'; // to basically give us "\A" instead of 'a' _asciiEscapes['b'] = CharacterEscapes.ESCAPE_STANDARD; // too force "\u0062" } @Override public int[] getEscapeCodesForAscii() { return _asciiEscapes; } @Override public SerializableString getEscapeSequence(int ch) { return null; } } @JsonFormat(shape=JsonFormat.Shape.OBJECT) static class LikeNumber extends Number { private static final long serialVersionUID = 1L; public int x; public LikeNumber(int value) { x = value; } @Override public double doubleValue() { return x; } @Override public float floatValue() { return x; } @Override public int intValue() { return x; } @Override public long longValue() { return x; } } // for [databind#631] static class Issue631Bean { @JsonSerialize(using=ParentClassSerializer.class) public Object prop; public Issue631Bean(Object o) { prop = o; } } static class ParentClassSerializer extends StdScalarSerializer { protected ParentClassSerializer() { super(Object.class); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { Object parent = gen.getCurrentValue(); String desc = (parent == null) ? "NULL" : parent.getClass().getSimpleName(); gen.writeString(desc+"/"+value); } } static class UCStringSerializer extends StdScalarSerializer { public UCStringSerializer() { super(String.class); } @Override public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeString(value.toUpperCase()); } } // IMPORTANT: must associate serializer via property annotations protected static class StringListWrapper { @JsonSerialize(contentUsing=UCStringSerializer.class) public List list; public StringListWrapper(String... values) { list = new ArrayList<>(); for (String value : values) { list.add(value); } } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testCustomization() throws Exception { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.addMixIn(Element.class, ElementMixin.class); Element element = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().createElement("el"); StringWriter sw = new StringWriter(); objectMapper.writeValue(sw, element); assertEquals(sw.toString(), "\"element\""); } @SuppressWarnings({ "unchecked", "rawtypes" }) public void testCustomLists() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); JsonSerializer ser = new CollectionSerializer(null, false, null, null); final JsonSerializer collectionSerializer = (JsonSerializer) ser; module.addSerializer(Collection.class, new JsonSerializer() { @Override public void serialize(Collection value, JsonGenerator gen, SerializerProvider provider) throws IOException { if (value.size() != 0) { collectionSerializer.serialize(value, gen, provider); } else { gen.writeNull(); } } }); mapper.registerModule(module); assertEquals("null", mapper.writeValueAsString(new ArrayList())); } // [databind#87]: delegating serializer public void testDelegating() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addSerializer(new StdDelegatingSerializer(Immutable.class, new StdConverter>() { @Override public Map convert(Immutable value) { HashMap map = new LinkedHashMap(); map.put("x", value.x()); map.put("y", value.y()); return map; } })); mapper.registerModule(module); assertEquals("{\"x\":3,\"y\":7}", mapper.writeValueAsString(new Immutable())); } // [databind#215]: Allow registering CharacterEscapes via ObjectWriter public void testCustomEscapes() throws Exception { assertEquals(quote("foo\\u0062\\Ar"), MAPPER.writer(new CustomEscapes()).writeValueAsString("foobar")); } public void testNumberSubclass() throws Exception { assertEquals(aposToQuotes("{'x':42}"), MAPPER.writeValueAsString(new LikeNumber(42))); } public void testWithCurrentValue() throws Exception { assertEquals(aposToQuotes("{'prop':'Issue631Bean/42'}"), MAPPER.writeValueAsString(new Issue631Bean(42))); } public void testWithCustomElements() throws Exception { // First variant that uses per-property override StringListWrapper wr = new StringListWrapper("a", null, "b"); assertEquals(aposToQuotes("{'list':['A',null,'B']}"), MAPPER.writeValueAsString(wr)); // and then per-type registration SimpleModule module = new SimpleModule("test", Version.unknownVersion()); module.addSerializer(String.class, new UCStringSerializer()); ObjectMapper mapper = new ObjectMapper() .registerModule(module); assertEquals(quote("FOOBAR"), mapper.writeValueAsString("foobar")); assertEquals(aposToQuotes("['FOO',null]"), mapper.writeValueAsString(new String[] { "foo", null })); List list = Arrays.asList("foo", null); assertEquals(aposToQuotes("['FOO',null]"), mapper.writeValueAsString(list)); Set set = new LinkedHashSet(Arrays.asList("foo", null)); assertEquals(aposToQuotes("['FOO',null]"), mapper.writeValueAsString(set)); } } TestCyclicTypes.java000066400000000000000000000042071325620701100352350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.databind.*; /** * Simple unit tests to verify that it is possible to handle * potentially cyclic structures, as long as object graph itself * is not cyclic. This is the case for directed hierarchies like * trees and DAGs. */ public class TestCyclicTypes extends BaseMapTest { /* /********************************************************** /* Helper bean classes /********************************************************** */ static class Bean { Bean _next; final String _name; public Bean(Bean next, String name) { _next = next; _name = name; } public Bean getNext() { return _next; } public String getName() { return _name; } public void assignNext(Bean n) { _next = n; } } /* /********************************************************** /* Types /********************************************************** */ public void testLinked() throws Exception { Bean last = new Bean(null, "last"); Bean first = new Bean(last, "first"); Map map = writeAndMap(new ObjectMapper(), first); assertEquals(2, map.size()); assertEquals("first", map.get("name")); @SuppressWarnings("unchecked") Map map2 = (Map) map.get("next"); assertNotNull(map2); assertEquals(2, map2.size()); assertEquals("last", map2.get("name")); assertNull(map2.get("next")); } /** * Test for verifying that [JACKSON-158] works as expected */ public void testSelfReference() throws Exception { Bean selfRef = new Bean(null, "self-refs"); Bean first = new Bean(selfRef, "first"); selfRef.assignNext(selfRef); ObjectMapper m = new ObjectMapper(); Bean[] wrapper = new Bean[] { first }; try { writeAndMap(m, wrapper); } catch (JsonMappingException e) { verifyException(e, "Direct self-reference leading to cycle"); } } } TestEmptyClass.java000066400000000000000000000060701325620701100350660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class TestEmptyClass extends BaseMapTest { static class Empty { } @JsonSerialize static class EmptyWithAnno { } // for [JACKSON-695]: @JsonSerialize(using=NonZeroSerializer.class) static class NonZero { public int nr; public NonZero(int i) { nr = i; } } @JsonInclude(JsonInclude.Include.NON_EMPTY) static class NonZeroWrapper { public NonZero value; public NonZeroWrapper(int i) { value = new NonZero(i); } } static class NonZeroSerializer extends JsonSerializer { @Override public void serialize(NonZero value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeNumber(value.nr); } @Override public boolean isEmpty(SerializerProvider provider, NonZero value) { if (value == null) return true; return (value.nr == 0); } } /* /********************************************************** /* Test methods /********************************************************** */ protected final ObjectMapper mapper = new ObjectMapper(); /** * Test to check that [JACKSON-201] works if there is a recognized * annotation (which indicates type is serializable) */ public void testEmptyWithAnnotations() throws Exception { // First: without annotations, should complain try { serializeAsString(mapper, new Empty()); } catch (JsonMappingException e) { verifyException(e, "No serializer found for class"); } // But not if there is a recognized annotation assertEquals("{}", serializeAsString(mapper, new EmptyWithAnno())); // Including class annotation through mix-ins ObjectMapper m2 = new ObjectMapper(); m2.addMixIn(Empty.class, EmptyWithAnno.class); assertEquals("{}", m2.writeValueAsString(new Empty())); } /** * Alternative it is possible to use a feature to allow * serializing empty classes, too */ public void testEmptyWithFeature() throws Exception { // should be enabled by default assertTrue(mapper.getSerializationConfig().isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); assertEquals("{}", serializeAsString(mapper, new Empty())); } // [JACKSON-695], JsonSerializer.isEmpty() public void testCustomNoEmpty() throws Exception { // first non-empty: assertEquals("{\"value\":123}", mapper.writeValueAsString(new NonZeroWrapper(123))); // then empty: assertEquals("{}", mapper.writeValueAsString(new NonZeroWrapper(0))); } } TestEnumSerialization.java000066400000000000000000000320521325620701100364430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; /** * Unit tests for verifying serialization of simple basic non-structured * types; primitives (and/or their wrappers), Strings. */ public class TestEnumSerialization extends BaseMapTest { /* /********************************************************** /* Helper enums /********************************************************** */ /** * Test enumeration for verifying Enum serialization functionality. */ protected enum TestEnum { A, B, C; private TestEnum() { } @Override public String toString() { return name().toLowerCase(); } } /** * Alternative version that forces use of "toString-serializer". */ @JsonSerialize(using=ToStringSerializer.class) protected enum AnnotatedTestEnum { A2, B2, C2; private AnnotatedTestEnum() { } @Override public String toString() { return name().toLowerCase(); } } protected enum EnumWithJsonValue { A("foo"), B("bar"); private final String name; private EnumWithJsonValue(String n) { name = n; } @Override public String toString() { return name; } @JsonValue public String external() { return "value:"+name; } } protected static interface ToStringMixin { @Override @JsonValue public String toString(); } protected static enum SerializableEnum implements JsonSerializable { A, B, C; private SerializableEnum() { } @Override public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) throws IOException, JsonProcessingException { serialize(jgen, provider); } @Override public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString("foo"); } } protected static enum LowerCaseEnum { A, B, C; private LowerCaseEnum() { } @Override public String toString() { return name().toLowerCase(); } } static class MapBean { public Map map = new HashMap(); public void add(TestEnum key, int value) { map.put(key, Integer.valueOf(value)); } } static enum NOT_OK { V1("v1"); protected String key; // any runtime-persistent annotation is fine NOT_OK(@JsonProperty String key) { this.key = key; } } static enum OK { V1("v1"); protected String key; OK(String key) { this.key = key; } } @SuppressWarnings({ "rawtypes", "serial" }) static class LowerCasingEnumSerializer extends StdSerializer { public LowerCasingEnumSerializer() { super(Enum.class); } @Override public void serialize(Enum value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeString(value.name().toLowerCase()); } } static enum MyEnum594 { VALUE_WITH_A_REALLY_LONG_NAME_HERE("longValue"); private final String key; private MyEnum594(String k) { key = k; } @JsonValue public String getKey() { return key; } } static class MyStuff594 { public Map stuff = new EnumMap(MyEnum594.class); public MyStuff594(String value) { stuff.put(MyEnum594.VALUE_WITH_A_REALLY_LONG_NAME_HERE, value); } } public class MyBean661 { private Map foo = new EnumMap(Foo661.class); public MyBean661(String value) { foo.put(Foo661.FOO, value); } @JsonAnyGetter @JsonSerialize(keyUsing = Foo661.Serializer.class) public Map getFoo() { return foo; } } enum Foo661 { FOO; public static class Serializer extends JsonSerializer { @Override public void serialize(Foo661 value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeFieldName("X-"+value.name()); } } } protected static enum LC749Enum { A, B, C; private LC749Enum() { } @Override public String toString() { return name().toLowerCase(); } } // for [databind#1322] protected enum EnumWithJsonProperty { @JsonProperty("aleph") A; } /* /********************************************************** /* Tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimple() throws Exception { assertEquals("\"B\"", MAPPER.writeValueAsString(TestEnum.B)); } public void testEnumSet() throws Exception { StringWriter sw = new StringWriter(); EnumSet value = EnumSet.of(TestEnum.B); MAPPER.writeValue(sw, value); assertEquals("[\"B\"]", sw.toString()); } /** * Whereas regular Enum serializer uses enum names, some users * prefer calling toString() instead. So let's verify that * this can be done using annotation for enum class. */ public void testEnumUsingToString() throws Exception { StringWriter sw = new StringWriter(); MAPPER.writeValue(sw, AnnotatedTestEnum.C2); assertEquals("\"c2\"", sw.toString()); } // Test [JACKSON-214] public void testSubclassedEnums() throws Exception { assertEquals("\"B\"", MAPPER.writeValueAsString(EnumWithSubClass.B)); } public void testEnumsWithJsonValue() throws Exception { assertEquals("\"value:bar\"", MAPPER.writeValueAsString(EnumWithJsonValue.B)); } public void testEnumsWithJsonValueUsingMixin() throws Exception { // can't share, as new mix-ins are added ObjectMapper m = new ObjectMapper(); m.addMixIn(TestEnum.class, ToStringMixin.class); assertEquals("\"b\"", m.writeValueAsString(TestEnum.B)); } // [databind#601] public void testEnumsWithJsonValueInMap() throws Exception { EnumMap input = new EnumMap(EnumWithJsonValue.class); input.put(EnumWithJsonValue.B, "x"); // 24-Sep-2015, tatu: SHOULD actually use annotated method, as per: assertEquals("{\"value:bar\":\"x\"}", MAPPER.writeValueAsString(input)); } /** * Test for ensuring that @JsonSerializable is used with Enum types as well * as with any other types. */ public void testSerializableEnum() throws Exception { assertEquals("\"foo\"", MAPPER.writeValueAsString(SerializableEnum.A)); } // [JACKSON-212] public void testToStringEnum() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); assertEquals("\"b\"", m.writeValueAsString(LowerCaseEnum.B)); // [databind#749] but should also be able to dynamically disable assertEquals("\"B\"", m.writer().without(SerializationFeature.WRITE_ENUMS_USING_TO_STRING) .writeValueAsString(LowerCaseEnum.B)); } public void testToStringEnumWithEnumMap() throws Exception { ObjectMapper m = new ObjectMapper(); m.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); EnumMap enums = new EnumMap(LowerCaseEnum.class); enums.put(LowerCaseEnum.C, "value"); assertEquals("{\"c\":\"value\"}", m.writeValueAsString(enums)); } public void testMapWithEnumKeys() throws Exception { MapBean bean = new MapBean(); bean.add(TestEnum.B, 3); // By default Enums serialized using `name()` String json = MAPPER.writeValueAsString(bean); assertEquals("{\"map\":{\"B\":3}}", json); // but can change json = MAPPER.writer() .with(SerializationFeature.WRITE_ENUMS_USING_TO_STRING) .writeValueAsString(bean); assertEquals("{\"map\":{\"b\":3}}", json); // [databind#1570] json = MAPPER.writer() .with(SerializationFeature.WRITE_ENUMS_USING_INDEX) .writeValueAsString(bean); assertEquals(aposToQuotes("{'map':{'"+TestEnum.B.ordinal()+"':3}}"), json); } public void testAsIndex() throws Exception { // By default, serialize using name ObjectMapper m = new ObjectMapper(); assertFalse(m.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX)); assertEquals(quote("B"), m.writeValueAsString(TestEnum.B)); // but we can change (dynamically, too!) it to be number-based m.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX); assertEquals("1", m.writeValueAsString(TestEnum.B)); } // [JACKSON-757] public void testAnnotationsOnEnumCtor() throws Exception { assertEquals(quote("V1"), MAPPER.writeValueAsString(OK.V1)); assertEquals(quote("V1"), MAPPER.writeValueAsString(NOT_OK.V1)); assertEquals(quote("V2"), MAPPER.writeValueAsString(NOT_OK2.V2)); } // [Issue#227] public void testGenericEnumSerializer() throws Exception { // By default, serialize using name ObjectMapper m = new ObjectMapper(); SimpleModule module = new SimpleModule("foobar"); module.addSerializer(Enum.class, new LowerCasingEnumSerializer()); m.registerModule(module); assertEquals(quote("b"), m.writeValueAsString(TestEnum.B)); } // [databind#594] public void testJsonValueForEnumMapKey() throws Exception { assertEquals(aposToQuotes("{'stuff':{'longValue':'foo'}}"), MAPPER.writeValueAsString(new MyStuff594("foo"))); } // [databind#661] public void testCustomEnumMapKeySerializer() throws Exception { String json = MAPPER.writeValueAsString(new MyBean661("abc")); assertEquals(aposToQuotes("{'X-FOO':'abc'}"), json); } // [databind#749] public void testEnumMapSerDefault() throws Exception { final ObjectMapper mapper = new ObjectMapper(); EnumMap m = new EnumMap(LC749Enum.class); m.put(LC749Enum.A, "value"); assertEquals("{\"A\":\"value\"}", mapper.writeValueAsString(m)); } public void testEnumMapSerDisableToString() throws Exception { final ObjectMapper mapper = new ObjectMapper(); ObjectWriter w = mapper.writer().without(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); EnumMap m = new EnumMap(LC749Enum.class); m.put(LC749Enum.A, "value"); assertEquals("{\"A\":\"value\"}", w.writeValueAsString(m)); } public void testEnumMapSerEnableToString() throws Exception { final ObjectMapper mapper = new ObjectMapper(); ObjectWriter w = mapper.writer().with(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); EnumMap m = new EnumMap(LC749Enum.class); m.put(LC749Enum.A, "value"); assertEquals("{\"a\":\"value\"}", w.writeValueAsString(m)); } // [databind#1322] public void testEnumsWithJsonProperty() throws Exception { assertEquals(quote("aleph"), MAPPER.writeValueAsString(EnumWithJsonProperty.A)); } // [databind#1535] public void testEnumKeysWithJsonProperty() throws Exception { Map input = new HashMap(); input.put(EnumWithJsonProperty.A, 13); assertEquals(aposToQuotes("{'aleph':13}"), MAPPER.writeValueAsString(input)); } // [databind#1322] public void testEnumsWithJsonPropertyInSet() throws Exception { assertEquals("[\"aleph\"]", MAPPER.writeValueAsString(EnumSet.of(EnumWithJsonProperty.A))); } // [databind#1322] public void testEnumsWithJsonPropertyAsKey() throws Exception { EnumMap input = new EnumMap(EnumWithJsonProperty.class); input.put(EnumWithJsonProperty.A, "b"); assertEquals("{\"aleph\":\"b\"}", MAPPER.writeValueAsString(input)); } } // [JACKSON-757], non-inner enum enum NOT_OK2 { V2("v2"); protected String key; // any runtime-persistent annotation is fine NOT_OK2(@JsonProperty String key) { this.key = key; } } TestGenericTypes.java000066400000000000000000000125341325620701100354050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class TestGenericTypes extends BaseMapTest { static class Account { private Long id; private String name; public Account(String name, Long id) { this.id = id; this.name = name; } public String getName() { return name; } public Long getId() { return id; } } static class Key { private final T id; public Key(T id) { this.id = id; } public T getId() { return id; } public Key getParent() { return null; } } static class Person1 { private Long id; private String name; private Key account; public Person1(String name) { this.name = name; } public String getName() { return name; } public Key getAccount() { return account; } public Long getId() { return id; } public void setAccount(Key account) { this.account = account; } } static class Person2 { private Long id; private String name; private List> accounts; public Person2(String name) { this.name = name; } public String getName() { return name; } public List> getAccounts() { return accounts; } public Long getId() { return id; } public void setAccounts(List> accounts) { this.accounts = accounts; } } static class GenericBogusWrapper { public Element wrapped; public GenericBogusWrapper(T v) { wrapped = new Element(v); } class Element { public T value; public Element(T v) { value = v; } } } // For [databind#728] static class Base727 { public int a; } @JsonPropertyOrder(alphabetic=true) static class Impl727 extends Base727 { public int b; public Impl727(int a, int b) { this.a = a; this.b = b; } } /* /********************************************************** /* Unit tests /********************************************************** */ final ObjectMapper MAPPER = new ObjectMapper(); @SuppressWarnings("unchecked") public void testIssue468a() throws Exception { Person1 p1 = new Person1("John"); p1.setAccount(new Key(new Account("something", 42L))); // First: ensure we can serialize (pre 1.7 this failed) String json = MAPPER.writeValueAsString(p1); // and then verify that results make sense Map map = MAPPER.readValue(json, Map.class); assertEquals("John", map.get("name")); Object ob = map.get("account"); assertNotNull(ob); Map acct = (Map) ob; Object idOb = acct.get("id"); assertNotNull(idOb); Map key = (Map) idOb; assertEquals("something", key.get("name")); assertEquals(Integer.valueOf(42), key.get("id")); } @SuppressWarnings("unchecked") public void testIssue468b() throws Exception { Person2 p2 = new Person2("John"); List> accounts = new ArrayList>(); accounts.add(new Key(new Account("a", 42L))); accounts.add(new Key(new Account("b", 43L))); accounts.add(new Key(new Account("c", 44L))); p2.setAccounts(accounts); // serialize without error: String json = MAPPER.writeValueAsString(p2); // then verify output Map map = MAPPER.readValue(json, Map.class); assertEquals("John", map.get("name")); Object ob = map.get("accounts"); assertNotNull(ob); List acctList = (List) ob; assertEquals(3, acctList.size()); // ... might want to verify more, but for now that should suffice } /** * Test related to unbound type variables, usually resulting * from inner classes of generic classes (like Sets). */ public void testUnboundTypes() throws Exception { GenericBogusWrapper list = new GenericBogusWrapper(Integer.valueOf(7)); String json = MAPPER.writeValueAsString(list); assertEquals("{\"wrapped\":{\"value\":7}}", json); } public void testRootTypeForCollections727() throws Exception { List input = new ArrayList(); input.add(new Impl727(1, 2)); final String EXP = aposToQuotes("[{'a':1,'b':2}]"); // Without type enforcement, produces expected output: assertEquals(EXP, MAPPER.writeValueAsString(input)); assertEquals(EXP, MAPPER.writer().writeValueAsString(input)); // but enforcing type will hinder: TypeReference typeRef = new TypeReference>() { }; assertEquals(EXP, MAPPER.writer().forType(typeRef).writeValueAsString(input)); } } TestIterable.java000066400000000000000000000105211325620701100345250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class TestIterable extends BaseMapTest { final static class IterableWrapper implements Iterable { List _ints = new ArrayList(); public IterableWrapper(int[] values) { for (int i : values) { _ints.add(Integer.valueOf(i)); } } @Override public Iterator iterator() { return _ints.iterator(); } } @JsonSerialize(typing=JsonSerialize.Typing.STATIC) static class BeanWithIterable { private final ArrayList values = new ArrayList(); { values.add("value"); } public Iterable getValues() { return values; } } static class BeanWithIterator { private final ArrayList values = new ArrayList(); { values.add("itValue"); } public Iterator getValues() { return values.iterator(); } } static class IntIterable implements Iterable { @Override public Iterator iterator() { return new IntIterator(1, 3); } } static class IntIterator implements Iterator { int i; final int last; public IntIterator(int first, int last) { i = first; this.last = last; } @Override public boolean hasNext() { return i <= last; } @Override public Integer next() { return i++; } @Override public void remove() { } public int getX() { return 13; } } // [databind#358] static class A { public String unexpected = "Bye."; } static class B { @JsonSerialize(as = Iterable.class, contentUsing = ASerializer.class) public List list = Arrays.asList(new A()); } static class ASerializer extends JsonSerializer { @Override public void serialize(A a, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException { jsonGenerator.writeStartArray(); jsonGenerator.writeString("Hello world."); jsonGenerator.writeEndArray(); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); private final ObjectMapper STATIC_MAPPER = new ObjectMapper(); { STATIC_MAPPER.enable(MapperFeature.USE_STATIC_TYPING); } public void testIterator() throws IOException { ArrayList l = new ArrayList(); l.add(1); l.add(null); l.add(-9); l.add(0); assertEquals("[1,null,-9,0]", MAPPER.writeValueAsString(l.iterator())); l.clear(); assertEquals("[]", MAPPER.writeValueAsString(l.iterator())); } public void testIterable() throws IOException { assertEquals("[1,2,3]", MAPPER.writeValueAsString(new IterableWrapper(new int[] { 1, 2, 3 }))); } public void testWithIterable() throws IOException { assertEquals("{\"values\":[\"value\"]}", STATIC_MAPPER.writeValueAsString(new BeanWithIterable())); assertEquals("[1,2,3]", STATIC_MAPPER.writeValueAsString(new IntIterable())); } public void testWithIterator() throws IOException { assertEquals("{\"values\":[\"itValue\"]}", STATIC_MAPPER.writeValueAsString(new BeanWithIterator())); // [databind#1977] ArrayList numbersList = new ArrayList<>(); numbersList.add(1); numbersList.add(0.25); String json = MAPPER.writeValueAsString(numbersList.iterator()); assertEquals("[1,0.25]", json); } // [databind#358] public void testIterable358() throws Exception { String json = MAPPER.writeValueAsString(new B()); assertEquals("{\"list\":[[\"Hello world.\"]]}", json); } } TestJacksonTypes.java000066400000000000000000000033071325620701100354170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.*; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Unit tests for those Jackson types we want to ensure can be serialized. */ public class TestJacksonTypes extends BaseMapTest { public void testLocation() throws IOException { File f = new File("/tmp/test.json"); JsonLocation loc = new JsonLocation(f, -1, 100, 13); ObjectMapper mapper = new ObjectMapper(); Map result = writeAndMap(mapper, loc); assertEquals(5, result.size()); assertEquals(f.getAbsolutePath(), result.get("sourceRef")); assertEquals(Integer.valueOf(-1), result.get("charOffset")); assertEquals(Integer.valueOf(-1), result.get("byteOffset")); assertEquals(Integer.valueOf(100), result.get("lineNr")); assertEquals(Integer.valueOf(13), result.get("columnNr")); } /** * Verify that {@link TokenBuffer} can be properly serialized * automatically, using the "standard" JSON sample document */ public void testTokenBuffer() throws Exception { // First, copy events from known good source (StringReader) JsonParser jp = createParserUsingReader(SAMPLE_DOC_JSON_SPEC); TokenBuffer tb = new TokenBuffer(null, false); while (jp.nextToken() != null) { tb.copyCurrentEvent(jp); } jp.close(); // Then serialize as String String str = serializeAsString(tb); tb.close(); // and verify it looks ok verifyJsonSpecSampleDoc(createParserUsingReader(str), true); } } TestJsonSerialize.java000066400000000000000000000173441325620701100355710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * This unit test suite tests use of @JsonClass Annotation * with bean serialization. */ public class TestJsonSerialize extends BaseMapTest { /* /********************************************************** /* Annotated helper classes /********************************************************** */ interface ValueInterface { public int getX(); } static class ValueClass implements ValueInterface { @Override public int getX() { return 3; } public int getY() { return 5; } } /** * Test class to verify that JsonSerialize.as * works as expected */ static class WrapperClassForAs { @JsonSerialize(as=ValueInterface.class) public ValueClass getValue() { return new ValueClass(); } } // This should indicate that static type be used for all fields @JsonSerialize(typing=JsonSerialize.Typing.STATIC) static class WrapperClassForStaticTyping { public ValueInterface getValue() { return new ValueClass(); } } static class WrapperClassForStaticTyping2 { @JsonSerialize(typing=JsonSerialize.Typing.STATIC) public ValueInterface getStaticValue() { return new ValueClass(); } @JsonSerialize(typing=JsonSerialize.Typing.DYNAMIC) public ValueInterface getDynamicValue() { return new ValueClass(); } } /** * Test bean that has an invalid {@link JsonSerialize} annotation. */ static class BrokenClass { // invalid annotation: String not a supertype of Long @JsonSerialize(as=String.class) public Long getValue() { return Long.valueOf(4L); } } @SuppressWarnings("serial") static class ValueMap extends HashMap { } @SuppressWarnings("serial") static class ValueList extends ArrayList { } @SuppressWarnings("serial") static class ValueLinkedList extends LinkedList { } // Classes for [JACKSON-294] static class Foo294 { @JsonProperty private String id; @JsonSerialize(using = Bar294Serializer.class) private Bar294 bar; public Foo294() { } public Foo294(String id, String id2) { this.id = id; bar = new Bar294(id2); } } static class Bar294{ @JsonProperty protected String id; @JsonProperty protected String name; public Bar294() { } public Bar294(String id) { this.id = id; } public String getId() { return id; } public String getName() { return name; } } static class Bar294Serializer extends JsonSerializer { @Override public void serialize(Bar294 bar, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeString(bar.id); } } /* /********************************************************** /* Main tests /********************************************************** */ final ObjectMapper MAPPER = objectMapper(); @SuppressWarnings("unchecked") public void testSimpleValueDefinition() throws Exception { Map result = writeAndMap(MAPPER, new WrapperClassForAs()); assertEquals(1, result.size()); Object ob = result.get("value"); // Should see only "x", not "y" result = (Map) ob; assertEquals(1, result.size()); assertEquals(Integer.valueOf(3), result.get("x")); } public void testBrokenAnnotation() throws Exception { try { serializeAsString(MAPPER, new BrokenClass()); fail("Should not succeed"); } catch (Exception e) { verifyException(e, "types not related"); } } @SuppressWarnings("unchecked") public void testStaticTypingForClass() throws Exception { Map result = writeAndMap(MAPPER, new WrapperClassForStaticTyping()); assertEquals(1, result.size()); Object ob = result.get("value"); // Should see only "x", not "y" result = (Map) ob; assertEquals(1, result.size()); assertEquals(Integer.valueOf(3), result.get("x")); } @SuppressWarnings("unchecked") public void testMixedTypingForClass() throws Exception { Map result = writeAndMap(MAPPER, new WrapperClassForStaticTyping2()); assertEquals(2, result.size()); Object obStatic = result.get("staticValue"); // Should see only "x", not "y" Map stat = (Map) obStatic; assertEquals(1, stat.size()); assertEquals(Integer.valueOf(3), stat.get("x")); Object obDynamic = result.get("dynamicValue"); // Should see both Map dyn = (Map) obDynamic; assertEquals(2, dyn.size()); assertEquals(Integer.valueOf(3), dyn.get("x")); assertEquals(Integer.valueOf(5), dyn.get("y")); } public void testStaticTypingWithMap() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.USE_STATIC_TYPING, true); ValueMap map = new ValueMap(); map.put("a", new ValueClass()); assertEquals("{\"a\":{\"x\":3}}", serializeAsString(m, map)); } public void testStaticTypingWithArrayList() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.USE_STATIC_TYPING, true); ValueList list = new ValueList(); list.add(new ValueClass()); assertEquals("[{\"x\":3}]", m.writeValueAsString(list)); } public void testStaticTypingWithLinkedList() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.USE_STATIC_TYPING, true); ValueLinkedList list = new ValueLinkedList(); list.add(new ValueClass()); assertEquals("[{\"x\":3}]", serializeAsString(m, list)); } public void testStaticTypingWithArray() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.USE_STATIC_TYPING, true); ValueInterface[] array = new ValueInterface[] { new ValueClass() }; assertEquals("[{\"x\":3}]", serializeAsString(m, array)); } public void testIssue294() throws Exception { assertEquals("{\"id\":\"fooId\",\"bar\":\"barId\"}", MAPPER.writeValueAsString(new Foo294("fooId", "barId"))); } @JsonPropertyOrder({ "a", "something" }) static class Response { public String a = "x"; @JsonProperty //does not show up public boolean isSomething() { return true; } } public void testWithIsGetter() throws Exception { ObjectMapper m = new ObjectMapper(); m.setVisibility(PropertyAccessor.GETTER, Visibility.NONE) .setVisibility(PropertyAccessor.FIELD, Visibility.ANY) .setVisibility(PropertyAccessor.CREATOR, Visibility.NONE) .setVisibility(PropertyAccessor.IS_GETTER, Visibility.NONE) .setVisibility(PropertyAccessor.SETTER, Visibility.NONE); final String JSON = m.writeValueAsString(new Response()); assertEquals(aposToQuotes("{'a':'x','something':true}"), JSON); } } TestJsonSerialize2.java000066400000000000000000000172101325620701100356430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.NullSerializer; @SuppressWarnings("serial") public class TestJsonSerialize2 extends BaseMapTest { static class SimpleKey { protected final String key; public SimpleKey(String str) { key = str; } @Override public String toString() { return "toString:"+key; } } static class SimpleValue { public final String value; public SimpleValue(String str) { value = str; } } @JsonPropertyOrder({"value", "value2"}) static class ActualValue extends SimpleValue { public final String other = "123"; public ActualValue(String str) { super(str); } } static class SimpleKeySerializer extends JsonSerializer { @Override public void serialize(SimpleKey key, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeFieldName("key "+key.key); } } static class SimpleValueSerializer extends JsonSerializer { @Override public void serialize(SimpleValue value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString("value "+value.value); } } @JsonSerialize(contentAs=SimpleValue.class) static class SimpleValueList extends ArrayList { } @JsonSerialize(contentAs=SimpleValue.class) static class SimpleValueMap extends HashMap { } @JsonSerialize(contentUsing=SimpleValueSerializer.class) static class SimpleValueListWithSerializer extends ArrayList { } @JsonSerialize(keyUsing=SimpleKeySerializer.class, contentUsing=SimpleValueSerializer.class) static class SimpleValueMapWithSerializer extends HashMap { } static class ListWrapperSimple { @JsonSerialize(contentAs=SimpleValue.class) public final ArrayList values = new ArrayList(); public ListWrapperSimple(String value) { values.add(new ActualValue(value)); } } static class ListWrapperWithSerializer { @JsonSerialize(contentUsing=SimpleValueSerializer.class) public final ArrayList values = new ArrayList(); public ListWrapperWithSerializer(String value) { values.add(new ActualValue(value)); } } static class MapWrapperSimple { @JsonSerialize(contentAs=SimpleValue.class) public final HashMap values = new HashMap(); public MapWrapperSimple(String key, String value) { values.put(new SimpleKey(key), new ActualValue(value)); } } static class MapWrapperWithSerializer { @JsonSerialize(keyUsing=SimpleKeySerializer.class, contentUsing=SimpleValueSerializer.class) public final HashMap values = new HashMap(); public MapWrapperWithSerializer(String key, String value) { values.put(new SimpleKey(key), new ActualValue(value)); } } static class NullBean { @JsonSerialize(using=NullSerializer.class) public String value = "abc"; } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); // test value annotation applied to List value class public void testSerializedAsListWithClassAnnotations() throws IOException { SimpleValueList list = new SimpleValueList(); list.add(new ActualValue("foo")); assertEquals("[{\"value\":\"foo\"}]", MAPPER.writeValueAsString(list)); } // test value annotation applied to Map value class public void testSerializedAsMapWithClassAnnotations() throws IOException { SimpleValueMap map = new SimpleValueMap(); map.put(new SimpleKey("x"), new ActualValue("y")); assertEquals("{\"toString:x\":{\"value\":\"y\"}}", MAPPER.writeValueAsString(map)); } // test Serialization annotation with List public void testSerializedAsListWithClassSerializer() throws IOException { ObjectMapper m = new ObjectMapper(); SimpleValueListWithSerializer list = new SimpleValueListWithSerializer(); list.add(new ActualValue("foo")); assertEquals("[\"value foo\"]", m.writeValueAsString(list)); } public void testSerializedAsListWithPropertyAnnotations() throws IOException { ListWrapperSimple input = new ListWrapperSimple("bar"); assertEquals("{\"values\":[{\"value\":\"bar\"}]}", MAPPER.writeValueAsString(input)); } public void testSerializedAsMapWithClassSerializer() throws IOException { SimpleValueMapWithSerializer map = new SimpleValueMapWithSerializer(); map.put(new SimpleKey("abc"), new ActualValue("123")); assertEquals("{\"key abc\":\"value 123\"}", MAPPER.writeValueAsString(map)); } public void testSerializedAsMapWithPropertyAnnotations() throws IOException { MapWrapperSimple input = new MapWrapperSimple("a", "b"); assertEquals("{\"values\":{\"toString:a\":{\"value\":\"b\"}}}", MAPPER.writeValueAsString(input)); } public void testSerializedAsListWithPropertyAnnotations2() throws IOException { ListWrapperWithSerializer input = new ListWrapperWithSerializer("abc"); assertEquals("{\"values\":[\"value abc\"]}", MAPPER.writeValueAsString(input)); } public void testSerializedAsMapWithPropertyAnnotations2() throws IOException { MapWrapperWithSerializer input = new MapWrapperWithSerializer("foo", "b"); assertEquals("{\"values\":{\"key foo\":\"value b\"}}", MAPPER.writeValueAsString(input)); } public void testEmptyInclusionContainers() throws IOException { ObjectMapper defMapper = MAPPER; ObjectMapper inclMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_EMPTY); ListWrapper list = new ListWrapper(); assertEquals("{\"list\":[]}", defMapper.writeValueAsString(list)); assertEquals("{}", inclMapper.writeValueAsString(list)); assertEquals("{}", inclMapper.writeValueAsString(new ListWrapper())); MapWrapper map = new MapWrapper(new HashMap()); assertEquals("{\"map\":{}}", defMapper.writeValueAsString(map)); assertEquals("{}", inclMapper.writeValueAsString(map)); assertEquals("{}", inclMapper.writeValueAsString(new MapWrapper(null))); ArrayWrapper array = new ArrayWrapper(new Integer[0]); assertEquals("{\"array\":[]}", defMapper.writeValueAsString(array)); assertEquals("{}", inclMapper.writeValueAsString(array)); assertEquals("{}", inclMapper.writeValueAsString(new ArrayWrapper(null))); } public void testNullSerializer() throws Exception { String json = MAPPER.writeValueAsString(new NullBean()); assertEquals("{\"value\":null}", json); } } TestJsonSerialize3.java000066400000000000000000000024371325620701100356510ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class TestJsonSerialize3 extends BaseMapTest { // [JACKSON-829] static class FooToBarSerializer extends JsonSerializer { @Override public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException { if ("foo".equals(value)) { jgen.writeString("bar"); } else { jgen.writeString(value); } } } static class MyObject { @JsonSerialize(contentUsing = FooToBarSerializer.class) List list; } /* /********************************************************** /* Test methods /********************************************************** */ public void testCustomContentSerializer() throws Exception { ObjectMapper m = new ObjectMapper(); MyObject object = new MyObject(); object.list = Arrays.asList("foo"); String json = m.writeValueAsString(object); assertEquals("{\"list\":[\"bar\"]}", json); } } TestJsonSerializeAs.java000066400000000000000000000067711325620701100360570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class TestJsonSerializeAs extends BaseMapTest { public interface Fooable { public int getFoo(); } // force use of interface @JsonSerialize(as=Fooable.class) public static class FooImpl implements Fooable { @Override public int getFoo() { return 42; } public int getBar() { return 15; } } static class FooImplNoAnno implements Fooable { @Override public int getFoo() { return 42; } public int getBar() { return 15; } } public class Fooables { public FooImpl[] getFoos() { return new FooImpl[] { new FooImpl() }; } } public class FooableWrapper { public FooImpl getFoo() { return new FooImpl(); } } // for [databind#1023] static class FooableWithFieldWrapper { @JsonSerialize(as=Fooable.class) public Fooable getFoo() { return new FooImplNoAnno(); } } interface Bean1178Base { public int getA(); } @JsonPropertyOrder({"a","b"}) static abstract class Bean1178Abstract implements Bean1178Base { @Override public int getA() { return 1; } public int getB() { return 2; } } static class Bean1178Impl extends Bean1178Abstract { public int getC() { return 3; } } static class Bean1178Wrapper { @JsonSerialize(contentAs=Bean1178Abstract.class) public List values; public Bean1178Wrapper(int count) { values = new ArrayList(); for (int i = 0; i < count; ++i) { values.add(new Bean1178Impl()); } } } static class Bean1178Holder { @JsonSerialize(as=Bean1178Abstract.class) public Bean1178Base value = new Bean1178Impl(); } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectWriter WRITER = objectWriter(); public void testSerializeAsInClass() throws IOException { assertEquals("{\"foo\":42}", WRITER.writeValueAsString(new FooImpl())); } public void testSerializeAsForArrayProp() throws IOException { assertEquals("{\"foos\":[{\"foo\":42}]}", WRITER.writeValueAsString(new Fooables())); } public void testSerializeAsForSimpleProp() throws IOException { assertEquals("{\"foo\":{\"foo\":42}}", WRITER.writeValueAsString(new FooableWrapper())); } // for [databind#1023] public void testSerializeWithFieldAnno() throws IOException { assertEquals("{\"foo\":{\"foo\":42}}", WRITER.writeValueAsString(new FooableWithFieldWrapper())); } // for [databind#1178] public void testSpecializedContentAs() throws IOException { assertEquals(aposToQuotes("{'values':[{'a':1,'b':2}]}"), WRITER.writeValueAsString(new Bean1178Wrapper(1))); } // for [databind#1231] (and continuation of [databind#1178]) public void testSpecializedAsIntermediate() throws IOException { assertEquals(aposToQuotes("{'value':{'a':1,'b':2}}"), WRITER.writeValueAsString(new Bean1178Holder())); } } TestKeySerializers.java000066400000000000000000000211101325620701100357370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.module.SimpleModule; public class TestKeySerializers extends BaseMapTest { public static class KarlSerializer extends JsonSerializer { @Override public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeFieldName("Karl"); } } public static class NullKeySerializer extends JsonSerializer { private String _null; public NullKeySerializer(String s) { _null = s; } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeFieldName(_null); } } public static class NullValueSerializer extends JsonSerializer { private String _null; public NullValueSerializer(String s) { _null = s; } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeString(_null); } } public static class NotKarlBean { public Map map = new HashMap(); { map.put("Not Karl", 1); } } public static class KarlBean { @JsonSerialize(keyUsing = KarlSerializer.class) public Map map = new HashMap(); { map.put("Not Karl", 1); } } enum ABC { A, B, C } enum AbcLC { A, B, C; @JsonValue public String toLC() { return name().toLowerCase(); } } static class ABCKeySerializer extends JsonSerializer { @Override public void serialize(ABC value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeFieldName("xxx"+value); } } @JsonSerialize(keyUsing = ABCKeySerializer.class) public static enum ABCMixin { } public static enum Outer { inner; } static class ABCMapWrapper { public Map stuff = new HashMap(); public ABCMapWrapper() { stuff.put(ABC.B, "bar"); } } static class BAR{ T value; public BAR(T value) { this.value = value; } @JsonValue public T getValue() { return value; } @Override public String toString() { return this.getClass().getSimpleName() + ", value:" + value ; } } static class UCString { private String value; public UCString(String v) { value = v.toUpperCase(); } @JsonValue public String asString() { return value; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testNotKarl() throws IOException { final String serialized = MAPPER.writeValueAsString(new NotKarlBean()); assertEquals("{\"map\":{\"Not Karl\":1}}", serialized); } public void testKarl() throws IOException { final String serialized = MAPPER.writeValueAsString(new KarlBean()); assertEquals("{\"map\":{\"Karl\":1}}", serialized); } // [databind#75]: caching of KeySerializers public void testBoth() throws IOException { // Let's NOT use shared one, to ensure caching starts from clean slate final ObjectMapper mapper = new ObjectMapper(); final String value1 = mapper.writeValueAsString(new NotKarlBean()); assertEquals("{\"map\":{\"Not Karl\":1}}", value1); final String value2 = mapper.writeValueAsString(new KarlBean()); assertEquals("{\"map\":{\"Karl\":1}}", value2); } // Test custom key serializer for enum public void testCustomForEnum() throws IOException { // cannot use shared mapper as we are registering a module final ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test"); mod.addKeySerializer(ABC.class, new ABCKeySerializer()); mapper.registerModule(mod); String json = mapper.writeValueAsString(new ABCMapWrapper()); assertEquals("{\"stuff\":{\"xxxB\":\"bar\"}}", json); } public void testCustomNullSerializers() throws IOException { final ObjectMapper mapper = new ObjectMapper(); mapper.getSerializerProvider().setNullKeySerializer(new NullKeySerializer("NULL-KEY")); mapper.getSerializerProvider().setNullValueSerializer(new NullValueSerializer("NULL")); Map input = new HashMap<>(); input.put(null, 3); String json = mapper.writeValueAsString(input); assertEquals("{\"NULL-KEY\":3}", json); json = mapper.writeValueAsString(new Object[] { 1, null, true }); assertEquals("[1,\"NULL\",true]", json); } public void testCustomEnumInnerMapKey() throws Exception { Map outerMap = new HashMap(); Map> map = new EnumMap>(ABC.class); Map innerMap = new HashMap(); innerMap.put("one", "1"); map.put(ABC.A, innerMap); outerMap.put(Outer.inner, map); final ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test"); mod.setMixInAnnotation(ABC.class, ABCMixin.class); mod.addKeySerializer(ABC.class, new ABCKeySerializer()); mapper.registerModule(mod); JsonNode tree = mapper.convertValue(outerMap, JsonNode.class); JsonNode innerNode = tree.get("inner"); String key = innerNode.fieldNames().next(); assertEquals("xxxA", key); } // [databind#838] public void testUnWrappedMapWithDefaultType() throws Exception{ final ObjectMapper mapper = new ObjectMapper(); SimpleModule mod = new SimpleModule("test"); mod.addKeySerializer(ABC.class, new ABCKeySerializer()); mapper.registerModule(mod); TypeResolverBuilder typer = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL); typer = typer.init(JsonTypeInfo.Id.NAME, null); typer = typer.inclusion(JsonTypeInfo.As.PROPERTY); //typer = typer.typeProperty(TYPE_FIELD); typer = typer.typeIdVisibility(true); mapper.setDefaultTyping(typer); Map stuff = new HashMap(); stuff.put(ABC.B, "bar"); String json = mapper.writerFor(new TypeReference>() {}) .writeValueAsString(stuff); assertEquals("{\"@type\":\"HashMap\",\"xxxB\":\"bar\"}", json); } // [databind#838] @SuppressWarnings("deprecation") public void testUnWrappedMapWithKeySerializer() throws Exception{ SimpleModule mod = new SimpleModule("test"); mod.addKeySerializer(ABC.class, new ABCKeySerializer()); final ObjectMapper mapper = new ObjectMapper() .registerModule(mod) .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT) .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .disable(SerializationFeature.WRITE_NULL_MAP_VALUES) .setSerializationInclusion(JsonInclude.Include.NON_EMPTY) ; Map> stuff = new HashMap>(); stuff.put(ABC.B, new BAR("bar")); String json = mapper.writerFor(new TypeReference>>() {}) .writeValueAsString(stuff); assertEquals("{\"xxxB\":\"bar\"}", json); } // [databind#943] public void testDynamicMapKeys() throws Exception { Map stuff = new LinkedHashMap(); stuff.put(AbcLC.B, Integer.valueOf(3)); stuff.put(new UCString("foo"), Integer.valueOf(4)); String json = MAPPER.writeValueAsString(stuff); assertEquals(aposToQuotes("{'b':3,'FOO':4}"), json); } } TestMapSerialization.java000066400000000000000000000213451325620701100362570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; import com.fasterxml.jackson.databind.annotation.JsonSerialize; @SuppressWarnings("serial") public class TestMapSerialization extends BaseMapTest { @JsonSerialize(using=PseudoMapSerializer.class) static class PseudoMap extends LinkedHashMap { public PseudoMap(String... values) { for (int i = 0, len = values.length; i < len; i += 2) { put(values[i], values[i+1]); } } } static class PseudoMapSerializer extends JsonSerializer> { @Override public void serialize(Map value, JsonGenerator gen, SerializerProvider provider) throws IOException { // just use standard Map.toString(), output as JSON String gen.writeString(value.toString()); } } // [databind#335] static class MapOrderingBean { @JsonPropertyOrder(alphabetic=true) public LinkedHashMap map; public MapOrderingBean(String... keys) { map = new LinkedHashMap(); int ix = 1; for (String key : keys) { map.put(key, ix++); } } } // [databind#565]: Support ser/deser of Map.Entry static class StringIntMapEntry implements Map.Entry { public final String k; public final Integer v; public StringIntMapEntry(String k, Integer v) { this.k = k; this.v = v; } @Override public String getKey() { return k; } @Override public Integer getValue() { return v; } @Override public Integer setValue(Integer value) { throw new UnsupportedOperationException(); } } static class StringIntMapEntryWrapper { public StringIntMapEntry value; public StringIntMapEntryWrapper(String k, Integer v) { value = new StringIntMapEntry(k, v); } } // for [databind#691] @JsonTypeInfo(use=JsonTypeInfo.Id.NAME) @JsonTypeName("mymap") static class MapWithTypedValues extends LinkedHashMap { } @JsonTypeInfo(use = Id.CLASS) public static class Mixin691 { } /* /********************************************************** /* Test methods /********************************************************** */ final private ObjectMapper MAPPER = objectMapper(); public void testUsingObjectWriter() throws IOException { ObjectWriter w = MAPPER.writerFor(Object.class); Map map = new LinkedHashMap(); map.put("a", 1); String json = w.writeValueAsString(map); assertEquals(aposToQuotes("{'a':1}"), json); } public void testMapSerializer() throws IOException { assertEquals("\"{a=b, c=d}\"", MAPPER.writeValueAsString(new PseudoMap("a", "b", "c", "d"))); } // problems with map entries, values public void testMapKeySetValuesSerialization() throws IOException { Map map = new HashMap(); map.put("a", "b"); assertEquals("[\"a\"]", MAPPER.writeValueAsString(map.keySet())); assertEquals("[\"b\"]", MAPPER.writeValueAsString(map.values())); // TreeMap has similar inner class(es): map = new TreeMap(); map.put("c", "d"); assertEquals("[\"c\"]", MAPPER.writeValueAsString(map.keySet())); assertEquals("[\"d\"]", MAPPER.writeValueAsString(map.values())); // and for [JACKSON-533], same for concurrent maps map = new ConcurrentHashMap(); map.put("e", "f"); assertEquals("[\"e\"]", MAPPER.writeValueAsString(map.keySet())); assertEquals("[\"f\"]", MAPPER.writeValueAsString(map.values())); } // sort Map entries by key public void testOrderByKey() throws IOException { ObjectMapper m = new ObjectMapper(); assertFalse(m.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)); LinkedHashMap map = new LinkedHashMap(); map.put("b", 3); map.put("a", 6); // by default, no (re)ordering: assertEquals("{\"b\":3,\"a\":6}", m.writeValueAsString(map)); // but can be changed ObjectWriter sortingW = m.writer(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS); assertEquals("{\"a\":6,\"b\":3}", sortingW.writeValueAsString(map)); } // related to [databind#1411] public void testOrderByWithNulls() throws IOException { ObjectWriter sortingW = MAPPER.writer(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS); // 16-Oct-2016, tatu: but mind the null key, if any Map mapWithNullKey = new LinkedHashMap(); mapWithNullKey.put(null, 1); mapWithNullKey.put("b", 2); // 16-Oct-2016, tatu: By default, null keys are not accepted... try { /*String json =*/ sortingW.writeValueAsString(mapWithNullKey); //assertEquals(aposToQuotes("{'':1,'b':2}"), json); } catch (JsonMappingException e) { verifyException(e, "Null key for a Map not allowed"); } } // [Databind#335] public void testOrderByKeyViaProperty() throws IOException { MapOrderingBean input = new MapOrderingBean("c", "b", "a"); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'map':{'a':3,'b':2,'c':1}}"), json); } // [Databind#565] public void testMapEntry() throws IOException { StringIntMapEntry input = new StringIntMapEntry("answer", 42); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'answer':42}"), json); StringIntMapEntry[] array = new StringIntMapEntry[] { input }; json = MAPPER.writeValueAsString(array); assertEquals(aposToQuotes("[{'answer':42}]"), json); // and maybe with bit of extra typing? ObjectMapper mapper = new ObjectMapper().enableDefaultTyping(DefaultTyping.NON_FINAL); json = mapper.writeValueAsString(input); assertEquals(aposToQuotes("['"+StringIntMapEntry.class.getName()+"',{'answer':42}]"), json); } public void testMapEntryWrapper() throws IOException { StringIntMapEntryWrapper input = new StringIntMapEntryWrapper("answer", 42); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'value':{'answer':42}}"), json); } // [databind#691] public void testNullJsonMapping691() throws Exception { MapWithTypedValues input = new MapWithTypedValues(); input.put("id", "Test"); input.put("NULL", null); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'@type':'mymap','id':'Test','NULL':null}"), json); } // [databind#691] public void testNullJsonInTypedMap691() throws Exception { Map map = new HashMap(); map.put("NULL", null); ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(Object.class, Mixin691.class); String json = mapper.writeValueAsString(map); assertEquals("{\"@class\":\"java.util.HashMap\",\"NULL\":null}", json); } // [databind#1513] public void testConcurrentMaps() throws Exception { final ObjectWriter w = MAPPER.writer(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS); Map input = new ConcurrentSkipListMap(); input.put("x", "y"); input.put("a", "b"); String json = w.writeValueAsString(input); assertEquals(aposToQuotes("{'a':'b','x':'y'}"), json); input = new ConcurrentHashMap(); input.put("x", "y"); input.put("a", "b"); json = w.writeValueAsString(input); assertEquals(aposToQuotes("{'a':'b','x':'y'}"), json); // One more: while not technically concurrent map at all, exhibits same issue input = new Hashtable(); input.put("x", "y"); input.put("a", "b"); json = w.writeValueAsString(input); assertEquals(aposToQuotes("{'a':'b','x':'y'}"), json); } } TestRootType.java000066400000000000000000000160001325620701100345610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.StringWriter; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Unit tests for verifying functioning of [JACKSON-195], ability to * force specific root type for serialization (super type of value) */ public class TestRootType extends BaseMapTest { /* /********************************************************** /* Annotated helper classes /********************************************************** */ interface BaseInterface { int getB(); } static class BaseType implements BaseInterface { public String a = "a"; @Override public int getB() { return 3; } } static class SubType extends BaseType { public String a2 = "x"; public boolean getB2() { return true; } } @JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="beanClass") public abstract static class BaseClass398 { } public static class TestClass398 extends BaseClass398 { public String property = "aa"; } @JsonRootName("root") static class WithRootName { public int a = 3; } // [databind#412] static class TestCommandParent { public String uuid; public int type; } static class TestCommandChild extends TestCommandParent { } /* /********************************************************** /* Main tests /********************************************************** */ final ObjectMapper WRAP_ROOT_MAPPER = new ObjectMapper(); { WRAP_ROOT_MAPPER.configure(SerializationFeature.WRAP_ROOT_VALUE, true); } @SuppressWarnings("unchecked") public void testSuperClass() throws Exception { ObjectMapper mapper = objectMapper(); SubType bean = new SubType(); // first, test with dynamically detected type Map result = writeAndMap(mapper, bean); assertEquals(4, result.size()); assertEquals("a", result.get("a")); assertEquals(Integer.valueOf(3), result.get("b")); assertEquals("x", result.get("a2")); assertEquals(Boolean.TRUE, result.get("b2")); // and then using specified typed writer ObjectWriter w = mapper.writerFor(BaseType.class); String json = w.writeValueAsString(bean); result = (Map)mapper.readValue(json, Map.class); assertEquals(2, result.size()); assertEquals("a", result.get("a")); assertEquals(Integer.valueOf(3), result.get("b")); } public void testSuperInterface() throws Exception { ObjectMapper mapper = objectMapper(); SubType bean = new SubType(); // let's constrain by interface: ObjectWriter w = mapper.writerFor(BaseInterface.class); String json = w.writeValueAsString(bean); @SuppressWarnings("unchecked") Map result = mapper.readValue(json, Map.class); assertEquals(1, result.size()); assertEquals(Integer.valueOf(3), result.get("b")); } public void testInArray() throws Exception { ObjectMapper mapper = new ObjectMapper(); // must force static typing, otherwise won't matter a lot mapper.configure(MapperFeature.USE_STATIC_TYPING, true); SubType[] ob = new SubType[] { new SubType() }; String json = mapper.writerFor(BaseInterface[].class).writeValueAsString(ob); // should propagate interface type through due to root declaration; static typing assertEquals("[{\"b\":3}]", json); } /** * Unit test to ensure that proper exception is thrown if declared * root type is not compatible with given value instance. */ public void testIncompatibleRootType() throws Exception { ObjectMapper mapper = objectMapper(); SubType bean = new SubType(); // and then let's try using incompatible type ObjectWriter w = mapper.writerFor(HashMap.class); try { w.writeValueAsString(bean); fail("Should have failed due to incompatible type"); } catch (JsonProcessingException e) { verifyException(e, "Incompatible types"); } // and also with alternate output method try { w.writeValueAsBytes(bean); fail("Should have failed due to incompatible type"); } catch (JsonProcessingException e) { verifyException(e, "Incompatible types"); } } public void testJackson398() throws Exception { ObjectMapper mapper = objectMapper(); JavaType collectionType = TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, BaseClass398.class); List typedList = new ArrayList(); typedList.add(new TestClass398()); final String EXP = "[{\"beanClass\":\"TestRootType$TestClass398\",\"property\":\"aa\"}]"; // First simplest way: String json = mapper.writerFor(collectionType).writeValueAsString(typedList); assertEquals(EXP, json); StringWriter out = new StringWriter(); JsonFactory f = new JsonFactory(); mapper.writerFor(collectionType).writeValue(f.createGenerator(out), typedList); assertEquals(EXP, out.toString()); } // [JACKSON-163] public void testRootWrapping() throws Exception { String json = WRAP_ROOT_MAPPER.writeValueAsString(new StringWrapper("abc")); assertEquals("{\"StringWrapper\":{\"str\":\"abc\"}}", json); } /** * Test to verify that there is support for specifying root type as primitive, * even if wrapper value is passed (there is no way to pass primitive values as * Objects); this to support frameworks that may pass unprocessed * {@link java.lang.reflect.Type} from field or method. */ public void testIssue456WrapperPart() throws Exception { ObjectMapper mapper = objectMapper(); assertEquals("123", mapper.writerFor(Integer.TYPE).writeValueAsString(Integer.valueOf(123))); assertEquals("456", mapper.writerFor(Long.TYPE).writeValueAsString(Long.valueOf(456L))); } public void testRootNameAnnotation() throws Exception { String json = WRAP_ROOT_MAPPER.writeValueAsString(new WithRootName()); assertEquals("{\"root\":{\"a\":3}}", json); } // [databind#412] public void testRootNameWithExplicitType() throws Exception { TestCommandChild cmd = new TestCommandChild(); cmd.uuid = "1234"; cmd.type = 1; ObjectWriter writer = WRAP_ROOT_MAPPER.writerFor(TestCommandParent.class); String json = writer.writeValueAsString(cmd); assertEquals("{\"TestCommandParent\":{\"uuid\":\"1234\",\"type\":1}}", json); } } TestSerializationOrder.java000066400000000000000000000102511325620701100366070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying that constraints on ordering of serialized * properties are held. */ public class TestSerializationOrder extends BaseMapTest { /* /********************************************************** /* Annotated helper classes /********************************************************** */ static class BeanWithCreator { public int a; public int b; public int c; @JsonCreator public BeanWithCreator(@JsonProperty("c") int c, @JsonProperty("a") int a) { this.a = a; this.c = c; } } @JsonPropertyOrder({"c", "a", "b"}) static class BeanWithOrder { public int d, b, a, c; public BeanWithOrder(int a, int b, int c, int d) { this.a = a; this.b = b; this.c = c; this.d = d; } } @JsonPropertyOrder(value={"d"}, alphabetic=true) static class SubBeanWithOrder extends BeanWithOrder { public SubBeanWithOrder(int a, int b, int c, int d) { super(a, b, c, d); } } @JsonPropertyOrder({"b", "a", // note: including non-existant properties is fine (has no effect, but not an error) "foobar", "c" }) static class OrderMixIn { } @JsonPropertyOrder(value={"a","b","x","z"}) static class BeanFor268 { @JsonProperty("a") public String xA = "a"; @JsonProperty("z") public String aZ = "z"; @JsonProperty("b") public String xB() { return "b"; } @JsonProperty("x") public String aX() { return "x"; } } static class BeanFor459 { public int d = 4; public int c = 3; public int b = 2; public int a = 1; } // For [Issue#311] @JsonPropertyOrder(alphabetic = true) public class BeanForGH311 { private final int a; private final int b; @JsonCreator public BeanForGH311(@JsonProperty("b") int b, @JsonProperty("a") int a) { //b and a are out of order, although alphabetic = true this.a = a; this.b = b; } public int getA() { return a; } public int getB() { return b; } } /* /********************************************* /* Unit tests /********************************************* */ final ObjectMapper MAPPER = new ObjectMapper(); // Test for [JACKSON-170] public void testImplicitOrderByCreator() throws Exception { assertEquals("{\"c\":1,\"a\":2,\"b\":0}", MAPPER.writeValueAsString(new BeanWithCreator(1, 2))); } public void testExplicitOrder() throws Exception { assertEquals("{\"c\":3,\"a\":1,\"b\":2,\"d\":4}", MAPPER.writeValueAsString(new BeanWithOrder(1, 2, 3, 4))); } public void testAlphabeticOrder() throws Exception { assertEquals("{\"d\":4,\"a\":1,\"b\":2,\"c\":3}", MAPPER.writeValueAsString(new SubBeanWithOrder(1, 2, 3, 4))); } public void testOrderWithMixins() throws Exception { ObjectMapper m = new ObjectMapper(); m.addMixIn(BeanWithOrder.class, OrderMixIn.class); assertEquals("{\"b\":2,\"a\":1,\"c\":3,\"d\":4}", serializeAsString(m, new BeanWithOrder(1, 2, 3, 4))); } public void testOrderWrt268() throws Exception { assertEquals("{\"a\":\"a\",\"b\":\"b\",\"x\":\"x\",\"z\":\"z\"}", MAPPER.writeValueAsString(new BeanFor268())); } public void testOrderWithFeature() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true); assertEquals("{\"a\":1,\"b\":2,\"c\":3,\"d\":4}", m.writeValueAsString(new BeanFor459())); } // [Issue#311] public void testAlphaAndCreatorOrdering() throws Exception { ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true); String json = m.writeValueAsString(new BeanForGH311(2, 1)); assertEquals("{\"a\":1,\"b\":2}", json); } } TestSerializerProvider.java000066400000000000000000000036421325620701100366300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.BeanSerializerFactory; public class TestSerializerProvider extends com.fasterxml.jackson.databind.BaseMapTest { static class MyBean { public int getX() { return 3; } } static class NoPropsBean { } public void testFindExplicit() throws JsonMappingException { ObjectMapper mapper = new ObjectMapper(); SerializationConfig config = mapper.getSerializationConfig(); SerializerFactory f = new BeanSerializerFactory(null); DefaultSerializerProvider prov = new DefaultSerializerProvider.Impl().createInstance(config, f); // Should have working default key and null key serializers assertNotNull(prov.findKeySerializer(mapper.constructType(String.class), null)); assertNotNull(prov.getDefaultNullKeySerializer()); assertNotNull(prov.getDefaultNullValueSerializer()); // as well as 'unknown type' one (throws exception) assertNotNull(prov.getUnknownTypeSerializer(getClass())); assertTrue(prov.createInstance(config, f).hasSerializerFor(String.class, null)); // call twice to verify it'll be cached (second code path) assertTrue(prov.createInstance(config, f).hasSerializerFor(String.class, null)); assertTrue(prov.createInstance(config, f).hasSerializerFor(MyBean.class, null)); assertTrue(prov.createInstance(config, f).hasSerializerFor(MyBean.class, null)); // And then some negative testing AtomicReference cause = new AtomicReference(); assertFalse(prov.createInstance(config, f).hasSerializerFor(NoPropsBean.class, cause)); Throwable t = cause.get(); // no actual exception: just fails since there are no properties assertNull(t); } } TestSimpleTypes.java000066400000000000000000000105141325620701100352560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import com.fasterxml.jackson.core.Base64Variants; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import static org.junit.Assert.*; /** * Unit tests for verifying serialization of simple basic non-structured * types; primitives (and/or their wrappers), Strings. */ public class TestSimpleTypes extends BaseMapTest { private final ObjectMapper MAPPER = new ObjectMapper(); public void testBoolean() throws Exception { assertEquals("true", serializeAsString(MAPPER, Boolean.TRUE)); assertEquals("false", serializeAsString(MAPPER, Boolean.FALSE)); } public void testBooleanArray() throws Exception { assertEquals("[true,false]", serializeAsString(MAPPER, new boolean[] { true, false} )); assertEquals("[true,false]", serializeAsString(MAPPER, new Boolean[] { Boolean.TRUE, Boolean.FALSE} )); } public void testByteArray() throws Exception { byte[] data = { 1, 17, -3, 127, -128 }; Byte[] data2 = new Byte[data.length]; for (int i = 0; i < data.length; ++i) { data2[i] = data[i]; // auto-boxing } // For this we need to deserialize, to get base64 codec String str1 = serializeAsString(MAPPER, data); String str2 = serializeAsString(MAPPER, data2); assertArrayEquals(data, MAPPER.readValue(str1, byte[].class)); assertArrayEquals(data2, MAPPER.readValue(str2, Byte[].class)); } // as per [Issue#42], allow Base64 variant use as well public void testBase64Variants() throws Exception { final byte[] INPUT = "abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890X".getBytes("UTF-8"); // default encoding is "MIME, no linefeeds", so: assertEquals(quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA=="), MAPPER.writeValueAsString(INPUT)); assertEquals(quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA=="), MAPPER.writer(Base64Variants.MIME_NO_LINEFEEDS).writeValueAsString(INPUT)); // but others should be slightly different assertEquals(quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1\\ndnd4eXoxMjM0NTY3ODkwWA=="), MAPPER.writer(Base64Variants.MIME).writeValueAsString(INPUT)); assertEquals(quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA"), // no padding or LF MAPPER.writer(Base64Variants.MODIFIED_FOR_URL).writeValueAsString(INPUT)); // PEM mandates 64 char lines: assertEquals(quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamts\\nbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA=="), MAPPER.writer(Base64Variants.PEM).writeValueAsString(INPUT)); } public void testShortArray() throws Exception { assertEquals("[0,1]", serializeAsString(MAPPER, new short[] { 0, 1 })); assertEquals("[2,3]", serializeAsString(MAPPER, new Short[] { 2, 3 })); } public void testIntArray() throws Exception { assertEquals("[0,-3]", serializeAsString(MAPPER, new int[] { 0, -3 })); assertEquals("[13,9]", serializeAsString(MAPPER, new Integer[] { 13, 9 })); } /* Note: dealing with floating-point values is tricky; not sure if * we can really use equality tests here... JDK does have decent * conversions though, to retain accuracy and round-trippability. * But still... */ public void testFloat() throws Exception { double[] values = new double[] { 0.0, 1.0, 0.1, -37.01, 999.99, 0.3, 33.3, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY }; for (double d : values) { float f = (float) d; String expected = String.valueOf(f); if (Float.isNaN(f) || Float.isInfinite(f)) { expected = "\""+expected+"\""; } assertEquals(expected,serializeAsString(MAPPER, Float.valueOf(f))); } } public void testClass() throws Exception { String result = MAPPER.writeValueAsString(java.util.List.class); assertEquals("\"java.util.List\"", result); } } TestStatics.java000066400000000000000000000032301325620701100344070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * This unit test suite verifies that static fields and methods are * ignored wrt serialization */ public class TestStatics extends BaseMapTest { /* /********************************************************** /* Annotated helper classes /********************************************************** */ final static class FieldBean { public int x = 1; public static int y = 2; // not even @JsonProperty should make statics usable... @JsonProperty public static int z = 3; } final static class GetterBean { public int getX() { return 3; } public static int getA() { return -3; } // not even @JsonProperty should make statics usable... @JsonProperty public static int getFoo() { return 123; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testStaticFields() throws Exception { ObjectMapper m = new ObjectMapper(); Map result = writeAndMap(m, new FieldBean()); assertEquals(1, result.size()); assertEquals(Integer.valueOf(1), result.get("x")); } public void testStaticMethods() throws Exception { ObjectMapper m = new ObjectMapper(); Map result = writeAndMap(m, new GetterBean()); assertEquals(1, result.size()); assertEquals(Integer.valueOf(3), result.get("x")); } } TestTreeSerialization.java000066400000000000000000000100701325620701100364320ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.io.*; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.node.*; /** * This unit test suite tries to verify that JsonNode-based trees * can be serialized as expected */ public class TestTreeSerialization extends BaseMapTest { final static class Bean { public String getX() { return "y"; } public int getY() { return 13; } } @SuppressWarnings("unchecked") public void testSimpleViaObjectMapper() throws IOException { ObjectMapper mapper = new ObjectMapper(); // also need tree mapper to construct tree to serialize ObjectNode n = mapper.getNodeFactory().objectNode(); n.put("number", 15); n.put("string", "abc"); ObjectNode n2 = n.putObject("ob"); n2.putArray("arr"); StringWriter sw = new StringWriter(); JsonGenerator jg = mapper.getFactory().createGenerator(sw); mapper.writeTree(jg, n); Map result = (Map) mapper.readValue(sw.toString(), Map.class); assertEquals(3, result.size()); assertEquals("abc", result.get("string")); assertEquals(Integer.valueOf(15), result.get("number")); Map ob = (Map) result.get("ob"); assertEquals(1, ob.size()); List list = (List) ob.get("arr"); assertEquals(0, list.size()); jg.close(); } /** * Simple test to verify that POJONodes (JsonNode wrapper around * any old Java object) work with serialization */ @SuppressWarnings("unchecked") public void testPOJOString() throws Exception { ObjectMapper mapper = new ObjectMapper(); // also need tree mapper to construct tree to serialize ObjectNode n = mapper.getNodeFactory().objectNode(); n.set("pojo", mapper.getNodeFactory().pojoNode("abc")); StringWriter sw = new StringWriter(); JsonGenerator jg = mapper.getFactory().createGenerator(sw); mapper.writeTree(jg, n); Map result = (Map) mapper.readValue(sw.toString(), Map.class); assertEquals(1, result.size()); assertEquals("abc", result.get("pojo")); jg.close(); } @SuppressWarnings("unchecked") public void testPOJOIntArray() throws IOException { ObjectMapper mapper = new ObjectMapper(); ObjectNode n = mapper.getNodeFactory().objectNode(); n.set("pojo", mapper.getNodeFactory().pojoNode(new int[] { 1, 2, 3 })); StringWriter sw = new StringWriter(); JsonGenerator jg = mapper.getFactory().createGenerator(sw); mapper.writeTree(jg, n); Map result = (Map) mapper.readValue(sw.toString(), Map.class); assertEquals(1, result.size()); // int array becomes a list when mapped to general Object: List list = (List) result.get("pojo"); assertEquals(3, list.size()); for (int i = 0; i < 3; ++i) { assertEquals(Integer.valueOf(i+1), list.get(i)); } jg.close(); } @SuppressWarnings("unchecked") public void testPOJOBean() throws IOException { ObjectMapper mapper = new ObjectMapper(); // also need tree mapper to construct tree to serialize ObjectNode n = mapper.getNodeFactory().objectNode(); n.set("pojo", mapper.getNodeFactory().pojoNode(new Bean())); StringWriter sw = new StringWriter(); JsonGenerator jg = mapper.getFactory().createGenerator(sw); mapper.writeTree(jg, n); Map result = (Map) mapper.readValue(sw.toString(), Map.class); assertEquals(1, result.size()); Map bean = (Map) result.get("pojo"); assertEquals(2, bean.size()); assertEquals("y", bean.get("x")); assertEquals(Integer.valueOf(13), bean.get("y")); jg.close(); } } TestTypedRootValueSerialization.java000066400000000000000000000050761325620701100404730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class TestTypedRootValueSerialization extends BaseMapTest { // [JACKSON-822] static interface Issue822Interface { public int getA(); } // If this annotation is added, things will work: //@com.fasterxml.jackson.databind.annotation.JsonSerialize(as=Issue822Interface.class) // but it should not be necessary when root type is passed static class Issue822Impl implements Issue822Interface { @Override public int getA() { return 3; } public int getB() { return 9; } } // First ensure that basic interface-override works: public void testTypedSerialization() throws Exception { ObjectMapper mapper = new ObjectMapper(); String singleJson = mapper.writerFor(Issue822Interface.class).writeValueAsString(new Issue822Impl()); // start with specific value case: assertEquals("{\"a\":3}", singleJson); } // [JACKSON-822]: ensure that type can be coerced public void testTypedArrays() throws Exception { ObjectMapper mapper = new ObjectMapper(); // Work-around when real solution not yet implemented: // mapper.enable(MapperFeature.USE_STATIC_TYPING); assertEquals("[{\"a\":3}]", mapper.writerFor(Issue822Interface[].class).writeValueAsString( new Issue822Interface[] { new Issue822Impl() })); } // [JACKSON-822]: ensure that type can be coerced public void testTypedLists() throws Exception { ObjectMapper mapper = new ObjectMapper(); // Work-around when real solution not yet implemented: // mapper.enable(MapperFeature.USE_STATIC_TYPING); List list = new ArrayList(); list.add(new Issue822Impl()); String listJson = mapper.writerFor(new TypeReference>(){}) .writeValueAsString(list); assertEquals("[{\"a\":3}]", listJson); } public void testTypedMaps() throws Exception { ObjectMapper mapper = new ObjectMapper(); Map map = new HashMap(); map.put("a", new Issue822Impl()); String listJson = mapper.writerFor(new TypeReference>(){}) .writeValueAsString(map); assertEquals("{\"a\":{\"a\":3}}", listJson); } } TestVirtualProperties.java000066400000000000000000000105221325620701100365020ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/serpackage com.fasterxml.jackson.databind.ser; import java.util.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonAppend; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.util.Annotations; /** * Tests for verifying that one can append virtual properties after regular ones. * * @since 2.5 */ public class TestVirtualProperties extends BaseMapTest { @JsonAppend(attrs={ @JsonAppend.Attr("id"), @JsonAppend.Attr(value="internal", propName="extra", required=true) }) static class SimpleBean { public int value = 13; } @JsonAppend(prepend=true, attrs={ @JsonAppend.Attr("id"), @JsonAppend.Attr(value="internal", propName="extra") }) static class SimpleBeanPrepend { public int value = 13; } enum ABC { A, B, C; } @JsonAppend(attrs=@JsonAppend.Attr(value="desc", include=JsonInclude.Include.NON_EMPTY)) static class OptionalsBean { public int value = 28; } @SuppressWarnings("serial") static class CustomVProperty extends VirtualBeanPropertyWriter { private CustomVProperty() { super(); } private CustomVProperty(BeanPropertyDefinition propDef, Annotations ctxtAnn, JavaType type) { super(propDef, ctxtAnn, type); } @Override protected Object value(Object bean, JsonGenerator jgen, SerializerProvider prov) { if (_name.toString().equals("id")) { return "abc123"; } if (_name.toString().equals("extra")) { return new int[] { 42 }; } return "???"; } @Override public VirtualBeanPropertyWriter withConfig(MapperConfig config, AnnotatedClass declaringClass, BeanPropertyDefinition propDef, JavaType type) { return new CustomVProperty(propDef, declaringClass.getAnnotations(), type); } } @JsonAppend(prepend=true, props={ @JsonAppend.Prop(value=CustomVProperty.class, name="id"), @JsonAppend.Prop(value=CustomVProperty.class, name="extra") }) static class CustomVBean { public int value = 72; } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectWriter WRITER = objectWriter(); public void testAttributeProperties() throws Exception { Map stuff = new LinkedHashMap(); stuff.put("x", 3); stuff.put("y", ABC.B); String json = WRITER.withAttribute("id", "abc123") .withAttribute("internal", stuff) .writeValueAsString(new SimpleBean()); assertEquals(aposToQuotes("{'value':13,'id':'abc123','extra':{'x':3,'y':'B'}}"), json); json = WRITER.withAttribute("id", "abc123") .withAttribute("internal", stuff) .writeValueAsString(new SimpleBeanPrepend()); assertEquals(aposToQuotes("{'id':'abc123','extra':{'x':3,'y':'B'},'value':13}"), json); } public void testAttributePropInclusion() throws Exception { // first, with desc String json = WRITER.withAttribute("desc", "nice") .writeValueAsString(new OptionalsBean()); assertEquals(aposToQuotes("{'value':28,'desc':'nice'}"), json); // then with null (not defined) json = WRITER.writeValueAsString(new OptionalsBean()); assertEquals(aposToQuotes("{'value':28}"), json); // and finally "empty" json = WRITER.withAttribute("desc", "") .writeValueAsString(new OptionalsBean()); assertEquals(aposToQuotes("{'value':28}"), json); } public void testCustomProperties() throws Exception { String json = WRITER.withAttribute("desc", "nice") .writeValueAsString(new CustomVBean()); assertEquals(aposToQuotes("{'id':'abc123','extra':[42],'value':72}"), json); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filter/000077500000000000000000000000001325620701100326405ustar00rootroot00000000000000IgnorePropsForSerTest.java000066400000000000000000000076411325620701100376640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class IgnorePropsForSerTest extends BaseMapTest { @JsonIgnoreProperties({"b", "c"}) static class IgnoreSome { public int a = 3; public String b = "x"; public int getC() { return -6; } public String getD() { return "abc"; } } @SuppressWarnings("serial") @JsonIgnoreProperties({"@class"}) static class MyMap extends HashMap { } //allow use of @JsonIgnoreProperties for properties static class WrapperWithPropIgnore { @JsonIgnoreProperties("y") public XY value = new XY(); } static class XY { public int x = 1; public int y = 2; } static class WrapperWithPropIgnore2 { @JsonIgnoreProperties("z") public XYZ value = new XYZ(); } @JsonIgnoreProperties({"x"}) static class XYZ { public int x = 1; public int y = 2; public int z = 3; } // also ought to work without full typing? static class WrapperWithPropIgnoreUntyped { @JsonIgnoreProperties("y") public Object value = new XYZ(); } static class MapWrapper { @JsonIgnoreProperties({"a"}) public final HashMap value = new HashMap(); { value.put("a", 1); value.put("b", 2); } } /* /**************************************************************** /* Unit tests /**************************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testExplicitIgnoralWithBean() throws Exception { IgnoreSome value = new IgnoreSome(); Map result = writeAndMap(MAPPER, value); assertEquals(2, result.size()); // verify that specified fields are ignored assertFalse(result.containsKey("b")); assertFalse(result.containsKey("c")); // and that others are not assertEquals(Integer.valueOf(value.a), result.get("a")); assertEquals(value.getD(), result.get("d")); } public void testExplicitIgnoralWithMap() throws Exception { // test simulating need to filter out metadata like class name MyMap value = new MyMap(); value.put("a", "b"); value.put("@class", MyMap.class.getName()); Map result = writeAndMap(MAPPER, value); assertEquals(1, result.size()); // verify that specified field is ignored assertFalse(result.containsKey("@class")); // and that others are not assertEquals(value.get("a"), result.get("a")); } public void testIgnoreViaOnlyProps() throws Exception { assertEquals("{\"value\":{\"x\":1}}", MAPPER.writeValueAsString(new WrapperWithPropIgnore())); } // Also: should be fine even if nominal type is `java.lang.Object` public void testIgnoreViaPropForUntyped() throws Exception { assertEquals("{\"value\":{\"z\":3}}", MAPPER.writeValueAsString(new WrapperWithPropIgnoreUntyped())); } public void testIgnoreWithMapProperty() throws Exception { assertEquals("{\"value\":{\"b\":2}}", MAPPER.writeValueAsString(new MapWrapper())); } public void testIgnoreViaPropsAndClass() throws Exception { assertEquals("{\"value\":{\"y\":2}}", MAPPER.writeValueAsString(new WrapperWithPropIgnore2())); } public void testIgnoreViaConfigOverride() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(Point.class) .setIgnorals(JsonIgnoreProperties.Value.forIgnoredProperties("x")); assertEquals("{\"y\":3}", mapper.writeValueAsString(new Point(2, 3))); } } JsonInclude1327Test.java000066400000000000000000000032751325620701100370250ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.util.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * Unit tests for checking that alternative settings for * {@link JsonSerialize#include} annotation property work * as expected. */ public class JsonInclude1327Test extends BaseMapTest { @JsonInclude(JsonInclude.Include.NON_EMPTY) static class Issue1327BeanEmpty { public List myList = new ArrayList(); } static class Issue1327BeanAlways { @JsonInclude(JsonInclude.Include.ALWAYS) public List myList = new ArrayList(); } /* /********************************************************** /* Unit tests /********************************************************** */ // for [databind#1327] public void testClassDefaultsForEmpty() throws Exception { ObjectMapper om = new ObjectMapper(); om.setSerializationInclusion(JsonInclude.Include.NON_NULL); final String jsonString = om.writeValueAsString(new Issue1327BeanEmpty()); if (jsonString.contains("myList")) { fail("Should not contain `myList`: "+jsonString); } } public void testClassDefaultsForAlways() throws Exception { ObjectMapper om = new ObjectMapper(); om.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); final String jsonString = om.writeValueAsString(new Issue1327BeanAlways()); if (!jsonString.contains("myList")) { fail("Should contain `myList` with Include.ALWAYS: "+jsonString); } } } JsonIncludeArrayTest.java000066400000000000000000000103201325620701100374740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; public class JsonIncludeArrayTest extends BaseMapTest { static class NonEmptyByteArray { @JsonInclude(JsonInclude.Include.NON_EMPTY) public byte[] value; public NonEmptyByteArray(byte... v) { value = v; } } static class NonEmptyShortArray { @JsonInclude(JsonInclude.Include.NON_EMPTY) public short[] value; public NonEmptyShortArray(short... v) { value = v; } } static class NonEmptyCharArray { @JsonInclude(JsonInclude.Include.NON_EMPTY) public char[] value; public NonEmptyCharArray(char... v) { value = v; } } static class NonEmptyIntArray { @JsonInclude(JsonInclude.Include.NON_EMPTY) public int[] value; public NonEmptyIntArray(int... v) { value = v; } } static class NonEmptyLongArray { @JsonInclude(JsonInclude.Include.NON_EMPTY) public long[] value; public NonEmptyLongArray(long... v) { value = v; } } static class NonEmptyBooleanArray { @JsonInclude(JsonInclude.Include.NON_EMPTY) public boolean[] value; public NonEmptyBooleanArray(boolean... v) { value = v; } } static class NonEmptyDoubleArray { @JsonInclude(JsonInclude.Include.NON_EMPTY) public double[] value; public NonEmptyDoubleArray(double... v) { value = v; } } static class NonEmptyFloatArray { @JsonInclude(JsonInclude.Include.NON_EMPTY) public float[] value; public NonEmptyFloatArray(float... v) { value = v; } } /* /********************************************************** /* Test methods /********************************************************** */ final private ObjectMapper MAPPER = new ObjectMapper(); public void testByteArray() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new NonEmptyByteArray())); } public void testShortArray() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new NonEmptyShortArray())); assertEquals("{\"value\":[1]}", MAPPER.writeValueAsString(new NonEmptyShortArray((short) 1))); } public void testCharArray() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new NonEmptyCharArray())); // by default considered to be serialized as String assertEquals("{\"value\":\"ab\"}", MAPPER.writeValueAsString(new NonEmptyCharArray('a', 'b'))); // but can force as sparse (real) array too assertEquals("{\"value\":[\"a\",\"b\"]}", MAPPER .writer().with(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS) .writeValueAsString(new NonEmptyCharArray('a', 'b'))); } public void testIntArray() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new NonEmptyIntArray())); assertEquals("{\"value\":[2]}", MAPPER.writeValueAsString(new NonEmptyIntArray(2))); } public void testLongArray() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new NonEmptyLongArray())); assertEquals("{\"value\":[3,4]}", MAPPER.writeValueAsString(new NonEmptyLongArray(3, 4))); } public void testBooleanArray() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new NonEmptyBooleanArray())); assertEquals("{\"value\":[true,false]}", MAPPER.writeValueAsString(new NonEmptyBooleanArray(true,false))); } public void testDoubleArray() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new NonEmptyDoubleArray())); assertEquals("{\"value\":[0.25,-1.0]}", MAPPER.writeValueAsString(new NonEmptyDoubleArray(0.25,-1.0))); } public void testFloatArray() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new NonEmptyFloatArray())); assertEquals("{\"value\":[0.5]}", MAPPER.writeValueAsString(new NonEmptyFloatArray(0.5f))); } } JsonIncludeCollectionTest.java000066400000000000000000000021711325620701100405160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.util.Arrays; import java.util.EnumSet; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class JsonIncludeCollectionTest extends BaseMapTest { static class NonEmptyEnumSet { @JsonInclude(JsonInclude.Include.NON_EMPTY) public EnumSet v; public NonEmptyEnumSet(ABC...values) { if (values.length == 0) { v = EnumSet.noneOf(ABC.class); } else { v = EnumSet.copyOf(Arrays.asList(values)); } } } /* /********************************************************** /* Test methods /********************************************************** */ final private ObjectMapper MAPPER = new ObjectMapper(); public void testEnumSet() throws Exception { assertEquals("{}", MAPPER.writeValueAsString(new NonEmptyEnumSet())); assertEquals("{\"v\":[\"B\"]}", MAPPER.writeValueAsString(new NonEmptyEnumSet(ABC.B))); } } JsonIncludeCustomTest.java000066400000000000000000000061121325620701100376740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; // Tests for [databind#888] public class JsonIncludeCustomTest extends BaseMapTest { static class FooFilter { @Override public boolean equals(Object other) { if (other == null) { // do NOT filter out nulls return false; } // in fact, only filter out exact String "foo" return "foo".equals(other); } } // for testing prob with `equals(null)` which SHOULD be allowed static class BrokenFilter { @Override public boolean equals(Object other) { /*String str = */ other.toString(); return false; } } static class FooBean { @JsonInclude(value=JsonInclude.Include.CUSTOM, valueFilter=FooFilter.class) public String value; public FooBean(String v) { value = v; } } static class FooMapBean { @JsonInclude(content=JsonInclude.Include.CUSTOM, contentFilter=FooFilter.class) public Map stuff = new LinkedHashMap(); public FooMapBean add(String key, String value) { stuff.put(key, value); return this; } } static class BrokenBean { @JsonInclude(value=JsonInclude.Include.CUSTOM, valueFilter=BrokenFilter.class) public String value; public BrokenBean(String v) { value = v; } } /* /********************************************************** /* Test methods, success /********************************************************** */ final private ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleCustomFilter() throws Exception { assertEquals(aposToQuotes("{'value':'x'}"), MAPPER.writeValueAsString(new FooBean("x"))); assertEquals("{}", MAPPER.writeValueAsString(new FooBean("foo"))); } public void testCustomFilterWithMap() throws Exception { FooMapBean input = new FooMapBean() .add("a", "1") .add("b", "foo") .add("c", "2"); assertEquals(aposToQuotes("{'stuff':{'a':'1','c':'2'}}"), MAPPER.writeValueAsString(input)); } /* /********************************************************** /* Test methods, fail handling /********************************************************** */ public void testBrokenFilter() throws Exception { try { String json = MAPPER.writeValueAsString(new BrokenBean("foo")); fail("Should not pass, produced: "+json); } catch (InvalidDefinitionException e) { verifyException(e, "Problem determining whether filter of type"); verifyException(e, "filter out `null`"); } } } JsonIncludeOverrideTest.java000066400000000000000000000202441325620701100402030ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; /** * Unit tests for checking that overridden settings for * {@link com.fasterxml.jackson.databind.annotation.JsonSerialize#include} annotation property work * as expected. */ public class JsonIncludeOverrideTest extends BaseMapTest { @JsonPropertyOrder({"list", "map"}) static class EmptyListMapBean { public List list = Collections.emptyList(); public Map map = Collections.emptyMap(); } @JsonInclude(JsonInclude.Include.ALWAYS) @JsonPropertyOrder({"num", "annotated", "plain"}) static class MixedTypeAlwaysBean { @JsonInclude(JsonInclude.Include.USE_DEFAULTS) public Integer num = null; @JsonInclude(JsonInclude.Include.NON_NULL) public String annotated = null; public String plain = null; } @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({"num", "annotated", "plain"}) static class MixedTypeNonNullBean { @JsonInclude(JsonInclude.Include.USE_DEFAULTS) public Integer num = null; @JsonInclude(JsonInclude.Include.ALWAYS) public String annotated = null; public String plain = null; } public void testPropConfigOverridesForInclude() throws IOException { ObjectMapper mapper = new ObjectMapper(); // First, with defaults, both included: JsonIncludeOverrideTest.EmptyListMapBean empty = new JsonIncludeOverrideTest.EmptyListMapBean(); assertEquals(aposToQuotes("{'list':[],'map':{}}"), mapper.writeValueAsString(empty)); // and then change inclusion criteria for either mapper = new ObjectMapper(); mapper.configOverride(Map.class) .setInclude(JsonInclude.Value.construct(JsonInclude.Include.NON_EMPTY, null)); assertEquals(aposToQuotes("{'list':[]}"), mapper.writeValueAsString(empty)); mapper = new ObjectMapper(); mapper.configOverride(List.class) .setInclude(JsonInclude.Value.construct(JsonInclude.Include.NON_EMPTY, null)); assertEquals(aposToQuotes("{'map':{}}"), mapper.writeValueAsString(empty)); } public void testOverrideForIncludeAsPropertyNonNull() throws Exception { ObjectMapper mapper = new ObjectMapper(); // First, with defaults, all but NON_NULL annotated included JsonIncludeOverrideTest.MixedTypeAlwaysBean nullValues = new JsonIncludeOverrideTest.MixedTypeAlwaysBean(); assertEquals(aposToQuotes("{'num':null,'plain':null}"), mapper.writeValueAsString(nullValues)); // and then change inclusion as property criteria for either mapper = new ObjectMapper(); mapper.configOverride(String.class) .setIncludeAsProperty(JsonInclude.Value .construct(JsonInclude.Include.NON_NULL, null)); assertEquals("{\"num\":null}", mapper.writeValueAsString(nullValues)); mapper = new ObjectMapper(); mapper.configOverride(Integer.class) .setIncludeAsProperty(JsonInclude.Value .construct(JsonInclude.Include.NON_NULL, null)); assertEquals("{\"plain\":null}", mapper.writeValueAsString(nullValues)); } public void testOverrideForIncludeAsPropertyAlways() throws Exception { ObjectMapper mapper = new ObjectMapper(); // First, with defaults, only ALWAYS annotated included JsonIncludeOverrideTest.MixedTypeNonNullBean nullValues = new JsonIncludeOverrideTest.MixedTypeNonNullBean(); assertEquals("{\"annotated\":null}", mapper.writeValueAsString(nullValues)); // and then change inclusion as property criteria for either mapper = new ObjectMapper(); mapper.configOverride(String.class) .setIncludeAsProperty(JsonInclude.Value .construct(JsonInclude.Include.ALWAYS, null)); assertEquals(aposToQuotes("{'annotated':null,'plain':null}"), mapper.writeValueAsString(nullValues)); mapper = new ObjectMapper(); mapper.configOverride(Integer.class) .setIncludeAsProperty(JsonInclude.Value .construct(JsonInclude.Include.ALWAYS, null)); assertEquals(aposToQuotes("{'num':null,'annotated':null}"), mapper.writeValueAsString(nullValues)); } public void testOverridesForIncludeAndIncludeAsPropertyNonNull() throws Exception { // First, with ALWAYS override on containing bean, all included JsonIncludeOverrideTest.MixedTypeNonNullBean nullValues = new JsonIncludeOverrideTest.MixedTypeNonNullBean(); ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(JsonIncludeOverrideTest.MixedTypeNonNullBean.class) .setInclude(JsonInclude.Value .construct(JsonInclude.Include.ALWAYS, null)); assertEquals(aposToQuotes("{'num':null,'annotated':null,'plain':null}"), mapper.writeValueAsString(nullValues)); // and then change inclusion as property criteria for either mapper = new ObjectMapper(); mapper.configOverride(JsonIncludeOverrideTest.MixedTypeNonNullBean.class) .setInclude(JsonInclude.Value .construct(JsonInclude.Include.ALWAYS, null)); mapper.configOverride(String.class) .setIncludeAsProperty(JsonInclude.Value .construct(JsonInclude.Include.NON_NULL, null)); assertEquals(aposToQuotes("{'num':null,'annotated':null}"), mapper.writeValueAsString(nullValues)); mapper = new ObjectMapper(); mapper.configOverride(JsonIncludeOverrideTest.MixedTypeNonNullBean.class) .setInclude(JsonInclude.Value .construct(JsonInclude.Include.ALWAYS, null)); mapper.configOverride(Integer.class) .setIncludeAsProperty(JsonInclude.Value .construct(JsonInclude.Include.NON_NULL, null)); assertEquals(aposToQuotes("{'annotated':null,'plain':null}"), mapper.writeValueAsString(nullValues)); } public void testOverridesForIncludeAndIncludeAsPropertyAlways() throws Exception { // First, with NON_NULL override on containing bean, empty JsonIncludeOverrideTest.MixedTypeAlwaysBean nullValues = new JsonIncludeOverrideTest.MixedTypeAlwaysBean(); ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(JsonIncludeOverrideTest.MixedTypeAlwaysBean.class) .setInclude(JsonInclude.Value .construct(JsonInclude.Include.NON_NULL, null)); assertEquals("{}", mapper.writeValueAsString(nullValues)); // and then change inclusion as property criteria for either mapper = new ObjectMapper(); mapper.configOverride(JsonIncludeOverrideTest.MixedTypeAlwaysBean.class) .setInclude(JsonInclude.Value .construct(JsonInclude.Include.NON_NULL, null)); mapper.configOverride(String.class) .setIncludeAsProperty(JsonInclude.Value .construct(JsonInclude.Include.ALWAYS, null)); assertEquals("{\"plain\":null}", mapper.writeValueAsString(nullValues)); mapper = new ObjectMapper(); mapper.configOverride(JsonIncludeOverrideTest.MixedTypeAlwaysBean.class) .setInclude(JsonInclude.Value .construct(JsonInclude.Include.NON_NULL, null)); mapper.configOverride(Integer.class) .setIncludeAsProperty(JsonInclude.Value .construct(JsonInclude.Include.ALWAYS, null)); assertEquals("{\"num\":null}", mapper.writeValueAsString(nullValues)); } } JsonIncludeTest.java000066400000000000000000000247401325620701100365100ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * Unit tests for checking that alternative settings for * {@link JsonSerialize#include} annotation property work * as expected. */ public class JsonIncludeTest extends BaseMapTest { static class SimpleBean { public String getA() { return "a"; } public String getB() { return null; } } @JsonInclude(JsonInclude.Include.ALWAYS) // just to ensure default static class NoNullsBean { @JsonInclude(JsonInclude.Include.NON_NULL) public String getA() { return null; } public String getB() { return null; } } @JsonInclude(JsonInclude.Include.NON_DEFAULT) static class NonDefaultBean { String _a = "a", _b = "b"; NonDefaultBean() { } public String getA() { return _a; } public String getB() { return _b; } } // [databind#998]: Do not require no-arg constructor; but if not, defaults check // has weaker interpretation @JsonPropertyOrder({ "x", "y", "z" }) @JsonInclude(JsonInclude.Include.NON_DEFAULT) static class NonDefaultBeanXYZ { public int x; public int y = 3; public int z = 7; NonDefaultBeanXYZ(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } } @JsonInclude(JsonInclude.Include.NON_DEFAULT) static class MixedBean { String _a = "a", _b = "b"; MixedBean() { } public String getA() { return _a; } @JsonInclude(JsonInclude.Include.NON_NULL) public String getB() { return _b; } } // to ensure that default values work for collections as well @JsonInclude(JsonInclude.Include.NON_DEFAULT) static class ListBean { public List strings = new ArrayList(); } @JsonInclude(JsonInclude.Include.NON_DEFAULT) static class ArrayBean { public int[] ints = new int[] { 1, 2 }; } // Test to ensure that default exclusion works for fields too @JsonPropertyOrder({ "i1", "i2" }) static class DefaultIntBean { @JsonInclude(JsonInclude.Include.NON_DEFAULT) public int i1; @JsonInclude(JsonInclude.Include.NON_DEFAULT) public Integer i2; public DefaultIntBean(int i1, Integer i2) { this.i1 = i1; this.i2 = i2; } } static class NonEmptyString { @JsonInclude(JsonInclude.Include.NON_EMPTY) public String value; public NonEmptyString(String v) { value = v; } } static class NonEmptyInt { @JsonInclude(JsonInclude.Include.NON_EMPTY) public int value; public NonEmptyInt(int v) { value = v; } } static class NonEmptyDouble { @JsonInclude(JsonInclude.Include.NON_EMPTY) public double value; public NonEmptyDouble(double v) { value = v; } } static class NonEmpty { @JsonInclude(JsonInclude.Include.NON_EMPTY) public T value; public NonEmpty(T v) { value = v; } } static class NonEmptyDate extends NonEmpty { public NonEmptyDate(Date v) { super(v); } } static class NonEmptyCalendar extends NonEmpty { public NonEmptyCalendar(Calendar v) { super(v); } } static class NonDefault { @JsonInclude(JsonInclude.Include.NON_DEFAULT) public T value; public NonDefault(T v) { value = v; } } static class NonDefaultDate extends NonDefault { public NonDefaultDate(Date v) { super(v); } } static class NonDefaultCalendar extends NonDefault { public NonDefaultCalendar(Calendar v) { super(v); } } // [databind#1351] static class Issue1351Bean { public final String first; public final double second; public Issue1351Bean(String first, double second) { this.first = first; this.second = second; } } @JsonInclude(JsonInclude.Include.NON_DEFAULT) static abstract class Issue1351NonBeanParent { protected final int num; protected Issue1351NonBeanParent(int num) { this.num = num; } @JsonProperty("num") public int getNum() { return num; } } static class Issue1351NonBean extends Issue1351NonBeanParent { private String str; @JsonCreator public Issue1351NonBean(@JsonProperty("num") int num) { super(num); } public String getStr() { return str; } public void setStr(String str) { this.str = str; } } /* /********************************************************** /* Test methods /********************************************************** */ final private ObjectMapper MAPPER = new ObjectMapper(); public void testGlobal() throws IOException { Map result = writeAndMap(MAPPER, new SimpleBean()); assertEquals(2, result.size()); assertEquals("a", result.get("a")); assertNull(result.get("b")); assertTrue(result.containsKey("b")); } public void testNonNullByClass() throws IOException { Map result = writeAndMap(MAPPER, new NoNullsBean()); assertEquals(1, result.size()); assertFalse(result.containsKey("a")); assertNull(result.get("a")); assertTrue(result.containsKey("b")); assertNull(result.get("b")); } public void testNonDefaultByClass() throws IOException { NonDefaultBean bean = new NonDefaultBean(); // need to change one of defaults bean._a = "notA"; Map result = writeAndMap(MAPPER, bean); assertEquals(1, result.size()); assertTrue(result.containsKey("a")); assertEquals("notA", result.get("a")); assertFalse(result.containsKey("b")); assertNull(result.get("b")); } // [databind#998] public void testNonDefaultByClassNoCtor() throws IOException { NonDefaultBeanXYZ bean = new NonDefaultBeanXYZ(1, 2, 0); String json = MAPPER.writeValueAsString(bean); assertEquals(aposToQuotes("{'x':1,'y':2}"), json); } public void testMixedMethod() throws IOException { MixedBean bean = new MixedBean(); bean._a = "xyz"; bean._b = null; Map result = writeAndMap(MAPPER, bean); assertEquals(1, result.size()); assertEquals("xyz", result.get("a")); assertFalse(result.containsKey("b")); bean._a = "a"; bean._b = "b"; result = writeAndMap(MAPPER, bean); assertEquals(1, result.size()); assertEquals("b", result.get("b")); assertFalse(result.containsKey("a")); } public void testDefaultForEmptyList() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new ListBean())); } // NON_DEFAULT shoud work for arrays too public void testNonEmptyDefaultArray() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new ArrayBean())); } public void testDefaultForIntegers() throws IOException { assertEquals("{}", MAPPER.writeValueAsString(new DefaultIntBean(0, Integer.valueOf(0)))); assertEquals("{\"i2\":1}", MAPPER.writeValueAsString(new DefaultIntBean(0, Integer.valueOf(1)))); assertEquals("{\"i1\":3}", MAPPER.writeValueAsString(new DefaultIntBean(3, Integer.valueOf(0)))); } public void testEmptyInclusionScalars() throws IOException { ObjectMapper defMapper = MAPPER; ObjectMapper inclMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_EMPTY); // First, Strings StringWrapper str = new StringWrapper(""); assertEquals("{\"str\":\"\"}", defMapper.writeValueAsString(str)); assertEquals("{}", inclMapper.writeValueAsString(str)); assertEquals("{}", inclMapper.writeValueAsString(new StringWrapper())); assertEquals("{\"value\":\"x\"}", defMapper.writeValueAsString(new NonEmptyString("x"))); assertEquals("{}", defMapper.writeValueAsString(new NonEmptyString(""))); // Then numbers // 11-Nov-2015, tatu: As of Jackson 2.7, scalars should NOT be considered empty, // except for wrappers if they are `null` assertEquals("{\"value\":12}", defMapper.writeValueAsString(new NonEmptyInt(12))); assertEquals("{\"value\":0}", defMapper.writeValueAsString(new NonEmptyInt(0))); assertEquals("{\"value\":1.25}", defMapper.writeValueAsString(new NonEmptyDouble(1.25))); assertEquals("{\"value\":0.0}", defMapper.writeValueAsString(new NonEmptyDouble(0.0))); IntWrapper zero = new IntWrapper(0); assertEquals("{\"i\":0}", defMapper.writeValueAsString(zero)); assertEquals("{\"i\":0}", inclMapper.writeValueAsString(zero)); } // [databind#1351], [databind#1417] public void testIssue1351() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); assertEquals(aposToQuotes("{}"), mapper.writeValueAsString(new Issue1351Bean(null, (double) 0))); // [databind#1417] assertEquals(aposToQuotes("{}"), mapper.writeValueAsString(new Issue1351NonBean(0))); } // [databind#1550] public void testInclusionOfDate() throws Exception { final Date input = new Date(0L); assertEquals(aposToQuotes("{'value':0}"), MAPPER.writeValueAsString(new NonEmptyDate(input))); assertEquals("{}", MAPPER.writeValueAsString(new NonDefaultDate(input))); } // [databind#1550] public void testInclusionOfCalendar() throws Exception { final Calendar input = new GregorianCalendar(); input.setTimeInMillis(0L); assertEquals(aposToQuotes("{'value':0}"), MAPPER.writeValueAsString(new NonEmptyCalendar(input))); assertEquals("{}", MAPPER.writeValueAsString(new NonDefaultCalendar(input))); } } MapInclusionTest.java000066400000000000000000000052461325620701100366740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; public class MapInclusionTest extends BaseMapTest { static class NoEmptiesMapContainer { @JsonInclude(value=JsonInclude.Include.NON_EMPTY, content=JsonInclude.Include.NON_EMPTY) public Map stuff = new LinkedHashMap(); public NoEmptiesMapContainer add(String key, String value) { stuff.put(key, value); return this; } } static class NoNullsMapContainer { @JsonInclude(value=JsonInclude.Include.NON_NULL, content=JsonInclude.Include.NON_NULL) public Map stuff = new LinkedHashMap(); public NoNullsMapContainer add(String key, String value) { stuff.put(key, value); return this; } } static class NoNullsNotEmptyMapContainer { @JsonInclude(value=JsonInclude.Include.NON_EMPTY, content=JsonInclude.Include.NON_NULL) public Map stuff = new LinkedHashMap(); public NoNullsNotEmptyMapContainer add(String key, String value) { stuff.put(key, value); return this; } } /* /********************************************************** /* Test methods /********************************************************** */ final private ObjectMapper MAPPER = objectMapper(); // [databind#588] public void testNonEmptyValueMapViaProp() throws IOException { String json = MAPPER.writeValueAsString(new NoEmptiesMapContainer() .add("a", null) .add("b", "")); assertEquals(aposToQuotes("{}"), json); } public void testNoNullsMap() throws IOException { NoNullsMapContainer input = new NoNullsMapContainer() .add("a", null) .add("b", ""); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'stuff':{'b':''}}"), json); } public void testNonEmptyNoNullsMap() throws IOException { NoNullsNotEmptyMapContainer input = new NoNullsNotEmptyMapContainer() .add("a", null) .add("b", ""); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'stuff':{'b':''}}"), json); json = MAPPER.writeValueAsString(new NoNullsNotEmptyMapContainer() .add("a", null) .add("b", null)); assertEquals(aposToQuotes("{}"), json); } } NullSerializationTest.java000066400000000000000000000075071325620701100377450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.io.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider; import com.fasterxml.jackson.databind.ser.SerializerFactory; public class NullSerializationTest extends BaseMapTest { static class NullSerializer extends JsonSerializer { @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeString("foobar"); } } static class Bean1 { public String name = null; } static class Bean2 { public String type = null; } @SuppressWarnings("serial") static class MyNullProvider extends DefaultSerializerProvider { public MyNullProvider() { super(); } public MyNullProvider(MyNullProvider base, SerializationConfig config, SerializerFactory jsf) { super(base, config, jsf); } // not really a proper impl, but has to do @Override public DefaultSerializerProvider copy() { return this; } @Override public DefaultSerializerProvider createInstance(SerializationConfig config, SerializerFactory jsf) { return new MyNullProvider(this, config, jsf); } @Override public JsonSerializer findNullValueSerializer(BeanProperty property) throws JsonMappingException { if ("name".equals(property.getName())) { return new NullSerializer(); } return super.findNullValueSerializer(property); } } static class BeanWithNullProps { @JsonSerialize(nullsUsing=NullSerializer.class) public String a = null; } /* @JsonSerialize(nullsUsing=NullSerializer.class) static class NullValuedType { } */ /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testSimple() throws Exception { assertEquals("null", MAPPER.writeValueAsString(null)); } public void testOverriddenDefaultNulls() throws Exception { DefaultSerializerProvider sp = new DefaultSerializerProvider.Impl(); sp.setNullValueSerializer(new NullSerializer()); ObjectMapper m = new ObjectMapper(); m.setSerializerProvider(sp); assertEquals("\"foobar\"", m.writeValueAsString(null)); } public void testCustomNulls() throws Exception { ObjectMapper m = new ObjectMapper(); m.setSerializerProvider(new MyNullProvider()); assertEquals("{\"name\":\"foobar\"}", m.writeValueAsString(new Bean1())); assertEquals("{\"type\":null}", m.writeValueAsString(new Bean2())); } // #281 public void testCustomNullForTrees() throws Exception { ObjectNode root = MAPPER.createObjectNode(); root.putNull("a"); // by default, null is... well, null assertEquals("{\"a\":null}", MAPPER.writeValueAsString(root)); // but then we can customize it: DefaultSerializerProvider prov = new MyNullProvider(); prov.setNullValueSerializer(new NullSerializer()); ObjectMapper m = new ObjectMapper(); m.setSerializerProvider(prov); assertEquals("{\"a\":\"foobar\"}", m.writeValueAsString(root)); } public void testNullSerializerForProperty() throws Exception { assertEquals("{\"a\":\"foobar\"}", MAPPER.writeValueAsString(new BeanWithNullProps())); } } TestAnyGetterFiltering.java000066400000000000000000000070351325620701100400370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.PropertyWriter; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; /** * Unit tests for ensuring that entries accessible via "any filter" * can also be filtered with JSON Filter functionality. */ public class TestAnyGetterFiltering extends BaseMapTest { @JsonFilter("anyFilter") public static class AnyBean { private Map properties = new HashMap(); { properties.put("a", "1"); properties.put("b", "2"); } @JsonAnyGetter public Map anyProperties() { return properties; } } public static class AnyBeanWithIgnores { private Map properties = new LinkedHashMap(); { properties.put("a", "1"); properties.put("bogus", "2"); properties.put("b", "3"); } @JsonAnyGetter @JsonIgnoreProperties({ "bogus" }) public Map anyProperties() { return properties; } } // [databind#1655] @JsonFilter("CustomFilter") static class OuterObject { public int getExplicitProperty() { return 42; } @JsonAnyGetter public Map getAny() { Map extra = new HashMap<>(); extra.put("dynamicProperty", "I will not serialize"); return extra; } } static class CustomFilter extends SimpleBeanPropertyFilter { @Override public void serializeAsField(Object pojo, JsonGenerator gen, SerializerProvider provider, PropertyWriter writer) throws Exception { if (pojo instanceof OuterObject) { writer.serializeAsField(pojo, gen, provider); } } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testAnyGetterFiltering() throws Exception { FilterProvider prov = new SimpleFilterProvider().addFilter("anyFilter", SimpleBeanPropertyFilter.filterOutAllExcept("b")); assertEquals("{\"b\":\"2\"}", MAPPER.writer(prov).writeValueAsString(new AnyBean())); } // for [databind#1142] public void testAnyGetterIgnore() throws Exception { assertEquals(aposToQuotes("{'a':'1','b':'3'}"), MAPPER.writeValueAsString(new AnyBeanWithIgnores())); } // [databind#1655] public void testAnyGetterPojo1655() throws Exception { FilterProvider filters = new SimpleFilterProvider().addFilter("CustomFilter", new CustomFilter()); String json = MAPPER.writer(filters).writeValueAsString(new OuterObject()); Map stuff = MAPPER.readValue(json, Map.class); if (stuff.size() != 2) { fail("Should have 2 properties, got: "+stuff); } } } TestIgnoredTypes.java000066400000000000000000000071711325620701100367060ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; /** * Test for type-based ignoral, both via annotations (JsonIgnoreType) * and "config overrides" (2.8 and above). */ public class TestIgnoredTypes extends BaseMapTest { @JsonIgnoreType class IgnoredType { // note: non-static, can't be deserialized public IgnoredType(IgnoredType src) { } } @JsonIgnoreType(false) static class NonIgnoredType { public int value = 13; public IgnoredType ignored; } // // And test for mix-in annotations @JsonIgnoreType static class Person { public String name; public Person() { } public Person(String name) { this.name = name; } } static class PersonWrapper { public int value = 1; public Person person = new Person("Foo"); } @JsonIgnoreType static abstract class PersonMixin { } static class Wrapper { public int value = 3; public Wrapped wrapped = new Wrapped(7); } static class Wrapped { public int x; // make default ctor fail public Wrapped() { throw new RuntimeException("Should not be called"); } public Wrapped(int x0) { x = x0; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testIgnoredType() throws Exception { final ObjectMapper mapper = objectMapper(); // First: should be ok in general, even though couldn't build deserializer (due to non-static inner class): NonIgnoredType bean = mapper.readValue("{\"value\":13}", NonIgnoredType.class); assertNotNull(bean); assertEquals(13, bean.value); // And also ok to see something with that value; will just get ignored bean = mapper.readValue("{ \"ignored\":[1,2,{}], \"value\":9 }", NonIgnoredType.class); assertNotNull(bean); assertEquals(9, bean.value); } public void testSingleWithMixins() throws Exception { SimpleModule module = new SimpleModule(); module.setMixInAnnotation(Person.class, PersonMixin.class); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(module); PersonWrapper input = new PersonWrapper(); String json = mapper.writeValueAsString(input); assertEquals("{\"value\":1}", json); } public void testListWithMixins() throws Exception { SimpleModule module = new SimpleModule(); module.setMixInAnnotation(Person.class, PersonMixin.class); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(module); List persons = new ArrayList(); persons.add(new Person("Bob")); String json = mapper.writeValueAsString(persons); assertEquals("[{\"name\":\"Bob\"}]", json); } public void testIgnoreUsingConfigOverride() throws Exception { final ObjectMapper mapper = objectMapper(); mapper.configOverride(Wrapped.class).setIsIgnoredType(true); // serialize , first String json = mapper.writeValueAsString(new Wrapper()); assertEquals(aposToQuotes("{'value':3}"), json); // then deserialize Wrapper result = mapper.readValue(aposToQuotes("{'value':5,'wrapped':false}"), Wrapper.class); assertEquals(5, result.value); } } TestJsonFilter.java000066400000000000000000000155501325620701100363510ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonStreamContext; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.PropertyWriter; import com.fasterxml.jackson.databind.ser.impl.*; /** * Tests for verifying that bean property filtering using JsonFilter * works as expected. */ public class TestJsonFilter extends BaseMapTest { @JsonFilter("RootFilter") @JsonPropertyOrder({ "a", "b" }) static class Bean { public String a = "a"; public String b = "b"; } @JsonFilter("checkSiblingContextFilter") static class CheckSiblingContextBean { public A a = new A(); public B b = new B(); @JsonFilter("checkSiblingContextFilter") static class A { } @JsonFilter("checkSiblingContextFilter") static class B { public C c = new C(); @JsonFilter("checkSiblingContextFilter") static class C { } } } static class CheckSiblingContextFilter extends SimpleBeanPropertyFilter { @Override public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception { JsonStreamContext sc = jgen.getOutputContext(); if (writer.getName() != null && writer.getName().equals("c")) { //This assertion is failing as sc.getParent() incorrectly returns 'a'. If you comment out the member 'a' // in the CheckSiblingContextBean, you'll see that the sc.getParent() correctly returns 'b' assertEquals("b", sc.getParent().getCurrentName()); } writer.serializeAsField(bean, jgen, prov); } } public void testCheckSiblingContextFilter() { FilterProvider prov = new SimpleFilterProvider().addFilter("checkSiblingContextFilter", new CheckSiblingContextFilter()); ObjectMapper mapper = new ObjectMapper(); mapper.setFilterProvider(prov); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); mapper.valueToTree(new CheckSiblingContextBean()); } // [Issue#89] static class Pod { protected String username; // @JsonProperty(value = "user_password") protected String userPassword; public String getUsername() { return username; } public void setUsername(String value) { this.username = value; } @JsonIgnore @JsonProperty(value = "user_password") public java.lang.String getUserPassword() { return userPassword; } @JsonProperty(value = "user_password") public void setUserPassword(String value) { this.userPassword = value; } } // [Issue#306]: JsonFilter for properties, too! @JsonPropertyOrder(alphabetic=true) static class FilteredProps { // will default to using "RootFilter", only including 'a' public Bean first = new Bean(); // but minimal includes 'b' @JsonFilter("b") public Bean second = new Bean(); } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleInclusionFilter() throws Exception { FilterProvider prov = new SimpleFilterProvider().addFilter("RootFilter", SimpleBeanPropertyFilter.filterOutAllExcept("a")); assertEquals("{\"a\":\"a\"}", MAPPER.writer(prov).writeValueAsString(new Bean())); // [JACKSON-504]: also verify it works via mapper ObjectMapper mapper = new ObjectMapper(); mapper.setFilterProvider(prov); assertEquals("{\"a\":\"a\"}", mapper.writeValueAsString(new Bean())); } public void testIncludeAllFilter() throws Exception { FilterProvider prov = new SimpleFilterProvider().addFilter("RootFilter", SimpleBeanPropertyFilter.serializeAll()); assertEquals("{\"a\":\"a\",\"b\":\"b\"}", MAPPER.writer(prov).writeValueAsString(new Bean())); } public void testSimpleExclusionFilter() throws Exception { FilterProvider prov = new SimpleFilterProvider().addFilter("RootFilter", SimpleBeanPropertyFilter.serializeAllExcept("a")); assertEquals("{\"b\":\"b\"}", MAPPER.writer(prov).writeValueAsString(new Bean())); } // should handle missing case gracefully public void testMissingFilter() throws Exception { // First: default behavior should be to throw an exception try { MAPPER.writeValueAsString(new Bean()); fail("Should have failed without configured filter"); } catch (JsonMappingException e) { // should be resolved to a MappingException (internally may be something else) verifyException(e, "Cannot resolve PropertyFilter with id 'RootFilter'"); } // but when changing behavior, should work difference SimpleFilterProvider fp = new SimpleFilterProvider().setFailOnUnknownId(false); ObjectMapper mapper = new ObjectMapper(); mapper.setFilterProvider(fp); String json = mapper.writeValueAsString(new Bean()); assertEquals("{\"a\":\"a\",\"b\":\"b\"}", json); } // defaulting, as per [JACKSON-449] public void testDefaultFilter() throws Exception { FilterProvider prov = new SimpleFilterProvider().setDefaultFilter(SimpleBeanPropertyFilter.filterOutAllExcept("b")); assertEquals("{\"b\":\"b\"}", MAPPER.writer(prov).writeValueAsString(new Bean())); } // [Issue#89] combining @JsonIgnore, @JsonProperty public void testIssue89() throws Exception { ObjectMapper mapper = new ObjectMapper(); Pod pod = new Pod(); pod.username = "Bob"; pod.userPassword = "s3cr3t!"; String json = mapper.writeValueAsString(pod); assertEquals("{\"username\":\"Bob\"}", json); Pod pod2 = mapper.readValue("{\"username\":\"Bill\",\"user_password\":\"foo!\"}", Pod.class); assertEquals("Bill", pod2.username); assertEquals("foo!", pod2.userPassword); } // Wrt [Issue#306] public void testFilterOnProperty() throws Exception { FilterProvider prov = new SimpleFilterProvider() .addFilter("RootFilter", SimpleBeanPropertyFilter.filterOutAllExcept("a")) .addFilter("b", SimpleBeanPropertyFilter.filterOutAllExcept("b")); assertEquals("{\"first\":{\"a\":\"a\"},\"second\":{\"b\":\"b\"}}", MAPPER.writer(prov).writeValueAsString(new FilteredProps())); } } TestMapFiltering.java000066400000000000000000000241671325620701100366570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.io.IOException; import java.lang.annotation.*; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JsonFilter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.*; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; import com.fasterxml.jackson.databind.ser.std.MapProperty; @SuppressWarnings("serial") public class TestMapFiltering extends BaseMapTest { @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface CustomOffset { public int value(); } @JsonFilter("filterForMaps") static class FilteredBean extends LinkedHashMap { } static class MapBean { @JsonFilter("filterX") @CustomOffset(1) public Map values; public MapBean() { values = new LinkedHashMap(); values.put("a", 1); values.put("b", 5); values.put("c", 9); } } static class MapBeanNoOffset { @JsonFilter("filterX") public Map values; public MapBeanNoOffset() { values = new LinkedHashMap(); values.put("a", 1); values.put("b", 2); values.put("c", 3); } } static class TestMapFilter implements PropertyFilter { @Override public void serializeAsField(Object bean, JsonGenerator g, SerializerProvider provider, PropertyWriter writer) throws Exception { String name = writer.getName(); // sanity checks assertNotNull(writer.getType()); assertEquals(name, writer.getFullName().getSimpleName()); if (!"a".equals(name)) { return; } CustomOffset n = writer.findAnnotation(CustomOffset.class); int offset = (n == null) ? 0 : n.value(); // 12-Jun-2017, tatu: With 2.9, `value` is the surrounding POJO, so // need to do casting MapProperty prop = (MapProperty) writer; Integer old = (Integer) prop.getValue(); prop.setValue(Integer.valueOf(offset + old.intValue())); writer.serializeAsField(bean, g, provider); } @Override public void serializeAsElement(Object elementValue, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception { // not needed for testing } @Override @Deprecated public void depositSchemaProperty(PropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException { } @Override public void depositSchemaProperty(PropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException { } } // [databind#527] static class NoNullValuesMapContainer { @JsonInclude(content=JsonInclude.Include.NON_NULL) public Map stuff = new LinkedHashMap(); public NoNullValuesMapContainer add(String key, String value) { stuff.put(key, value); return this; } } // [databind#527] @JsonInclude(content=JsonInclude.Include.NON_NULL) static class NoNullsStringMap extends LinkedHashMap { public NoNullsStringMap add(String key, String value) { put(key, value); return this; } } // [databind#527] @JsonInclude(content=JsonInclude.Include.NON_ABSENT) static class NoAbsentStringMap extends LinkedHashMap> { public NoAbsentStringMap add(String key, Object value) { put(key, new AtomicReference(value)); return this; } } // [databind#527] @JsonInclude(content=JsonInclude.Include.NON_EMPTY) static class NoEmptyStringsMap extends LinkedHashMap { public NoEmptyStringsMap add(String key, String value) { put(key, value); return this; } } // [databind#497]: both Map AND contents excluded if empty static class Wrapper497 { @JsonInclude(content=JsonInclude.Include.NON_EMPTY, value=JsonInclude.Include.NON_EMPTY) public StringMap497 values; public Wrapper497(StringMap497 v) { values = v; } } static class StringMap497 extends LinkedHashMap { public StringMap497 add(String key, String value) { put(key, value); return this; } } /* /********************************************************** /* Unit tests /********************************************************** */ final ObjectMapper MAPPER = objectMapper(); public void testMapFilteringViaProps() throws Exception { FilterProvider prov = new SimpleFilterProvider().addFilter("filterX", SimpleBeanPropertyFilter.filterOutAllExcept("b")); String json = MAPPER.writer(prov).writeValueAsString(new MapBean()); assertEquals(aposToQuotes("{'values':{'b':5}}"), json); } public void testMapFilteringViaClass() throws Exception { FilteredBean bean = new FilteredBean(); bean.put("a", 4); bean.put("b", 3); FilterProvider prov = new SimpleFilterProvider().addFilter("filterForMaps", SimpleBeanPropertyFilter.filterOutAllExcept("b")); String json = MAPPER.writer(prov).writeValueAsString(bean); assertEquals(aposToQuotes("{'b':3}"), json); } // [databind#527] public void testNonNullValueMapViaProp() throws IOException { String json = MAPPER.writeValueAsString(new NoNullValuesMapContainer() .add("a", "foo") .add("b", null) .add("c", "bar")); assertEquals(aposToQuotes("{'stuff':{'a':'foo','c':'bar'}}"), json); } // [databind#522] public void testMapFilteringWithAnnotations() throws Exception { FilterProvider prov = new SimpleFilterProvider().addFilter("filterX", new TestMapFilter()); String json = MAPPER.writer(prov).writeValueAsString(new MapBean()); // a=1 should become a=2 assertEquals(aposToQuotes("{'values':{'a':2}}"), json); // and then one without annotation as contrast json = MAPPER.writer(prov).writeValueAsString(new MapBeanNoOffset()); assertEquals(aposToQuotes("{'values':{'a':1}}"), json); } // [databind#527] public void testMapNonNullValue() throws IOException { String json = MAPPER.writeValueAsString(new NoNullsStringMap() .add("a", "foo") .add("b", null) .add("c", "bar")); assertEquals(aposToQuotes("{'a':'foo','c':'bar'}"), json); } // [databind#527] public void testMapNonEmptyValue() throws IOException { String json = MAPPER.writeValueAsString(new NoEmptyStringsMap() .add("a", "foo") .add("b", "bar") .add("c", "")); assertEquals(aposToQuotes("{'a':'foo','b':'bar'}"), json); } // Test to ensure absent content of AtomicReference handled properly // [databind#527] public void testMapAbsentValue() throws IOException { String json = MAPPER.writeValueAsString(new NoAbsentStringMap() .add("a", "foo") .add("b", null)); assertEquals(aposToQuotes("{'a':'foo'}"), json); } @SuppressWarnings("deprecation") public void testMapNullSerialization() throws IOException { ObjectMapper m = new ObjectMapper(); Map map = new HashMap(); map.put("a", null); // by default, should output null-valued entries: assertEquals("{\"a\":null}", m.writeValueAsString(map)); // but not if explicitly asked not to (note: config value is dynamic here) m = new ObjectMapper(); m.disable(SerializationFeature.WRITE_NULL_MAP_VALUES); assertEquals("{}", m.writeValueAsString(map)); } // [databind#527] public void testMapWithOnlyEmptyValues() throws IOException { String json; // First, non empty: json = MAPPER.writeValueAsString(new Wrapper497(new StringMap497() .add("a", "123"))); assertEquals(aposToQuotes("{'values':{'a':'123'}}"), json); // then empty json = MAPPER.writeValueAsString(new Wrapper497(new StringMap497() .add("a", "") .add("b", null))); assertEquals(aposToQuotes("{}"), json); } public void testMapViaGlobalNonEmpty() throws Exception { // basic Map subclass: ObjectMapper mapper = new ObjectMapper(); mapper.setDefaultPropertyInclusion(JsonInclude.Value.empty() .withContentInclusion(JsonInclude.Include.NON_EMPTY)); assertEquals(aposToQuotes("{'a':'b'}"), mapper.writeValueAsString( new StringMap497() .add("x", "") .add("a", "b") )); } public void testMapViaTypeOverride() throws Exception { // basic Map subclass: ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(Map.class) .setInclude(JsonInclude.Value.empty() .withContentInclusion(JsonInclude.Include.NON_EMPTY)); assertEquals(aposToQuotes("{'a':'b'}"), mapper.writeValueAsString( new StringMap497() .add("foo", "") .add("a", "b") )); } } TestSimpleSerializationIgnore.java000066400000000000000000000064611325620701100414260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/filterpackage com.fasterxml.jackson.databind.ser.filter; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * This unit test suite tests use of {@link JsonIgnore} annotations * with bean serialization; as well as {@link JsonIgnoreType}. */ public class TestSimpleSerializationIgnore extends BaseMapTest { // Class for testing enabled {@link JsonIgnore} annotation final static class SizeClassEnabledIgnore { @JsonIgnore public int getY() { return 9; } // note: must be public to be seen public int getX() { return 1; } @JsonIgnore public int getY2() { return 1; } @JsonIgnore public int getY3() { return 2; } } // Class for testing disabled {@link JsonIgnore} annotation final static class SizeClassDisabledIgnore { // note: must be public to be seen public int getX() { return 3; } @JsonIgnore(false) public int getY() { return 4; } } static class BaseClassIgnore { @JsonProperty("x") @JsonIgnore public int x() { return 1; } public int getY() { return 2; } } static class SubClassNonIgnore extends BaseClassIgnore { /* Annotations to disable ignorance, in sub-class; note that * we must still get "JsonProperty" fro super class */ @Override @JsonIgnore(false) public int x() { return 3; } } @JsonIgnoreType static class IgnoredType { } @JsonIgnoreType(false) static class NonIgnoredType { public int value = 13; public IgnoredType ignored = new IgnoredType(); } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleIgnore() throws Exception { // Should see "x", not "y" Map result = writeAndMap(MAPPER, new SizeClassEnabledIgnore()); assertEquals(1, result.size()); assertEquals(Integer.valueOf(1), result.get("x")); assertNull(result.get("y")); } public void testDisabledIgnore() throws Exception { // Should see "x" and "y" Map result = writeAndMap(MAPPER, new SizeClassDisabledIgnore()); assertEquals(2, result.size()); assertEquals(Integer.valueOf(3), result.get("x")); assertEquals(Integer.valueOf(4), result.get("y")); } /** * Test case to verify that ignore tag can also be disabled * via inheritance */ public void testIgnoreOver() throws Exception { // should only see "y" Map result = writeAndMap(MAPPER, new BaseClassIgnore()); assertEquals(1, result.size()); assertEquals(Integer.valueOf(2), result.get("y")); // Should see "x" and "y" result = writeAndMap(MAPPER, new SubClassNonIgnore()); assertEquals(2, result.size()); assertEquals(Integer.valueOf(3), result.get("x")); assertEquals(Integer.valueOf(2), result.get("y")); } public void testIgnoreType() throws Exception { assertEquals("{\"value\":13}", MAPPER.writeValueAsString(new NonIgnoredType())); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/jdk/000077500000000000000000000000001325620701100321235ustar00rootroot00000000000000AtomicTypeSerializationTest.java000066400000000000000000000113141325620701100403630ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/jdkpackage com.fasterxml.jackson.databind.ser.jdk; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.atomic.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * Unit tests for verifying serialization of {@link java.util.concurrent.atomic.AtomicReference} * and other atomic types, via various settings. */ public class AtomicTypeSerializationTest extends BaseMapTest { static class UCStringWrapper { @JsonSerialize(contentUsing=UpperCasingSerializer.class) public AtomicReference value; public UCStringWrapper(String s) { value = new AtomicReference(s); } } // [datatypes-java8#17] @JsonPropertyOrder({ "date1", "date2", "date" }) static class ContextualOptionals { public AtomicReference date; @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy+MM+dd") public AtomicReference date1; @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy*MM*dd") public AtomicReference date2; } // [databind#1673] static class ContainerA { public AtomicReference strategy = new AtomicReference<>((Strategy) new Foo(42)); } static class ContainerB { public AtomicReference> strategy; { List list = new ArrayList<>(); list.add(new Foo(42)); strategy = new AtomicReference<>(list); } } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(name = "Foo", value = Foo.class) }) interface Strategy { } static class Foo implements Strategy { public int foo; @JsonCreator Foo(@JsonProperty("foo") int foo) { this.foo = foo; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testAtomicBoolean() throws Exception { assertEquals("true", MAPPER.writeValueAsString(new AtomicBoolean(true))); assertEquals("false", MAPPER.writeValueAsString(new AtomicBoolean(false))); } public void testAtomicInteger() throws Exception { assertEquals("1", MAPPER.writeValueAsString(new AtomicInteger(1))); assertEquals("-9", MAPPER.writeValueAsString(new AtomicInteger(-9))); } public void testAtomicLong() throws Exception { assertEquals("0", MAPPER.writeValueAsString(new AtomicLong(0))); } public void testAtomicReference() throws Exception { String[] strs = new String[] { "abc" }; assertEquals("[\"abc\"]", MAPPER.writeValueAsString(new AtomicReference(strs))); } public void testCustomSerializer() throws Exception { final String VALUE = "fooBAR"; String json = MAPPER.writeValueAsString(new UCStringWrapper(VALUE)); assertEquals(json, aposToQuotes("{'value':'FOOBAR'}")); } public void testContextualAtomicReference() throws Exception { SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd"); df.setTimeZone(TimeZone.getTimeZone("UTC")); final ObjectMapper mapper = objectMapper(); mapper.setDateFormat(df); ContextualOptionals input = new ContextualOptionals(); input.date = new AtomicReference<>(new Date(0L)); input.date1 = new AtomicReference<>(new Date(0L)); input.date2 = new AtomicReference<>(new Date(0L)); final String json = mapper.writeValueAsString(input); assertEquals(aposToQuotes( "{'date1':'1970+01+01','date2':'1970*01*01','date':'1970/01/01'}"), json); } // [databind#1673] public void testPolymorphicReferenceSimple() throws Exception { final String EXPECTED = "{\"type\":\"Foo\",\"foo\":42}"; String json = MAPPER.writeValueAsString(new ContainerA()); assertEquals("{\"strategy\":" + EXPECTED + "}", json); } // [databind#1673] public void testPolymorphicReferenceListOf() throws Exception { final String EXPECTED = "{\"type\":\"Foo\",\"foo\":42}"; // Reproduction of issue seen with scala.Option and java8 Optional types: // https://github.com/FasterXML/jackson-module-scala/issues/346#issuecomment-336483326 String json = MAPPER.writeValueAsString(new ContainerB()); assertEquals("{\"strategy\":[" + EXPECTED + "]}", json); } } CollectionSerializationTest.java000066400000000000000000000225661325620701100404130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/jdkpackage com.fasterxml.jackson.databind.ser.jdk; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class CollectionSerializationTest extends BaseMapTest { enum Key { A, B, C }; // Field-based simple bean with a single property, "values" final static class CollectionBean { @JsonProperty // not required public Collection values; public CollectionBean(Collection c) { values = c; } } static class EnumMapBean { EnumMap _map; public EnumMapBean(EnumMap m) { _map = m; } public EnumMap getMap() { return _map; } } /** * Class needed for testing [JACKSON-220] */ @SuppressWarnings("serial") @JsonSerialize(using=ListSerializer.class) static class PseudoList extends ArrayList { public PseudoList(String... values) { super(Arrays.asList(values)); } } static class ListSerializer extends JsonSerializer> { @Override public void serialize(List value, JsonGenerator gen, SerializerProvider provider) throws IOException { // just use standard List.toString(), output as JSON String gen.writeString(value.toString()); } } // for [JACKSON-254], suppression of empty collections static class EmptyListBean { public List empty = new ArrayList(); } static class EmptyArrayBean { public String[] empty = new String[0]; } static class StaticListWrapper { protected List list; public StaticListWrapper(String ... v) { list = new ArrayList(Arrays.asList(v)); } protected StaticListWrapper() { } public List getList( ) { return list; } public void setList(List l) { list = l; } } /* /********************************************************** /* Test methods /********************************************************** */ private final static ObjectMapper MAPPER = new ObjectMapper(); public void testCollections() throws IOException { // Let's try different collections, arrays etc final int entryLen = 98; for (int type = 0; type < 4; ++type) { Object value; if (type == 0) { // first, array int[] ints = new int[entryLen]; for (int i = 0; i < entryLen; ++i) { ints[i] = Integer.valueOf(i); } value = ints; } else { Collection c; switch (type) { case 1: c = new LinkedList(); break; case 2: c = new TreeSet(); // has to be ordered break; default: c = new ArrayList(); break; } for (int i = 0; i < entryLen; ++i) { c.add(Integer.valueOf(i)); } value = c; } String json = MAPPER.writeValueAsString(value); // and then need to verify: JsonParser jp = new JsonFactory().createParser(json); assertToken(JsonToken.START_ARRAY, jp.nextToken()); for (int i = 0; i < entryLen; ++i) { assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertEquals(i, jp.getIntValue()); } assertToken(JsonToken.END_ARRAY, jp.nextToken()); jp.close(); } } @SuppressWarnings("resource") public void testBigCollection() throws IOException { final int COUNT = 9999; ArrayList value = new ArrayList(); for (int i = 0; i <= COUNT; ++i) { value.add(i); } // Let's test using 3 main variants... for (int mode = 0; mode < 3; ++mode) { JsonParser jp = null; switch (mode) { case 0: { byte[] data = MAPPER.writeValueAsBytes(value); jp = new JsonFactory().createParser(data); } break; case 1: { StringWriter sw = new StringWriter(value.size()); MAPPER.writeValue(sw, value); jp = createParserUsingReader(sw.toString()); } break; case 2: { String str = MAPPER.writeValueAsString(value); jp = createParserUsingReader(str); } break; } // and verify assertToken(JsonToken.START_ARRAY, jp.nextToken()); for (int i = 0; i <= COUNT; ++i) { assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertEquals(i, jp.getIntValue()); } assertToken(JsonToken.END_ARRAY, jp.nextToken()); jp.close(); } } public void testEnumMap() throws IOException { EnumMap map = new EnumMap(Key.class); map.put(Key.B, "xyz"); map.put(Key.C, "abc"); // assuming EnumMap uses enum entry order, which I think is true... String json = MAPPER.writeValueAsString(map); assertEquals("{\"B\":\"xyz\",\"C\":\"abc\"}",json.trim()); } // Test that checks that empty collections are properly serialized // when they are Bean properties @SuppressWarnings("unchecked") public void testEmptyBeanCollection() throws IOException { Collection x = new ArrayList(); x.add("foobar"); CollectionBean cb = new CollectionBean(x); Map result = writeAndMap(MAPPER, cb); assertEquals(1, result.size()); assertTrue(result.containsKey("values")); Collection x2 = (Collection) result.get("values"); assertNotNull(x2); assertEquals(x, x2); } public void testNullBeanCollection() throws IOException { CollectionBean cb = new CollectionBean(null); Map result = writeAndMap(MAPPER, cb); assertEquals(1, result.size()); assertTrue(result.containsKey("values")); assertNull(result.get("values")); } @SuppressWarnings("unchecked") public void testEmptyBeanEnumMap() throws IOException { EnumMap map = new EnumMap(Key.class); EnumMapBean b = new EnumMapBean(map); Map result = writeAndMap(MAPPER, b); assertEquals(1, result.size()); assertTrue(result.containsKey("map")); // we deserialized to untyped, not back to bean, so: Map map2 = (Map) result.get("map"); assertNotNull(map2); assertEquals(0, map2.size()); } // Should also be able to serialize null EnumMaps as expected public void testNullBeanEnumMap() throws IOException { EnumMapBean b = new EnumMapBean(null); Map result = writeAndMap(MAPPER, b); assertEquals(1, result.size()); assertTrue(result.containsKey("map")); assertNull(result.get("map")); } public void testListSerializer() throws IOException { assertEquals(quote("[ab, cd, ef]"), MAPPER.writeValueAsString(new PseudoList("ab", "cd", "ef"))); assertEquals(quote("[]"), MAPPER.writeValueAsString(new PseudoList())); } @SuppressWarnings("deprecation") public void testEmptyListOrArray() throws IOException { // by default, empty lists serialized normally EmptyListBean list = new EmptyListBean(); EmptyArrayBean array = new EmptyArrayBean(); assertTrue(MAPPER.isEnabled(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS)); assertEquals("{\"empty\":[]}", MAPPER.writeValueAsString(list)); assertEquals("{\"empty\":[]}", MAPPER.writeValueAsString(array)); // note: value of setting may be cached when constructing serializer, need a new instance ObjectMapper m = new ObjectMapper(); m.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false); assertEquals("{}", m.writeValueAsString(list)); assertEquals("{}", m.writeValueAsString(array)); } public void testStaticList() throws IOException { // First: au naturel StaticListWrapper w = new StaticListWrapper("a", "b", "c"); String json = MAPPER.writeValueAsString(w); assertEquals(aposToQuotes("{'list':['a','b','c']}"), json); // but then with default typing ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(DefaultTyping.NON_FINAL); json = mapper.writeValueAsString(w); assertEquals(aposToQuotes(String.format("['%s',{'list':['%s',['a','b','c']]}]", w.getClass().getName(), w.list.getClass().getName())), json); } } DateSerializationTest.java000066400000000000000000000334211325620701100371650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/jdkpackage com.fasterxml.jackson.databind.ser.jdk; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import org.junit.Assert; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.util.StdDateFormat; public class DateSerializationTest extends BaseMapTest { static class TimeZoneBean { private TimeZone tz; public TimeZoneBean(String name) { tz = TimeZone.getTimeZone(name); } public TimeZone getTz() { return tz; } } static class DateAsNumberBean { @JsonFormat(shape=JsonFormat.Shape.NUMBER) public Date date; public DateAsNumberBean(long l) { date = new java.util.Date(l); } } static class DateAsStringBean { @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd") public Date date; public DateAsStringBean(long l) { date = new java.util.Date(l); } } static class DateAsDefaultStringBean { @JsonFormat(shape=JsonFormat.Shape.STRING) public Date date; public DateAsDefaultStringBean(long l) { date = new java.util.Date(l); } } static class DateInCETBean { @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd,HH:00", timezone="CET") public Date date; public DateInCETBean(long l) { date = new java.util.Date(l); } } static class CalendarAsStringBean { @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd") public Calendar value; public CalendarAsStringBean(long l) { value = new GregorianCalendar(); value.setTimeInMillis(l); } } static class DateAsDefaultBean { public Date date; public DateAsDefaultBean(long l) { date = new java.util.Date(l); } } static class DateAsDefaultBeanWithEmptyJsonFormat { @JsonFormat public Date date; public DateAsDefaultBeanWithEmptyJsonFormat(long l) { date = new java.util.Date(l); } } static class DateAsDefaultBeanWithPattern { @JsonFormat(pattern="yyyy-MM-dd") public Date date; public DateAsDefaultBeanWithPattern(long l) { date = new java.util.Date(l); } } static class DateAsDefaultBeanWithLocale { @JsonFormat(locale = "fr") public Date date; public DateAsDefaultBeanWithLocale(long l) { date = new java.util.Date(l); } } static class DateAsDefaultBeanWithTimezone { @JsonFormat(timezone="CET") public Date date; public DateAsDefaultBeanWithTimezone(long l) { date = new java.util.Date(l); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testDateNumeric() throws IOException { // default is to output time stamps... assertTrue(MAPPER.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)); // shouldn't matter which offset we give... String json = MAPPER.writeValueAsString(new Date(199L)); assertEquals("199", json); } public void testDateISO8601() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); serialize( mapper, judate(1970, 1, 1, 02, 00, 00, 0, "GMT+2"), "1970-01-01T00:00:00.000+0000"); serialize( mapper, judate(1970, 1, 1, 00, 00, 00, 0, "UTC"), "1970-01-01T00:00:00.000+0000"); } /** * Use a default TZ other than UTC. Dates must be serialized using that TZ. */ public void testDateISO8601_customTZ() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.setTimeZone(TimeZone.getTimeZone("GMT+2")); serialize( mapper, judate(1970, 1, 1, 00, 00, 00, 0, "GMT+2"), "1970-01-01T00:00:00.000+0200"); serialize( mapper, judate(1970, 1, 1, 00, 00, 00, 0, "UTC"), "1970-01-01T02:00:00.000+0200"); } /** * Configure the StdDateFormat to serialize TZ offset with a colon between hours and minutes * * See [databind#1744] */ public void testDateISO8601_colonInTZ() throws IOException { StdDateFormat dateFormat = new StdDateFormat(); assertFalse(dateFormat.isColonIncludedInTimeZone()); dateFormat = dateFormat.withColonInTimeZone(true); assertTrue(dateFormat.isColonIncludedInTimeZone()); ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.setDateFormat(dateFormat); serialize( mapper, judate(1970, 1, 1, 02, 00, 00, 0, "GMT+2"), "1970-01-01T00:00:00.000+00:00"); serialize( mapper, judate(1970, 1, 1, 00, 00, 00, 0, "UTC"), "1970-01-01T00:00:00.000+00:00"); } public void testDateOther() throws IOException { ObjectMapper mapper = new ObjectMapper(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss"); mapper.setDateFormat(df); mapper.setTimeZone(TimeZone.getTimeZone("PST")); // let's hit epoch start, offset by a bit serialize( mapper, judate(1970, 1, 1, 00, 00, 00, 0, "UTC"), "1969-12-31X16:00:00"); } public void testTimeZone() throws IOException { TimeZone input = TimeZone.getTimeZone("PST"); String json = MAPPER.writeValueAsString(input); assertEquals(quote("PST"), json); } public void testTimeZoneInBean() throws IOException { String json = MAPPER.writeValueAsString(new TimeZoneBean("PST")); assertEquals("{\"tz\":\"PST\"}", json); } public void testDateUsingObjectWriter() throws IOException { DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss"); TimeZone tz = TimeZone.getTimeZone("PST"); assertEquals(quote("1969-12-31X16:00:00"), MAPPER.writer(df) .with(tz) .writeValueAsString(new Date(0L))); ObjectWriter w = MAPPER.writer((DateFormat)null); assertEquals("0", w.writeValueAsString(new Date(0L))); w = w.with(df).with(tz); assertEquals(quote("1969-12-31X16:00:00"), w.writeValueAsString(new Date(0L))); w = w.with((DateFormat) null); assertEquals("0", w.writeValueAsString(new Date(0L))); } public void testDatesAsMapKeys() throws IOException { ObjectMapper mapper = new ObjectMapper(); Map map = new HashMap(); assertFalse(mapper.isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)); map.put(new Date(0L), Integer.valueOf(1)); // by default will serialize as ISO-8601 values... assertEquals("{\"1970-01-01T00:00:00.000+0000\":1}", mapper.writeValueAsString(map)); // but can change to use timestamps too mapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, true); assertEquals("{\"0\":1}", mapper.writeValueAsString(map)); } public void testDateWithJsonFormat() throws Exception { ObjectMapper mapper = new ObjectMapper(); String json; // first: test overriding writing as timestamp mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writeValueAsString(new DateAsNumberBean(0L)); assertEquals(aposToQuotes("{'date':0}"), json); // then reverse mapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writer().with(getUTCTimeZone()).writeValueAsString(new DateAsStringBean(0L)); assertEquals("{\"date\":\"1970-01-01\"}", json); // and with different DateFormat; CET is one hour ahead of GMT json = mapper.writeValueAsString(new DateInCETBean(0L)); assertEquals("{\"date\":\"1970-01-01,01:00\"}", json); // and for [Issue#423] as well: json = mapper.writer().with(getUTCTimeZone()).writeValueAsString(new CalendarAsStringBean(0L)); assertEquals("{\"value\":\"1970-01-01\"}", json); // and with default (ISO8601) format (databind#1109) json = mapper.writeValueAsString(new DateAsDefaultStringBean(0L)); assertEquals("{\"date\":\"1970-01-01T00:00:00.000+0000\"}", json); } /** * Test to ensure that setting a TimeZone _after_ dateformat should enforce * that timezone on format, regardless of TimeZone format had. */ public void testWithTimeZoneOverride() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd/HH:mm z")); mapper.setTimeZone(TimeZone.getTimeZone("PST")); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // pacific time is GMT-8; so midnight becomes 16:00 previous day: serialize( mapper, judate(1969, 12, 31, 16, 00, 00, 00, "PST"), "1969-12-31/16:00 PST"); // Let's also verify that Locale won't matter too much... mapper.setLocale(Locale.FRANCE); serialize( mapper, judate(1969, 12, 31, 16, 00, 00, 00, "PST"), "1969-12-31/16:00 PST"); // Also: should be able to dynamically change timezone: ObjectWriter w = mapper.writer(); w = w.with(TimeZone.getTimeZone("EST")); String json = w.writeValueAsString(new Date(0)); assertEquals(quote("1969-12-31/19:00 EST"), json); } /** * Test to ensure that the default shape is correctly inferred as string or numeric, * when this shape is not explicitly set with a @JsonFormat annotation */ public void testDateDefaultShape() throws Exception { ObjectMapper mapper = new ObjectMapper(); // No @JsonFormat => default to user config mapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); String json = mapper.writeValueAsString(new DateAsDefaultBean(0L)); assertEquals(aposToQuotes("{'date':0}"), json); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writeValueAsString(new DateAsDefaultBean(0L)); assertEquals(aposToQuotes("{'date':'1970-01-01T00:00:00.000+0000'}"), json); // Empty @JsonFormat => default to user config mapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writeValueAsString(new DateAsDefaultBeanWithEmptyJsonFormat(0L)); assertEquals(aposToQuotes("{'date':0}"), json); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writeValueAsString(new DateAsDefaultBeanWithEmptyJsonFormat(0L)); assertEquals(aposToQuotes("{'date':'1970-01-01T00:00:00.000+0000'}"), json); // @JsonFormat with Shape.ANY and pattern => STRING shape, regardless of user config mapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writeValueAsString(new DateAsDefaultBeanWithPattern(0L)); assertEquals(aposToQuotes("{'date':'1970-01-01'}"), json); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writeValueAsString(new DateAsDefaultBeanWithPattern(0L)); assertEquals(aposToQuotes("{'date':'1970-01-01'}"), json); // @JsonFormat with Shape.ANY and locale => STRING shape, regardless of user config mapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writeValueAsString(new DateAsDefaultBeanWithLocale(0L)); assertEquals(aposToQuotes("{'date':'1970-01-01T00:00:00.000+0000'}"), json); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writeValueAsString(new DateAsDefaultBeanWithLocale(0L)); assertEquals(aposToQuotes("{'date':'1970-01-01T00:00:00.000+0000'}"), json); // @JsonFormat with Shape.ANY and timezone => STRING shape, regardless of user config mapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writeValueAsString(new DateAsDefaultBeanWithTimezone(0L)); assertEquals(aposToQuotes("{'date':'1970-01-01T01:00:00.000+0100'}"), json); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = mapper.writeValueAsString(new DateAsDefaultBeanWithTimezone(0L)); assertEquals(aposToQuotes("{'date':'1970-01-01T01:00:00.000+0100'}"), json); } // [databind#1648]: contextual default format should be used public void testFormatWithoutPattern() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss")); String json = mapper.writeValueAsString(new DateAsDefaultBeanWithTimezone(0L)); assertEquals(aposToQuotes("{'date':'1970-01-01X01:00:00'}"), json); } private static Date judate(int year, int month, int day, int hour, int minutes, int seconds, int millis, String tz) { Calendar cal = Calendar.getInstance(); cal.set(year, month-1, day, hour, minutes, seconds); cal.set(Calendar.MILLISECOND, millis); cal.setTimeZone(TimeZone.getTimeZone(tz)); return cal.getTime(); } private void serialize(ObjectMapper mapper, Object date, String expected) throws IOException { String actual = mapper.writeValueAsString(date); Assert.assertEquals(quote(expected), actual); } } JDKTypeSerializationTest.java000066400000000000000000000156061325620701100375670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/jdkpackage com.fasterxml.jackson.databind.ser.jdk; import java.io.*; import java.math.BigDecimal; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.*; import java.util.regex.Pattern; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; /** * Unit tests for JDK types not covered by other tests (i.e. things * that are not Enums, Collections, Maps, or standard Date/Time types) */ public class JDKTypeSerializationTest extends com.fasterxml.jackson.databind.BaseMapTest { private final ObjectMapper MAPPER = objectMapper(); static class InetAddressBean { public InetAddress value; public InetAddressBean(InetAddress i) { value = i; } } public void testBigDecimal() throws Exception { Map map = new HashMap(); String PI_STR = "3.14159265"; map.put("pi", new BigDecimal(PI_STR)); String str = MAPPER.writeValueAsString(map); assertEquals("{\"pi\":3.14159265}", str); } public void testBigDecimalAsPlainString() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN); Map map = new HashMap(); String PI_STR = "3.00000000"; map.put("pi", new BigDecimal(PI_STR)); String str = mapper.writeValueAsString(map); assertEquals("{\"pi\":3.00000000}", str); } public void testFile() throws IOException { // this may get translated to different representation on Windows, maybe Mac: File f = new File(new File("/tmp"), "foo.text"); String str = MAPPER.writeValueAsString(f); // escape backslashes (for portability with windows) String escapedAbsPath = f.getAbsolutePath().replaceAll("\\\\", "\\\\\\\\"); assertEquals(quote(escapedAbsPath), str); } public void testRegexps() throws IOException { final String PATTERN_STR = "\\s+([a-b]+)\\w?"; Pattern p = Pattern.compile(PATTERN_STR); Map input = new HashMap(); input.put("p", p); Map result = writeAndMap(MAPPER, input); assertEquals(p.pattern(), result.get("p")); } public void testCurrency() throws IOException { Currency usd = Currency.getInstance("USD"); assertEquals(quote("USD"), MAPPER.writeValueAsString(usd)); } public void testLocale() throws IOException { assertEquals(quote("en"), MAPPER.writeValueAsString(new Locale("en"))); assertEquals(quote("es_ES"), MAPPER.writeValueAsString(new Locale("es", "ES"))); assertEquals(quote("fi_FI_savo"), MAPPER.writeValueAsString(new Locale("FI", "fi", "savo"))); assertEquals(quote("en_US"), MAPPER.writeValueAsString(Locale.US)); // [databind#1123] assertEquals(quote(""), MAPPER.writeValueAsString(Locale.ROOT)); } public void testInetAddress() throws IOException { assertEquals(quote("127.0.0.1"), MAPPER.writeValueAsString(InetAddress.getByName("127.0.0.1"))); InetAddress input = InetAddress.getByName("google.com"); assertEquals(quote("google.com"), MAPPER.writeValueAsString(input)); ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(InetAddress.class) .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.NUMBER)); String json = mapper.writeValueAsString(input); assertEquals(quote(input.getHostAddress()), json); assertEquals(String.format("{\"value\":\"%s\"}", input.getHostAddress()), mapper.writeValueAsString(new InetAddressBean(input))); } public void testInetSocketAddress() throws IOException { assertEquals(quote("127.0.0.1:8080"), MAPPER.writeValueAsString(new InetSocketAddress("127.0.0.1", 8080))); assertEquals(quote("google.com:6667"), MAPPER.writeValueAsString(new InetSocketAddress("google.com", 6667))); assertEquals(quote("[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443"), MAPPER.writeValueAsString(new InetSocketAddress("2001:db8:85a3:8d3:1319:8a2e:370:7348", 443))); } // [JACKSON-597] public void testClass() throws IOException { assertEquals(quote("java.lang.String"), MAPPER.writeValueAsString(String.class)); assertEquals(quote("int"), MAPPER.writeValueAsString(Integer.TYPE)); assertEquals(quote("boolean"), MAPPER.writeValueAsString(Boolean.TYPE)); assertEquals(quote("void"), MAPPER.writeValueAsString(Void.TYPE)); } // [JACKSON-789] public void testCharset() throws IOException { assertEquals(quote("UTF-8"), MAPPER.writeValueAsString(Charset.forName("UTF-8"))); } // [Issue#239]: Support serialization of ByteBuffer public void testByteBuffer() throws IOException { final byte[] INPUT_BYTES = new byte[] { 1, 2, 3, 4, 5 }; String exp = MAPPER.writeValueAsString(INPUT_BYTES); ByteBuffer bbuf = ByteBuffer.wrap(INPUT_BYTES); assertEquals(exp, MAPPER.writeValueAsString(bbuf)); // so far so good, but must ensure Native buffers also work: ByteBuffer bbuf2 = ByteBuffer.allocateDirect(5); bbuf2.put(INPUT_BYTES); assertEquals(exp, MAPPER.writeValueAsString(bbuf2)); } // Verify that efficient UUID codec won't mess things up: public void testUUIDs() throws IOException { // first, couple of generated UUIDs: for (String value : new String[] { "76e6d183-5f68-4afa-b94a-922c1fdb83f8", "540a88d1-e2d8-4fb1-9396-9212280d0a7f", "2c9e441d-1cd0-472d-9bab-69838f877574", "591b2869-146e-41d7-8048-e8131f1fdec5", "82994ac2-7b23-49f2-8cc5-e24cf6ed77be", "00000007-0000-0000-0000-000000000000" }) { UUID uuid = UUID.fromString(value); String json = MAPPER.writeValueAsString(uuid); assertEquals(quote(uuid.toString()), json); // Also, wrt [#362], should convert cleanly String str = MAPPER.convertValue(uuid, String.class); assertEquals(value, str); } // then use templating; note that these are not exactly valid UUIDs // wrt spec (type bits etc), but JDK UUID should deal ok final String TEMPL = "00000000-0000-0000-0000-000000000000"; final String chars = "123456789abcdef"; for (int i = 0; i < chars.length(); ++i) { String value = TEMPL.replace('0', chars.charAt(i)); UUID uuid = UUID.fromString(value); String json = MAPPER.writeValueAsString(uuid); assertEquals(quote(uuid.toString()), json); } } } KeySerializers1679Test.java000066400000000000000000000012571325620701100370500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/jdkpackage com.fasterxml.jackson.databind.ser.jdk; import java.util.*; import com.fasterxml.jackson.databind.*; public class KeySerializers1679Test extends BaseMapTest { /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); // [databind#1679] public void testRecursion1679() throws Exception { Map objectMap = new HashMap(); objectMap.put(new Object(), "foo"); String json = MAPPER.writeValueAsString(objectMap); assertNotNull(json); } } MapKeySerializationTest.java000066400000000000000000000060241325620701100374750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/jdkpackage com.fasterxml.jackson.databind.ser.jdk; import java.io.IOException; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.core.Base64Variants; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; @SuppressWarnings("serial") public class MapKeySerializationTest extends BaseMapTest { // for [databind#47] public static class Wat { private final String wat; @JsonCreator Wat(String wat) { this.wat = wat; } @JsonValue public String getWat() { return wat; } @Override public String toString() { return "(String)[Wat: " + wat + "]"; } } static class WatMap extends HashMap { } static class DefaultKeySerializer extends JsonSerializer { @Override public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException { g.writeFieldName("DEFAULT:"+value); } } /* /********************************************************** /* Test methods /********************************************************** */ final private ObjectMapper MAPPER = objectMapper(); // [databind#47] public void testMapJsonValueKey47() throws Exception { WatMap input = new WatMap(); input.put(new Wat("3"), true); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'3':true}"), json); } // [databind#682] public void testClassKey() throws IOException { Map,Integer> map = new LinkedHashMap,Integer>(); map.put(String.class, 2); String json = MAPPER.writeValueAsString(map); assertEquals(aposToQuotes("{'java.lang.String':2}"), json); } public void testDefaultKeySerializer() throws IOException { ObjectMapper m = new ObjectMapper(); m.getSerializerProvider().setDefaultKeySerializer(new DefaultKeySerializer()); Map map = new HashMap(); map.put("a", "b"); assertEquals("{\"DEFAULT:a\":\"b\"}", m.writeValueAsString(map)); } // [databind#1552] public void testMapsWithBinaryKeys() throws Exception { byte[] binary = new byte[] { 1, 2, 3, 4, 5 }; // First, using wrapper MapWrapper input = new MapWrapper<>(binary, "stuff"); String expBase64 = Base64Variants.MIME.encode(binary); assertEquals(aposToQuotes("{'map':{'"+expBase64+"':'stuff'}}"), MAPPER.writeValueAsString(input)); // and then dynamically.. Map map = new LinkedHashMap<>(); map.put(binary, "xyz"); assertEquals(aposToQuotes("{'"+expBase64+"':'xyz'}"), MAPPER.writeValueAsString(map)); } } NumberSerTest.java000066400000000000000000000131421325620701100354520ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/jdkpackage com.fasterxml.jackson.databind.ser.jdk; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * Unit tests for verifying serialization of simple basic non-structured * types; primitives (and/or their wrappers), Strings. */ public class NumberSerTest extends BaseMapTest { private final ObjectMapper MAPPER = objectMapper(); static class IntWrapper { public int i; public IntWrapper(int value) { i = value; } } static class DoubleWrapper { public double value; public DoubleWrapper(double v) { value = v; } } static class BigDecimalWrapper { public BigDecimal value; public BigDecimalWrapper(BigDecimal v) { value = v; } } static class IntAsString { @JsonFormat(shape=JsonFormat.Shape.STRING) @JsonProperty("value") public int foo = 3; } static class LongAsString { @JsonFormat(shape=JsonFormat.Shape.STRING) public long value = 4; } static class DoubleAsString { @JsonFormat(shape=JsonFormat.Shape.STRING) public double value = -0.5; } static class BigIntegerAsString { @JsonFormat(shape=JsonFormat.Shape.STRING) public BigInteger value = BigInteger.valueOf(123456L); } static class BigDecimalAsString { @JsonFormat(shape=JsonFormat.Shape.STRING) public BigDecimal value = BigDecimal.valueOf(0.25); } static class NumberWrapper { // ensure it will use `Number` as statically force type, when looking for serializer @JsonSerialize(as=Number.class) public Number value; public NumberWrapper(Number v) { value = v; } } /* /********************************************************** /* Test methods /********************************************************** */ public void testDouble() throws Exception { double[] values = new double[] { 0.0, 1.0, 0.1, -37.01, 999.99, 0.3, 33.3, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY }; for (double d : values) { String expected = String.valueOf(d); if (Double.isNaN(d) || Double.isInfinite(d)) { expected = "\""+d+"\""; } assertEquals(expected, MAPPER.writeValueAsString(Double.valueOf(d))); } } public void testBigInteger() throws Exception { BigInteger[] values = new BigInteger[] { BigInteger.ONE, BigInteger.TEN, BigInteger.ZERO, BigInteger.valueOf(1234567890L), new BigInteger("123456789012345678901234568"), new BigInteger("-1250000124326904597090347547457") }; for (BigInteger value : values) { String expected = value.toString(); assertEquals(expected, MAPPER.writeValueAsString(value)); } } public void testNumbersAsString() throws Exception { assertEquals(aposToQuotes("{'value':'3'}"), MAPPER.writeValueAsString(new IntAsString())); assertEquals(aposToQuotes("{'value':'4'}"), MAPPER.writeValueAsString(new LongAsString())); assertEquals(aposToQuotes("{'value':'-0.5'}"), MAPPER.writeValueAsString(new DoubleAsString())); assertEquals(aposToQuotes("{'value':'0.25'}"), MAPPER.writeValueAsString(new BigDecimalAsString())); assertEquals(aposToQuotes("{'value':'123456'}"), MAPPER.writeValueAsString(new BigIntegerAsString())); } public void testConfigOverridesForNumbers() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(Integer.TYPE) // for `int` .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); mapper.configOverride(Double.TYPE) // for `double` .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); mapper.configOverride(BigDecimal.class) .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); assertEquals(aposToQuotes("{'i':'3'}"), mapper.writeValueAsString(new IntWrapper(3))); assertEquals(aposToQuotes("{'value':'0.75'}"), mapper.writeValueAsString(new DoubleWrapper(0.75))); assertEquals(aposToQuotes("{'value':'-0.5'}"), mapper.writeValueAsString(new BigDecimalWrapper(BigDecimal.valueOf(-0.5)))); } public void testNumberType() throws Exception { assertEquals(aposToQuotes("{'value':1}"), MAPPER.writeValueAsString(new NumberWrapper(Byte.valueOf((byte) 1)))); assertEquals(aposToQuotes("{'value':2}"), MAPPER.writeValueAsString(new NumberWrapper(Short.valueOf((short) 2)))); assertEquals(aposToQuotes("{'value':3}"), MAPPER.writeValueAsString(new NumberWrapper(Integer.valueOf(3)))); assertEquals(aposToQuotes("{'value':4}"), MAPPER.writeValueAsString(new NumberWrapper(Long.valueOf(4L)))); assertEquals(aposToQuotes("{'value':0.5}"), MAPPER.writeValueAsString(new NumberWrapper(Float.valueOf(0.5f)))); assertEquals(aposToQuotes("{'value':0.05}"), MAPPER.writeValueAsString(new NumberWrapper(Double.valueOf(0.05)))); assertEquals(aposToQuotes("{'value':123}"), MAPPER.writeValueAsString(new NumberWrapper(BigInteger.valueOf(123)))); assertEquals(aposToQuotes("{'value':0.025}"), MAPPER.writeValueAsString(new NumberWrapper(BigDecimal.valueOf(0.025)))); } } SqlDateSerializationTest.java000066400000000000000000000070011325620701100376400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/jdkpackage com.fasterxml.jackson.databind.ser.jdk; import java.io.IOException; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // Tests for `java.sql.Date`, `java.sql.Time` and `java.sql.Timestamp` public class SqlDateSerializationTest extends BaseMapTest { static class SqlDateAsDefaultBean { public java.sql.Date date; public SqlDateAsDefaultBean(long l) { date = new java.sql.Date(l); } } static class SqlDateAsNumberBean { @JsonFormat(shape=JsonFormat.Shape.NUMBER) public java.sql.Date date; public SqlDateAsNumberBean(long l) { date = new java.sql.Date(l); } } // for [databind#1407] static class Person { @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd") public java.sql.Date dateOfBirth; } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); @SuppressWarnings("deprecation") public void testSqlDate() throws IOException { // use date 1999-04-01 (note: months are 0-based, use constant) final java.sql.Date date99 = new java.sql.Date(99, Calendar.APRIL, 1); final java.sql.Date date0 = new java.sql.Date(0); // 11-Oct-2016, tatu: As per [databind#219] we really should use global // defaults in 2.9, even if this changes behavior. assertEquals(String.valueOf(date99.getTime()), MAPPER.writeValueAsString(date99)); assertEquals(aposToQuotes("{'date':0}"), MAPPER.writeValueAsString(new SqlDateAsDefaultBean(0L))); // but may explicitly force timestamp too assertEquals(aposToQuotes("{'date':0}"), MAPPER.writeValueAsString(new SqlDateAsNumberBean(0L))); // And also should be able to use String output as need be: ObjectWriter w = MAPPER.writer().without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); assertEquals(quote("1999-04-01"), w.writeValueAsString(date99)); assertEquals(quote(date0.toString()), w.writeValueAsString(date0)); assertEquals(aposToQuotes("{'date':'"+date0.toString()+"'}"), w.writeValueAsString(new SqlDateAsDefaultBean(0L))); } public void testSqlTime() throws IOException { java.sql.Time time = new java.sql.Time(0L); // not 100% sure what we should expect wrt timezone, but what serializes // does use is quite simple: assertEquals(quote(time.toString()), MAPPER.writeValueAsString(time)); } public void testSqlTimestamp() throws IOException { java.sql.Timestamp input = new java.sql.Timestamp(0L); // just should produce same output as standard `java.util.Date`: Date altTnput = new Date(0L); assertEquals(MAPPER.writeValueAsString(altTnput), MAPPER.writeValueAsString(input)); } public void testPatternWithSqlDate() throws Exception { ObjectMapper mapper = new ObjectMapper(); // `java.sql.Date` applies system default zone (and not UTC) mapper.setTimeZone(TimeZone.getDefault()); Person i = new Person(); i.dateOfBirth = java.sql.Date.valueOf("1980-04-14"); assertEquals(aposToQuotes("{'dateOfBirth':'1980.04.14'}"), mapper.writeValueAsString(i)); } } UntypedSerializationTest.java000066400000000000000000000075701325620701100377460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/ser/jdkpackage com.fasterxml.jackson.databind.ser.jdk; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; /** * This unit test suite tries verify simplest aspects of * "Native" java type mapper; basically that is can properly serialize * core JDK objects to JSON. */ public class UntypedSerializationTest extends BaseMapTest { public void testFromArray() throws Exception { ArrayList doc = new ArrayList(); doc.add("Elem1"); doc.add(Integer.valueOf(3)); Map struct = new LinkedHashMap(); struct.put("first", Boolean.TRUE); struct.put("Second", new ArrayList()); doc.add(struct); doc.add(Boolean.FALSE); ObjectMapper mapper = new ObjectMapper(); JsonFactory f = new JsonFactory(); // loop more than once, just to ensure caching works ok (during second round) for (int i = 0; i < 3; ++i) { String str = mapper.writeValueAsString(doc); JsonParser jp = f.createParser(str); assertEquals(JsonToken.START_ARRAY, jp.nextToken()); assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals("Elem1", getAndVerifyText(jp)); assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertEquals(3, jp.getIntValue()); assertEquals(JsonToken.START_OBJECT, jp.nextToken()); assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); assertEquals("first", getAndVerifyText(jp)); assertEquals(JsonToken.VALUE_TRUE, jp.nextToken()); assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); assertEquals("Second", getAndVerifyText(jp)); if (jp.nextToken() != JsonToken.START_ARRAY) { fail("Expected START_ARRAY: JSON == '"+str+"'"); } assertEquals(JsonToken.END_ARRAY, jp.nextToken()); assertEquals(JsonToken.END_OBJECT, jp.nextToken()); assertEquals(JsonToken.VALUE_FALSE, jp.nextToken()); assertEquals(JsonToken.END_ARRAY, jp.nextToken()); assertNull(jp.nextToken()); jp.close(); } } public void testFromMap() throws Exception { LinkedHashMap doc = new LinkedHashMap(); JsonFactory f = new JsonFactory(); doc.put("a1", "\"text\""); doc.put("int", Integer.valueOf(137)); doc.put("foo bar", Long.valueOf(1234567890L)); ObjectMapper mapper = new ObjectMapper(); for (int i = 0; i < 3; ++i) { String str = mapper.writeValueAsString(doc); JsonParser jp = f.createParser(str); assertEquals(JsonToken.START_OBJECT, jp.nextToken()); assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); assertEquals("a1", getAndVerifyText(jp)); assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals("\"text\"", getAndVerifyText(jp)); assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); assertEquals("int", getAndVerifyText(jp)); assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertEquals(137, jp.getIntValue()); assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); assertEquals("foo bar", getAndVerifyText(jp)); assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); assertEquals(1234567890L, jp.getLongValue()); assertEquals(JsonToken.END_OBJECT, jp.nextToken()); assertNull(jp.nextToken()); jp.close(); } } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/struct/000077500000000000000000000000001325620701100321065ustar00rootroot00000000000000BackReference1878Test.java000066400000000000000000000014031325620701100365370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; /** * @author Reda.Housni-Alaoui */ public class BackReference1878Test extends BaseMapTest { static class Child { @JsonBackReference public Parent b; } static class Parent { @JsonManagedReference public Child a; } private final ObjectMapper MAPPER = new ObjectMapper(); public void testChildDeserialization() throws Exception { Child child = MAPPER.readValue("{\"b\": {}}", Child.class); assertNotNull(child.b); } } EmptyArrayAsNullTest.java000066400000000000000000000112601325620701100367460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; /** * Tests to verify implementation of [databind#540]; also for * follow up work of: * * - [databind#994] */ public class EmptyArrayAsNullTest extends BaseMapTest { private final ObjectMapper MAPPER = new ObjectMapper(); private final ObjectReader DEFAULT_READER = MAPPER.reader(); private final ObjectReader READER_WITH_ARRAYS = DEFAULT_READER .with(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT); static class Bean { public String a = "foo"; } final static String EMPTY_ARRAY = " [\n]"; /* /********************************************************** /* Test methods, settings /********************************************************** */ public void testSettings() { assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)); assertFalse(DEFAULT_READER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)); assertTrue(READER_WITH_ARRAYS.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)); } /* /********************************************************** /* Test methods, POJOs /********************************************************** */ // [databind#540] public void testPOJOFromEmptyArray() throws Exception { // first, verify default settings which do not accept empty Array try { DEFAULT_READER.forType(Bean.class) .readValue(EMPTY_ARRAY); fail("Should not accept Empty Array for POJO by default"); } catch (JsonMappingException e) { verifyException(e, "START_ARRAY token"); assertValidLocation(e.getLocation()); } // should be ok to enable dynamically: Bean result = READER_WITH_ARRAYS.forType(Bean.class) .readValue(EMPTY_ARRAY); assertNull(result); } /* /********************************************************** /* Test methods, Maps /********************************************************** */ public void testMapFromEmptyArray() throws Exception { // first, verify default settings which do not accept empty Array try { DEFAULT_READER.forType(Map.class) .readValue(EMPTY_ARRAY); fail("Should not accept Empty Array for Map by default"); } catch (JsonMappingException e) { verifyException(e, "START_ARRAY token"); } // should be ok to enable dynamically: Map result = READER_WITH_ARRAYS.forType(Map.class) .readValue(EMPTY_ARRAY); assertNull(result); } public void testEnumMapFromEmptyArray() throws Exception { EnumMap result2 = READER_WITH_ARRAYS.forType(new TypeReference>() { }) .readValue(EMPTY_ARRAY); assertNull(result2); } /* /********************************************************** /* Test methods, primitives/wrappers /********************************************************** */ public void testWrapperFromEmptyArray() throws Exception { _testNullWrapper(Boolean.class); _testNullWrapper(Byte.class); _testNullWrapper(Character.class); _testNullWrapper(Short.class); _testNullWrapper(Integer.class); _testNullWrapper(Long.class); _testNullWrapper(Float.class); _testNullWrapper(Double.class); } /* /********************************************************** /* Test methods, other /********************************************************** */ public void testNullStringFromEmptyArray() throws Exception { _testNullWrapper(String.class); } public void testNullEnumFromEmptyArray() throws Exception { _testNullWrapper(ABC.class); } public void testStdJdkTypesFromEmptyArray() throws Exception { _testNullWrapper(BigInteger.class); _testNullWrapper(BigDecimal.class); _testNullWrapper(UUID.class); _testNullWrapper(Date.class); _testNullWrapper(Calendar.class); } /* /********************************************************** /* Helper methods /********************************************************** */ private void _testNullWrapper(Class cls) throws Exception { Object result = READER_WITH_ARRAYS.forType(cls).readValue(EMPTY_ARRAY); assertNull(result); } } FormatFeatureAcceptSingleTest.java000066400000000000000000000146141325620701100405660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.util.EnumSet; import java.util.List; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class FormatFeatureAcceptSingleTest extends BaseMapTest { static class StringArrayNotAnnoted { public String[] values; protected StringArrayNotAnnoted() { } public StringArrayNotAnnoted(String ... v) { values = v; } } static class StringArrayWrapper { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public String[] values; } static class BooleanArrayWrapper { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public boolean[] values; } static class IntArrayWrapper { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public int[] values; } static class LongArrayWrapper { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public long[] values; } static class FloatArrayWrapper { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public float[] values; } static class DoubleArrayWrapper { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public double[] values; } static class StringListWrapper { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public List values; } static class EnumSetWrapper { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public EnumSet values; } static class RolesInArray { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public Role[] roles; } static class RolesInList { @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public List roles; } static class Role { public String ID; public String Name; } private final ObjectMapper MAPPER = new ObjectMapper(); /* /********************************************************** /* Test methods, reading with single-element unwrapping /********************************************************** */ public void testSingleStringArrayRead() throws Exception { String json = aposToQuotes( "{ 'values': 'first' }"); StringArrayWrapper result = MAPPER.readValue(json, StringArrayWrapper.class); assertNotNull(result.values); assertEquals(1, result.values.length); assertEquals("first", result.values[0]); // and then without annotation, but with global override ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(String[].class).setFormat(JsonFormat.Value.empty() .withFeature(JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); StringArrayNotAnnoted result2 = mapper.readValue(json, StringArrayNotAnnoted.class); assertNotNull(result2.values); assertEquals(1, result2.values.length); assertEquals("first", result2.values[0]); } public void testSingleIntArrayRead() throws Exception { String json = aposToQuotes( "{ 'values': 123 }"); IntArrayWrapper result = MAPPER.readValue(json, IntArrayWrapper.class); assertNotNull(result.values); assertEquals(1, result.values.length); assertEquals(123, result.values[0]); } public void testSingleLongArrayRead() throws Exception { String json = aposToQuotes( "{ 'values': -205 }"); LongArrayWrapper result = MAPPER.readValue(json, LongArrayWrapper.class); assertNotNull(result.values); assertEquals(1, result.values.length); assertEquals(-205L, result.values[0]); } public void testSingleBooleanArrayRead() throws Exception { String json = aposToQuotes( "{ 'values': true }"); BooleanArrayWrapper result = MAPPER.readValue(json, BooleanArrayWrapper.class); assertNotNull(result.values); assertEquals(1, result.values.length); assertEquals(true, result.values[0]); } public void testSingleDoubleArrayRead() throws Exception { String json = aposToQuotes( "{ 'values': -0.5 }"); DoubleArrayWrapper result = MAPPER.readValue(json, DoubleArrayWrapper.class); assertNotNull(result.values); assertEquals(1, result.values.length); assertEquals(-0.5, result.values[0]); } public void testSingleFloatArrayRead() throws Exception { String json = aposToQuotes( "{ 'values': 0.25 }"); FloatArrayWrapper result = MAPPER.readValue(json, FloatArrayWrapper.class); assertNotNull(result.values); assertEquals(1, result.values.length); assertEquals(0.25f, result.values[0]); } public void testSingleElementArrayRead() throws Exception { String json = aposToQuotes( "{ 'roles': { 'Name': 'User', 'ID': '333' } }"); RolesInArray response = MAPPER.readValue(json, RolesInArray.class); assertNotNull(response.roles); assertEquals(1, response.roles.length); assertEquals("333", response.roles[0].ID); } public void testSingleStringListRead() throws Exception { String json = aposToQuotes( "{ 'values': 'first' }"); StringListWrapper result = MAPPER.readValue(json, StringListWrapper.class); assertNotNull(result.values); assertEquals(1, result.values.size()); assertEquals("first", result.values.get(0)); } public void testSingleElementListRead() throws Exception { String json = aposToQuotes( "{ 'roles': { 'Name': 'User', 'ID': '333' } }"); RolesInList response = MAPPER.readValue(json, RolesInList.class); assertNotNull(response.roles); assertEquals(1, response.roles.size()); assertEquals("333", response.roles.get(0).ID); } public void testSingleEnumSetRead() throws Exception { EnumSetWrapper result = MAPPER.readValue(aposToQuotes("{ 'values': 'B' }"), EnumSetWrapper.class); assertNotNull(result.values); assertEquals(1, result.values.size()); assertEquals(ABC.B, result.values.iterator().next()); } } FormatFeatureOrderedMapTest.java000066400000000000000000000020271325620701100402420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Tests for {@link JsonFormat} and specifically JsonFormat.Features. */ public class FormatFeatureOrderedMapTest extends BaseMapTest { static class SortedKeysMap { @JsonFormat(with = JsonFormat.Feature.WRITE_SORTED_MAP_ENTRIES) public Map values = new LinkedHashMap<>(); protected SortedKeysMap() { } public SortedKeysMap put(String key, int value) { values.put(key, value); return this; } } private final ObjectMapper MAPPER = new ObjectMapper(); // [databind#1232]: allow forcing sorting on Map keys public void testOrderedMaps() throws Exception { SortedKeysMap map = new SortedKeysMap() .put("b", 2) .put("a", 1); assertEquals(aposToQuotes("{'values':{'a':1,'b':2}}"), MAPPER.writeValueAsString(map)); } } FormatFeatureUnwrapSingleTest.java000066400000000000000000000173611325620701100406450ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.net.URI; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class FormatFeatureUnwrapSingleTest extends BaseMapTest { static class StringArrayNotAnnoted { public String[] values; protected StringArrayNotAnnoted() { } public StringArrayNotAnnoted(String ... v) { values = v; } } @JsonPropertyOrder( { "strings", "ints", "bools" }) static class WrapWriteWithArrays { @JsonProperty("strings") @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public String[] _strings = new String[] { "a" }; @JsonFormat(without={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public int[] ints = new int[] { 1 }; public boolean[] bools = new boolean[] { true }; } static class UnwrapShortArray { @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public short[] v = { (short) 7 }; } static class UnwrapIntArray { @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public int[] v = { 3 }; } static class UnwrapLongArray { @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public long[] v = { 1L }; } static class UnwrapBooleanArray { @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public boolean[] v = { true }; } static class UnwrapFloatArray { @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public float[] v = { 0.5f }; } static class UnwrapDoubleArray { @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public double[] v = { 0.25 }; } static class UnwrapIterable { @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) @JsonSerialize(as=Iterable.class) public Iterable v; public UnwrapIterable() { v = Collections.singletonList("foo"); } public UnwrapIterable(String... values) { v = Arrays.asList(values); } } static class UnwrapCollection { @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) @JsonSerialize(as=Collection.class) public Collection v; public UnwrapCollection() { v = Collections.singletonList("foo"); } public UnwrapCollection(String... values) { v = new LinkedHashSet(Arrays.asList(values)); } } static class UnwrapStringLike { @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public URI[] v = { URI.create("http://foo") }; } @JsonPropertyOrder( { "strings", "ints", "bools", "enums" }) static class WrapWriteWithCollections { @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public List strings = Arrays.asList("a"); @JsonFormat(without={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public Collection ints = Arrays.asList(Integer.valueOf(1)); public Set bools = Collections.singleton(true); @JsonFormat(with={ JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED }) public EnumSet enums = EnumSet.of(ABC.B); } /* /********************************************************** /* Test methods, writing with single-element unwrapping /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testWithArrayTypes() throws Exception { // default: strings unwrapped, ints wrapped assertEquals(aposToQuotes("{'strings':'a','ints':[1],'bools':[true]}"), MAPPER.writeValueAsString(new WrapWriteWithArrays())); // change global default to "yes, unwrap"; changes 'bools' only assertEquals(aposToQuotes("{'strings':'a','ints':[1],'bools':true}"), MAPPER.writer().with(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) .writeValueAsString(new WrapWriteWithArrays())); // change global default to "no, don't, unwrap", same as first case assertEquals(aposToQuotes("{'strings':'a','ints':[1],'bools':[true]}"), MAPPER.writer().without(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) .writeValueAsString(new WrapWriteWithArrays())); // And then without SerializationFeature but with config override: ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(String[].class).setFormat(JsonFormat.Value.empty() .withFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)); assertEquals(aposToQuotes("{'values':'a'}"), mapper.writeValueAsString(new StringArrayNotAnnoted("a"))); } public void testWithCollectionTypes() throws Exception { // default: strings unwrapped, ints wrapped assertEquals(aposToQuotes("{'strings':'a','ints':[1],'bools':[true],'enums':'B'}"), MAPPER.writeValueAsString(new WrapWriteWithCollections())); // change global default to "yes, unwrap"; changes 'bools' only assertEquals(aposToQuotes("{'strings':'a','ints':[1],'bools':true,'enums':'B'}"), MAPPER.writer().with(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) .writeValueAsString(new WrapWriteWithCollections())); // change global default to "no, don't, unwrap", same as first case assertEquals(aposToQuotes("{'strings':'a','ints':[1],'bools':[true],'enums':'B'}"), MAPPER.writer().without(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) .writeValueAsString(new WrapWriteWithCollections())); } public void testUnwrapWithPrimitiveArraysEtc() throws Exception { assertEquals("{\"v\":7}", MAPPER.writeValueAsString(new UnwrapShortArray())); assertEquals("{\"v\":3}", MAPPER.writeValueAsString(new UnwrapIntArray())); assertEquals("{\"v\":1}", MAPPER.writeValueAsString(new UnwrapLongArray())); assertEquals("{\"v\":true}", MAPPER.writeValueAsString(new UnwrapBooleanArray())); assertEquals("{\"v\":0.5}", MAPPER.writeValueAsString(new UnwrapFloatArray())); assertEquals("{\"v\":0.25}", MAPPER.writeValueAsString(new UnwrapDoubleArray())); assertEquals("0.5", MAPPER.writer().with(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) .writeValueAsString(new double[] { 0.5 })); assertEquals("{\"v\":\"foo\"}", MAPPER.writeValueAsString(new UnwrapIterable())); assertEquals("{\"v\":\"x\"}", MAPPER.writeValueAsString(new UnwrapIterable("x"))); assertEquals("{\"v\":[\"x\",null]}", MAPPER.writeValueAsString(new UnwrapIterable("x", null))); assertEquals("{\"v\":\"foo\"}", MAPPER.writeValueAsString(new UnwrapCollection())); assertEquals("{\"v\":\"x\"}", MAPPER.writeValueAsString(new UnwrapCollection("x"))); assertEquals("{\"v\":[\"x\",null]}", MAPPER.writeValueAsString(new UnwrapCollection("x", null))); assertEquals("{\"v\":\"http://foo\"}", MAPPER.writeValueAsString(new UnwrapStringLike())); } } PojoAsArray646Test.java000066400000000000000000000060161325620701100361670ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class PojoAsArray646Test extends BaseMapTest { @JsonFormat(shape = JsonFormat.Shape.ARRAY) @JsonPropertyOrder(alphabetic = true) static class Outer { protected Map attributes; public Outer() { attributes = new HashMap(); } @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY) public Map getAttributes() { return attributes; } } @JsonFormat(shape = JsonFormat.Shape.ARRAY) @JsonPropertyOrder(alphabetic = true) static class TheItem { @JsonFormat(shape = JsonFormat.Shape.ARRAY) @JsonPropertyOrder(alphabetic = true) public static class NestedItem { public String nestedStrValue; @JsonCreator public NestedItem(@JsonProperty("nestedStrValue") String nestedStrValue) { this.nestedStrValue = nestedStrValue; } } private String strValue; private boolean boolValue; private List nestedItems; @JsonCreator public TheItem(@JsonProperty("strValue") String strValue, @JsonProperty("boolValue") boolean boolValue, @JsonProperty("nestedItems") List nestedItems) { this.strValue = strValue; this.boolValue = boolValue; this.nestedItems = nestedItems; } public String getStrValue() { return strValue; } public void setStrValue(String strValue) { this.strValue = strValue; } public boolean isBoolValue() { return boolValue; } public void setBoolValue(boolean boolValue) { this.boolValue = boolValue; } public List getNestedItems() { return nestedItems; } public void setNestedItems(List nestedItems) { this.nestedItems = nestedItems; } } /* /********************************************************** /* Tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testWithCustomTypeId() throws Exception { List nestedList = new ArrayList(); nestedList.add(new TheItem.NestedItem("foo1")); nestedList.add(new TheItem.NestedItem("foo2")); TheItem item = new TheItem("first", false, nestedList); Outer outer = new Outer(); outer.getAttributes().put("entry1", item); String json = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(outer); Outer result = MAPPER.readValue(json, Outer.class); assertNotNull(result); assertNotNull(result.attributes); assertEquals(1, result.attributes.size()); } } ScalarCoercionTest.java000066400000000000000000000176471325620701100364400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.MismatchedInputException; // for [databind#1106] public class ScalarCoercionTest extends BaseMapTest { private final ObjectMapper COERCING_MAPPER = new ObjectMapper(); { COERCING_MAPPER.enable(MapperFeature.ALLOW_COERCION_OF_SCALARS); } private final ObjectMapper NOT_COERCING_MAPPER = new ObjectMapper(); { NOT_COERCING_MAPPER.disable(MapperFeature.ALLOW_COERCION_OF_SCALARS); } /* /********************************************************** /* Unit tests: coercion from empty String /********************************************************** */ public void testNullValueFromEmpty() throws Exception { // wrappers accept `null` fine _verifyNullOkFromEmpty(Boolean.class, null); // but primitives require non-null _verifyNullOkFromEmpty(Boolean.TYPE, Boolean.FALSE); _verifyNullOkFromEmpty(Byte.class, null); _verifyNullOkFromEmpty(Byte.TYPE, Byte.valueOf((byte) 0)); _verifyNullOkFromEmpty(Short.class, null); _verifyNullOkFromEmpty(Short.TYPE, Short.valueOf((short) 0)); _verifyNullOkFromEmpty(Character.class, null); _verifyNullOkFromEmpty(Character.TYPE, Character.valueOf((char) 0)); _verifyNullOkFromEmpty(Integer.class, null); _verifyNullOkFromEmpty(Integer.TYPE, Integer.valueOf(0)); _verifyNullOkFromEmpty(Long.class, null); _verifyNullOkFromEmpty(Long.TYPE, Long.valueOf(0L)); _verifyNullOkFromEmpty(Float.class, null); _verifyNullOkFromEmpty(Float.TYPE, Float.valueOf(0.0f)); _verifyNullOkFromEmpty(Double.class, null); _verifyNullOkFromEmpty(Double.TYPE, Double.valueOf(0.0)); _verifyNullOkFromEmpty(BigInteger.class, null); _verifyNullOkFromEmpty(BigDecimal.class, null); } private void _verifyNullOkFromEmpty(Class type, Object exp) throws IOException { Object result = COERCING_MAPPER.readerFor(type) .with(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT) .readValue("\"\""); if (exp == null) { assertNull(result); } else { assertEquals(exp, result); } } public void testNullFailFromEmpty() throws Exception { _verifyNullFail(Boolean.class); _verifyNullFail(Boolean.TYPE); _verifyNullFail(Byte.class); _verifyNullFail(Byte.TYPE); _verifyNullFail(Short.class); _verifyNullFail(Short.TYPE); _verifyNullFail(Character.class); _verifyNullFail(Character.TYPE); _verifyNullFail(Integer.class); _verifyNullFail(Integer.TYPE); _verifyNullFail(Long.class); _verifyNullFail(Long.TYPE); _verifyNullFail(Float.class); _verifyNullFail(Float.TYPE); _verifyNullFail(Double.class); _verifyNullFail(Double.TYPE); _verifyNullFail(BigInteger.class); _verifyNullFail(BigDecimal.class); } private void _verifyNullFail(Class type) throws IOException { try { NOT_COERCING_MAPPER.readerFor(type).readValue("\"\""); fail("Should have failed for "+type); } catch (MismatchedInputException e) { verifyException(e, "Cannot coerce empty String"); verifyException(e, "Null value for"); } } /* /********************************************************** /* Unit tests: coercion from secondary representations /********************************************************** */ public void testStringCoercionOk() throws Exception { // first successful coercions. Boolean has a ton... _verifyCoerceSuccess("1", Boolean.TYPE, Boolean.TRUE); _verifyCoerceSuccess("1", Boolean.class, Boolean.TRUE); _verifyCoerceSuccess(quote("true"), Boolean.TYPE, Boolean.TRUE); _verifyCoerceSuccess(quote("true"), Boolean.class, Boolean.TRUE); _verifyCoerceSuccess(quote("True"), Boolean.TYPE, Boolean.TRUE); _verifyCoerceSuccess(quote("True"), Boolean.class, Boolean.TRUE); _verifyCoerceSuccess("0", Boolean.TYPE, Boolean.FALSE); _verifyCoerceSuccess("0", Boolean.class, Boolean.FALSE); _verifyCoerceSuccess(quote("false"), Boolean.TYPE, Boolean.FALSE); _verifyCoerceSuccess(quote("false"), Boolean.class, Boolean.FALSE); _verifyCoerceSuccess(quote("False"), Boolean.TYPE, Boolean.FALSE); _verifyCoerceSuccess(quote("False"), Boolean.class, Boolean.FALSE); _verifyCoerceSuccess(quote("123"), Byte.TYPE, Byte.valueOf((byte) 123)); _verifyCoerceSuccess(quote("123"), Byte.class, Byte.valueOf((byte) 123)); _verifyCoerceSuccess(quote("123"), Short.TYPE, Short.valueOf((short) 123)); _verifyCoerceSuccess(quote("123"), Short.class, Short.valueOf((short) 123)); _verifyCoerceSuccess(quote("123"), Integer.TYPE, Integer.valueOf(123)); _verifyCoerceSuccess(quote("123"), Integer.class, Integer.valueOf(123)); _verifyCoerceSuccess(quote("123"), Long.TYPE, Long.valueOf(123)); _verifyCoerceSuccess(quote("123"), Long.class, Long.valueOf(123)); _verifyCoerceSuccess(quote("123.5"), Float.TYPE, Float.valueOf(123.5f)); _verifyCoerceSuccess(quote("123.5"), Float.class, Float.valueOf(123.5f)); _verifyCoerceSuccess(quote("123.5"), Double.TYPE, Double.valueOf(123.5)); _verifyCoerceSuccess(quote("123.5"), Double.class, Double.valueOf(123.5)); _verifyCoerceSuccess(quote("123"), BigInteger.class, BigInteger.valueOf(123)); _verifyCoerceSuccess(quote("123.0"), BigDecimal.class, new BigDecimal("123.0")); } public void testStringCoercionFail() throws Exception { _verifyCoerceFail(quote("true"), Boolean.TYPE); _verifyCoerceFail(quote("true"), Boolean.class); _verifyCoerceFail(quote("123"), Byte.TYPE); _verifyCoerceFail(quote("123"), Byte.class); _verifyCoerceFail(quote("123"), Short.TYPE); _verifyCoerceFail(quote("123"), Short.class); _verifyCoerceFail(quote("123"), Integer.TYPE); _verifyCoerceFail(quote("123"), Integer.class); _verifyCoerceFail(quote("123"), Long.TYPE); _verifyCoerceFail(quote("123"), Long.class); _verifyCoerceFail(quote("123.5"), Float.TYPE); _verifyCoerceFail(quote("123.5"), Float.class); _verifyCoerceFail(quote("123.5"), Double.TYPE); _verifyCoerceFail(quote("123.5"), Double.class); _verifyCoerceFail(quote("123"), BigInteger.class); _verifyCoerceFail(quote("123.0"), BigDecimal.class); } public void testMiscCoercionFail() throws Exception { // And then we have coercions from more esoteric types too _verifyCoerceFail("1", Boolean.TYPE); _verifyCoerceFail("1", Boolean.class); _verifyCoerceFail("65", Character.class); _verifyCoerceFail("65", Character.TYPE); } /* /********************************************************** /* Helper methods /********************************************************** */ private void _verifyCoerceSuccess(String input, Class type, Object exp) throws IOException { Object result = COERCING_MAPPER.readerFor(type) .readValue(input); assertEquals(exp, result); } private void _verifyCoerceFail(String input, Class type) throws IOException { try { NOT_COERCING_MAPPER.readerFor(type) .readValue(input); fail("Should not have allowed coercion"); } catch (MismatchedInputException e) { verifyException(e, "Cannot coerce "); verifyException(e, " for type `"); verifyException(e, "enable `MapperFeature.ALLOW_COERCION_OF_SCALARS` to allow"); } } } SingleValueAsArrayTest.java000066400000000000000000000052261325620701100372400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class SingleValueAsArrayTest extends BaseMapTest { private static final String JSON = "[{\"message\":\"messageHere\"}]"; static class Bean1421A { List bs = Collections.emptyList(); @JsonCreator Bean1421A(final List bs) { this.bs = bs; } } static class Messages { List cs = Collections.emptyList(); @JsonCreator Messages(final List cs) { this.cs = cs; } } static class MessageWrapper { String message; @JsonCreator MessageWrapper(@JsonProperty("message") String message) { this.message = message; } } static class Bean1421B { T value; @JsonCreator public Bean1421B(T value) { this.value = value; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); { MAPPER.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); } public void testSuccessfulDeserializationOfObjectWithChainedArrayCreators() throws IOException { Bean1421A result = MAPPER.readValue(JSON, Bean1421A.class); assertNotNull(result); } public void testWithSingleString() throws Exception { Bean1421B> a = MAPPER.readValue(quote("test2"), new TypeReference>>() {}); List expected = new ArrayList<>(); expected.add("test2"); assertEquals(expected, a.value); } public void testPrimitives() throws Exception { int[] i = MAPPER.readValue("16", int[].class); assertEquals(1, i.length); assertEquals(16, i[0]); long[] l = MAPPER.readValue("1234", long[].class); assertEquals(1, l.length); assertEquals(1234L, l[0]); double[] d = MAPPER.readValue("12.5", double[].class); assertEquals(1, d.length); assertEquals(12.5, d[0]); boolean[] b = MAPPER.readValue("true", boolean[].class); assertEquals(1, d.length); assertEquals(true, b[0]); } } TestBackRefsWithPolymorphic.java000066400000000000000000000145561325620701100403070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.io.IOException; import java.util.Map; import java.util.TreeMap; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; // Unit test for [JACKSON-890] public class TestBackRefsWithPolymorphic extends BaseMapTest { @JsonPropertyOrder(alphabetic=true) interface Entity { @JsonIgnore String getEntityType(); Long getId(); void setId(Long id); @JsonIgnore void setPersistable(); } @JsonDeserialize(as = NestedPropertySheetImpl.class) interface NestedPropertySheet extends Property { @Override PropertySheet getValue(); void setValue(PropertySheet propertySheet); } @JsonDeserialize(as = AbstractProperty.class) @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") interface Property extends Entity { String getName(); PropertySheet getParentSheet(); T getValue(); void setName(String name); void setParentSheet(PropertySheet parentSheet); } @JsonDeserialize(as = PropertySheetImpl.class) @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") @SuppressWarnings("rawtypes") interface PropertySheet extends Entity { void addProperty(Property property); Map getProperties(); void setProperties(Map properties); } @JsonDeserialize(as = StringPropertyImpl.class) interface StringProperty extends Property { @Override String getValue(); void setValue(String value); } static class AbstractEntity implements Entity { private long id; @Override public String getEntityType() { return ""; } @Override public Long getId() { return id; } @Override public void setId(Long id) { this.id = id; } @Override public void setPersistable() { } } abstract static class AbstractProperty extends AbstractEntity implements Property { private String m_name; private PropertySheet m_parentSheet; protected AbstractProperty() { } protected AbstractProperty(String name) { m_name = name; } @Override public String getName() { return m_name; } @JsonBackReference("propertySheet-properties") @Override public PropertySheet getParentSheet() { return m_parentSheet; } @Override public void setName(String name) { m_name = name; } @Override public void setParentSheet(PropertySheet parentSheet) { m_parentSheet = parentSheet; } } @JsonPropertyOrder(alphabetic=true) static class NestedPropertySheetImpl extends AbstractProperty implements NestedPropertySheet { private PropertySheet m_propertySheet; protected NestedPropertySheetImpl(String name, PropertySheet propertySheet) { super(name); m_propertySheet = propertySheet; } NestedPropertySheetImpl() { } @Override public PropertySheet getValue() { return m_propertySheet; } @Override public void setValue(PropertySheet propertySheet) { m_propertySheet = propertySheet; } } @SuppressWarnings("rawtypes") static class PropertySheetImpl extends AbstractEntity implements PropertySheet { private Map m_properties; @Override public void addProperty(Property property) { if (m_properties == null) { m_properties = new TreeMap(); } property.setParentSheet(this); m_properties.put(property.getName(), property); } @JsonDeserialize(as = TreeMap.class, keyAs = String.class, contentAs = Property.class) @JsonManagedReference("propertySheet-properties") @Override public Map getProperties() { return m_properties; } @Override public void setProperties(Map properties) { m_properties = properties; } } static class StringPropertyImpl extends AbstractProperty implements StringProperty { private String m_value; public StringPropertyImpl(String name, String value) { super(name); m_value = value; } StringPropertyImpl() { } @Override public String getValue() { return m_value; } @Override public void setValue(String value) { m_value = value; } } static class YetAnotherClass extends StringPropertyImpl { } /* /********************************************************** /* Test methods /********************************************************** */ private final String CLASS_NAME = getClass().getName(); // NOTE: order is arbitrary, test is fragile... has to work for now private final String JSON = "{\"@class\":\""+CLASS_NAME+"$PropertySheetImpl\",\"id\":0,\"properties\":{\"p1name\":{\"@class\":" +"\"" +CLASS_NAME+ "$StringPropertyImpl\",\"id\":0,\"name\":\"p1name\",\"value\":\"p1value\"}," +"\"p2name\":{\"@class\":\""+CLASS_NAME+"$StringPropertyImpl\",\"id\":0," +"\"name\":\"p2name\",\"value\":\"p2value\"}}}"; private final ObjectMapper MAPPER = new ObjectMapper(); public void testDeserialize() throws IOException { PropertySheet input = MAPPER.readValue(JSON, PropertySheet.class); assertEquals(JSON, MAPPER.writeValueAsString(input)); } public void testSerialize() throws IOException { PropertySheet sheet = new PropertySheetImpl(); sheet.addProperty(new StringPropertyImpl("p1name", "p1value")); sheet.addProperty(new StringPropertyImpl("p2name", "p2value")); String actual = MAPPER.writeValueAsString(sheet); assertEquals(JSON, actual); } } TestForwardReference.java000066400000000000000000000045371325620701100367660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.io.IOException; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; /** * Test for testing forward reference handling */ public class TestForwardReference extends BaseMapTest { private final ObjectMapper MAPPER = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .enable(SerializationFeature.INDENT_OUTPUT) .setSerializationInclusion(JsonInclude.Include.NON_NULL); /** Tests that we can read a hierarchical structure with forward references*/ public void testForwardRef() throws IOException { MAPPER.readValue("{" + " \"@type\" : \"TestForwardReference$ForwardReferenceContainerClass\"," + " \"frc\" : \"willBeForwardReferenced\"," + " \"yac\" : {" + " \"@type\" : \"TestForwardReference$YetAnotherClass\"," + " \"frc\" : {" + " \"@type\" : \"One\"," + " \"id\" : \"willBeForwardReferenced\"" + " }," + " \"id\" : \"anId\"" + " }," + " \"id\" : \"ForwardReferenceContainerClass1\"" + "}", ForwardReferenceContainerClass.class); } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include= JsonTypeInfo.As.PROPERTY) public static class ForwardReferenceContainerClass { public ForwardReferenceClass frc; public YetAnotherClass yac; public String id; } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") @JsonSubTypes({ @JsonSubTypes.Type(value = ForwardReferenceClassOne.class, name = "One"), @JsonSubTypes.Type(value = ForwardReferenceClassTwo.class, name = "Two")}) static abstract class ForwardReferenceClass { public String id; public void setId(String id) { this.id = id; } } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY) static class YetAnotherClass { public YetAnotherClass() {} public ForwardReferenceClass frc; public String id; } public static class ForwardReferenceClassOne extends ForwardReferenceClass { } public static class ForwardReferenceClassTwo extends ForwardReferenceClass { } } TestPOJOAsArray.java000066400000000000000000000220111325620701100355600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat.Shape; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class TestPOJOAsArray extends BaseMapTest { static class PojoAsArrayWrapper { @JsonFormat(shape=JsonFormat.Shape.ARRAY) public PojoAsArray value; public PojoAsArrayWrapper() { } public PojoAsArrayWrapper(String name, int x, int y, boolean c) { value = new PojoAsArray(name, x, y, c); } } @JsonPropertyOrder(alphabetic=true) static class NonAnnotatedXY { public int x, y; public NonAnnotatedXY() { } public NonAnnotatedXY(int x0, int y0) { x = x0; y = y0; } } // note: must be serialized/deserialized alphabetically; fields NOT declared in that order @JsonPropertyOrder(alphabetic=true) static class PojoAsArray { public int x, y; public String name; public boolean complete; public PojoAsArray() { } public PojoAsArray(String name, int x, int y, boolean c) { this.name = name; this.x = x; this.y = y; this.complete = c; } } @JsonPropertyOrder(alphabetic=true) @JsonFormat(shape=JsonFormat.Shape.ARRAY) static class FlatPojo { public int x, y; public String name; public boolean complete; public FlatPojo() { } public FlatPojo(String name, int x, int y, boolean c) { this.name = name; this.x = x; this.y = y; this.complete = c; } } static class ForceArraysIntrospector extends JacksonAnnotationIntrospector { private static final long serialVersionUID = 1L; @Override public JsonFormat.Value findFormat(Annotated a) { return new JsonFormat.Value().withShape(JsonFormat.Shape.ARRAY); } } static class A { public B value = new B(); } @JsonPropertyOrder(alphabetic=true) static class B { public int x = 1; public int y = 2; } @JsonFormat(shape=Shape.ARRAY) static class SingleBean { public String name = "foo"; } @JsonPropertyOrder(alphabetic=true) @JsonFormat(shape=Shape.ARRAY) static class TwoStringsBean { public String bar = null; public String foo = "bar"; } @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder(alphabetic=true) static class AsArrayWithMap { public Map attrs; public AsArrayWithMap() { } public AsArrayWithMap(int x, int y) { attrs = new HashMap(); attrs.put(x, y); } } @JsonFormat(shape=JsonFormat.Shape.ARRAY) static class CreatorWithIndex { protected int _a, _b; @JsonCreator public CreatorWithIndex(@JsonProperty(index=0, value="a") int a, @JsonProperty(index=1, value="b") int b) { this._a = a; this._b = b; } } /* /***************************************************** /* Basic tests /***************************************************** */ private final static ObjectMapper MAPPER = new ObjectMapper(); /** * Test that verifies that property annotation works */ public void testReadSimplePropertyValue() throws Exception { String json = "{\"value\":[true,\"Foobar\",42,13]}"; PojoAsArrayWrapper p = MAPPER.readValue(json, PojoAsArrayWrapper.class); assertNotNull(p.value); assertTrue(p.value.complete); assertEquals("Foobar", p.value.name); assertEquals(42, p.value.x); assertEquals(13, p.value.y); } /** * Test that verifies that Class annotation works */ public void testReadSimpleRootValue() throws Exception { String json = "[false,\"Bubba\",1,2]"; FlatPojo p = MAPPER.readValue(json, FlatPojo.class); assertFalse(p.complete); assertEquals("Bubba", p.name); assertEquals(1, p.x); assertEquals(2, p.y); } /** * Test that verifies that property annotation works */ public void testWriteSimplePropertyValue() throws Exception { String json = MAPPER.writeValueAsString(new PojoAsArrayWrapper("Foobar", 42, 13, true)); // will have wrapper POJO, then POJO-as-array.. assertEquals("{\"value\":[true,\"Foobar\",42,13]}", json); } /** * Test that verifies that Class annotation works */ public void testWriteSimpleRootValue() throws Exception { String json = MAPPER.writeValueAsString(new FlatPojo("Bubba", 1, 2, false)); // will have wrapper POJO, then POJO-as-array.. assertEquals("[false,\"Bubba\",1,2]", json); } // [Issue#223] public void testNullColumn() throws Exception { assertEquals("[null,\"bar\"]", MAPPER.writeValueAsString(new TwoStringsBean())); } /* /***************************************************** /* Compatibility with "single-elem as array" feature /***************************************************** */ public void testSerializeAsArrayWithSingleProperty() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); String json = mapper.writeValueAsString(new SingleBean()); assertEquals("\"foo\"", json); } public void testBeanAsArrayUnwrapped() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); SingleBean result = mapper.readValue("[\"foobar\"]", SingleBean.class); assertNotNull(result); assertEquals("foobar", result.name); } /* /***************************************************** /* Round-trip tests /***************************************************** */ public void testAnnotationOverride() throws Exception { // by default, POJOs become JSON Objects; assertEquals("{\"value\":{\"x\":1,\"y\":2}}", MAPPER.writeValueAsString(new A())); // but override should change it: ObjectMapper mapper2 = new ObjectMapper(); mapper2.setAnnotationIntrospector(new ForceArraysIntrospector()); assertEquals("[[1,2]]", mapper2.writeValueAsString(new A())); // and allow reading back, too } public void testWithMaps() throws Exception { AsArrayWithMap input = new AsArrayWithMap(1, 2); String json = MAPPER.writeValueAsString(input); AsArrayWithMap output = MAPPER.readValue(json, AsArrayWithMap.class); assertNotNull(output); assertNotNull(output.attrs); assertEquals(1, output.attrs.size()); assertEquals(Integer.valueOf(2), output.attrs.get(1)); } public void testSimpleWithIndex() throws Exception { // as POJO: // CreatorWithIndex value = MAPPER.readValue(aposToQuotes("{'b':1,'a':2}"), CreatorWithIndex value = MAPPER.readValue(aposToQuotes("[2,1]"), CreatorWithIndex.class); assertEquals(2, value._a); assertEquals(1, value._b); } public void testWithConfigOverrides() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(NonAnnotatedXY.class) .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.ARRAY)); String json = mapper.writeValueAsString(new NonAnnotatedXY(2, 3)); assertEquals("[2,3]", json); // also, read it back NonAnnotatedXY result = mapper.readValue(json, NonAnnotatedXY.class); assertNotNull(result); assertEquals(3, result.y); } /* /***************************************************** /* Failure tests /***************************************************** */ public void testUnknownExtraProp() throws Exception { String json = "{\"value\":[true,\"Foobar\",42,13, false]}"; try { MAPPER.readValue(json, PojoAsArrayWrapper.class); fail("should not pass with extra element"); } catch (MismatchedInputException e) { verifyException(e, "Unexpected JSON values"); } // but actually fine if skip-unknown set PojoAsArrayWrapper v = MAPPER.readerFor(PojoAsArrayWrapper.class) .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .readValue(json); assertNotNull(v); // note: +1 for both so assertEquals(v.value.x, 42); assertEquals(v.value.y, 13); assertTrue(v.value.complete); assertEquals("Foobar", v.value.name); } } TestPOJOAsArrayAdvanced.java000066400000000000000000000112551325620701100372160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class TestPOJOAsArrayAdvanced extends BaseMapTest { @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder(alphabetic=true) static class CreatorAsArray { protected int x, y; public int a, b; @JsonCreator public CreatorAsArray(@JsonProperty("x") int x, @JsonProperty("y") int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } } @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder({"a","b","x","y"}) static class CreatorAsArrayShuffled { protected int x, y; public int a, b; @JsonCreator public CreatorAsArrayShuffled(@JsonProperty("x") int x, @JsonProperty("y") int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } } static class ViewA { } static class ViewB { } @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder(alphabetic=true) static class AsArrayWithView { @JsonView(ViewA.class) public int a; @JsonView(ViewB.class) public int b; public int c; } @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder(alphabetic=true) static class AsArrayWithViewAndCreator { @JsonView(ViewA.class) public int a; @JsonView(ViewB.class) public int b; public int c; @JsonCreator public AsArrayWithViewAndCreator(@JsonProperty("a") int a, @JsonProperty("b") int b, @JsonProperty("c") int c) { this.a = a; this.b = b; this.c = c; } } /* /***************************************************** /* Basic tests /***************************************************** */ private final static ObjectMapper MAPPER = new ObjectMapper(); public void testWithView() throws Exception { // Ok, first, ensure that serializer will "black out" filtered properties AsArrayWithView input = new AsArrayWithView(); input.a = 1; input.b = 2; input.c = 3; String json = MAPPER.writerWithView(ViewA.class).writeValueAsString(input); assertEquals("[1,null,3]", json); // and then that conversely deserializer does something similar AsArrayWithView result = MAPPER.readerFor(AsArrayWithView.class).withView(ViewB.class) .readValue("[1,2,3]"); // should include 'c' (not view-able) and 'b' (include in ViewB) but not 'a' assertEquals(3, result.c); assertEquals(2, result.b); assertEquals(0, result.a); } public void testWithViewAndCreator() throws Exception { AsArrayWithViewAndCreator result = MAPPER.readerFor(AsArrayWithViewAndCreator.class) .withView(ViewB.class) .readValue("[1,2,3]"); // should include 'c' (not view-able) and 'b' (include in ViewB) but not 'a' assertEquals(3, result.c); assertEquals(2, result.b); assertEquals(0, result.a); } public void testWithCreatorsOrdered() throws Exception { CreatorAsArray input = new CreatorAsArray(3, 4); input.a = 1; input.b = 2; // note: Creator properties get sorted ahead of others, hence not [1,2,3,4] but: String json = MAPPER.writeValueAsString(input); assertEquals("[3,4,1,2]", json); // and should get back in proper order, too CreatorAsArray output = MAPPER.readValue(json, CreatorAsArray.class); assertEquals(1, output.a); assertEquals(2, output.b); assertEquals(3, output.x); assertEquals(4, output.y); } // Same as above, but ordering of properties different... public void testWithCreatorsShuffled() throws Exception { CreatorAsArrayShuffled input = new CreatorAsArrayShuffled(3, 4); input.a = 1; input.b = 2; // note: explicit ordering overrides implicit creators-first ordering: String json = MAPPER.writeValueAsString(input); assertEquals("[1,2,3,4]", json); // and should get back in proper order, too CreatorAsArrayShuffled output = MAPPER.readValue(json, CreatorAsArrayShuffled.class); assertEquals(1, output.a); assertEquals(2, output.b); assertEquals(3, output.x); assertEquals(4, output.y); } } TestPOJOAsArrayWithBuilder.java000066400000000000000000000136341325620701100377360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; /** * Unit tests for "POJO as array" feature using Builder-style * POJO construction. */ public class TestPOJOAsArrayWithBuilder extends BaseMapTest { @JsonDeserialize(builder=SimpleBuilderXY.class) @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder(alphabetic=true) static class ValueClassXY { final int _x, _y; protected ValueClassXY(int x, int y) { _x = x+1; _y = y+1; } } @JsonFormat(shape=JsonFormat.Shape.ARRAY) static class SimpleBuilderXY { public int x, y; protected SimpleBuilderXY() { } protected SimpleBuilderXY(int x0, int y0) { x = x0; y = y0; } public SimpleBuilderXY withX(int x0) { this.x = x0; return this; } public SimpleBuilderXY withY(int y0) { this.y = y0; return this; } public ValueClassXY build() { return new ValueClassXY(x, y); } } // Also, with creator: @JsonDeserialize(builder=CreatorBuilder.class) @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder(alphabetic=true) static class CreatorValue { final int a, b, c; protected CreatorValue(int a, int b, int c) { this.a = a; this.b = b; this.c = c; } } @JsonFormat(shape=JsonFormat.Shape.ARRAY) static class CreatorBuilder { private final int a, b; private int c; @JsonCreator public CreatorBuilder(@JsonProperty("a") int a, @JsonProperty("b") int b) { this.a = a; this.b = b; } @JsonView(String.class) public CreatorBuilder withC(int v) { c = v; return this; } public CreatorValue build() { return new CreatorValue(a, b, c); } } /* /***************************************************** /* Basic tests /***************************************************** */ private final static ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleBuilder() throws Exception { // Ok, first, ensure that serializer will "black out" filtered properties ValueClassXY value = MAPPER.readValue("[1,2]", ValueClassXY.class); assertEquals(2, value._x); assertEquals(3, value._y); } // Won't work, but verify exception public void testBuilderWithUpdate() throws Exception { // Ok, first, simple case of all values being present try { /*value =*/ MAPPER.readerFor(ValueClassXY.class) .withValueToUpdate(new ValueClassXY(6, 7)) .readValue("[1,2]"); fail("Should not pass"); } catch (InvalidDefinitionException e) { verifyException(e, "Deserialization of"); verifyException(e, "by passing existing instance"); verifyException(e, "ValueClassXY"); } } /* /***************************************************** /* Creator test(s) /***************************************************** */ // test to ensure @JsonCreator also works public void testWithCreator() throws Exception { CreatorValue value = MAPPER.readValue("[1,2,3]", CreatorValue.class); assertEquals(1, value.a); assertEquals(2, value.b); assertEquals(3, value.c); // and should be ok with partial too? value = MAPPER.readValue("[1,2]", CreatorValue.class); assertEquals(1, value.a); assertEquals(2, value.b); assertEquals(0, value.c); value = MAPPER.readValue("[1]", CreatorValue.class); assertEquals(1, value.a); assertEquals(0, value.b); assertEquals(0, value.c); value = MAPPER.readValue("[]", CreatorValue.class); assertEquals(0, value.a); assertEquals(0, value.b); assertEquals(0, value.c); } public void testWithCreatorAndView() throws Exception { ObjectReader reader = MAPPER.readerFor(CreatorValue.class); CreatorValue value; // First including values in view value = reader.withView(String.class).readValue("[1,2,3]"); assertEquals(1, value.a); assertEquals(2, value.b); assertEquals(3, value.c); // then not including view value = reader.withView(Character.class).readValue("[1,2,3]"); assertEquals(1, value.a); assertEquals(2, value.b); assertEquals(0, value.c); } /* /***************************************************** /* Failure tests /***************************************************** */ public void testUnknownExtraProp() throws Exception { String json = "[1, 2, 3, 4]"; try { MAPPER.readValue(json, ValueClassXY.class); fail("should not pass with extra element"); } catch (MismatchedInputException e) { verifyException(e, "Unexpected JSON values"); } // but actually fine if skip-unknown set ValueClassXY v = MAPPER.readerFor(ValueClassXY.class) .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .readValue(json); assertNotNull(v); // note: +1 for both so assertEquals(v._x, 2); assertEquals(v._y, 3); } } TestParentChildReferences.java000066400000000000000000000257451325620701100377460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.*; public class TestParentChildReferences extends BaseMapTest { /* /********************************************************** /* Test classes /********************************************************** */ /** * First, a simple 'tree': just parent/child linkage */ static class SimpleTreeNode { public String name; // Reference back to parent; reference, ignored during ser, // re-constructed during deser @JsonBackReference public SimpleTreeNode parent; // Reference that is serialized normally during ser, back // reference within pointed-to instance assigned to point to // referring bean ("this") @JsonManagedReference public SimpleTreeNode child; public SimpleTreeNode() { this(null); } public SimpleTreeNode(String n) { name = n; } } static class SimpleTreeNode2 { public String name; protected SimpleTreeNode2 parent; protected SimpleTreeNode2 child; public SimpleTreeNode2() { this(null); } public SimpleTreeNode2(String n) { name = n; } @JsonBackReference public SimpleTreeNode2 getParent() { return parent; } public void setParent(SimpleTreeNode2 p) { parent = p; } @JsonManagedReference public SimpleTreeNode2 getChild() { return child; } public void setChild(SimpleTreeNode2 c) { child = c; } } /** * Then nodes with two separate linkages; parent/child * and prev/next-sibling */ static class FullTreeNode { public String name; // parent-child links @JsonBackReference("parent") public FullTreeNode parent; @JsonManagedReference("parent") public FullTreeNode firstChild; // sibling-links @JsonManagedReference("sibling") public FullTreeNode next; @JsonBackReference("sibling") protected FullTreeNode prev; public FullTreeNode() { this(null); } public FullTreeNode(String name) { this.name = name; } } /** * Class for testing managed references via arrays */ static class NodeArray { @JsonManagedReference("arr") public ArrayNode[] nodes; } static class ArrayNode { public String name; @JsonBackReference("arr") public NodeArray parent; public ArrayNode() { this(null); } public ArrayNode(String n) { name = n; } } /** * Class for testing managed references via Collections */ static class NodeList { @JsonManagedReference public List nodes; } static class NodeForList { public String name; @JsonBackReference public NodeList parent; public NodeForList() { this(null); } public NodeForList(String n) { name = n; } } static class NodeMap { @JsonManagedReference public Map nodes; } static class NodeForMap { public String name; @JsonBackReference public NodeMap parent; public NodeForMap() { this(null); } public NodeForMap(String n) { name = n; } } public static class Parent { @JsonManagedReference protected final List children = new ArrayList(); public List getChildren() { return children; } public void addChild(Child child) { children.add(child); child.setParent(this); } } public static class Child { protected Parent parent; protected final String value; // So that the bean is not empty of properties public Child(@JsonProperty("value") String value) { this.value = value; } public String getValue() { return value; } @JsonBackReference public Parent getParent() { return parent; } public void setParent(Parent parent) { this.parent = parent; } } @JsonTypeInfo(use=Id.NAME) @JsonSubTypes({@JsonSubTypes.Type(ConcreteNode.class)}) static abstract class AbstractNode { public String id; @JsonManagedReference public AbstractNode next; @JsonBackReference public AbstractNode prev; } @JsonTypeName("concrete") static class ConcreteNode extends AbstractNode { public ConcreteNode() { } public ConcreteNode(String id) { this.id = id; } } // [JACKSON-708] static class Model708 { } static class Advertisement708 extends Model708 { public String title; @JsonManagedReference public List photos; } static class Photo708 extends Model708 { public int id; @JsonBackReference public Advertisement708 advertisement; } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); public void testSimpleRefs() throws Exception { SimpleTreeNode root = new SimpleTreeNode("root"); SimpleTreeNode child = new SimpleTreeNode("kid"); root.child = child; child.parent = root; String json = MAPPER.writeValueAsString(root); SimpleTreeNode resultNode = MAPPER.readValue(json, SimpleTreeNode.class); assertEquals("root", resultNode.name); SimpleTreeNode resultChild = resultNode.child; assertNotNull(resultChild); assertEquals("kid", resultChild.name); assertSame(resultChild.parent, resultNode); } // [JACKSON-693] public void testSimpleRefsWithGetter() throws Exception { SimpleTreeNode2 root = new SimpleTreeNode2("root"); SimpleTreeNode2 child = new SimpleTreeNode2("kid"); root.child = child; child.parent = root; String json = MAPPER.writeValueAsString(root); SimpleTreeNode2 resultNode = MAPPER.readValue(json, SimpleTreeNode2.class); assertEquals("root", resultNode.name); SimpleTreeNode2 resultChild = resultNode.child; assertNotNull(resultChild); assertEquals("kid", resultChild.name); assertSame(resultChild.parent, resultNode); } public void testFullRefs() throws Exception { FullTreeNode root = new FullTreeNode("root"); FullTreeNode child1 = new FullTreeNode("kid1"); FullTreeNode child2 = new FullTreeNode("kid2"); root.firstChild = child1; child1.parent = root; child1.next = child2; child2.prev = child1; String json = MAPPER.writeValueAsString(root); FullTreeNode resultNode = MAPPER.readValue(json, FullTreeNode.class); assertEquals("root", resultNode.name); FullTreeNode resultChild = resultNode.firstChild; assertNotNull(resultChild); assertEquals("kid1", resultChild.name); assertSame(resultChild.parent, resultNode); // and then sibling linkage assertNull(resultChild.prev); FullTreeNode resultChild2 = resultChild.next; assertNotNull(resultChild2); assertEquals("kid2", resultChild2.name); assertSame(resultChild, resultChild2.prev); assertNull(resultChild2.next); } public void testArrayOfRefs() throws Exception { NodeArray root = new NodeArray(); ArrayNode node1 = new ArrayNode("a"); ArrayNode node2 = new ArrayNode("b"); root.nodes = new ArrayNode[] { node1, node2 }; String json = MAPPER.writeValueAsString(root); NodeArray result = MAPPER.readValue(json, NodeArray.class); ArrayNode[] kids = result.nodes; assertNotNull(kids); assertEquals(2, kids.length); assertEquals("a", kids[0].name); assertEquals("b", kids[1].name); assertSame(result, kids[0].parent); assertSame(result, kids[1].parent); } public void testListOfRefs() throws Exception { NodeList root = new NodeList(); NodeForList node1 = new NodeForList("a"); NodeForList node2 = new NodeForList("b"); root.nodes = Arrays.asList(node1, node2); String json = MAPPER.writeValueAsString(root); NodeList result = MAPPER.readValue(json, NodeList.class); List kids = result.nodes; assertNotNull(kids); assertEquals(2, kids.size()); assertEquals("a", kids.get(0).name); assertEquals("b", kids.get(1).name); assertSame(result, kids.get(0).parent); assertSame(result, kids.get(1).parent); } public void testMapOfRefs() throws Exception { NodeMap root = new NodeMap(); NodeForMap node1 = new NodeForMap("a"); NodeForMap node2 = new NodeForMap("b"); Map nodes = new HashMap(); nodes.put("a1", node1); nodes.put("b2", node2); root.nodes = nodes; String json = MAPPER.writeValueAsString(root); NodeMap result = MAPPER.readValue(json, NodeMap.class); Map kids = result.nodes; assertNotNull(kids); assertEquals(2, kids.size()); assertNotNull(kids.get("a1")); assertNotNull(kids.get("b2")); assertEquals("a", kids.get("a1").name); assertEquals("b", kids.get("b2").name); assertSame(result, kids.get("a1").parent); assertSame(result, kids.get("b2").parent); } // for [JACKSON-368] public void testAbstract368() throws Exception { AbstractNode parent = new ConcreteNode("p"); AbstractNode child = new ConcreteNode("c"); parent.next = child; child.prev = parent; // serialization ought to be ok String json = MAPPER.writeValueAsString(parent); AbstractNode root = MAPPER.readValue(json, AbstractNode.class); assertEquals(ConcreteNode.class, root.getClass()); assertEquals("p", root.id); assertNull(root.prev); AbstractNode leaf = root.next; assertNotNull(leaf); assertEquals("c", leaf.id); assertSame(root, leaf.prev); } public void testIssue693() throws Exception { Parent parent = new Parent(); parent.addChild(new Child("foo")); parent.addChild(new Child("bar")); byte[] bytes = MAPPER.writeValueAsBytes(parent); Parent value = MAPPER.readValue(bytes, Parent.class); for (Child child : value.children) { assertEquals(value, child.getParent()); } } public void testIssue708() throws Exception { Advertisement708 ad = MAPPER.readValue("{\"title\":\"Hroch\",\"photos\":[{\"id\":3}]}", Advertisement708.class); assertNotNull(ad); } } TestUnwrapped.java000066400000000000000000000137611325620701100355070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying that basic {@link JsonUnwrapped} annotation * handling works as expected; some more advanced tests are separated out * to more specific test classes (like prefix/suffix handling). */ public class TestUnwrapped extends BaseMapTest { static class Unwrapping { public String name; @JsonUnwrapped public Location location; public Unwrapping() { } public Unwrapping(String str, int x, int y) { name = str; location = new Location(x, y); } } final static class Location { public int x; public int y; public Location() { } public Location(int x, int y) { this.x = x; this.y = y; } } static class DeepUnwrapping { @JsonUnwrapped public Unwrapping unwrapped; public DeepUnwrapping() { } public DeepUnwrapping(String str, int x, int y) { unwrapped = new Unwrapping(str, x, y); } } static class UnwrappingWithCreator { public String name; @JsonUnwrapped public Location location; @JsonCreator public UnwrappingWithCreator(@JsonProperty("name") String n) { name = n; } } // Class with two unwrapped properties static class TwoUnwrappedProperties { @JsonUnwrapped public Location location; @JsonUnwrapped public Name name; public TwoUnwrappedProperties() { } } static class Name { public String first, last; } // [databind#615] static class Parent { @JsonUnwrapped public Child c1; public Parent() { } public Parent(String str) { c1 = new Child(str); } } static class Child { public String field; public Child() { } public Child(String f) { field = f; } } static class Inner { public String animal; } static class Outer { // @JsonProperty @JsonUnwrapped private Inner inner; } // [databind#1493]: case-insensitive handling static class Person { @JsonUnwrapped(prefix = "businessAddress.") public Address businessAddress; } static class Address { public String street; public String addon; public String zip; public String town; public String country; } /* /********************************************************** /* Tests, serialization /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleUnwrappingSerialize() throws Exception { assertEquals("{\"name\":\"Tatu\",\"x\":1,\"y\":2}", MAPPER.writeValueAsString(new Unwrapping("Tatu", 1, 2))); } public void testDeepUnwrappingSerialize() throws Exception { assertEquals("{\"name\":\"Tatu\",\"x\":1,\"y\":2}", MAPPER.writeValueAsString(new DeepUnwrapping("Tatu", 1, 2))); } /* /********************************************************** /* Tests, deserialization /********************************************************** */ public void testSimpleUnwrappedDeserialize() throws Exception { Unwrapping bean = MAPPER.readValue("{\"name\":\"Tatu\",\"y\":7,\"x\":-13}", Unwrapping.class); assertEquals("Tatu", bean.name); Location loc = bean.location; assertNotNull(loc); assertEquals(-13, loc.x); assertEquals(7, loc.y); } public void testDoubleUnwrapping() throws Exception { TwoUnwrappedProperties bean = MAPPER.readValue("{\"first\":\"Joe\",\"y\":7,\"last\":\"Smith\",\"x\":-13}", TwoUnwrappedProperties.class); Location loc = bean.location; assertNotNull(loc); assertEquals(-13, loc.x); assertEquals(7, loc.y); Name name = bean.name; assertNotNull(name); assertEquals("Joe", name.first); assertEquals("Smith", name.last); } public void testDeepUnwrapping() throws Exception { DeepUnwrapping bean = MAPPER.readValue("{\"x\":3,\"name\":\"Bob\",\"y\":27}", DeepUnwrapping.class); Unwrapping uw = bean.unwrapped; assertNotNull(uw); assertEquals("Bob", uw.name); Location loc = uw.location; assertNotNull(loc); assertEquals(3, loc.x); assertEquals(27, loc.y); } public void testUnwrappedDeserializeWithCreator() throws Exception { UnwrappingWithCreator bean = MAPPER.readValue("{\"x\":1,\"y\":2,\"name\":\"Tatu\"}", UnwrappingWithCreator.class); assertEquals("Tatu", bean.name); Location loc = bean.location; assertNotNull(loc); assertEquals(1, loc.x); assertEquals(2, loc.y); } public void testIssue615() throws Exception { Parent input = new Parent("name"); String json = MAPPER.writeValueAsString(input); Parent output = MAPPER.readValue(json, Parent.class); assertEquals("name", output.c1.field); } public void testUnwrappedAsPropertyIndicator() throws Exception { Inner inner = new Inner(); inner.animal = "Zebra"; Outer outer = new Outer(); outer.inner = inner; String actual = MAPPER.writeValueAsString(outer); assertTrue(actual.contains("animal")); assertTrue(actual.contains("Zebra")); assertFalse(actual.contains("inner")); } // [databind#1493]: case-insensitive handling public void testCaseInsensitiveUnwrap() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); Person p = mapper.readValue("{ }", Person.class); assertNotNull(p); } } TestUnwrappedRecursive383.java000066400000000000000000000020651325620701100376300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // Problem with recursive definition of unwrapping public class TestUnwrappedRecursive383 extends BaseMapTest { // [databind#383] static class RecursivePerson { public String name; public int age; @JsonUnwrapped(prefix="child.") public RecursivePerson child; } /* /********************************************************** /* Tests, serialization /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testRecursiveUsage() throws Exception { final String JSON = "{ 'name': 'Bob', 'age': 45, 'gender': 0, 'child.name': 'Bob jr', 'child.age': 15 }"; RecursivePerson p = MAPPER.readValue(aposToQuotes(JSON), RecursivePerson.class); assertNotNull(p); assertEquals("Bob", p.name); assertNotNull(p.child); assertEquals("Bob jr", p.child.name); } } TestUnwrappedWithPrefix.java000066400000000000000000000157531325620701100375240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class TestUnwrappedWithPrefix extends BaseMapTest { static class Unwrapping { public String name; @JsonUnwrapped public Location location; public Unwrapping() { } public Unwrapping(String str, int x, int y) { name = str; location = new Location(x, y); } } static class DeepUnwrapping { @JsonUnwrapped public Unwrapping unwrapped; public DeepUnwrapping() { } public DeepUnwrapping(String str, int x, int y) { unwrapped = new Unwrapping(str, x, y); } } static class Location { public int x; public int y; public Location() { } public Location(int x, int y) { this.x = x; this.y = y; } } // Class with unwrapping using prefixes static class PrefixUnwrap { public String name; @JsonUnwrapped(prefix="_") public Location location; public PrefixUnwrap() { } public PrefixUnwrap(String str, int x, int y) { name = str; location = new Location(x, y); } } static class DeepPrefixUnwrap { @JsonUnwrapped(prefix="u.") public PrefixUnwrap unwrapped; public DeepPrefixUnwrap() { } public DeepPrefixUnwrap(String str, int x, int y) { unwrapped = new PrefixUnwrap(str, x, y); } } // Let's actually test hierarchic names with unwrapping bit more: static class ConfigRoot { @JsonUnwrapped(prefix="general.") public ConfigGeneral general = new ConfigGeneral(); @JsonUnwrapped(prefix="misc.") public ConfigMisc misc = new ConfigMisc(); public ConfigRoot() { } public ConfigRoot(String name, int value) { general = new ConfigGeneral(name); misc.value = value; } } static class ConfigAlternate { @JsonUnwrapped public ConfigGeneral general = new ConfigGeneral(); @JsonUnwrapped(prefix="misc.") public ConfigMisc misc = new ConfigMisc(); public int id; public ConfigAlternate() { } public ConfigAlternate(int id, String name, int value) { this.id = id; general = new ConfigGeneral(name); misc.value = value; } } static class ConfigGeneral { @JsonUnwrapped(prefix="names.") public ConfigNames names = new ConfigNames(); public ConfigGeneral() { } public ConfigGeneral(String name) { names.name = name; } } static class ConfigNames { public String name = "x"; } static class ConfigMisc { public int value; } // For [Issue#226] static class Parent { @JsonUnwrapped(prefix="c1.") public Child c1; @JsonUnwrapped(prefix="c2.") public Child c2; } static class Child { @JsonUnwrapped(prefix="sc2.") public SubChild sc1; } static class SubChild { public String value; } /* /********************************************************** /* Tests, serialization /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testPrefixedUnwrappingSerialize() throws Exception { assertEquals("{\"name\":\"Tatu\",\"_x\":1,\"_y\":2}", MAPPER.writeValueAsString(new PrefixUnwrap("Tatu", 1, 2))); } public void testDeepPrefixedUnwrappingSerialize() throws Exception { String json = MAPPER.writeValueAsString(new DeepPrefixUnwrap("Bubba", 1, 1)); assertEquals("{\"u.name\":\"Bubba\",\"u._x\":1,\"u._y\":1}", json); } public void testHierarchicConfigSerialize() throws Exception { String json = MAPPER.writeValueAsString(new ConfigRoot("Fred", 25)); assertEquals("{\"general.names.name\":\"Fred\",\"misc.value\":25}", json); } /* /********************************************************** /* Tests, deserialization /********************************************************** */ public void testPrefixedUnwrapping() throws Exception { PrefixUnwrap bean = MAPPER.readValue("{\"name\":\"Axel\",\"_x\":4,\"_y\":7}", PrefixUnwrap.class); assertNotNull(bean); assertEquals("Axel", bean.name); assertNotNull(bean.location); assertEquals(4, bean.location.x); assertEquals(7, bean.location.y); } public void testDeepPrefixedUnwrappingDeserialize() throws Exception { DeepPrefixUnwrap bean = MAPPER.readValue("{\"u.name\":\"Bubba\",\"u._x\":2,\"u._y\":3}", DeepPrefixUnwrap.class); assertNotNull(bean.unwrapped); assertNotNull(bean.unwrapped.location); assertEquals(2, bean.unwrapped.location.x); assertEquals(3, bean.unwrapped.location.y); assertEquals("Bubba", bean.unwrapped.name); } public void testHierarchicConfigDeserialize() throws Exception { ConfigRoot root = MAPPER.readValue("{\"general.names.name\":\"Bob\",\"misc.value\":3}", ConfigRoot.class); assertNotNull(root.general); assertNotNull(root.general.names); assertNotNull(root.misc); assertEquals(3, root.misc.value); assertEquals("Bob", root.general.names.name); } /* /********************************************************** /* Tests, round-trip /********************************************************** */ public void testHierarchicConfigRoundTrip() throws Exception { ConfigAlternate input = new ConfigAlternate(123, "Joe", 42); String json = MAPPER.writeValueAsString(input); ConfigAlternate root = MAPPER.readValue(json, ConfigAlternate.class); assertEquals(123, root.id); assertNotNull(root.general); assertNotNull(root.general.names); assertNotNull(root.misc); assertEquals("Joe", root.general.names.name); assertEquals(42, root.misc.value); } public void testIssue226() throws Exception { Parent input = new Parent(); input.c1 = new Child(); input.c1.sc1 = new SubChild(); input.c1.sc1.value = "a"; input.c2 = new Child(); input.c2.sc1 = new SubChild(); input.c2.sc1.value = "b"; String json = MAPPER.writeValueAsString(input); Parent output = MAPPER.readValue(json, Parent.class); assertNotNull(output.c1); assertNotNull(output.c2); assertNotNull(output.c1.sc1); assertNotNull(output.c2.sc1); assertEquals("a", output.c1.sc1.value); assertEquals("b", output.c2.sc1.value); } } TestUnwrappedWithSameName647.java000066400000000000000000000016221325620701100402040ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.*; public class TestUnwrappedWithSameName647 extends BaseMapTest { static class UnwrappedWithSamePropertyName { public MailHolder mail; } static class MailHolder { @JsonUnwrapped public Mail mail; } static class Mail { public String mail; } private final ObjectMapper MAPPER = new ObjectMapper(); public void testUnwrappedWithSamePropertyName() throws Exception { final String JSON = "{'mail': {'mail': 'the mail text'}}"; UnwrappedWithSamePropertyName result = MAPPER.readValue(aposToQuotes(JSON), UnwrappedWithSamePropertyName.class); assertNotNull(result.mail); assertNotNull(result.mail.mail); assertEquals("the mail text", result.mail.mail.mail); } } TestUnwrappedWithTypeInfo.java000066400000000000000000000044501325620701100400140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; // Tests for [#81] public class TestUnwrappedWithTypeInfo extends BaseMapTest { @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, property="@type") @JsonTypeName("OuterType") static class Outer { private @JsonProperty String p1; public String getP1() { return p1; } public void setP1(String p1) { this.p1 = p1; } private Inner inner; public void setInner(Inner inner) { this.inner = inner; } @JsonUnwrapped public Inner getInner() { return inner; } } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, property="@type") @JsonTypeName("InnerType") static class Inner { private @JsonProperty String p2; public String getP2() { return p2; } public void setP2(String p2) { this.p2 = p2; } } /* /********************************************************** /* Tests, serialization /********************************************************** */ // [Issue#81] public void testDefaultUnwrappedWithTypeInfo() throws Exception { Outer outer = new Outer(); outer.setP1("101"); Inner inner = new Inner(); inner.setP2("202"); outer.setInner(inner); ObjectMapper mapper = new ObjectMapper(); try { mapper.writeValueAsString(outer); fail("Expected exception to be thrown."); } catch (JsonMappingException ex) { verifyException(ex, "requires use of type information"); } } public void testUnwrappedWithTypeInfoAndFeatureDisabled() throws Exception { Outer outer = new Outer(); outer.setP1("101"); Inner inner = new Inner(); inner.setP2("202"); outer.setInner(inner); ObjectMapper mapper = new ObjectMapper(); mapper = mapper.disable(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS); String json = mapper.writeValueAsString(outer); assertEquals("{\"@type\":\"OuterType\",\"p1\":\"101\",\"p2\":\"202\"}", json); } }UnwrapSingleArrayScalarsTest.java000066400000000000000000000446231325620701100404710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import java.io.IOException; import java.io.StringReader; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.util.UUID; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.exc.MismatchedInputException; public class UnwrapSingleArrayScalarsTest extends BaseMapTest { static class BooleanBean { boolean _v; void setV(boolean v) { _v = v; } } private final ObjectMapper MAPPER = new ObjectMapper(); private final ObjectReader NO_UNWRAPPING_READER = MAPPER.reader(); private final ObjectReader UNWRAPPING_READER = MAPPER.reader() .with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); /* /********************************************************** /* Tests for boolean /********************************************************** */ public void testBooleanPrimitiveArrayUnwrap() throws Exception { // [databind#381] final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); BooleanBean result = mapper.readValue(new StringReader("{\"v\":[true]}"), BooleanBean.class); assertTrue(result._v); _verifyMultiValueArrayFail("[{\"v\":[true,true]}]", BooleanBean.class); result = mapper.readValue("{\"v\":[null]}", BooleanBean.class); assertNotNull(result); assertFalse(result._v); result = mapper.readValue("[{\"v\":[null]}]", BooleanBean.class); assertNotNull(result); assertFalse(result._v); boolean[] array = mapper.readValue(new StringReader("[ [ null ] ]"), boolean[].class); assertNotNull(array); assertEquals(1, array.length); assertFalse(array[0]); } /* /********************************************************** /* Single-element as array tests, numbers /********************************************************** */ // [databind#381] public void testSingleElementScalarArrays() throws Exception { final int intTest = 932832; final double doubleTest = 32.3234; final long longTest = 2374237428374293423L; final short shortTest = (short) intTest; final float floatTest = 84.3743f; final byte byteTest = (byte) 43; final char charTest = 'c'; final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); final int intValue = mapper.readValue(asArray(intTest), Integer.TYPE); assertEquals(intTest, intValue); final Integer integerWrapperValue = mapper.readValue(asArray(Integer.valueOf(intTest)), Integer.class); assertEquals(Integer.valueOf(intTest), integerWrapperValue); final double doubleValue = mapper.readValue(asArray(doubleTest), Double.class); assertEquals(doubleTest, doubleValue); final Double doubleWrapperValue = mapper.readValue(asArray(Double.valueOf(doubleTest)), Double.class); assertEquals(Double.valueOf(doubleTest), doubleWrapperValue); final long longValue = mapper.readValue(asArray(longTest), Long.TYPE); assertEquals(longTest, longValue); final Long longWrapperValue = mapper.readValue(asArray(Long.valueOf(longTest)), Long.class); assertEquals(Long.valueOf(longTest), longWrapperValue); final short shortValue = mapper.readValue(asArray(shortTest), Short.TYPE); assertEquals(shortTest, shortValue); final Short shortWrapperValue = mapper.readValue(asArray(Short.valueOf(shortTest)), Short.class); assertEquals(Short.valueOf(shortTest), shortWrapperValue); final float floatValue = mapper.readValue(asArray(floatTest), Float.TYPE); assertEquals(floatTest, floatValue); final Float floatWrapperValue = mapper.readValue(asArray(Float.valueOf(floatTest)), Float.class); assertEquals(Float.valueOf(floatTest), floatWrapperValue); final byte byteValue = mapper.readValue(asArray(byteTest), Byte.TYPE); assertEquals(byteTest, byteValue); final Byte byteWrapperValue = mapper.readValue(asArray(Byte.valueOf(byteTest)), Byte.class); assertEquals(Byte.valueOf(byteTest), byteWrapperValue); final char charValue = mapper.readValue(asArray(quote(String.valueOf(charTest))), Character.TYPE); assertEquals(charTest, charValue); final Character charWrapperValue = mapper.readValue(asArray(quote(String.valueOf(charTest))), Character.class); assertEquals(Character.valueOf(charTest), charWrapperValue); final boolean booleanTrueValue = mapper.readValue(asArray(true), Boolean.TYPE); assertTrue(booleanTrueValue); final boolean booleanFalseValue = mapper.readValue(asArray(false), Boolean.TYPE); assertFalse(booleanFalseValue); final Boolean booleanWrapperTrueValue = mapper.readValue(asArray(Boolean.valueOf(true)), Boolean.class); assertEquals(Boolean.TRUE, booleanWrapperTrueValue); } public void testSingleElementArrayDisabled() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); try { mapper.readValue("[42]", Integer.class); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[42]", Integer.TYPE); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[42342342342342]", Long.class); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[42342342342342342]", Long.TYPE); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[42]", Short.class); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[42]", Short.TYPE); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[327.2323]", Float.class); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[82.81902]", Float.TYPE); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[22]", Byte.class); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[22]", Byte.TYPE); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("['d']", Character.class); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("['d']", Character.TYPE); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[true]", Boolean.class); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } try { mapper.readValue("[true]", Boolean.TYPE); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException exp) { //Exception was thrown correctly } } public void testMultiValueArrayException() throws IOException { _verifyMultiValueArrayFail("[42,42]", Integer.class); _verifyMultiValueArrayFail("[42,42]", Integer.TYPE); _verifyMultiValueArrayFail("[42342342342342,42342342342342]", Long.class); _verifyMultiValueArrayFail("[42342342342342342,42342342342342]", Long.TYPE); _verifyMultiValueArrayFail("[42,42]", Short.class); _verifyMultiValueArrayFail("[42,42]", Short.TYPE); _verifyMultiValueArrayFail("[22,23]", Byte.class); _verifyMultiValueArrayFail("[22,23]", Byte.TYPE); _verifyMultiValueArrayFail("[327.2323,327.2323]", Float.class); _verifyMultiValueArrayFail("[82.81902,327.2323]", Float.TYPE); _verifyMultiValueArrayFail("[42.273,42.273]", Double.class); _verifyMultiValueArrayFail("[42.2723,42.273]", Double.TYPE); _verifyMultiValueArrayFail(asArray(quote("c") + "," + quote("d")), Character.class); _verifyMultiValueArrayFail(asArray(quote("c") + "," + quote("d")), Character.TYPE); _verifyMultiValueArrayFail("[true,false]", Boolean.class); _verifyMultiValueArrayFail("[true,false]", Boolean.TYPE); } /* /********************************************************** /* Simple non-primitive types /********************************************************** */ public void testSingleString() throws Exception { String value = "FOO!"; String result = MAPPER.readValue("\""+value+"\"", String.class); assertEquals(value, result); } public void testSingleStringWrapped() throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); String value = "FOO!"; try { mapper.readValue("[\""+value+"\"]", String.class); fail("Exception not thrown when attempting to unwrap a single value 'String' array into a simple String"); } catch (MismatchedInputException exp) { verifyException(exp, "Cannot deserialize"); verifyException(exp, "out of START_ARRAY"); } mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); try { mapper.readValue("[\""+value+"\",\""+value+"\"]", String.class); fail("Exception not thrown when attempting to unwrap a single value 'String' array that contained more than one value into a simple String"); } catch (MismatchedInputException exp) { verifyException(exp, "Attempted to unwrap"); } String result = mapper.readValue("[\""+value+"\"]", String.class); assertEquals(value, result); } public void testBigDecimal() throws Exception { final ObjectMapper mapper = objectMapper(); mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); BigDecimal value = new BigDecimal("0.001"); BigDecimal result = mapper.readValue(value.toString(), BigDecimal.class); assertEquals(value, result); try { mapper.readValue("[" + value.toString() + "]", BigDecimal.class); fail("Exception was not thrown when attempting to read a single value array of BigDecimal when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled"); } catch (MismatchedInputException exp) { verifyException(exp, "Cannot deserialize"); verifyException(exp, "out of START_ARRAY"); } mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); result = mapper.readValue("[" + value.toString() + "]", BigDecimal.class); assertEquals(value, result); try { mapper.readValue("[" + value.toString() + "," + value.toString() + "]", BigDecimal.class); fail("Exception was not thrown when attempting to read a muti value array of BigDecimal when UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled"); } catch (MismatchedInputException exp) { verifyException(exp, "Attempted to unwrap"); } } public void testBigInteger() throws Exception { final ObjectMapper mapper = objectMapper(); mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); BigInteger value = new BigInteger("-1234567890123456789012345567809"); BigInteger result = mapper.readValue(value.toString(), BigInteger.class); assertEquals(value, result); try { mapper.readValue("[" + value.toString() + "]", BigInteger.class); fail("Exception was not thrown when attempting to read a single value array of BigInteger when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled"); } catch (MismatchedInputException exp) { verifyException(exp, "Cannot deserialize"); verifyException(exp, "out of START_ARRAY"); } mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); result = mapper.readValue("[" + value.toString() + "]", BigInteger.class); assertEquals(value, result); try { mapper.readValue("[" + value.toString() + "," + value.toString() + "]", BigInteger.class); fail("Exception was not thrown when attempting to read a multi-value array of BigInteger when UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled"); } catch (MismatchedInputException exp) { verifyException(exp, "Attempted to unwrap"); } } public void testClassAsArray() throws Exception { Class result = MAPPER .readerFor(Class.class) .with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS) .readValue(quote(String.class.getName())); assertEquals(String.class, result); try { MAPPER.readerFor(Class.class) .without(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS) .readValue("[" + quote(String.class.getName()) + "]"); fail("Did not throw exception when UNWRAP_SINGLE_VALUE_ARRAYS feature was disabled and attempted to read a Class array containing one element"); } catch (MismatchedInputException e) { verifyException(e, "out of START_ARRAY token"); } _verifyMultiValueArrayFail("[" + quote(Object.class.getName()) + "," + quote(Object.class.getName()) +"]", Class.class); result = MAPPER.readerFor(Class.class) .with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS) .readValue("[" + quote(String.class.getName()) + "]"); assertEquals(String.class, result); } public void testURIAsArray() throws Exception { final ObjectReader reader = MAPPER.readerFor(URI.class); final URI value = new URI("http://foo.com"); try { reader.without(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS) .readValue("[\""+value.toString()+"\"]"); fail("Did not throw exception for single value array when UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException e) { verifyException(e, "out of START_ARRAY token"); } _verifyMultiValueArrayFail("[\""+value.toString()+"\",\""+value.toString()+"\"]", URI.class); } public void testUUIDAsArray() throws Exception { final ObjectReader reader = MAPPER.readerFor(UUID.class); final String uuidStr = "76e6d183-5f68-4afa-b94a-922c1fdb83f8"; UUID uuid = UUID.fromString(uuidStr); try { NO_UNWRAPPING_READER.forType(UUID.class) .readValue("[" + quote(uuidStr) + "]"); fail("Exception was not thrown when UNWRAP_SINGLE_VALUE_ARRAYS is disabled and attempted to read a single value array as a single element"); } catch (MismatchedInputException e) { verifyException(e, "out of START_ARRAY token"); } assertEquals(uuid, reader.with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS) .readValue("[" + quote(uuidStr) + "]")); _verifyMultiValueArrayFail("[" + quote(uuidStr) + "," + quote(uuidStr) + "]", UUID.class); } /* /********************************************************** /* Helper methods /********************************************************** */ private void _verifyMultiValueArrayFail(String input, Class type) throws IOException { try { UNWRAPPING_READER.forType(type).readValue(input); fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled"); } catch (MismatchedInputException e) { verifyException(e, "Attempted to unwrap"); } } private static String asArray(Object value) { return "["+value+"]"; } } UnwrappedCreatorParam265Test.java000066400000000000000000000062331325620701100402410ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; public class UnwrappedCreatorParam265Test extends BaseMapTest { static class JAddress { public String address; public String city; public String state; protected JAddress() { } public JAddress(String address, String city, String state) { this.address = address; this.city = city; this.state = state; } } static class JPersonWithoutName { public String name; protected JAddress _address; @JsonCreator public JPersonWithoutName(@JsonProperty("name") String name, @JsonUnwrapped JAddress address) { this.name = name; _address = address; } @JsonUnwrapped public JAddress getAddress() { return _address; } } static class JPersonWithName { public String name; protected JAddress _address; @JsonCreator public JPersonWithName(@JsonProperty("name") String name, @JsonUnwrapped @JsonProperty("address") JAddress address) { this.name = name; _address = address; } @JsonUnwrapped public JAddress getAddress() { return _address; } } /* /********************************************************** /* Test methods /********************************************************** */ // For [databind#265]: handle problem by throwing exception public void testUnwrappedWithUnnamedCreatorParam() throws Exception { JPersonWithoutName person = new JPersonWithoutName("MyName", new JAddress("main street", "springfield", "WA")); ObjectMapper mapper = new ObjectMapper(); // serialization should be fine as far as that goes String json = mapper.writeValueAsString(person); // but not deserialization: try { /*JPersonWithoutName result =*/ mapper.readValue(json, JPersonWithoutName.class); fail("Should not pass"); } catch (InvalidDefinitionException e) { verifyException(e, "Cannot define Creator parameter"); verifyException(e, "@JsonUnwrapped"); } } // For [databind#265]: handle problem by throwing exception public void testUnwrappedWithNamedCreatorParam() throws Exception { JPersonWithName person = new JPersonWithName("MyName", new JAddress("main street", "springfield", "WA")); ObjectMapper mapper = new ObjectMapper(); // serialization should be fine as far as that goes String json = mapper.writeValueAsString(person); try { /*JPersonWithName result =*/ mapper.readValue(json, JPersonWithName.class); fail("Should not pass"); } catch (InvalidDefinitionException e) { verifyException(e, "Cannot define Creator property \"address\""); verifyException(e, "@JsonUnwrapped"); } } } UnwrappedWithView1559Test.java000066400000000000000000000023611325620701100375140ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/structpackage com.fasterxml.jackson.databind.struct; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.*; public class UnwrappedWithView1559Test extends BaseMapTest { @JsonInclude(JsonInclude.Include.NON_EMPTY) static final class Health { @JsonUnwrapped(prefix="xxx.") public Status status; } // NOTE: `final` is required to trigger [databind#1559] static final class Status { public String code; } /* /********************************************************** /* Tests methods /********************************************************** */ // for [databind#1559] public void testCanSerializeSimpleWithDefaultView() throws Exception { String json = new ObjectMapper().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false) .writeValueAsString(new Health()); assertEquals(aposToQuotes("{}"), json); // and just in case this, although won't matter wrt output json = new ObjectMapper().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true) .writeValueAsString(new Health()); assertEquals(aposToQuotes("{}"), json); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/type/000077500000000000000000000000001325620701100315435ustar00rootroot00000000000000ContainerTypesTest.java000066400000000000000000000102361325620701100361400ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.MapType; import com.fasterxml.jackson.databind.util.LRUMap; // for [databind#1415] public class ContainerTypesTest extends BaseMapTest { static abstract class LongList implements List { } static abstract class StringLongMap implements Map { } /* /********************************************************** /* Unit tests, success /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testExplicitCollectionType() throws Exception { JavaType t = MAPPER.getTypeFactory() .constructCollectionType(LongList.class, Long.class); assertEquals(LongList.class, t.getRawClass()); assertEquals(Long.class, t.getContentType().getRawClass()); } public void testImplicitCollectionType() throws Exception { JavaType t = MAPPER.getTypeFactory() .constructParametricType(List.class, Long.class); assertEquals(CollectionType.class, t.getClass()); assertEquals(List.class, t.getRawClass()); assertEquals(Long.class, t.getContentType().getRawClass()); } // [databind#1725] public void testMissingCollectionType() throws Exception { TypeFactory tf = MAPPER.getTypeFactory().withCache(new LRUMap(4, 8)); JavaType t = tf.constructParametricType(List.class, HashMap.class); assertEquals(CollectionType.class, t.getClass()); assertEquals(List.class, t.getRawClass()); assertEquals(HashMap.class, t.getContentType().getRawClass()); } public void testExplicitMapType() throws Exception { JavaType t = MAPPER.getTypeFactory() .constructMapType(StringLongMap.class, String.class, Long.class); assertEquals(StringLongMap.class, t.getRawClass()); assertEquals(String.class, t.getKeyType().getRawClass()); assertEquals(Long.class, t.getContentType().getRawClass()); } public void testImplicitMapType() throws Exception { JavaType t = MAPPER.getTypeFactory() .constructParametricType(Map.class, Long.class, Boolean.class); assertEquals(MapType.class, t.getClass()); assertEquals(Long.class, t.getKeyType().getRawClass()); assertEquals(Boolean.class, t.getContentType().getRawClass()); } /* /********************************************************** /* Unit tests, fails /********************************************************** */ public void testMismatchedCollectionType() throws Exception { try { MAPPER.getTypeFactory() .constructCollectionType(LongList.class, String.class); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "`"+getClass().getName()+"$LongList` did not resolve to something"); verifyException(e, "element type"); } } public void testMismatchedMapType() throws Exception { // first, mismatched key type try { MAPPER.getTypeFactory() .constructMapType(StringLongMap.class, Boolean.class, Long.class); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "`"+getClass().getName()+"$StringLongMap` did not resolve to something"); verifyException(e, "key type"); } // then, mismatched value type try { MAPPER.getTypeFactory() .constructMapType(StringLongMap.class, String.class, Class.class); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "`"+getClass().getName()+"$StringLongMap` did not resolve to something"); verifyException(e, "value type"); } } } DeprecatedConstructType1456Test.java000066400000000000000000000036401325620701100403210ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.lang.reflect.Method; import java.lang.reflect.Type; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; // Tests for [databind#1456]: resolution using methods deprecated // in 2.7, but used to work in 2.6 public class DeprecatedConstructType1456Test extends BaseMapTest { public static class BaseController { public void process(Entity entity) {} } public static class ImplController extends BaseController {} public static class BaseEntity {} public static class ImplEntity extends BaseEntity {} private final ObjectMapper MAPPER = new ObjectMapper(); @SuppressWarnings("deprecation") public void testGenericResolutionUsingDeprecated() throws Exception { Method proceed = BaseController.class.getMethod("process", BaseEntity.class); Type entityType = proceed.getGenericParameterTypes()[0]; JavaType resolvedType = MAPPER.getTypeFactory().constructType(entityType, ImplController.class); assertEquals(ImplEntity.class, resolvedType.getRawClass()); } // and this is how new code should resolve types if at all possible public void testGenericParameterViaClass() throws Exception { BeanDescription desc = MAPPER.getDeserializationConfig().introspect( MAPPER.constructType(ImplController.class)); AnnotatedClass ac = desc.getClassInfo(); AnnotatedMethod m = ac.findMethod("process", new Class[] { BaseEntity.class }); assertNotNull(m); assertEquals(1, m.getParameterCount()); AnnotatedParameter param = m.getParameter(0); assertEquals(ImplEntity.class, param.getType().getRawClass()); } } LocalTypeTest.java000066400000000000000000000017521325620701100350700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import com.fasterxml.jackson.databind.*; public class LocalTypeTest extends BaseMapTest { // [databind#609] static class EntityContainer { RuleForm entity; @SuppressWarnings("unchecked") public T getEntity() { return (T) entity; } public void setEntity(T e) { entity = e; } } static class RuleForm { public int value; public RuleForm() { } public RuleForm(int v) { value = v; } } // [databind#609] public void testLocalPartialType609() throws Exception { ObjectMapper mapper = new ObjectMapper(); EntityContainer input = new EntityContainer(); input.entity = new RuleForm(12); String json = mapper.writeValueAsString(input); EntityContainer output = mapper.readValue(json, EntityContainer.class); assertEquals(12, output.getEntity().value); } } NestedTypes1604Test.java000066400000000000000000000066361325620701100357640ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.*; // for [databind#1604] public class NestedTypes1604Test extends BaseMapTest { public static class Data { private T data; public Data(T data) { this.data = data; } public T getData() { return data; } public static Data> of(List data) { return new DataList<>(data); } public static Data> ofRefined(List data) { return new RefinedDataList<>(data); } public static Data> ofSneaky(List data) { return new SneakyDataList(data); } } public static class DataList extends Data> { public DataList(List data) { super(data); } } // And then add one level between types public static class RefinedDataList extends DataList { public RefinedDataList(List data) { super(data); } } // And/or add another type parameter that is not relevant (less common // but potential concern) public static class SneakyDataList extends Data> { public SneakyDataList(List data) { super(data); } } public static class Inner { private int index; public Inner(int index) { this.index = index; } public int getIndex() { return index; } } public static class BadOuter { private Data> inner; public BadOuter(Data> inner) { this.inner = inner; } public Data> getInner() { return inner; } } public static class GoodOuter { private DataList inner; public GoodOuter(DataList inner) { this.inner = inner; } public DataList getInner() { return inner; } } private final ObjectMapper objectMapper = newObjectMapper(); public void testIssue1604Simple() throws Exception { List inners = new ArrayList<>(); for (int i = 0; i < 2; i++) { inners.add(new Inner(i)); } BadOuter badOuter = new BadOuter(Data.of(inners)); // GoodOuter goodOuter = new GoodOuter(new DataList<>(inners)); // String json = objectMapper.writeValueAsString(goodOuter); // 11-Oct-2017, tatu: Fails with exception wrt type specialization String json = objectMapper.writeValueAsString(badOuter); assertNotNull(json); } public void testIssue1604Subtype() throws Exception { List inners = new ArrayList<>(); for (int i = 0; i < 2; i++) { inners.add(new Inner(i)); } BadOuter badOuter = new BadOuter(Data.ofRefined(inners)); String json = objectMapper.writeValueAsString(badOuter); assertNotNull(json); } public void testIssue1604Sneaky() throws Exception { List inners = new ArrayList<>(); for (int i = 0; i < 2; i++) { inners.add(new Inner(i)); } BadOuter badOuter = new BadOuter(Data.ofSneaky(inners)); String json = objectMapper.writeValueAsString(badOuter); assertNotNull(json); } } PolymorphicList036Test.java000066400000000000000000000054571325620701100365740ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.*; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.databind.*; // For [databind#936], losing parametric type information it seems public class PolymorphicList036Test extends BaseMapTest { // note: would prefer using CharSequence, but while abstract, that's deserialized // just fine as ... String static class StringyList implements Collection { private Collection _stuff; @JsonCreator public StringyList(Collection src) { _stuff = new ArrayList(src); } public StringyList() { _stuff = new ArrayList(); } @Override public boolean add(T arg) { return _stuff.add(arg); } @Override public boolean addAll(Collection args) { return _stuff.addAll(args); } @Override public void clear() { _stuff.clear(); } @Override public boolean contains(Object arg) { return _stuff.contains(arg); } @Override public boolean containsAll(Collection args) { return _stuff.containsAll(args); } @Override public boolean isEmpty() { return _stuff.isEmpty(); } @Override public Iterator iterator() { return _stuff.iterator(); } @Override public boolean remove(Object arg) { return _stuff.remove(arg); } @Override public boolean removeAll(Collection args) { return _stuff.removeAll(args); } @Override public boolean retainAll(Collection args) { return _stuff.retainAll(args); } @Override public int size() { return _stuff.size(); } @Override public Object[] toArray() { return _stuff.toArray(); } @Override public X[] toArray(X[] arg) { return _stuff.toArray(arg); } } private final ObjectMapper MAPPER = new ObjectMapper(); public void testPolymorphicWithOverride() throws Exception { JavaType type = MAPPER.getTypeFactory().constructCollectionType(StringyList.class, String.class); StringyList list = new StringyList(); list.add("value 1"); list.add("value 2"); String serialized = MAPPER.writeValueAsString(list); // System.out.println(serialized); StringyList deserialized = MAPPER.readValue(serialized, type); // System.out.println(deserialized); assertNotNull(deserialized); } } RecursiveType1658Test.java000066400000000000000000000024531325620701100363300ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder; public class RecursiveType1658Test extends BaseMapTest { @SuppressWarnings("serial") static class Tree extends HashMap> // implements Serializable { public Tree() { } public Tree(List children) { this(); for (final T t : children) { this.put(t, new Tree()); } } public List> getLeafTrees() { return null; } } public void testRecursive1658() throws Exception { Tree t = new Tree(Arrays.asList("hello", "world")); ObjectMapper mapper = new ObjectMapper(); final TypeResolverBuilder typer = new StdTypeResolverBuilder() .init(JsonTypeInfo.Id.CLASS, null) .inclusion(JsonTypeInfo.As.PROPERTY); mapper.setDefaultTyping(typer); String res = mapper.writeValueAsString(t); Tree tRead = mapper.readValue(res, Tree.class); assertNotNull(tRead); } } RecursiveTypeTest.java000066400000000000000000000067501325620701100360100ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.*; import com.fasterxml.jackson.databind.*; public class RecursiveTypeTest extends BaseMapTest { // for [databind#1301] @SuppressWarnings("serial") static class HashTree extends HashMap> { } // for [databind#938] public static interface Ability { } // for [databind#1647] static interface IFace {} // for [databind#1647] static class Base implements IFace { } // for [databind#1647] static class Sub extends Base { } public static final class ImmutablePair implements Map.Entry, Ability> { public final L key; public final R value; public ImmutablePair(final L key, final R value) { this.key = key; this.value = value; } @Override public L getKey() { return key; } @Override public R getValue() { return value; } @Override public R setValue(final R value) { throw new UnsupportedOperationException(); } static ImmutablePair of(final L left, final R right) { return new ImmutablePair(left, right); } } // for [databind#1301] public void testRecursiveType() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType type = tf.constructType(HashTree.class); assertNotNull(type); } // for [databind#1301] @SuppressWarnings("serial") static class DataDefinition extends HashMap { public DataDefinition definition; public DataDefinition elements; public String regex; public boolean required; public String type; } private final ObjectMapper MAPPER = new ObjectMapper(); // [databind#938] public void testRecursivePair() throws Exception { JavaType t = MAPPER.constructType(ImmutablePair.class); assertNotNull(t); assertEquals(ImmutablePair.class, t.getRawClass()); List> list = new ArrayList>(); list.add(ImmutablePair.of("Hello World!", 123d)); String json = MAPPER.writeValueAsString(list); assertNotNull(json); // cannot deserialize with current definition, however } // for [databind#1301] public void testJavaTypeToString() throws Exception { TypeFactory tf = objectMapper().getTypeFactory(); String desc = tf.constructType(DataDefinition.class).toString(); assertNotNull(desc); // could try comparing exact message, but since it's informational try looser: if (!desc.contains("map type")) { fail("Description should contain 'map type', did not: "+desc); } if (!desc.contains("recursive type")) { fail("Description should contain 'recursive type', did not: "+desc); } } // for [databind#1647] public void testSuperClassWithReferencedJavaType() { TypeFactory tf = objectMapper().getTypeFactory(); tf.constructType(Base.class); // must be constructed before sub to set the cache correctly JavaType subType = tf.constructType(Sub.class); // baseTypeFromSub should be a ResolvedRecursiveType in this test JavaType baseTypeFromSub = subType.getSuperClass(); assertNotNull(baseTypeFromSub.getSuperClass()); } } TestAnnotatedClass.java000066400000000000000000000075571325620701100361100ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.*; /** * Unit test for verifying that {@link AnnotatedClass} * works as expected. */ public class TestAnnotatedClass extends BaseMapTest { /* /********************************************************** /* Annotated helper classes /********************************************************** */ static class BaseClass { public int foo; public BaseClass(int x, int y) { } @JsonProperty public int x() { return 3; } } static class SubClass extends BaseClass { public SubClass() { this(1); } public SubClass(int x) { super(x, 2); } public int y() { return 3; } } static abstract class GenericBase { public abstract void setX(T value); } static class NumberBean extends GenericBase { @Override public void setX(Integer value) { } } /** * Test class for checking that field introspection * works as expected */ @SuppressWarnings("unused") static class FieldBean { // static, not to be included: public static boolean DUMMY; // not public, no annotations, shouldn't be included private long bar; @JsonProperty private String props; } // for [databind#1005] static class Bean1005 { // private to force creation of a synthetic constructor to avoid access issues private Bean1005(int i) {} } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testFieldIntrospection() { SerializationConfig config = MAPPER.getSerializationConfig(); JavaType t = MAPPER.constructType(FieldBean.class); AnnotatedClass ac = AnnotatedClassResolver.resolve(config, t, config); // AnnotatedClass does not ignore non-visible fields, yet assertEquals(2, ac.getFieldCount()); for (AnnotatedField f : ac.fields()) { String fname = f.getName(); if (!"bar".equals(fname) && !"props".equals(fname)) { fail("Unexpected field name '"+fname+"'"); } } } // For [databind#1005] public void testConstructorIntrospection() { // Need this call to ensure there is a synthetic constructor being generated // (not really needed otherwise) Bean1005 bean = new Bean1005(13); SerializationConfig config = MAPPER.getSerializationConfig(); JavaType t = MAPPER.constructType(bean.getClass()); AnnotatedClass ac = AnnotatedClassResolver.resolve(config, t, config); assertEquals(1, ac.getConstructors().size()); } public void testArrayTypeIntrospection() throws Exception { AnnotatedClass ac = AnnotatedClassResolver.resolve(MAPPER.getSerializationConfig(), MAPPER.constructType(int[].class), null); // 09-Jun-2017, tatu: During 2.9 development, access methods were failing at // certain points so assertFalse(ac.memberMethods().iterator().hasNext()); assertFalse(ac.fields().iterator().hasNext()); } public void testIntrospectionWithRawClass() throws Exception { AnnotatedClass ac = AnnotatedClassResolver.resolveWithoutSuperTypes(MAPPER.getSerializationConfig(), String.class, null); // 09-Jun-2017, tatu: During 2.9 development, access methods were failing at // certain points so assertFalse(ac.memberMethods().iterator().hasNext()); assertFalse(ac.fields().iterator().hasNext()); } } TestGenericFieldInSubtype.java000066400000000000000000000022551325620701100373560ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import com.fasterxml.jackson.databind.*; public class TestGenericFieldInSubtype extends BaseMapTest { // [JACKSON-677] public void test677() throws Exception { ObjectMapper mapper = new ObjectMapper(); // and bit more checking as per later comments JavaType t677 = mapper.constructType(Result677.Success677.class); assertNotNull(t677); Result677.Success677 s = new Result677.Success677(Integer.valueOf(4)); String json = mapper.writeValueAsString(s); assertEquals("{\"value\":4}", json); } // [JACKSON-887] public void testInnerType() throws Exception { ObjectMapper mapper = new ObjectMapper(); BaseType.SubType r = mapper.readValue("{}", BaseType.SubType.class); assertNotNull(r); } } class Result677 { public static class Success677 extends Result677 { public K value; public Success677() { } public Success677(K k) { value = k; } } } abstract class BaseType { public T value; public final static class SubType extends BaseType { } } TestGenericsBounded.java000066400000000000000000000123011325620701100362240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.io.Serializable; import java.util.*; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; @SuppressWarnings("serial") public class TestGenericsBounded extends BaseMapTest { static class Range> implements Serializable { protected E start, end; public Range(){ } public Range(E start, E end) { this.start = start; this.end = end; } public E getEnd() { return end; } public void setEnd(E e) { end = e; } public E getStart() { return start; } public void setStart(E s) { start = s; } } static class DoubleRange extends Range { public DoubleRange() { } public DoubleRange(Double s, Double e) { super(s, e); } } static class BoundedWrapper { public List values; } static class IntBean implements Serializable { public int x; } static class IntBeanWrapper { public T wrapped; } // Types for [JACKSON-778] static class Document {} static class Row {} static class RowWithDoc extends Row { @JsonProperty("d") D d; } static class ResultSet { @JsonProperty("rows") List rows; } static class ResultSetWithDoc extends ResultSet> {} static class MyDoc extends Document {} // [databind#537] interface AnnotatedValue { public String getAnnotation(); public E getValue(); } static class AnnotatedValueSimple implements AnnotatedValue { protected E value; protected AnnotatedValueSimple() { } public AnnotatedValueSimple(E v) { value = v; } @Override public String getAnnotation() { return null; } @Override public E getValue() { return value; } } static class CbFailing, ID> { private E item; public CbFailing(E item) { this.item = item; } public E getItem() { return item; } public ID getId() { return item.getValue(); } } /* /******************************************************* /* Unit tests /******************************************************* */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testLowerBound() throws Exception { IntBeanWrapper result = MAPPER.readValue("{\"wrapped\":{\"x\":3}}", IntBeanWrapper.class); assertNotNull(result); assertEquals(IntBean.class, result.wrapped.getClass()); assertEquals(3, result.wrapped.x); } // Test related to type bound handling problem within [JACKSON-190] public void testBounded() throws Exception { BoundedWrapper result = MAPPER.readValue ("{\"values\":[ {\"x\":3} ] } ", new TypeReference>() {}); List list = result.values; assertEquals(1, list.size()); Object ob = list.get(0); assertEquals(IntBean.class, ob.getClass()); assertEquals(3, result.values.get(0).x); } public void testGenericsComplex() throws Exception { DoubleRange in = new DoubleRange(-0.5, 0.5); String json = MAPPER.writeValueAsString(in); DoubleRange out = MAPPER.readValue(json, DoubleRange.class); assertNotNull(out); assertEquals(-0.5, out.start); assertEquals(0.5, out.end); } public void testIssue778() throws Exception { String json = "{\"rows\":[{\"d\":{}}]}"; final TypeReference typeRef = new TypeReference>() {}; // First, verify type introspection: JavaType type = MAPPER.getTypeFactory().constructType(typeRef); JavaType resultSetType = type.findSuperType(ResultSet.class); assertNotNull(resultSetType); assertEquals(1, resultSetType.containedTypeCount()); JavaType rowType = resultSetType.containedType(0); assertNotNull(rowType); assertEquals(RowWithDoc.class, rowType.getRawClass()); assertEquals(1, rowType.containedTypeCount()); JavaType docType = rowType.containedType(0); assertEquals(MyDoc.class, docType.getRawClass()); // type passed is correct, but somehow it gets mangled when passed... ResultSetWithDoc rs = MAPPER.readValue(json, type); Document d = rs.rows.iterator().next().d; assertEquals(MyDoc.class, d.getClass()); //expected MyDoc but was Document } // [databind#537] public void test() throws Exception { AnnotatedValueSimple item = new AnnotatedValueSimple(5); CbFailing, Integer> codebook = new CbFailing, Integer>(item); String json = MAPPER.writeValueAsString(codebook); assertNotNull(json); } } TestJavaType.java000066400000000000000000000207711325620701100347210ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JavaType; /** * Simple tests to verify that {@link JavaType} types work to * some degree */ public class TestJavaType extends BaseMapTest { static class BaseType { } static class SubType extends BaseType { } static enum MyEnum { A, B; } static enum MyEnum2 { A(1), B(2); private MyEnum2(int value) { } } // [databind#728] static class Issue728 { public C method(C input) { return null; } } public interface Generic1194 { public AtomicReference getGeneric(); public List getList(); public Map getMap(); } @SuppressWarnings("serial") static class AtomicStringReference extends AtomicReference { } /* /********************************************************** /* Test methods /********************************************************** */ public void testLocalType728() throws Exception { TypeFactory tf = TypeFactory.defaultInstance(); Method m = Issue728.class.getMethod("method", CharSequence.class); assertNotNull(m); // Start with return type // first type-erased JavaType t = tf.constructType(m.getReturnType()); assertEquals(CharSequence.class, t.getRawClass()); // then generic t = tf.constructType(m.getGenericReturnType()); assertEquals(CharSequence.class, t.getRawClass()); // then parameter type t = tf.constructType(m.getParameterTypes()[0]); assertEquals(CharSequence.class, t.getRawClass()); t = tf.constructType(m.getGenericParameterTypes()[0]); assertEquals(CharSequence.class, t.getRawClass()); } public void testSimpleClass() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType baseType = tf.constructType(BaseType.class); assertSame(BaseType.class, baseType.getRawClass()); assertTrue(baseType.hasRawClass(BaseType.class)); assertFalse(baseType.isTypeOrSubTypeOf(SubType.class)); assertFalse(baseType.isArrayType()); assertFalse(baseType.isContainerType()); assertFalse(baseType.isEnumType()); assertFalse(baseType.isInterface()); assertFalse(baseType.isPrimitive()); assertFalse(baseType.isReferenceType()); assertFalse(baseType.hasContentType()); assertNull(baseType.getContentType()); assertNull(baseType.getKeyType()); assertNull(baseType.getValueHandler()); assertEquals("Lcom/fasterxml/jackson/databind/type/TestJavaType$BaseType;", baseType.getGenericSignature()); assertEquals("Lcom/fasterxml/jackson/databind/type/TestJavaType$BaseType;", baseType.getErasedSignature()); } @SuppressWarnings("deprecation") public void testDeprecated() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType baseType = tf.constructType(BaseType.class); assertTrue(baseType.hasRawClass(BaseType.class)); assertNull(baseType.getParameterSource()); assertNull(baseType.getContentTypeHandler()); assertNull(baseType.getContentValueHandler()); assertFalse(baseType.hasValueHandler()); assertFalse(baseType.hasHandlers()); assertSame(baseType, baseType.forcedNarrowBy(BaseType.class)); JavaType sub = baseType.forcedNarrowBy(SubType.class); assertTrue(sub.hasRawClass(SubType.class)); } public void testArrayType() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType arrayT = ArrayType.construct(tf.constructType(String.class), null); assertNotNull(arrayT); assertTrue(arrayT.isContainerType()); assertFalse(arrayT.isReferenceType()); assertTrue(arrayT.hasContentType()); assertNotNull(arrayT.toString()); assertNotNull(arrayT.getContentType()); assertNull(arrayT.getKeyType()); assertTrue(arrayT.equals(arrayT)); assertFalse(arrayT.equals(null)); assertFalse(arrayT.equals("xyz")); assertTrue(arrayT.equals(ArrayType.construct(tf.constructType(String.class), null))); assertFalse(arrayT.equals(ArrayType.construct(tf.constructType(Integer.class), null))); } public void testMapType() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType mapT = tf.constructType(HashMap.class); assertTrue(mapT.isContainerType()); assertFalse(mapT.isReferenceType()); assertTrue(mapT.hasContentType()); assertNotNull(mapT.toString()); assertNotNull(mapT.getContentType()); assertNotNull(mapT.getKeyType()); assertEquals("Ljava/util/HashMap;", mapT.getGenericSignature()); assertEquals("Ljava/util/HashMap;", mapT.getErasedSignature()); assertTrue(mapT.equals(mapT)); assertFalse(mapT.equals(null)); assertFalse(mapT.equals("xyz")); } public void testEnumType() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType enumT = tf.constructType(MyEnum.class); assertTrue(enumT.isEnumType()); assertFalse(enumT.hasHandlers()); assertTrue(enumT.isTypeOrSubTypeOf(MyEnum.class)); assertTrue(enumT.isTypeOrSubTypeOf(Object.class)); assertNull(enumT.containedType(3)); assertTrue(enumT.containedTypeOrUnknown(3).isJavaLangObject()); assertEquals("Lcom/fasterxml/jackson/databind/type/TestJavaType$MyEnum;", enumT.getGenericSignature()); assertEquals("Lcom/fasterxml/jackson/databind/type/TestJavaType$MyEnum;", enumT.getErasedSignature()); assertTrue(tf.constructType(MyEnum2.class).isEnumType()); assertTrue(tf.constructType(MyEnum.A.getClass()).isEnumType()); assertTrue(tf.constructType(MyEnum2.A.getClass()).isEnumType()); } public void testClassKey() { ClassKey key = new ClassKey(String.class); assertEquals(0, key.compareTo(key)); assertTrue(key.equals(key)); assertFalse(key.equals(null)); assertFalse(key.equals("foo")); assertFalse(key.equals(new ClassKey(Integer.class))); assertEquals(String.class.getName(), key.toString()); } // [databind#116] public void testJavaTypeAsJLRType() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t1 = tf.constructType(getClass()); // should just get it back as-is: JavaType t2 = tf.constructType(t1); assertSame(t1, t2); } // [databind#1194] public void testGenericSignature1194() throws Exception { TypeFactory tf = TypeFactory.defaultInstance(); Method m; JavaType t; m = Generic1194.class.getMethod("getList"); t = tf.constructType(m.getGenericReturnType()); assertEquals("Ljava/util/List;", t.getGenericSignature()); assertEquals("Ljava/util/List;", t.getErasedSignature()); m = Generic1194.class.getMethod("getMap"); t = tf.constructType(m.getGenericReturnType()); assertEquals("Ljava/util/Map;", t.getGenericSignature()); m = Generic1194.class.getMethod("getGeneric"); t = tf.constructType(m.getGenericReturnType()); assertEquals("Ljava/util/concurrent/atomic/AtomicReference;", t.getGenericSignature()); } public void testAnchorTypeForRefTypes() throws Exception { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t = tf.constructType(AtomicStringReference.class); assertTrue(t.isReferenceType()); assertTrue(t.hasContentType()); ReferenceType rt = (ReferenceType) t; assertFalse(rt.isAnchorType()); assertEquals(AtomicReference.class, rt.getAnchorType().getRawClass()); } // for [databind#1290] public void testObjectToReferenceSpecialization() throws Exception { TypeFactory tf = TypeFactory.defaultInstance(); JavaType base = tf.constructType(Object.class); assertTrue(base.isJavaLangObject()); JavaType sub = tf.constructSpecializedType(base, AtomicReference.class); assertEquals(AtomicReference.class, sub.getRawClass()); assertTrue(sub.isReferenceType()); } } TestTypeBindings.java000066400000000000000000000055141325620701100355730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JavaType; /** * Simple tests to verify for generic type binding functionality * implemented by {@link TypeBindings} class. */ public class TestTypeBindings extends BaseMapTest { static class AbstractType { } static class LongStringType extends AbstractType { } static class InnerGenericTyping extends AbstractMap> { @Override public Set>> entrySet() { return null; } public class InnerClass extends AbstractMap> { @Override public Set>> entrySet() { return null; } } } // for [databind#76] @SuppressWarnings("serial") static class HashTree extends HashMap> { } /* /********************************************************** /* Test methods /********************************************************** */ private final TypeFactory DEFAULT_TF = TypeFactory.defaultInstance(); public void testInnerType() throws Exception { JavaType type = DEFAULT_TF.constructType(InnerGenericTyping.InnerClass.class); assertEquals(MapType.class, type.getClass()); JavaType keyType = type.getKeyType(); assertEquals(Object.class, keyType.getRawClass()); JavaType valueType = type.getContentType(); assertEquals(Collection.class, valueType.getRawClass()); JavaType vt2 = valueType.getContentType(); assertEquals(Object.class, vt2.getRawClass()); } // for [databind#76] public void testRecursiveType() { JavaType type = DEFAULT_TF.constructType(HashTree.class); assertNotNull(type); } public void testBindingsBasics() { TypeBindings b = TypeBindings.create(Collection.class, TypeFactory.unknownType()); // let's just call it -- should probably try to inspect but... assertNotNull(b.toString()); assertEquals(Object.class, b.getBoundType(0).getRawClass()); assertNull(b.getBoundName(-1)); assertNull(b.getBoundType(-1)); assertNull(b.getBoundName(1)); assertNull(b.getBoundType(1)); assertFalse(b.equals("foo")); } public void testInvalidBindings() { JavaType unknown = TypeFactory.unknownType(); try { TypeBindings.create(AbstractType.class, unknown); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Cannot create TypeBindings"); verifyException(e, "class expects 2"); } } } TestTypeFactory.java000066400000000000000000000603251325620701100354460ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; /** * Simple tests to verify that the {@link TypeFactory} constructs * type information as expected. */ public class TestTypeFactory extends BaseMapTest { /* /********************************************************** /* Helper types /********************************************************** */ enum EnumForCanonical { YES, NO; } static class SingleArgGeneric { } abstract static class MyMap extends IntermediateMap { } abstract static class IntermediateMap implements Map { } abstract static class MyList extends IntermediateList { } abstract static class IntermediateList implements List { } @SuppressWarnings("serial") static class GenericList extends ArrayList { } interface MapInterface extends Cloneable, IntermediateInterfaceMap { } interface IntermediateInterfaceMap extends Map { } @SuppressWarnings("serial") static class MyStringIntMap extends MyStringXMap { } @SuppressWarnings("serial") static class MyStringXMap extends HashMap { } // And one more, now with obfuscated type names; essentially it's just Map static abstract class IntLongMap extends XLongMap { } // trick here is that V now refers to key type, not value type static abstract class XLongMap extends XXMap { } static abstract class XXMap implements Map { } static class SneakyBean { public IntLongMap intMap; public MyList longList; } static class SneakyBean2 { // self-reference; should be resolved as "Comparable" public > T getFoobar() { return null; } } @SuppressWarnings("serial") public static class LongValuedMap extends HashMap { } static class StringLongMapBean { public LongValuedMap value; } static class StringListBean { public GenericList value; } static class CollectionLike { } static class MapLike { } static class Wrapper1297 { public T content; } /* /********************************************************** /* Unit tests /********************************************************** */ public void testSimpleTypes() { Class[] classes = new Class[] { boolean.class, byte.class, char.class, short.class, int.class, long.class, float.class, double.class, Boolean.class, Byte.class, Character.class, Short.class, Integer.class, Long.class, Float.class, Double.class, String.class, Object.class, Calendar.class, Date.class, }; TypeFactory tf = TypeFactory.defaultInstance(); for (Class clz : classes) { assertSame(clz, tf.constructType(clz).getRawClass()); assertSame(clz, tf.constructType(clz).getRawClass()); } } public void testArrays() { Class[] classes = new Class[] { boolean[].class, byte[].class, char[].class, short[].class, int[].class, long[].class, float[].class, double[].class, String[].class, Object[].class, Calendar[].class, }; TypeFactory tf = TypeFactory.defaultInstance(); for (Class clz : classes) { assertSame(clz, tf.constructType(clz).getRawClass()); Class elemType = clz.getComponentType(); assertSame(clz, tf.constructArrayType(elemType).getRawClass()); } } // [databind#810]: Fake Map type for Properties as public void testProperties() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t = tf.constructType(Properties.class); assertEquals(MapType.class, t.getClass()); assertSame(Properties.class, t.getRawClass()); MapType mt = (MapType) t; // so far so good. But how about parameterization? assertSame(String.class, mt.getKeyType().getRawClass()); assertSame(String.class, mt.getContentType().getRawClass()); } public void testIterator() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t = tf.constructType(new TypeReference>() { }); assertEquals(SimpleType.class, t.getClass()); assertSame(Iterator.class, t.getRawClass()); assertEquals(1, t.containedTypeCount()); assertEquals(tf.constructType(String.class), t.containedType(0)); assertNull(t.containedType(1)); } /** * Test for verifying that parametric types can be constructed * programmatically */ @SuppressWarnings("deprecation") public void testParametricTypes() { TypeFactory tf = TypeFactory.defaultInstance(); // first, simple class based JavaType t = tf.constructParametrizedType(ArrayList.class, Collection.class, String.class); // ArrayList assertEquals(CollectionType.class, t.getClass()); JavaType strC = tf.constructType(String.class); assertEquals(1, t.containedTypeCount()); assertEquals(strC, t.containedType(0)); assertNull(t.containedType(1)); // Then using JavaType JavaType t2 = tf.constructParametrizedType(Map.class, Map.class, strC, t); // Map> // should actually produce a MapType assertEquals(MapType.class, t2.getClass()); assertEquals(2, t2.containedTypeCount()); assertEquals(strC, t2.containedType(0)); assertEquals(t, t2.containedType(1)); assertNull(t2.containedType(2)); // and then custom generic type as well JavaType custom = tf.constructParametrizedType(SingleArgGeneric.class, SingleArgGeneric.class, String.class); assertEquals(SimpleType.class, custom.getClass()); assertEquals(1, custom.containedTypeCount()); assertEquals(strC, custom.containedType(0)); assertNull(custom.containedType(1)); // should also be able to access variable name: assertEquals("X", custom.containedTypeName(0)); // And finally, ensure that we can't create invalid combinations try { // Maps must take 2 type parameters, not just one tf.constructParametrizedType(Map.class, Map.class, strC); } catch (IllegalArgumentException e) { verifyException(e, "Cannot create TypeBindings for class java.util.Map"); } try { // Type only accepts one type param tf.constructParametrizedType(SingleArgGeneric.class, SingleArgGeneric.class, strC, strC); } catch (IllegalArgumentException e) { verifyException(e, "Cannot create TypeBindings for class "); } } /** * Test for checking that canonical name handling works ok */ public void testCanonicalNames() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t = tf.constructType(java.util.Calendar.class); String can = t.toCanonical(); assertEquals("java.util.Calendar", can); assertEquals(t, tf.constructFromCanonical(can)); // Generic maps and collections will default to Object.class if type-erased t = tf.constructType(java.util.ArrayList.class); can = t.toCanonical(); assertEquals("java.util.ArrayList", can); assertEquals(t, tf.constructFromCanonical(can)); t = tf.constructType(java.util.TreeMap.class); can = t.toCanonical(); assertEquals("java.util.TreeMap", can); assertEquals(t, tf.constructFromCanonical(can)); // And then EnumMap (actual use case for us) t = tf.constructMapType(EnumMap.class, EnumForCanonical.class, String.class); can = t.toCanonical(); assertEquals("java.util.EnumMap", can); assertEquals(t, tf.constructFromCanonical(can)); // [databind#1941]: allow "raw" types too t = tf.constructFromCanonical("java.util.List"); assertEquals(List.class, t.getRawClass()); assertEquals(CollectionType.class, t.getClass()); // 01-Mar-2018, tatu: not 100% should we expect type parameters here... // But currently we do NOT get any /* assertEquals(1, t.containedTypeCount()); assertEquals(Object.class, t.containedType(0).getRawClass()); */ assertEquals(Object.class, t.getContentType().getRawClass()); can = t.toCanonical(); assertEquals("java.util.List", can); assertEquals(t, tf.constructFromCanonical(can)); } // [databind#1768] @SuppressWarnings("serial") public void testCanonicalWithSpaces() { TypeFactory tf = TypeFactory.defaultInstance(); Object objects = new TreeMap() { }; // to get subtype String reflectTypeName = objects.getClass().getGenericSuperclass().toString(); JavaType t1 = tf.constructType(objects.getClass().getGenericSuperclass()); // This will throw an Exception if you don't remove all white spaces from the String. JavaType t2 = tf.constructFromCanonical(reflectTypeName); assertNotNull(t2); assertEquals(t2, t1); } /* /********************************************************** /* Unit tests: collection type parameter resolution /********************************************************** */ public void testCollections() { // Ok, first: let's test what happens when we pass 'raw' Collection: TypeFactory tf = TypeFactory.defaultInstance(); JavaType t = tf.constructType(ArrayList.class); assertEquals(CollectionType.class, t.getClass()); assertSame(ArrayList.class, t.getRawClass()); // And then the proper way t = tf.constructType(new TypeReference>() { }); assertEquals(CollectionType.class, t.getClass()); assertSame(ArrayList.class, t.getRawClass()); JavaType elemType = ((CollectionType) t).getContentType(); assertNotNull(elemType); assertSame(SimpleType.class, elemType.getClass()); assertSame(String.class, elemType.getRawClass()); // And alternate method too t = tf.constructCollectionType(ArrayList.class, String.class); assertEquals(CollectionType.class, t.getClass()); assertSame(String.class, ((CollectionType) t).getContentType().getRawClass()); } // since 2.7 public void testCollectionTypesRefined() { TypeFactory tf = newTypeFactory(); JavaType type = tf.constructType(new TypeReference>() { }); assertEquals(List.class, type.getRawClass()); assertEquals(Long.class, type.getContentType().getRawClass()); // No super-class, since it's an interface: assertNull(type.getSuperClass()); // But then refine to reflect sub-classing JavaType subtype = tf.constructSpecializedType(type, ArrayList.class); assertEquals(ArrayList.class, subtype.getRawClass()); assertEquals(Long.class, subtype.getContentType().getRawClass()); // but with refinement, should have non-null super class JavaType superType = subtype.getSuperClass(); assertNotNull(superType); assertEquals(AbstractList.class, superType.getRawClass()); } /* /********************************************************** /* Unit tests: map type parameter resolution /********************************************************** */ public void testMaps() { TypeFactory tf = newTypeFactory(); // Ok, first: let's test what happens when we pass 'raw' Map: JavaType t = tf.constructType(HashMap.class); assertEquals(MapType.class, t.getClass()); assertSame(HashMap.class, t.getRawClass()); // Then explicit construction t = tf.constructMapType(TreeMap.class, String.class, Integer.class); assertEquals(MapType.class, t.getClass()); assertSame(String.class, ((MapType) t).getKeyType().getRawClass()); assertSame(Integer.class, ((MapType) t).getContentType().getRawClass()); // And then with TypeReference t = tf.constructType(new TypeReference>() { }); assertEquals(MapType.class, t.getClass()); assertSame(HashMap.class, t.getRawClass()); MapType mt = (MapType) t; assertEquals(tf.constructType(String.class), mt.getKeyType()); assertEquals(tf.constructType(Integer.class), mt.getContentType()); t = tf.constructType(new TypeReference>() { }); assertEquals(MapType.class, t.getClass()); assertSame(LongValuedMap.class, t.getRawClass()); mt = (MapType) t; assertEquals(tf.constructType(Boolean.class), mt.getKeyType()); assertEquals(tf.constructType(Long.class), mt.getContentType()); JavaType type = tf.constructType(new TypeReference>() { }); MapType mapType = (MapType) type; assertEquals(tf.constructType(String.class), mapType.getKeyType()); assertEquals(tf.constructType(Boolean.class), mapType.getContentType()); } // since 2.7 public void testMapTypesRefined() { TypeFactory tf = newTypeFactory(); JavaType type = tf.constructType(new TypeReference>>() { }); MapType mapType = (MapType) type; assertEquals(Map.class, mapType.getRawClass()); assertEquals(String.class, mapType.getKeyType().getRawClass()); assertEquals(List.class, mapType.getContentType().getRawClass()); assertEquals(Integer.class, mapType.getContentType().getContentType().getRawClass()); // No super-class, since it's an interface: assertNull(type.getSuperClass()); // But then refine to reflect sub-classing JavaType subtype = tf.constructSpecializedType(type, LinkedHashMap.class); assertEquals(LinkedHashMap.class, subtype.getRawClass()); assertEquals(String.class, subtype.getKeyType().getRawClass()); assertEquals(List.class, subtype.getContentType().getRawClass()); assertEquals(Integer.class, subtype.getContentType().getContentType().getRawClass()); // but with refinement, should have non-null super class JavaType superType = subtype.getSuperClass(); assertNotNull(superType); assertEquals(HashMap.class, superType.getRawClass()); // which also should have proper typing assertEquals(String.class, superType.getKeyType().getRawClass()); assertEquals(List.class, superType.getContentType().getRawClass()); assertEquals(Integer.class, superType.getContentType().getContentType().getRawClass()); } public void testTypeGeneralization() { TypeFactory tf = newTypeFactory(); MapType t = tf.constructMapType(HashMap.class, String.class, Long.class); JavaType superT = tf.constructGeneralizedType(t, Map.class); assertEquals(String.class, superT.getKeyType().getRawClass()); assertEquals(Long.class, superT.getContentType().getRawClass()); assertSame(t, tf.constructGeneralizedType(t, HashMap.class)); // plus check there is super/sub relationship try { tf.constructGeneralizedType(t, TreeMap.class); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "not a super-type of"); } } public void testMapTypesRaw() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType type = tf.constructType(HashMap.class); MapType mapType = (MapType) type; assertEquals(tf.constructType(Object.class), mapType.getKeyType()); assertEquals(tf.constructType(Object.class), mapType.getContentType()); } public void testMapTypesAdvanced() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType type = tf.constructType(MyMap.class); MapType mapType = (MapType) type; assertEquals(tf.constructType(String.class), mapType.getKeyType()); assertEquals(tf.constructType(Long.class), mapType.getContentType()); type = tf.constructType(MapInterface.class); mapType = (MapType) type; assertEquals(tf.constructType(String.class), mapType.getKeyType()); assertEquals(tf.constructType(Integer.class), mapType.getContentType()); type = tf.constructType(MyStringIntMap.class); mapType = (MapType) type; assertEquals(tf.constructType(String.class), mapType.getKeyType()); assertEquals(tf.constructType(Integer.class), mapType.getContentType()); } /** * Specific test to verify that complicate name mangling schemes * do not fool type resolver */ public void testMapTypesSneaky() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType type = tf.constructType(IntLongMap.class); MapType mapType = (MapType) type; assertEquals(tf.constructType(Integer.class), mapType.getKeyType()); assertEquals(tf.constructType(Long.class), mapType.getContentType()); } /** * Plus sneaky types may be found via introspection as well. */ public void testSneakyFieldTypes() throws Exception { TypeFactory tf = TypeFactory.defaultInstance(); Field field = SneakyBean.class.getDeclaredField("intMap"); JavaType type = tf.constructType(field.getGenericType()); assertTrue(type instanceof MapType); MapType mapType = (MapType) type; assertEquals(tf.constructType(Integer.class), mapType.getKeyType()); assertEquals(tf.constructType(Long.class), mapType.getContentType()); field = SneakyBean.class.getDeclaredField("longList"); type = tf.constructType(field.getGenericType()); assertTrue(type instanceof CollectionType); CollectionType collectionType = (CollectionType) type; assertEquals(tf.constructType(Long.class), collectionType.getContentType()); } /** * Looks like type handling actually differs for properties, too. */ public void testSneakyBeanProperties() throws Exception { ObjectMapper mapper = new ObjectMapper(); StringLongMapBean bean = mapper.readValue("{\"value\":{\"a\":123}}", StringLongMapBean.class); assertNotNull(bean); Map map = bean.value; assertEquals(1, map.size()); assertEquals(Long.valueOf(123), map.get("a")); StringListBean bean2 = mapper.readValue("{\"value\":[\"...\"]}", StringListBean.class); assertNotNull(bean2); List list = bean2.value; assertSame(GenericList.class, list.getClass()); assertEquals(1, list.size()); assertEquals("...", list.get(0)); } public void testSneakySelfRefs() throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(new SneakyBean2()); assertEquals("{\"foobar\":null}", json); } /* /********************************************************** /* Unit tests: handling of specific JDK types /********************************************************** */ public void testAtomicArrayRefParameters() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType type = tf.constructType(new TypeReference>() { }); JavaType[] params = tf.findTypeParameters(type, AtomicReference.class); assertNotNull(params); assertEquals(1, params.length); assertEquals(tf.constructType(long[].class), params[0]); } static abstract class StringIntMapEntry implements Map.Entry { } public void testMapEntryResolution() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t = tf.constructType(StringIntMapEntry.class); JavaType mapEntryType = t.findSuperType(Map.Entry.class); assertNotNull(mapEntryType); assertTrue(mapEntryType.hasGenericTypes()); assertEquals(2, mapEntryType.containedTypeCount()); assertEquals(String.class, mapEntryType.containedType(0).getRawClass()); assertEquals(Integer.class, mapEntryType.containedType(1).getRawClass()); } /* /********************************************************** /* Unit tests: construction of "raw" types /********************************************************** */ public void testRawCollections() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType type = tf.constructRawCollectionType(ArrayList.class); assertTrue(type.isContainerType()); assertEquals(TypeFactory.unknownType(), type.getContentType()); type = tf.constructRawCollectionLikeType(CollectionLike.class); // must have type vars assertTrue(type.isCollectionLikeType()); assertEquals(TypeFactory.unknownType(), type.getContentType()); // actually, should also allow "no type vars" case type = tf.constructRawCollectionLikeType(String.class); assertTrue(type.isCollectionLikeType()); assertEquals(TypeFactory.unknownType(), type.getContentType()); } public void testRawMaps() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType type = tf.constructRawMapType(HashMap.class); assertTrue(type.isContainerType()); assertEquals(TypeFactory.unknownType(), type.getKeyType()); assertEquals(TypeFactory.unknownType(), type.getContentType()); type = tf.constructRawMapLikeType(MapLike.class); // must have type vars assertTrue(type.isMapLikeType()); assertEquals(TypeFactory.unknownType(), type.getKeyType()); assertEquals(TypeFactory.unknownType(), type.getContentType()); // actually, should also allow "no type vars" case type = tf.constructRawMapLikeType(String.class); assertTrue(type.isMapLikeType()); assertEquals(TypeFactory.unknownType(), type.getKeyType()); assertEquals(TypeFactory.unknownType(), type.getContentType()); } /* /********************************************************** /* Unit tests: other /********************************************************** */ public void testMoreSpecificType() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t1 = tf.constructCollectionType(Collection.class, Object.class); JavaType t2 = tf.constructCollectionType(List.class, Object.class); assertSame(t2, tf.moreSpecificType(t1, t2)); assertSame(t2, tf.moreSpecificType(t2, t1)); t1 = tf.constructType(Double.class); t2 = tf.constructType(Number.class); assertSame(t1, tf.moreSpecificType(t1, t2)); assertSame(t1, tf.moreSpecificType(t2, t1)); // and then unrelated, return first t1 = tf.constructType(Double.class); t2 = tf.constructType(String.class); assertSame(t1, tf.moreSpecificType(t1, t2)); assertSame(t2, tf.moreSpecificType(t2, t1)); } // [databind#489] public void testCacheClearing() { TypeFactory tf = TypeFactory.defaultInstance().withModifier(null); assertEquals(0, tf._typeCache.size()); tf.constructType(getClass()); // 19-Oct-2015, tatu: This is pretty fragile but assertEquals(6, tf._typeCache.size()); tf.clearCache(); assertEquals(0, tf._typeCache.size()); } // for [databind#1297] public void testRawMapType() { TypeFactory tf = TypeFactory.defaultInstance().withModifier(null); // to get a new copy JavaType type = tf.constructParametricType(Wrapper1297.class, Map.class); assertNotNull(type); assertEquals(Wrapper1297.class, type.getRawClass()); } } TestTypeFactory1604.java000066400000000000000000000110151325620701100357510ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; // for [databind#1604] public class TestTypeFactory1604 extends BaseMapTest { static class Data1604 { } static class DataList1604 extends Data1604> { } static class RefinedDataList1604 extends DataList1604 { } public static class SneakyDataList1604 extends Data1604> { } static class TwoParam1604 { } static class SneakyTwoParam1604 extends TwoParam1604> { } public void testCustomTypesRefinedSimple() { TypeFactory tf = newTypeFactory(); JavaType base = tf.constructType(new TypeReference>>() { }); assertEquals(Data1604.class, base.getRawClass()); assertEquals(1, base.containedTypeCount()); assertEquals(List.class, base.containedType(0).getRawClass()); JavaType subtype = tf.constructSpecializedType(base, DataList1604.class); assertEquals(DataList1604.class, subtype.getRawClass()); assertEquals(1, subtype.containedTypeCount()); JavaType paramType = subtype.containedType(0); assertEquals(Long.class, paramType.getRawClass()); } public void testCustomTypesRefinedNested() { TypeFactory tf = newTypeFactory(); JavaType base = tf.constructType(new TypeReference>>() { }); assertEquals(Data1604.class, base.getRawClass()); JavaType subtype = tf.constructSpecializedType(base, RefinedDataList1604.class); assertEquals(RefinedDataList1604.class, subtype.getRawClass()); assertEquals(DataList1604.class, subtype.getSuperClass().getRawClass()); assertEquals(1, subtype.containedTypeCount()); JavaType paramType = subtype.containedType(0); assertEquals(Long.class, paramType.getRawClass()); } public void testCustomTypesRefinedSneaky() { TypeFactory tf = newTypeFactory(); JavaType base = tf.constructType(new TypeReference>>() { }); assertEquals(Data1604.class, base.getRawClass()); JavaType subtype = tf.constructSpecializedType(base, SneakyDataList1604.class); assertEquals(SneakyDataList1604.class, subtype.getRawClass()); assertEquals(2, subtype.containedTypeCount()); assertEquals(Long.class, subtype.containedType(1).getRawClass()); // first one, "bogus", has to be essentially "unknown" assertEquals(Object.class, subtype.containedType(0).getRawClass()); // and have correct parent too assertEquals(Data1604.class, subtype.getSuperClass().getRawClass()); } public void testTwoParamSneakyCustom() { TypeFactory tf = newTypeFactory(); JavaType type = tf.constructType(new TypeReference>>() { }); assertEquals(TwoParam1604.class, type.getRawClass()); assertEquals(String.class, type.containedType(0).getRawClass()); JavaType ct = type.containedType(1); assertEquals(List.class, ct.getRawClass()); assertEquals(Long.class, ct.getContentType().getRawClass()); JavaType subtype = tf.constructSpecializedType(type, SneakyTwoParam1604.class); assertEquals(SneakyTwoParam1604.class, subtype.getRawClass()); assertEquals(TwoParam1604.class, subtype.getSuperClass().getRawClass()); assertEquals(2, subtype.containedTypeCount()); // should properly resolve type parameters despite sneaky switching, including "unwounding" // `List` wrapper JavaType first = subtype.containedType(0); assertEquals(Long.class, first.getRawClass()); JavaType second = subtype.containedType(1); assertEquals(String.class, second.getRawClass()); } // Also: let's not allow mismatching binding public void testErrorForMismatch() { TypeFactory tf = newTypeFactory(); // NOTE: plain `String` NOT `List` JavaType base = tf.constructType(new TypeReference>() { }); try { tf.constructSpecializedType(base, DataList1604.class); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "Failed to specialize"); verifyException(e, "Data1604"); verifyException(e, "DataList1604"); } } } TestTypeFactoryWithClassLoader.java000066400000000000000000000123541325620701100404160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import static org.mockito.Mockito.*; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @RunWith(PowerMockRunner.class) @PrepareForTest(TypeFactory.class) public class TestTypeFactoryWithClassLoader { @Mock private TypeModifier typeModifier; private static ClassLoader classLoader; private static ClassLoader threadClassLoader; private static String aClassName; private ObjectMapper mapper; @BeforeClass public static void beforeClass() { classLoader = AClass.class.getClassLoader(); aClassName = AClass.getStaticClassName(); threadClassLoader = Thread.currentThread().getContextClassLoader(); Assert.assertNotNull(threadClassLoader); } @Before public void before() { mapper = new ObjectMapper(); } @After public void after() { Thread.currentThread().setContextClassLoader(threadClassLoader); mapper = null; } @Test public void testUsesCorrectClassLoaderWhenThreadClassLoaderIsNull() throws ClassNotFoundException { Thread.currentThread().setContextClassLoader(null); TypeFactory spySut = spy(mapper.getTypeFactory().withModifier(typeModifier).withClassLoader(classLoader)); Class clazz = spySut.findClass(aClassName); verify(spySut).getClassLoader(); verify(spySut).classForName(any(String.class), any(Boolean.class), eq(classLoader)); Assert.assertNotNull(clazz); Assert.assertEquals(classLoader, spySut.getClassLoader()); Assert.assertEquals(typeModifier,spySut._modifiers[0]); Assert.assertEquals(null, Thread.currentThread().getContextClassLoader()); } @Test public void testUsesCorrectClassLoaderWhenThreadClassLoaderIsNotNull() throws ClassNotFoundException { TypeFactory spySut = spy(mapper.getTypeFactory().withModifier(typeModifier).withClassLoader(classLoader)); Class clazz = spySut.findClass(aClassName); verify(spySut).getClassLoader(); verify(spySut).classForName(any(String.class), any(Boolean.class), eq(classLoader)); Assert.assertNotNull(clazz); Assert.assertEquals(classLoader, spySut.getClassLoader()); Assert.assertEquals(typeModifier,spySut._modifiers[0]); } @Test public void testCallingOnlyWithModifierGivesExpectedResults(){ TypeFactory sut = mapper.getTypeFactory().withModifier(typeModifier); Assert.assertNull(sut.getClassLoader()); Assert.assertEquals(typeModifier,sut._modifiers[0]); } @Test public void testCallingOnlyWithClassLoaderGivesExpectedResults(){ TypeFactory sut = mapper.getTypeFactory().withClassLoader(classLoader); Assert.assertNotNull(sut.getClassLoader()); Assert.assertArrayEquals(null,sut._modifiers); } @Test public void testDefaultTypeFactoryNotAffectedByWithConstructors() { TypeFactory sut = mapper.getTypeFactory().withModifier(typeModifier).withClassLoader(classLoader); Assert.assertEquals(classLoader, sut.getClassLoader()); Assert.assertEquals(typeModifier,sut._modifiers[0]); Assert.assertNull(mapper.getTypeFactory().getClassLoader()); Assert.assertArrayEquals(null,mapper.getTypeFactory()._modifiers); } @Test public void testSetsTheCorrectClassLoderIfUsingWithModifierFollowedByWithClassLoader() { TypeFactory sut = mapper.getTypeFactory().withModifier(typeModifier).withClassLoader(classLoader); Assert.assertNotNull(sut.getClassLoader()); } @Test public void testSetsTheCorrectClassLoderIfUsingWithClassLoaderFollowedByWithModifier() { TypeFactory sut = mapper.getTypeFactory().withClassLoader(classLoader).withModifier(typeModifier); Assert.assertNotNull(sut.getClassLoader()); } @Test public void testThreadContextClassLoaderIsUsedIfNotUsingWithClassLoader() throws ClassNotFoundException { TypeFactory spySut = spy(mapper.getTypeFactory()); Assert.assertNull(spySut.getClassLoader()); Class clazz = spySut.findClass(aClassName); Assert.assertNotNull(clazz); verify(spySut).classForName(any(String.class), any(Boolean.class), eq(threadClassLoader)); } @Test public void testUsesFallBackClassLoaderIfNoThreadClassLoaderAndNoWithClassLoader() throws ClassNotFoundException { Thread.currentThread().setContextClassLoader(null); TypeFactory spySut = spy(mapper.getTypeFactory()); Assert.assertNull(spySut.getClassLoader()); Assert.assertArrayEquals(null,spySut._modifiers); Class clazz = spySut.findClass(aClassName); Assert.assertNotNull(clazz); verify(spySut).classForName(any(String.class)); } public static class AClass { private String _foo, _bar; protected final static Class thisClass = new Object() { }.getClass().getEnclosingClass(); public AClass() { } public AClass(String foo, String bar) { _foo = foo; _bar = bar; } public String getFoo() { return _foo; } public String getBar() { return _bar; } public void setFoo(String foo) { _foo = foo; } public void setBar(String bar) { _bar = bar; } public static String getStaticClassName() { return thisClass.getCanonicalName().replace("."+thisClass.getSimpleName(), "$"+thisClass.getSimpleName()); } } } TestTypeFactoryWithRecursiveTypes.java000066400000000000000000000017311325620701100412130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.type.TypeFactory; // https://github.com/FasterXML/jackson-databind/issues/1647 public class TestTypeFactoryWithRecursiveTypes extends BaseMapTest { static interface IFace { } static class Base implements IFace { @JsonProperty int base = 1; } static class Sub extends Base { @JsonProperty int sub = 2; } public void testBasePropertiesIncludedWhenSerializingSubWhenSubTypeLoadedAfterBaseType() throws IOException { TypeFactory tf = TypeFactory.defaultInstance(); tf.constructType(Base.class); tf.constructType(Sub.class); Sub sub = new Sub(); String serialized = objectMapper().writeValueAsString(sub); assertEquals("{\"base\":1,\"sub\":2}", serialized); } } TestTypeResolution.java000066400000000000000000000060501325620701100361750ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.io.Serializable; import java.util.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.MapType; import com.fasterxml.jackson.databind.type.TypeFactory; @SuppressWarnings("serial") public class TestTypeResolution extends BaseMapTest { public static class LongValuedMap extends HashMap { } static class GenericList extends ArrayList { } static class GenericList2 extends GenericList { } static class LongList extends GenericList2 { } static class MyLongList extends LongList { } static class Range> implements Serializable { public Range(E start, E end) { } } static class DoubleRange extends Range { public DoubleRange() { super(null, null); } public DoubleRange(Double s, Double e) { super(s, e); } } /* /********************************************************** /* Test methods /********************************************************** */ public void testMaps() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t = tf.constructType(new TypeReference>() { }); MapType type = (MapType) t; assertSame(LongValuedMap.class, type.getRawClass()); assertEquals(tf.constructType(String.class), type.getKeyType()); assertEquals(tf.constructType(Long.class), type.getContentType()); } public void testListViaTypeRef() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t = tf.constructType(new TypeReference>() {}); CollectionType type = (CollectionType) t; assertSame(MyLongList.class, type.getRawClass()); assertEquals(tf.constructType(Long.class), type.getContentType()); } public void testListViaClass() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t = tf.constructType(LongList.class); JavaType type = (CollectionType) t; assertSame(LongList.class, type.getRawClass()); assertEquals(tf.constructType(Long.class), type.getContentType()); } public void testGeneric() { TypeFactory tf = TypeFactory.defaultInstance(); // First, via simple sub-class JavaType t = tf.constructType(DoubleRange.class); JavaType rangeParams = t.findSuperType(Range.class); assertEquals(1, rangeParams.containedTypeCount()); assertEquals(Double.class, rangeParams.containedType(0).getRawClass()); // then using TypeRef t = tf.constructType(new TypeReference() { }); rangeParams = t.findSuperType(Range.class); assertEquals(1, rangeParams.containedTypeCount()); assertEquals(Double.class, rangeParams.containedType(0).getRawClass()); } } TypeAliasesTest.java000066400000000000000000000021531325620701100354130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/typepackage com.fasterxml.jackson.databind.type; import java.util.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for more complicated type definitions where type name * aliasing can confuse naive resolution algorithms. */ public class TypeAliasesTest extends BaseMapTest { public static abstract class Base { public T inconsequential = null; } public static abstract class BaseData { public T dataObj; } public static class Child extends Base { public static class ChildData extends BaseData> { } } /* /******************************************************* /* Unit tests /******************************************************* */ // Reproducing [databind#743] public void testAliasResolutionIssue743() throws Exception { String s3 = "{\"dataObj\" : [ \"one\", \"two\", \"three\" ] }"; ObjectMapper m = new ObjectMapper(); Child.ChildData d = m.readValue(s3, Child.ChildData.class); assertNotNull(d.dataObj); assertEquals(3, d.dataObj.size()); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/util/000077500000000000000000000000001325620701100315375ustar00rootroot00000000000000ArrayBuildersTest.java000066400000000000000000000063361325620701100357430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.Arrays; import java.util.HashSet; import org.junit.Assert; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.util.ArrayBuilders.BooleanBuilder; import com.fasterxml.jackson.databind.util.ArrayBuilders.ByteBuilder; import com.fasterxml.jackson.databind.util.ArrayBuilders.DoubleBuilder; import com.fasterxml.jackson.databind.util.ArrayBuilders.FloatBuilder; import com.fasterxml.jackson.databind.util.ArrayBuilders.IntBuilder; import com.fasterxml.jackson.databind.util.ArrayBuilders.LongBuilder; import com.fasterxml.jackson.databind.util.ArrayBuilders.ShortBuilder; public class ArrayBuildersTest extends BaseMapTest { // [databind#157] public void testInsertInListNoDup() { String [] arr = new String[]{"me", "you", "him"}; String [] newarr; newarr = ArrayBuilders.insertInListNoDup(arr, "you"); Assert.assertArrayEquals(new String[]{"you", "me", "him"}, newarr); newarr = ArrayBuilders.insertInListNoDup(arr, "me"); Assert.assertArrayEquals(new String[]{"me", "you","him"}, newarr); newarr = ArrayBuilders.insertInListNoDup(arr, "him"); Assert.assertArrayEquals(new String[]{"him", "me", "you"}, newarr); newarr = ArrayBuilders.insertInListNoDup(arr, "foobar"); Assert.assertArrayEquals(new String[]{"foobar", "me", "you", "him"}, newarr); } public void testBuilderAccess() { ArrayBuilders builders = new ArrayBuilders(); BooleanBuilder bb = builders.getBooleanBuilder(); assertNotNull(bb); assertSame(bb, builders.getBooleanBuilder()); ByteBuilder b2 = builders.getByteBuilder(); assertNotNull(b2); assertSame(b2, builders.getByteBuilder()); ShortBuilder sb = builders.getShortBuilder(); assertNotNull(sb); assertSame(sb, builders.getShortBuilder()); IntBuilder ib = builders.getIntBuilder(); assertNotNull(ib); assertSame(ib, builders.getIntBuilder()); LongBuilder lb = builders.getLongBuilder(); assertNotNull(lb); assertSame(lb, builders.getLongBuilder()); FloatBuilder fb = builders.getFloatBuilder(); assertNotNull(fb); assertSame(fb, builders.getFloatBuilder()); DoubleBuilder db = builders.getDoubleBuilder(); assertNotNull(db); assertSame(db, builders.getDoubleBuilder()); } public void testArrayComparator() { final int[] INT3 = new int[] { 3, 4, 5 }; Object comp = ArrayBuilders.getArrayComparator(INT3); assertFalse(comp.equals(null)); assertTrue(comp.equals(INT3)); assertTrue(comp.equals(new int[] { 3, 4, 5 })); assertFalse(comp.equals(new int[] { 5 })); assertFalse(comp.equals(new int[] { 3, 4 })); assertFalse(comp.equals(new int[] { 3, 5, 4 })); assertFalse(comp.equals(new int[] { 3, 4, 5, 6 })); } public void testArraySet() { HashSet set = ArrayBuilders.arrayToSet(new String[] { "foo", "bar" }); assertEquals(2, set.size()); assertEquals(new HashSet(Arrays.asList("bar", "foo")), set); } } BeanUtilTest.java000066400000000000000000000124301325620701100346660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.type.TypeFactory; public class BeanUtilTest extends BaseMapTest { static class IsGetters { public boolean isPrimitive() { return false; } public Boolean isWrapper() { return false; } public String isNotGetter() { return null; } public boolean is() { return false; } } static class Getters { public String getCallbacks() { return null; } public String getMetaClass() { return null; } public boolean get() { return false; } } static class Setters { public void setFoo() { } public void notSetter() { } public void set() { } } /* /********************************************************** /* Test methods /********************************************************** */ public void testNameMangle() { assertEquals("foo", BeanUtil.legacyManglePropertyName("getFoo", 3)); assertEquals("foo", BeanUtil.stdManglePropertyName("getFoo", 3)); assertEquals("url", BeanUtil.legacyManglePropertyName("getURL", 3)); assertEquals("URL", BeanUtil.stdManglePropertyName("getURL", 3)); } public void testGetDefaultValue() { TypeFactory tf = TypeFactory.defaultInstance(); // For collection/array/Map types, should give `NOT_EMPTY`: assertEquals(JsonInclude.Include.NON_EMPTY, BeanUtil.getDefaultValue(tf.constructType(Map.class))); assertEquals(JsonInclude.Include.NON_EMPTY, BeanUtil.getDefaultValue(tf.constructType(List.class))); assertEquals(JsonInclude.Include.NON_EMPTY, BeanUtil.getDefaultValue(tf.constructType(Object[].class))); // as well as ReferenceTypes, String assertEquals(JsonInclude.Include.NON_EMPTY, BeanUtil.getDefaultValue(tf.constructType(AtomicReference.class))); assertEquals("", BeanUtil.getDefaultValue(tf.constructType(String.class))); // primitive/wrappers have others assertEquals(Integer.valueOf(0), BeanUtil.getDefaultValue(tf.constructType(Integer.class))); // but POJOs have no real default assertNull(BeanUtil.getDefaultValue(tf.constructType(getClass()))); } public void testIsGetter() throws Exception { _testIsGetter("isPrimitive", "primitive"); _testIsGetter("isWrapper", "wrapper"); _testIsGetter("isNotGetter", null); _testIsGetter("is", null); } public void testOkNameForGetter() throws Exception { // mostly chosen to exercise groovy exclusion _testOkNameForGetter("getCallbacks", "callbacks"); _testOkNameForGetter("getMetaClass", "metaClass"); _testOkNameForGetter("get", null); } public void testOkNameForSetter() throws Exception { _testOkNameForSetter("setFoo", "foo"); _testOkNameForSetter("notSetter", null); _testOkNameForSetter("set", null); } /* /********************************************************** /* Helper methods /********************************************************** */ private void _testIsGetter(String name, String expName) throws Exception { _testIsGetter(name, expName, true); _testIsGetter(name, expName, false); } private void _testIsGetter(String name, String expName, boolean useStd) throws Exception { AnnotatedMethod m = _method(IsGetters.class, name); if (expName == null) { assertNull(BeanUtil.okNameForIsGetter(m, name, useStd)); } else { assertEquals(expName, BeanUtil.okNameForIsGetter(m, name, useStd)); } } private void _testOkNameForGetter(String name, String expName) throws Exception { _testOkNameForGetter(name, expName, true); _testOkNameForGetter(name, expName, false); } private void _testOkNameForGetter(String name, String expName, boolean useStd) throws Exception { AnnotatedMethod m = _method(Getters.class, name); if (expName == null) { assertNull(BeanUtil.okNameForGetter(m, useStd)); } else { assertEquals(expName, BeanUtil.okNameForGetter(m, useStd)); } } private void _testOkNameForSetter(String name, String expName) throws Exception { _testOkNameForSetter(name, expName, true); _testOkNameForSetter(name, expName, false); } @SuppressWarnings("deprecation") private void _testOkNameForSetter(String name, String expName, boolean useStd) throws Exception { AnnotatedMethod m = _method(Setters.class, name); if (expName == null) { assertNull(BeanUtil.okNameForSetter(m, useStd)); } else { assertEquals(expName, BeanUtil.okNameForSetter(m, useStd)); } } private AnnotatedMethod _method(Class cls, String name, Class...parameterTypes) throws Exception { return new AnnotatedMethod(null, cls.getMethod(name, parameterTypes), null, null); } } ByteBufferUtilsTest.java000066400000000000000000000017351325620701100362470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.nio.ByteBuffer; import com.fasterxml.jackson.databind.BaseMapTest; public class ByteBufferUtilsTest extends BaseMapTest { public void testByteBufferInput() throws Exception { byte[] input = new byte[] { 1, 2, 3 }; ByteBufferBackedInputStream wrapped = new ByteBufferBackedInputStream(ByteBuffer.wrap(input)); assertEquals(3, wrapped.available()); assertEquals(1, wrapped.read()); byte[] buffer = new byte[10]; assertEquals(2, wrapped.read(buffer, 0, 5)); wrapped.close(); } public void testByteBufferOutput() throws Exception { ByteBuffer b = ByteBuffer.wrap(new byte[10]); ByteBufferBackedOutputStream wrappedOut = new ByteBufferBackedOutputStream(b); wrappedOut.write(1); wrappedOut.write(new byte[] { 2, 3 }); assertEquals(3, b.position()); assertEquals(7, b.remaining()); wrappedOut.close(); } } ClassUtilTest.java000066400000000000000000000155631325620701100351000ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.util.ClassUtil; public class ClassUtilTest extends BaseMapTest { /* /********************************************************** /* Test classes, enums /********************************************************** */ /* Test classes and interfaces needed for testing class util * methods */ static abstract class BaseClass implements Comparable, BaseInt { BaseClass(String str) { } } interface BaseInt { } interface SubInt extends BaseInt { } enum TestEnum { A; } abstract class InnerNonStatic { } static class Inner { protected Inner() { throw new IllegalStateException("test"); } } static abstract class SubClass extends BaseClass implements SubInt { SubClass() { super("x"); } } static abstract class ConcreteAndAbstract { public abstract void a(); public void c() { } } /* /********************************************************** /* Test methods /********************************************************** */ public void testIsConcrete() throws Exception { assertTrue(ClassUtil.isConcrete(getClass())); assertFalse(ClassUtil.isConcrete(BaseClass.class)); assertFalse(ClassUtil.isConcrete(BaseInt.class)); assertFalse(ClassUtil.isConcrete(ConcreteAndAbstract.class.getDeclaredMethod("a"))); assertTrue(ClassUtil.isConcrete(ConcreteAndAbstract.class.getDeclaredMethod("c"))); } public void testCanBeABeanType() { assertEquals("annotation", ClassUtil.canBeABeanType(java.lang.annotation.Retention.class)); assertEquals("array", ClassUtil.canBeABeanType(String[].class)); assertEquals("enum", ClassUtil.canBeABeanType(TestEnum.class)); assertEquals("primitive", ClassUtil.canBeABeanType(Integer.TYPE)); assertNull(ClassUtil.canBeABeanType(Integer.class)); assertEquals("non-static member class", ClassUtil.isLocalType(InnerNonStatic.class, false)); assertNull(ClassUtil.isLocalType(Integer.class, false)); } public void testExceptionHelpers() { RuntimeException e = new RuntimeException("test"); RuntimeException wrapper = new RuntimeException(e); assertSame(e, ClassUtil.getRootCause(wrapper)); try { ClassUtil.throwAsIAE(e); fail("Shouldn't get this far"); } catch (RuntimeException e2) { assertSame(e, e2); } Error err = new Error(); try { ClassUtil.throwAsIAE(err); fail("Shouldn't get this far"); } catch (Error errAct) { assertSame(err, errAct); } try { ClassUtil.unwrapAndThrowAsIAE(wrapper); fail("Shouldn't get this far"); } catch (RuntimeException e2) { assertSame(e, e2); } } public void testFailedCreateInstance() { try { ClassUtil.createInstance(BaseClass.class, true); } catch (IllegalArgumentException e) { verifyException(e, "has no default"); } try { // false means ctor would need to be public ClassUtil.createInstance(Inner.class, false); } catch (IllegalArgumentException e) { verifyException(e, "is not accessible"); } // and finally, check that we'll get expected exception... try { ClassUtil.createInstance(Inner.class, true); } catch (IllegalStateException e) { verifyException(e, "test"); } } public void testPrimitiveDefaultValue() { assertEquals(Integer.valueOf(0), ClassUtil.defaultValue(Integer.TYPE)); assertEquals(Long.valueOf(0L), ClassUtil.defaultValue(Long.TYPE)); assertEquals(Character.valueOf('\0'), ClassUtil.defaultValue(Character.TYPE)); assertEquals(Short.valueOf((short) 0), ClassUtil.defaultValue(Short.TYPE)); assertEquals(Byte.valueOf((byte) 0), ClassUtil.defaultValue(Byte.TYPE)); assertEquals(Double.valueOf(0.0), ClassUtil.defaultValue(Double.TYPE)); assertEquals(Float.valueOf(0.0f), ClassUtil.defaultValue(Float.TYPE)); assertEquals(Boolean.FALSE, ClassUtil.defaultValue(Boolean.TYPE)); try { ClassUtil.defaultValue(String.class); } catch (IllegalArgumentException e) { verifyException(e, "String is not a primitive type"); } } public void testPrimitiveWrapperType() { assertEquals(Byte.class, ClassUtil.wrapperType(Byte.TYPE)); assertEquals(Short.class, ClassUtil.wrapperType(Short.TYPE)); assertEquals(Character.class, ClassUtil.wrapperType(Character.TYPE)); assertEquals(Integer.class, ClassUtil.wrapperType(Integer.TYPE)); assertEquals(Long.class, ClassUtil.wrapperType(Long.TYPE)); assertEquals(Double.class, ClassUtil.wrapperType(Double.TYPE)); assertEquals(Float.class, ClassUtil.wrapperType(Float.TYPE)); assertEquals(Boolean.class, ClassUtil.wrapperType(Boolean.TYPE)); try { ClassUtil.wrapperType(String.class); fail("Should not pass"); } catch (IllegalArgumentException e) { verifyException(e, "String is not a primitive type"); } } public void testWrapperToPrimitiveType() { assertEquals(Integer.TYPE, ClassUtil.primitiveType(Integer.class)); assertEquals(Long.TYPE, ClassUtil.primitiveType(Long.class)); assertEquals(Character.TYPE, ClassUtil.primitiveType(Character.class)); assertEquals(Short.TYPE, ClassUtil.primitiveType(Short.class)); assertEquals(Byte.TYPE, ClassUtil.primitiveType(Byte.class)); assertEquals(Float.TYPE, ClassUtil.primitiveType(Float.class)); assertEquals(Double.TYPE, ClassUtil.primitiveType(Double.class)); assertEquals(Boolean.TYPE, ClassUtil.primitiveType(Boolean.class)); assertNull(ClassUtil.primitiveType(String.class)); } public void testFindEnumType() { assertEquals(TestEnum.class, ClassUtil.findEnumType(TestEnum.A)); // different codepaths for empty and non-empty EnumSets... assertEquals(TestEnum.class, ClassUtil.findEnumType(EnumSet.allOf(TestEnum.class))); assertEquals(TestEnum.class, ClassUtil.findEnumType(EnumSet.noneOf(TestEnum.class))); assertEquals(TestEnum.class, ClassUtil.findEnumType(new EnumMap(TestEnum.class))); } public void testDescs() { final String exp = "`java.lang.String`"; assertEquals(exp, ClassUtil.getClassDescription("foo")); assertEquals(exp, ClassUtil.getClassDescription(String.class)); } } CompactStringObjectMapTest.java000066400000000000000000000014001325620701100375200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.*; import com.fasterxml.jackson.databind.BaseMapTest; public class CompactStringObjectMapTest extends BaseMapTest { public void testBig() { Map all = new LinkedHashMap<>(); for (int i = 0; i < 1000; ++i) { String key = "key"+i; all.put(key, key); } CompactStringObjectMap map = CompactStringObjectMap.construct(all); assertEquals(1000, map.keys().size()); for (String key : all.keySet()) { assertEquals(key, map.find(key)); } // and then bogus empty keys assertNull(map.find("key1000")); assertNull(map.find("keyXXX")); assertNull(map.find("")); } } EnumValuesTest.java000066400000000000000000000047341325620701100352570ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.List; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.SerializationFeature; public class EnumValuesTest extends BaseMapTest { enum ABC { A("A"), B("b"), C("C"); private final String desc; private ABC(String d) { desc = d; } @Override public String toString() { return desc; } } final ObjectMapper MAPPER = new ObjectMapper(); @SuppressWarnings("unchecked") public void testConstructFromName() { SerializationConfig cfg = MAPPER.getSerializationConfig() .without(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); Class> enumClass = (Class>)(Class) ABC.class; EnumValues values = EnumValues.construct(cfg, enumClass); assertEquals("A", values.serializedValueFor(ABC.A).toString()); assertEquals("B", values.serializedValueFor(ABC.B).toString()); assertEquals("C", values.serializedValueFor(ABC.C).toString()); assertEquals(3, values.values().size()); assertEquals(3, values.internalMap().size()); } @SuppressWarnings("unchecked") public void testConstructWithToString() { SerializationConfig cfg = MAPPER.getSerializationConfig() .with(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); Class> enumClass = (Class>)(Class) ABC.class; EnumValues values = EnumValues.construct(cfg, enumClass); assertEquals("A", values.serializedValueFor(ABC.A).toString()); assertEquals("b", values.serializedValueFor(ABC.B).toString()); assertEquals("C", values.serializedValueFor(ABC.C).toString()); assertEquals(3, values.values().size()); assertEquals(3, values.internalMap().size()); } public void testEnumResolver() { EnumResolver enumRes = EnumResolver.constructUnsafeUsingToString(ABC.class, null); assertEquals(ABC.B, enumRes.getEnum(1)); assertNull(enumRes.getEnum(-1)); assertNull(enumRes.getEnum(3)); assertEquals(2, enumRes.lastValidIndex()); List> enums = enumRes.getEnums(); assertEquals(3, enums.size()); assertEquals(ABC.A, enums.get(0)); assertEquals(ABC.B, enums.get(1)); assertEquals(ABC.C, enums.get(2)); } } ISO8601DateFormatTest.java000066400000000000000000000037401325620701100361070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.text.DateFormat; import java.util.*; import com.fasterxml.jackson.databind.BaseMapTest; @SuppressWarnings("deprecation") public class ISO8601DateFormatTest extends BaseMapTest { private ISO8601DateFormat df; private Date date; @Override public void setUp() { Calendar cal = new GregorianCalendar(2007, 8 - 1, 13, 19, 51, 23); cal.setTimeZone(TimeZone.getTimeZone("GMT")); cal.set(Calendar.MILLISECOND, 0); date = cal.getTime(); df = new ISO8601DateFormat(); } public void testFormat() { String result = df.format(date); assertEquals("2007-08-13T19:51:23Z", result); } public void testParse() throws Exception { Date result = df.parse("2007-08-13T19:51:23Z"); assertEquals(date, result); // Test parsing date-only values with and without a timezone designation Date dateOnly = df.parse("2007-08-14"); Calendar cal = new GregorianCalendar(2007, 8-1, 14); assertEquals(cal.getTime(), dateOnly); dateOnly = df.parse("2007-08-14Z"); cal = new GregorianCalendar(2007, 8-1, 14); cal.setTimeZone(TimeZone.getTimeZone("GMT")); assertEquals(cal.getTime(), dateOnly); } public void testPartialParse() throws Exception { java.text.ParsePosition pos = new java.text.ParsePosition(0); String timestamp = "2007-08-13T19:51:23Z"; Date result = df.parse(timestamp + "hello", pos); assertEquals(date, result); assertEquals(timestamp.length(), pos.getIndex()); } public void testCloneObject() throws Exception { DateFormat clone = (DateFormat)df.clone(); assertSame(df, clone); } public void testHashCodeEquals() throws Exception { // for [databind#1130] DateFormat defaultDF = StdDateFormat.instance; defaultDF.hashCode(); assertTrue(defaultDF.equals(defaultDF)); } } ISO8601UtilsTest.java000066400000000000000000000200471325620701100351600ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import com.fasterxml.jackson.databind.BaseMapTest; import java.text.ParseException; import java.text.ParsePosition; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import java.util.concurrent.TimeUnit; @SuppressWarnings("deprecation") public class ISO8601UtilsTest extends BaseMapTest { private Date date; private Date dateWithoutTime; private Date dateZeroMillis; private Date dateZeroSecondAndMillis; @Override public void setUp() { Calendar cal = new GregorianCalendar(2007, 8 - 1, 13, 19, 51, 23); cal.setTimeZone(TimeZone.getTimeZone("GMT")); cal.set(Calendar.MILLISECOND, 789); date = cal.getTime(); cal.set(Calendar.MILLISECOND, 0); dateZeroMillis = cal.getTime(); cal.set(Calendar.SECOND, 0); dateZeroSecondAndMillis = cal.getTime(); cal = new GregorianCalendar(2007, 8 - 1, 13, 0, 0, 0); cal.set(Calendar.MILLISECOND, 0); cal.setTimeZone(TimeZone.getTimeZone("GMT")); dateWithoutTime = cal.getTime(); } public void testFormat() { String result = ISO8601Utils.format(date); assertEquals("2007-08-13T19:51:23Z", result); } public void testFormatMillis() { String result = ISO8601Utils.format(date, true); assertEquals("2007-08-13T19:51:23.789Z", result); result = ISO8601Utils.format(date, false); assertEquals("2007-08-13T19:51:23Z", result); } public void testFormatTimeZone() { String result = ISO8601Utils.format(date, false, TimeZone.getTimeZone("GMT+02:00")); assertEquals("2007-08-13T21:51:23+02:00", result); result = ISO8601Utils.format(date, true, TimeZone.getTimeZone("GMT+02:00")); assertEquals("2007-08-13T21:51:23.789+02:00", result); result = ISO8601Utils.format(date, true, TimeZone.getTimeZone("GMT")); assertEquals("2007-08-13T19:51:23.789Z", result); } public void testParse() throws java.text.ParseException { Date d = ISO8601Utils.parse("2007-08-13T19:51:23.789Z", new ParsePosition(0)); assertEquals(date, d); d = ISO8601Utils.parse("2007-08-13T19:51:23Z", new ParsePosition(0)); assertEquals(dateZeroMillis, d); d = ISO8601Utils.parse("2007-08-13T21:51:23.789+02:00", new ParsePosition(0)); assertEquals(date, d); } public void testParseShortDate() throws java.text.ParseException { Date d = ISO8601Utils.parse("20070813T19:51:23.789Z", new ParsePosition(0)); assertEquals(date, d); d = ISO8601Utils.parse("20070813T19:51:23Z", new ParsePosition(0)); assertEquals(dateZeroMillis, d); d = ISO8601Utils.parse("20070813T21:51:23.789+02:00", new ParsePosition(0)); assertEquals(date, d); } public void testParseShortTime() throws java.text.ParseException { Date d = ISO8601Utils.parse("2007-08-13T195123.789Z", new ParsePosition(0)); assertEquals(date, d); d = ISO8601Utils.parse("2007-08-13T195123Z", new ParsePosition(0)); assertEquals(dateZeroMillis, d); d = ISO8601Utils.parse("2007-08-13T215123.789+02:00", new ParsePosition(0)); assertEquals(date, d); } public void testParseShortDateTime() throws java.text.ParseException { Date d = ISO8601Utils.parse("20070813T195123.789Z", new ParsePosition(0)); assertEquals(date, d); d = ISO8601Utils.parse("20070813T195123Z", new ParsePosition(0)); assertEquals(dateZeroMillis, d); d = ISO8601Utils.parse("20070813T215123.789+02:00", new ParsePosition(0)); assertEquals(date, d); } public void testParseWithoutTime() throws ParseException { Date d = ISO8601Utils.parse("2007-08-13Z", new ParsePosition(0)); assertEquals(dateWithoutTime, d); d = ISO8601Utils.parse("20070813Z", new ParsePosition(0)); assertEquals(dateWithoutTime, d); d = ISO8601Utils.parse("2007-08-13+00:00", new ParsePosition(0)); assertEquals(dateWithoutTime, d); d = ISO8601Utils.parse("20070813+00:00", new ParsePosition(0)); assertEquals(dateWithoutTime, d); } public void testParseOptional() throws java.text.ParseException { Date d = ISO8601Utils.parse("2007-08-13T19:51Z", new ParsePosition(0)); assertEquals(dateZeroSecondAndMillis, d); d = ISO8601Utils.parse("2007-08-13T1951Z", new ParsePosition(0)); assertEquals(dateZeroSecondAndMillis, d); d = ISO8601Utils.parse("2007-08-13T21:51+02:00", new ParsePosition(0)); assertEquals(dateZeroSecondAndMillis, d); } public void testParseRfc3339Examples() throws java.text.ParseException { // Two digit milliseconds. Date d = ISO8601Utils.parse("1985-04-12T23:20:50.52Z", new ParsePosition(0)); assertEquals(newDate(1985, 4, 12, 23, 20, 50, 520, 0), d); d = ISO8601Utils.parse("1996-12-19T16:39:57-08:00", new ParsePosition(0)); assertEquals(newDate(1996, 12, 19, 16, 39, 57, 0, -8 * 60), d); // Truncated leap second. d = ISO8601Utils.parse("1990-12-31T23:59:60Z", new ParsePosition(0)); assertEquals(newDate(1990, 12, 31, 23, 59, 59, 0, 0), d); // Truncated leap second. d = ISO8601Utils.parse("1990-12-31T15:59:60-08:00", new ParsePosition(0)); assertEquals(newDate(1990, 12, 31, 15, 59, 59, 0, -8 * 60), d); // Two digit milliseconds. d = ISO8601Utils.parse("1937-01-01T12:00:27.87+00:20", new ParsePosition(0)); assertEquals(newDate(1937, 1, 1, 12, 0, 27, 870, 20), d); } public void testFractionalSeconds() throws java.text.ParseException { Date d = ISO8601Utils.parse("1970-01-01T00:00:00.9Z", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 900, 0), d); d = ISO8601Utils.parse("1970-01-01T00:00:00.09Z", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 90, 0), d); d = ISO8601Utils.parse("1970-01-01T00:00:00.009Z", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 9, 0), d); d = ISO8601Utils.parse("1970-01-01T00:00:00.0009Z", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 0, 0), d); d = ISO8601Utils.parse("1970-01-01T00:00:00.2147483647Z", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 214, 0), d); d = ISO8601Utils.parse("1970-01-01T00:00:00.2147483648Z", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 214, 0), d); d = ISO8601Utils.parse("1970-01-01T00:00:00.9+02:00", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 900, 2 * 60), d); d = ISO8601Utils.parse("1970-01-01T00:00:00.09+02:00", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 90, 2 * 60), d); d = ISO8601Utils.parse("1970-01-01T00:00:00.009+02:00", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 9, 2 * 60), d); d = ISO8601Utils.parse("1970-01-01T00:00:00.0009+02:00", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 0, 2 * 60), d); d = ISO8601Utils.parse("1970-01-01T00:00:00.2147483648+02:00", new ParsePosition(0)); assertEquals(newDate(1970, 1, 1, 0, 0, 0, 214, 2 * 60), d); } public void testDecimalWithoutDecimalPointButNoFractionalSeconds() throws java.text.ParseException { try { ISO8601Utils.parse("1970-01-01T00:00:00.Z", new ParsePosition(0)); fail(); } catch (ParseException expected) { } } private Date newDate(int year, int month, int day, int hour, int minute, int second, int millis, int timezoneOffsetMinutes) { Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT")); calendar.set(year, month - 1, day, hour, minute, second); calendar.set(Calendar.MILLISECOND, millis); return new Date(calendar.getTimeInMillis() - TimeUnit.MINUTES.toMillis(timezoneOffsetMinutes)); } } JSONPObjectTest.java000066400000000000000000000027061325620701100352100ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.IOException; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class JSONPObjectTest extends BaseMapTest { private final String CALLBACK = "callback"; private final ObjectMapper MAPPER = new ObjectMapper(); /** * Unit tests for checking that JSONP breaking characters U+2028 and U+2029 are escaped when creating a {@link JSONPObject}. */ public void testU2028Escaped() throws IOException { String containsU2028 = String.format("This string contains %c char", '\u2028'); JSONPObject jsonpObject = new JSONPObject(CALLBACK, containsU2028); String valueAsString = MAPPER.writeValueAsString(jsonpObject); assertFalse(valueAsString.contains("\u2028")); } public void testU2029Escaped() throws IOException { String containsU2029 = String.format("This string contains %c char", '\u2029'); JSONPObject jsonpObject = new JSONPObject(CALLBACK, containsU2029); String valueAsString = MAPPER.writeValueAsString(jsonpObject); assertFalse(valueAsString.contains("\u2029")); } public void testU2030NotEscaped() throws IOException { String containsU2030 = String.format("This string contains %c char", '\u2030'); JSONPObject jsonpObject = new JSONPObject(CALLBACK, containsU2030); String valueAsString = MAPPER.writeValueAsString(jsonpObject); assertTrue(valueAsString.contains("\u2030")); } } JsonParserSequenceTest.java000066400000000000000000000034231325620701100367440ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.util.JsonParserSequence; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class JsonParserSequenceTest extends BaseMapTest { private final ObjectMapper MAPPER = objectMapper(); /** * Verifies fix for [core#372] */ @SuppressWarnings("resource") public void testJsonParserSequenceOverridesSkipChildren() throws Exception { // Create parser from TokenBuffer containing an incomplete JSON object TokenBuffer buf1 = new TokenBuffer(MAPPER, false); buf1.writeStartObject(); buf1.writeFieldName("foo"); buf1.writeStartObject(); JsonParser parser1 = buf1.asParser(); // Create parser from second TokenBuffer that completes the object started by the first buffer TokenBuffer buf2 = new TokenBuffer(MAPPER, false); buf2.writeEndObject(); buf2.writeEndObject(); JsonParser parser2 = buf2.asParser(); // Create sequence of both parsers and verify tokens JsonParser parserSequence = JsonParserSequence.createFlattened(false, parser1, parser2); assertToken(JsonToken.START_OBJECT, parserSequence.nextToken()); assertToken(JsonToken.FIELD_NAME, parserSequence.nextToken()); assertToken(JsonToken.START_OBJECT, parserSequence.nextToken()); // Skip children of current token. JsonParserSequence's overridden version should switch to the next parser // in the sequence parserSequence.skipChildren(); // Verify last token assertToken(JsonToken.END_OBJECT, parserSequence.nextToken()); } } NameTransformerTest.java000066400000000000000000000013641325620701100362720ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import com.fasterxml.jackson.databind.BaseMapTest; public class NameTransformerTest extends BaseMapTest { public void testSimpleTransformer() throws Exception { NameTransformer xfer; xfer = NameTransformer.simpleTransformer("a", null); assertEquals("aFoo", xfer.transform("Foo")); assertEquals("Foo", xfer.reverse("aFoo")); xfer = NameTransformer.simpleTransformer(null, "++"); assertEquals("foo++", xfer.transform("foo")); assertEquals("foo", xfer.reverse("foo++")); xfer = NameTransformer.simpleTransformer("(", ")"); assertEquals("(foo)", xfer.transform("foo")); assertEquals("foo", xfer.reverse("(foo)")); } } RawValueTest.java000066400000000000000000000012231325620701100347070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JsonSerializable; public class RawValueTest extends BaseMapTest { public void testEquality() { RawValue raw1 = new RawValue("foo"); RawValue raw1b = new RawValue("foo"); RawValue raw2 = new RawValue("bar"); assertTrue(raw1.equals(raw1)); assertTrue(raw1.equals(raw1b)); assertFalse(raw1.equals(raw2)); assertFalse(raw1.equals(null)); assertFalse(new RawValue((JsonSerializable) null).equals(raw1)); assertNotNull(raw1.toString()); } } TestObjectBuffer.java000066400000000000000000000041231325620701100355230ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.util.*; import com.fasterxml.jackson.databind.BaseMapTest; public class TestObjectBuffer extends BaseMapTest { /** * First a test that treats results as plain old Object[] */ public void testUntyped() { _testObjectBuffer(null); } public void testTyped() { _testObjectBuffer(Integer.class); } /* /********************************************************** /* Helper methods /********************************************************** */ private void _testObjectBuffer(Class clz) { int[] SIZES = new int[] { 3, 19, 99, 1007, 79000, 256001 }; // Let's loop separately for reused instance, new instance for (int reuse = 0; reuse < 2; ++reuse) { ObjectBuffer buf = (reuse == 0) ? null : new ObjectBuffer(); // then distinct sizes for (int sizeIndex = 0; sizeIndex < SIZES.length; ++sizeIndex) { int size = SIZES[sizeIndex]; Random r = new Random(size); ObjectBuffer thisBuf = (buf == null) ? new ObjectBuffer() : buf; Object[] chunk = thisBuf.resetAndStart(); int ix = 0; for (int i = 0; i < size; ++i) { if (ix >= chunk.length) { chunk = thisBuf.appendCompletedChunk(chunk); ix = 0; } chunk[ix++] = Integer.valueOf(r.nextInt()); } Object[] result; if (clz == null) { result = thisBuf.completeAndClearBuffer(chunk, ix); } else { result = thisBuf.completeAndClearBuffer(chunk, ix, clz); } assertEquals(size, result.length); r = new Random(size); for (int i = 0; i < size; ++i) { assertEquals(r.nextInt(), ((Integer) result[i]).intValue()); } } } } } TestStdDateFormat.java000066400000000000000000000105171325620701100356700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.text.ParseException; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.util.StdDateFormat; public class TestStdDateFormat extends BaseMapTest { @SuppressWarnings("deprecation") public void testFactories() { TimeZone tz = TimeZone.getTimeZone("GMT"); Locale loc = Locale.US; assertNotNull(StdDateFormat.getISO8601Format(tz, loc)); assertNotNull(StdDateFormat.getRFC1123Format(tz, loc)); } // [databind#803] public void testLenientDefaults() throws Exception { StdDateFormat f = StdDateFormat.instance; // default should be lenient assertTrue(f.isLenient()); StdDateFormat f2 = f.clone(); assertTrue(f2.isLenient()); f2.setLenient(false); assertFalse(f2.isLenient()); f2.setLenient(true); assertTrue(f2.isLenient()); // and for testing, finally, leave as non-lenient f2.setLenient(false); assertFalse(f2.isLenient()); StdDateFormat f3 = f2.clone(); assertFalse(f3.isLenient()); } public void testISO8601RegexpDateOnly() throws Exception { Pattern p = StdDateFormat.PATTERN_PLAIN; Matcher m = p.matcher("1997-07-16"); assertTrue(m.matches()); // no matching groups... } public void testISO8601RegexpFull() throws Exception { /* String PATTERN_PLAIN_STR = "\\d\\d\\d\\d[-]\\d\\d[-]\\d\\d"; Pattern PATTERN_ISO8601 = Pattern.compile(PATTERN_PLAIN_STR +"[T]\\d\\d[:]\\d\\d(?:[:]\\d\\d)?" // hours, minutes, optional seconds +"(\\.\\d+)?" // optional second fractions +"(Z|[+-]\\d\\d(?:[:]?\\d\\d)?)?" // optional timeoffset/Z ); final Pattern p = PATTERN_ISO8601; */ final Pattern p = StdDateFormat.PATTERN_ISO8601; Matcher m; // First simple full representation (except no millisecs) m = p.matcher("1997-07-16T19:20:00+01:00"); assertTrue(m.matches()); assertEquals(2, m.groupCount()); assertNull(m.group(1)); // no match (why not empty String) assertEquals("+01:00", m.group(2)); // Then with 'Z' instead m = p.matcher("1997-07-16T19:20:00Z"); assertTrue(m.matches()); assertNull(m.group(1)); assertEquals("Z", m.group(2)); // Then drop seconds too m = p.matcher("1997-07-16T19:20+01:00"); assertTrue(m.matches()); assertNull(m.group(1)); assertEquals("+01:00", m.group(2)); // Full with milliseconds: m = p.matcher("1997-07-16T19:20:00.2+03:00"); assertTrue(m.matches()); assertEquals(2, m.groupCount()); assertEquals(".2", m.group(1)); assertEquals("+03:00", m.group(2)); m = p.matcher("1972-12-28T00:00:00.01-0300"); assertTrue(m.matches()); assertEquals(".01", m.group(1)); assertEquals("-0300", m.group(2)); m = p.matcher("1972-12-28T00:00:00.400+00"); assertTrue(m.matches()); assertEquals(".400", m.group(1)); assertEquals("+00", m.group(2)); // and then drop time offset AND seconds m = p.matcher("1972-12-28T04:15"); assertTrue(m.matches()); assertNull(m.group(1)); assertNull(m.group(2)); } public void testLenientParsing() throws Exception { StdDateFormat f = StdDateFormat.instance.clone(); f.setLenient(false); // first, legal dates are... legal Date dt = f.parse("2015-11-30"); assertNotNull(dt); // but as importantly, when not lenient, do not allow try { f.parse("2015-11-32"); fail("Should not pass"); } catch (ParseException e) { verifyException(e, "Cannot parse date"); } // ... yet, with lenient, do allow f.setLenient(true); dt = f.parse("2015-11-32"); assertNotNull(dt); } public void testInvalid() { StdDateFormat std = new StdDateFormat(); try { std.parse("foobar"); } catch (java.text.ParseException e) { verifyException(e, "Cannot parse"); } } } TestTokenBuffer.java000066400000000000000000000560651325620701100354110ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/utilpackage com.fasterxml.jackson.databind.util; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.UUID; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.JsonParser.NumberType; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.core.util.JsonParserSequence; import com.fasterxml.jackson.databind.*; public class TestTokenBuffer extends BaseMapTest { private final ObjectMapper MAPPER = objectMapper(); static class Base1730 { } static class Sub1730 extends Base1730 { } /* /********************************************************** /* Basic TokenBuffer tests /********************************************************** */ public void testBasicConfig() throws IOException { TokenBuffer buf; buf = new TokenBuffer(MAPPER, false); assertEquals(MAPPER.version(), buf.version()); assertSame(MAPPER, buf.getCodec()); assertNotNull(buf.getOutputContext()); assertFalse(buf.isClosed()); buf.setCodec(null); assertNull(buf.getCodec()); assertFalse(buf.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII)); buf.enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); assertTrue(buf.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII)); buf.disable(JsonGenerator.Feature.ESCAPE_NON_ASCII); assertFalse(buf.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII)); buf.close(); assertTrue(buf.isClosed()); } /** * Test writing of individual simple values */ public void testSimpleWrites() throws IOException { TokenBuffer buf = new TokenBuffer(null, false); // no ObjectCodec // First, with empty buffer JsonParser p = buf.asParser(); assertNull(p.getCurrentToken()); assertNull(p.nextToken()); p.close(); // Then with simple text buf.writeString("abc"); p = buf.asParser(); assertNull(p.getCurrentToken()); assertToken(JsonToken.VALUE_STRING, p.nextToken()); assertEquals("abc", p.getText()); assertNull(p.nextToken()); p.close(); // Then, let's append at root level buf.writeNumber(13); p = buf.asParser(); assertNull(p.getCurrentToken()); assertToken(JsonToken.VALUE_STRING, p.nextToken()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(13, p.getIntValue()); assertNull(p.nextToken()); p.close(); buf.close(); } // For 2.9, explicit "isNaN" check public void testSimpleNumberWrites() throws IOException { TokenBuffer buf = new TokenBuffer(null, false); double[] values1 = new double[] { 0.25, Double.NaN, -2.0, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY }; float[] values2 = new float[] { Float.NEGATIVE_INFINITY, 0.25f, Float.POSITIVE_INFINITY }; for (double v : values1) { buf.writeNumber(v); } for (float v : values2) { buf.writeNumber(v); } JsonParser p = buf.asParser(); assertNull(p.getCurrentToken()); for (double v : values1) { assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); double actual = p.getDoubleValue(); boolean expNan = Double.isNaN(v) || Double.isInfinite(v); assertEquals(expNan, p.isNaN()); assertEquals(0, Double.compare(v, actual)); } for (float v : values2) { assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); float actual = p.getFloatValue(); boolean expNan = Float.isNaN(v) || Float.isInfinite(v); assertEquals(expNan, p.isNaN()); assertEquals(0, Float.compare(v, actual)); } p.close(); buf.close(); } // [databind#1729] public void testNumberOverflowInt() throws IOException { try (TokenBuffer buf = new TokenBuffer(null, false)) { long big = 1L + Integer.MAX_VALUE; buf.writeNumber(big); try (JsonParser p = buf.asParser()) { assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(NumberType.LONG, p.getNumberType()); try { p.getIntValue(); fail("Expected failure for `int` overflow"); } catch (JsonParseException e) { verifyException(e, "Numeric value ("+big+") out of range of int"); } } } // and ditto for coercion. try (TokenBuffer buf = new TokenBuffer(null, false)) { long big = 1L + Integer.MAX_VALUE; buf.writeNumber(String.valueOf(big)); try (JsonParser p = buf.asParser()) { // NOTE: oddity of buffering, no inspection of "real" type if given String... assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); try { p.getIntValue(); fail("Expected failure for `int` overflow"); } catch (JsonParseException e) { verifyException(e, "Numeric value ("+big+") out of range of int"); } } } } public void testNumberOverflowLong() throws IOException { try (TokenBuffer buf = new TokenBuffer(null, false)) { BigInteger big = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); buf.writeNumber(big); try (JsonParser p = buf.asParser()) { assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(NumberType.BIG_INTEGER, p.getNumberType()); try { p.getLongValue(); fail("Expected failure for `long` overflow"); } catch (JsonParseException e) { verifyException(e, "Numeric value ("+big+") out of range of long"); } } } } public void testParentContext() throws IOException { TokenBuffer buf = new TokenBuffer(null, false); // no ObjectCodec buf.writeStartObject(); buf.writeFieldName("b"); buf.writeStartObject(); buf.writeFieldName("c"); //This assertion succeeds as expected assertEquals("b", buf.getOutputContext().getParent().getCurrentName()); buf.writeString("cval"); buf.writeEndObject(); buf.writeEndObject(); buf.close(); } public void testSimpleArray() throws IOException { TokenBuffer buf = new TokenBuffer(null, false); // no ObjectCodec // First, empty array assertTrue(buf.getOutputContext().inRoot()); buf.writeStartArray(); assertTrue(buf.getOutputContext().inArray()); buf.writeEndArray(); assertTrue(buf.getOutputContext().inRoot()); JsonParser p = buf.asParser(); assertNull(p.getCurrentToken()); assertTrue(p.getParsingContext().inRoot()); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertTrue(p.getParsingContext().inArray()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertTrue(p.getParsingContext().inRoot()); assertNull(p.nextToken()); p.close(); buf.close(); // Then one with simple contents buf = new TokenBuffer(null, false); buf.writeStartArray(); buf.writeBoolean(true); buf.writeNull(); buf.writeEndArray(); p = buf.asParser(); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.VALUE_TRUE, p.nextToken()); assertTrue(p.getBooleanValue()); assertToken(JsonToken.VALUE_NULL, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertNull(p.nextToken()); p.close(); buf.close(); // And finally, with array-in-array buf = new TokenBuffer(null, false); buf.writeStartArray(); buf.writeStartArray(); buf.writeBinary(new byte[3]); buf.writeEndArray(); buf.writeEndArray(); p = buf.asParser(); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.START_ARRAY, p.nextToken()); // TokenBuffer exposes it as embedded object... assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); Object ob = p.getEmbeddedObject(); assertNotNull(ob); assertTrue(ob instanceof byte[]); assertEquals(3, ((byte[]) ob).length); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertNull(p.nextToken()); p.close(); buf.close(); } public void testSimpleObject() throws IOException { TokenBuffer buf = new TokenBuffer(null, false); // First, empty JSON Object assertTrue(buf.getOutputContext().inRoot()); buf.writeStartObject(); assertTrue(buf.getOutputContext().inObject()); buf.writeEndObject(); assertTrue(buf.getOutputContext().inRoot()); JsonParser p = buf.asParser(); assertNull(p.getCurrentToken()); assertTrue(p.getParsingContext().inRoot()); assertToken(JsonToken.START_OBJECT, p.nextToken()); assertTrue(p.getParsingContext().inObject()); assertToken(JsonToken.END_OBJECT, p.nextToken()); assertTrue(p.getParsingContext().inRoot()); assertNull(p.nextToken()); p.close(); buf.close(); // Then one with simple contents buf = new TokenBuffer(null, false); buf.writeStartObject(); buf.writeNumberField("num", 1.25); buf.writeEndObject(); p = buf.asParser(); assertNull(p.getCurrentToken()); assertToken(JsonToken.START_OBJECT, p.nextToken()); assertNull(p.getCurrentName()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); assertEquals("num", p.getCurrentName()); // and override should also work: p.overrideCurrentName("bah"); assertEquals("bah", p.getCurrentName()); assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); assertEquals(1.25, p.getDoubleValue()); // should still have access to (overridden) name assertEquals("bah", p.getCurrentName()); assertToken(JsonToken.END_OBJECT, p.nextToken()); // but not any more assertNull(p.getCurrentName()); assertNull(p.nextToken()); p.close(); buf.close(); } /** * Verify handling of that "standard" test document (from JSON * specification) */ public void testWithJSONSampleDoc() throws Exception { // First, copy events from known good source (StringReader) JsonParser p = createParserUsingReader(SAMPLE_DOC_JSON_SPEC); TokenBuffer tb = new TokenBuffer(null, false); while (p.nextToken() != null) { tb.copyCurrentEvent(p); } // And then request verification; first structure only: verifyJsonSpecSampleDoc(tb.asParser(), false); // then content check too: verifyJsonSpecSampleDoc(tb.asParser(), true); tb.close(); p.close(); // 19-Oct-2016, tatu: Just for fun, trigger `toString()` for code coverage String desc = tb.toString(); assertNotNull(desc); } public void testAppend() throws IOException { TokenBuffer buf1 = new TokenBuffer(null, false); buf1.writeStartObject(); buf1.writeFieldName("a"); buf1.writeBoolean(true); TokenBuffer buf2 = new TokenBuffer(null, false); buf2.writeFieldName("b"); buf2.writeNumber(13); buf2.writeEndObject(); buf1.append(buf2); // and verify that we got it all... JsonParser p = buf1.asParser(); assertToken(JsonToken.START_OBJECT, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); assertEquals("a", p.getCurrentName()); assertToken(JsonToken.VALUE_TRUE, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); assertEquals("b", p.getCurrentName()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(13, p.getIntValue()); assertToken(JsonToken.END_OBJECT, p.nextToken()); p.close(); buf1.close(); buf2.close(); } // Since 2.3 had big changes to UUID handling, let's verify we can // deal with public void testWithUUID() throws IOException { for (String value : new String[] { "00000007-0000-0000-0000-000000000000", "76e6d183-5f68-4afa-b94a-922c1fdb83f8", "540a88d1-e2d8-4fb1-9396-9212280d0a7f", "2c9e441d-1cd0-472d-9bab-69838f877574", "591b2869-146e-41d7-8048-e8131f1fdec5", "82994ac2-7b23-49f2-8cc5-e24cf6ed77be", }) { TokenBuffer buf = new TokenBuffer(MAPPER, false); // no ObjectCodec UUID uuid = UUID.fromString(value); MAPPER.writeValue(buf, uuid); buf.close(); // and bring it back UUID out = MAPPER.readValue(buf.asParser(), UUID.class); assertEquals(uuid.toString(), out.toString()); // second part: As per [databind#362], should NOT use binary with TokenBuffer JsonParser p = buf.asParser(); assertEquals(JsonToken.VALUE_STRING, p.nextToken()); String str = p.getText(); assertEquals(value, str); p.close(); } } /* /********************************************************** /* Tests for read/output contexts /********************************************************** */ // for [databind#984]: ensure output context handling identical public void testOutputContext() throws IOException { TokenBuffer buf = new TokenBuffer(null, false); // no ObjectCodec StringWriter w = new StringWriter(); JsonGenerator gen = MAPPER.getFactory().createGenerator(w); // test content: [{"a":1,"b":{"c":2}},{"a":2,"b":{"c":3}}] buf.writeStartArray(); gen.writeStartArray(); _verifyOutputContext(buf, gen); buf.writeStartObject(); gen.writeStartObject(); _verifyOutputContext(buf, gen); buf.writeFieldName("a"); gen.writeFieldName("a"); _verifyOutputContext(buf, gen); buf.writeNumber(1); gen.writeNumber(1); _verifyOutputContext(buf, gen); buf.writeFieldName("b"); gen.writeFieldName("b"); _verifyOutputContext(buf, gen); buf.writeStartObject(); gen.writeStartObject(); _verifyOutputContext(buf, gen); buf.writeFieldName("c"); gen.writeFieldName("c"); _verifyOutputContext(buf, gen); buf.writeNumber(2); gen.writeNumber(2); _verifyOutputContext(buf, gen); buf.writeEndObject(); gen.writeEndObject(); _verifyOutputContext(buf, gen); buf.writeEndObject(); gen.writeEndObject(); _verifyOutputContext(buf, gen); buf.writeEndArray(); gen.writeEndArray(); _verifyOutputContext(buf, gen); buf.close(); gen.close(); } private void _verifyOutputContext(JsonGenerator gen1, JsonGenerator gen2) { _verifyOutputContext(gen1.getOutputContext(), gen2.getOutputContext()); } private void _verifyOutputContext(JsonStreamContext ctxt1, JsonStreamContext ctxt2) { if (ctxt1 == null) { if (ctxt2 == null) { return; } fail("Context 1 null, context 2 not null: "+ctxt2); } else if (ctxt2 == null) { fail("Context 2 null, context 1 not null: "+ctxt1); } if (!ctxt1.toString().equals(ctxt2.toString())) { fail("Different output context: token-buffer's = "+ctxt1+", json-generator's: "+ctxt2); } if (ctxt1.inObject()) { assertTrue(ctxt2.inObject()); String str1 = ctxt1.getCurrentName(); String str2 = ctxt2.getCurrentName(); if ((str1 != str2) && !str1.equals(str2)) { fail("Expected name '"+str2+"' (JsonParser), TokenBuffer had '"+str1+"'"); } } else if (ctxt1.inArray()) { assertTrue(ctxt2.inArray()); assertEquals(ctxt1.getCurrentIndex(), ctxt2.getCurrentIndex()); } _verifyOutputContext(ctxt1.getParent(), ctxt2.getParent()); } // [databind#1253] public void testParentSiblingContext() throws IOException { TokenBuffer buf = new TokenBuffer(null, false); // no ObjectCodec // {"a":{},"b":{"c":"cval"}} buf.writeStartObject(); buf.writeFieldName("a"); buf.writeStartObject(); buf.writeEndObject(); buf.writeFieldName("b"); buf.writeStartObject(); buf.writeFieldName("c"); //This assertion fails (because of 'a') assertEquals("b", buf.getOutputContext().getParent().getCurrentName()); buf.writeString("cval"); buf.writeEndObject(); buf.writeEndObject(); buf.close(); } public void testBasicSerialize() throws IOException { TokenBuffer buf; // let's see how empty works... buf = new TokenBuffer(MAPPER, false); assertEquals("", MAPPER.writeValueAsString(buf)); buf.close(); buf = new TokenBuffer(MAPPER, false); buf.writeStartArray(); buf.writeBoolean(true); buf.writeBoolean(false); long l = 1L + Integer.MAX_VALUE; buf.writeNumber(l); buf.writeNumber((short) 4); buf.writeNumber(0.5); buf.writeEndArray(); assertEquals(aposToQuotes("[true,false,"+l+",4,0.5]"), MAPPER.writeValueAsString(buf)); buf.close(); buf = new TokenBuffer(MAPPER, false); buf.writeStartObject(); buf.writeFieldName(new SerializedString("foo")); buf.writeNull(); buf.writeFieldName("bar"); buf.writeNumber(BigInteger.valueOf(123)); buf.writeFieldName("dec"); buf.writeNumber(BigDecimal.valueOf(5).movePointLeft(2)); assertEquals(aposToQuotes("{'foo':null,'bar':123,'dec':0.05}"), MAPPER.writeValueAsString(buf)); buf.close(); } /* /********************************************************** /* Tests to verify interaction of TokenBuffer and JsonParserSequence /********************************************************** */ public void testWithJsonParserSequenceSimple() throws IOException { // Let's join a TokenBuffer with JsonParser first TokenBuffer buf = new TokenBuffer(null, false); buf.writeStartArray(); buf.writeString("test"); JsonParser p = createParserUsingReader("[ true, null ]"); JsonParserSequence seq = JsonParserSequence.createFlattened(false, buf.asParser(), p); assertEquals(2, seq.containedParsersCount()); assertFalse(p.isClosed()); assertFalse(seq.hasCurrentToken()); assertNull(seq.getCurrentToken()); assertNull(seq.getCurrentName()); assertToken(JsonToken.START_ARRAY, seq.nextToken()); assertToken(JsonToken.VALUE_STRING, seq.nextToken()); assertEquals("test", seq.getText()); // end of first parser input, should switch over: assertToken(JsonToken.START_ARRAY, seq.nextToken()); assertToken(JsonToken.VALUE_TRUE, seq.nextToken()); assertToken(JsonToken.VALUE_NULL, seq.nextToken()); assertToken(JsonToken.END_ARRAY, seq.nextToken()); /* 17-Jan-2009, tatus: At this point, we may or may not get an * exception, depending on how underlying parsers work. * Ideally this should be fixed, probably by asking underlying * parsers to disable checking for balanced start/end markers. */ // for this particular case, we won't get an exception tho... assertNull(seq.nextToken()); // not an error to call again... assertNull(seq.nextToken()); // also: original parsers should be closed assertTrue(p.isClosed()); p.close(); buf.close(); seq.close(); } /** * Test to verify that TokenBuffer and JsonParserSequence work together * as expected. */ @SuppressWarnings("resource") public void testWithMultipleJsonParserSequences() throws IOException { TokenBuffer buf1 = new TokenBuffer(null, false); buf1.writeStartArray(); TokenBuffer buf2 = new TokenBuffer(null, false); buf2.writeString("a"); TokenBuffer buf3 = new TokenBuffer(null, false); buf3.writeNumber(13); TokenBuffer buf4 = new TokenBuffer(null, false); buf4.writeEndArray(); JsonParserSequence seq1 = JsonParserSequence.createFlattened(false, buf1.asParser(), buf2.asParser()); assertEquals(2, seq1.containedParsersCount()); JsonParserSequence seq2 = JsonParserSequence.createFlattened(false, buf3.asParser(), buf4.asParser()); assertEquals(2, seq2.containedParsersCount()); JsonParserSequence combo = JsonParserSequence.createFlattened(false, seq1, seq2); // should flatten it to have 4 underlying parsers assertEquals(4, combo.containedParsersCount()); assertToken(JsonToken.START_ARRAY, combo.nextToken()); assertToken(JsonToken.VALUE_STRING, combo.nextToken()); assertEquals("a", combo.getText()); assertToken(JsonToken.VALUE_NUMBER_INT, combo.nextToken()); assertEquals(13, combo.getIntValue()); assertToken(JsonToken.END_ARRAY, combo.nextToken()); assertNull(combo.nextToken()); buf1.close(); buf2.close(); buf3.close(); buf4.close(); } // [databind#743] public void testRawValues() throws Exception { final String RAW = "{\"a\":1}"; TokenBuffer buf = new TokenBuffer(null, false); buf.writeRawValue(RAW); // first: raw value won't be transformed in any way: JsonParser p = buf.asParser(); assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); assertEquals(RawValue.class, p.getEmbeddedObject().getClass()); assertNull(p.nextToken()); p.close(); buf.close(); // then verify it would be serialized just fine assertEquals(RAW, MAPPER.writeValueAsString(buf)); } // [databind#1730] public void testEmbeddedObjectCoerceCheck() throws Exception { TokenBuffer buf = new TokenBuffer(null, false); Object inputPojo = new Sub1730(); buf.writeEmbeddedObject(inputPojo); // first: raw value won't be transformed in any way: JsonParser p = buf.asParser(); Base1730 out = MAPPER.readValue(p, Base1730.class); assertSame(inputPojo, out); p.close(); buf.close(); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/views/000077500000000000000000000000001325620701100317175ustar00rootroot00000000000000DefaultViewTest.java000066400000000000000000000040721325620701100355650ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/viewspackage com.fasterxml.jackson.databind.views; import java.io.IOException; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // for [databind#507], supporting default views public class DefaultViewTest extends BaseMapTest { // Classes that represent views static class ViewA { } static class ViewAA extends ViewA { } static class ViewB { } static class ViewBB extends ViewB { } @JsonView(ViewA.class) @JsonPropertyOrder({ "a", "b" }) static class Defaulting { public int a = 3; @JsonView(ViewB.class) public int b = 5; } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testDeserialization() throws IOException { final String JSON = aposToQuotes("{'a':1,'b':2}"); // first: no views: Defaulting result = MAPPER.readerFor(Defaulting.class) .readValue(JSON); assertEquals(result.a, 1); assertEquals(result.b, 2); // Then views; first A, then B(B) result = MAPPER.readerFor(Defaulting.class) .withView(ViewA.class) .readValue(JSON); assertEquals(result.a, 1); assertEquals(result.b, 5); result = MAPPER.readerFor(Defaulting.class) .withView(ViewBB.class) .readValue(JSON); assertEquals(result.a, 3); assertEquals(result.b, 2); } public void testSerialization() throws IOException { assertEquals(aposToQuotes("{'a':3,'b':5}"), MAPPER.writeValueAsString(new Defaulting())); assertEquals(aposToQuotes("{'a':3}"), MAPPER.writerWithView(ViewA.class) .writeValueAsString(new Defaulting())); assertEquals(aposToQuotes("{'b':5}"), MAPPER.writerWithView(ViewB.class) .writeValueAsString(new Defaulting())); } } TestViewDeserialization.java000066400000000000000000000103171325620701100373260ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/viewspackage com.fasterxml.jackson.databind.views; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.*; public class TestViewDeserialization extends BaseMapTest { // Classes that represent views static class ViewA { } static class ViewAA extends ViewA { } static class ViewB { } static class ViewBB extends ViewB { } static class Bean { @JsonView(ViewA.class) public int a; @JsonView({ViewAA.class, ViewB.class}) public String aa; protected int b; @JsonView(ViewB.class) public void setB(int value) { b = value; } } static class DefaultsBean { public int a; @JsonView(ViewA.class) public int b; } static class ViewsAndCreatorBean { @JsonView(ViewA.class) public int a; @JsonView(ViewB.class) public int b; @JsonCreator public ViewsAndCreatorBean(@JsonProperty("a") int a, @JsonProperty("b") int b) { this.a = a; this.b = b; } } /* /************************************************************************ /* Tests /************************************************************************ */ private final ObjectMapper mapper = new ObjectMapper(); public void testSimple() throws Exception { // by default, should have it all... Bean bean = mapper .readValue("{\"a\":3, \"aa\":\"foo\", \"b\": 9 }", Bean.class); assertEquals(3, bean.a); assertEquals("foo", bean.aa); assertEquals(9, bean.b); // but with different views, different contents bean = mapper.readerWithView(ViewAA.class) .forType(Bean.class) .readValue("{\"a\":3, \"aa\":\"foo\", \"b\": 9 }"); // should include 'a' and 'aa' (as per view) assertEquals(3, bean.a); assertEquals("foo", bean.aa); // but not 'b' assertEquals(0, bean.b); bean = mapper.readerWithView(ViewA.class) .forType(Bean.class) .readValue("{\"a\":1, \"aa\":\"x\", \"b\": 3 }"); assertEquals(1, bean.a); assertNull(bean.aa); assertEquals(0, bean.b); bean = mapper.readerFor(Bean.class) .withView(ViewB.class) .readValue("{\"a\":-3, \"aa\":\"y\", \"b\": 2 }"); assertEquals(0, bean.a); assertEquals("y", bean.aa); assertEquals(2, bean.b); } public void testWithoutDefaultInclusion() throws Exception { // without active view, all included still: DefaultsBean bean = mapper .readValue("{\"a\":3, \"b\": 9 }", DefaultsBean.class); assertEquals(3, bean.a); assertEquals(9, bean.b); ObjectMapper myMapper = new ObjectMapper(); myMapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION); // but with, say, AA, will not get 'b' bean = myMapper.readerWithView(ViewAA.class) .forType(DefaultsBean.class) .readValue("{\"a\":1, \"b\": 2 }"); // 'a' not there any more assertEquals(0, bean.a); assertEquals(2, bean.b); } public void testWithCreatorAndViews() throws Exception { ViewsAndCreatorBean result; result = mapper.readerFor(ViewsAndCreatorBean.class) .withView(ViewA.class) .readValue(aposToQuotes("{'a':1,'b':2}")); assertEquals(1, result.a); assertEquals(0, result.b); result = mapper.readerFor(ViewsAndCreatorBean.class) .withView(ViewB.class) .readValue(aposToQuotes("{'a':1,'b':2}")); assertEquals(0, result.a); assertEquals(2, result.b); // and actually... fine to skip incompatible stuff too result = mapper.readerFor(ViewsAndCreatorBean.class) .withView(ViewB.class) .readValue(aposToQuotes("{'a':[ 1, 23, { } ],'b':2}")); assertEquals(0, result.a); assertEquals(2, result.b); } } TestViewSerialization.java000066400000000000000000000137131325620701100370200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/viewspackage com.fasterxml.jackson.databind.views; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying JSON view functionality: ability to declaratively * suppress subset of properties from being serialized. */ public class TestViewSerialization extends BaseMapTest { // Classes that represent views static class ViewA { } static class ViewAA extends ViewA { } static class ViewB { } static class ViewBB extends ViewB { } static class Bean { @JsonView(ViewA.class) public String a = "1"; @JsonView({ViewAA.class, ViewB.class}) public String aa = "2"; @JsonView(ViewB.class) public String getB() { return "3"; } } /** * Bean with mix of explicitly annotated * properties, and implicit ones that may or may * not be included in views. */ static class MixedBean { @JsonView(ViewA.class) public String a = "1"; public String getB() { return "2"; } } /** * As indicated by [JACKSON-261], @JsonView should imply * that associated element (method, field) is to be considered * a property */ static class ImplicitBean { @JsonView(ViewA.class) private int a = 1; } static class VisibilityBean { @JsonProperty protected String id = "id"; @JsonView(ViewA.class) public String value = "x"; } public static class WebView { } public static class OtherView { } public static class Foo { @JsonView(WebView.class) public int getFoo() { return 3; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); @SuppressWarnings("unchecked") public void testSimple() throws IOException { StringWriter sw = new StringWriter(); // Ok, first, using no view whatsoever; all 3 Bean bean = new Bean(); Map map = writeAndMap(MAPPER, bean); assertEquals(3, map.size()); // Then with "ViewA", just one property sw = new StringWriter(); MAPPER.writerWithView(ViewA.class).writeValue(sw, bean); map = MAPPER.readValue(sw.toString(), Map.class); assertEquals(1, map.size()); assertEquals("1", map.get("a")); // "ViewAA", 2 properties sw = new StringWriter(); MAPPER.writerWithView(ViewAA.class).writeValue(sw, bean); map = MAPPER.readValue(sw.toString(), Map.class); assertEquals(2, map.size()); assertEquals("1", map.get("a")); assertEquals("2", map.get("aa")); // "ViewB", 2 prop2 String json = MAPPER.writerWithView(ViewB.class).writeValueAsString(bean); map = MAPPER.readValue(json, Map.class); assertEquals(2, map.size()); assertEquals("2", map.get("aa")); assertEquals("3", map.get("b")); // and "ViewBB", 2 as well json = MAPPER.writerWithView(ViewBB.class).writeValueAsString(bean); map = MAPPER.readValue(json, Map.class); assertEquals(2, map.size()); assertEquals("2", map.get("aa")); assertEquals("3", map.get("b")); // and finally, without view. json = MAPPER.writerWithView(null).writeValueAsString(bean); map = MAPPER.readValue(json, Map.class); assertEquals(3, map.size()); } /** * Unit test to verify implementation of [JACKSON-232], to * allow "opt-in" handling for JSON Views: that is, that * default for properties is to exclude unless included in * a view. */ @SuppressWarnings("unchecked") public void testDefaultExclusion() throws IOException { MixedBean bean = new MixedBean(); // default setting: both fields will get included String json = MAPPER.writerWithView(ViewA.class).writeValueAsString(bean); Map map = MAPPER.readValue(json, Map.class); assertEquals(2, map.size()); assertEquals("1", map.get("a")); assertEquals("2", map.get("b")); // but can also change (but not necessarily on the fly...) ObjectMapper mapper = new ObjectMapper(); mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); // with this setting, only explicit inclusions count: json = mapper.writerWithView(ViewA.class).writeValueAsString(bean); map = mapper.readValue(json, Map.class); assertEquals(1, map.size()); assertEquals("1", map.get("a")); assertNull(map.get("b")); // but without view, view processing disabled: json = mapper.writer().withView(null).writeValueAsString(bean); map = mapper.readValue(json, Map.class); assertEquals(2, map.size()); assertEquals("1", map.get("a")); assertEquals("2", map.get("b")); } /** * As per [JACKSON-261], @JsonView annotation should imply that associated * method/field does indicate a property. */ public void testImplicitAutoDetection() throws Exception { assertEquals("{\"a\":1}", MAPPER.writeValueAsString(new ImplicitBean())); } public void testVisibility() throws Exception { VisibilityBean bean = new VisibilityBean(); // Without view setting, should only see "id" String json = MAPPER.writerWithView(Object.class).writeValueAsString(bean); //json = mapper.writeValueAsString(bean); assertEquals("{\"id\":\"id\"}", json); } // [JACKSON-868] public void test868() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); String json = mapper.writerWithView(OtherView.class).writeValueAsString(new Foo()); assertEquals(json, "{}"); } } TestViewsSerialization2.java000066400000000000000000000074431325620701100372700ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/viewspackage com.fasterxml.jackson.databind.views; import java.io.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestViewsSerialization2 extends BaseMapTest { /* /************************************************************************ /* Helper classes /************************************************************************ */ static class Views { public interface View { } public interface ExtendedView extends View { } } static class ComplexTestData { String nameNull = null; String nameComplex = "complexValue"; String nameComplexHidden = "nameComplexHiddenValue"; SimpleTestData testData = new SimpleTestData( ); SimpleTestData[] testDataArray = new SimpleTestData[] { new SimpleTestData( ), null }; @JsonView( Views.View.class ) public String getNameNull() { return nameNull; } public void setNameNull( String nameNull ) { this.nameNull = nameNull; } @JsonView( Views.View.class ) public String getNameComplex() { return nameComplex; } public void setNameComplex( String nameComplex ) { this.nameComplex = nameComplex; } public String getNameComplexHidden() { return nameComplexHidden; } public void setNameComplexHidden( String nameComplexHidden ) { this.nameComplexHidden = nameComplexHidden; } @JsonView( Views.View.class ) public SimpleTestData getTestData() { return testData; } public void setTestData( SimpleTestData testData ) { this.testData = testData; } @JsonView( Views.View.class ) public SimpleTestData[] getTestDataArray() { return testDataArray; } public void setTestDataArray( SimpleTestData[] testDataArray ) { this.testDataArray = testDataArray; } } static class SimpleTestData { String name = "shown"; String nameHidden = "hidden"; @JsonView( Views.View.class ) public String getName() { return name; } public void setName( String name ) { this.name = name; } public String getNameHidden( ) { return nameHidden; } public void setNameHidden( String nameHidden ) { this.nameHidden = nameHidden; } } /* /************************************************************************ /* Tests /************************************************************************ */ public void testDataBindingUsage( ) throws Exception { ObjectMapper mapper = createMapper(); String result = serializeWithObjectMapper(new ComplexTestData( ), Views.View.class, mapper); assertEquals(-1, result.indexOf( "nameHidden" )); } public void testDataBindingUsageWithoutView( ) throws Exception { ObjectMapper mapper = createMapper(); String json = serializeWithObjectMapper(new ComplexTestData( ), null, mapper); assertTrue(json.indexOf( "nameHidden" ) > 0); } /* /************************************************************************ /* Helper methods /************************************************************************ */ private ObjectMapper createMapper() { ObjectMapper mapper = newObjectMapper(); mapper.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false ); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL ); mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false ); return mapper; } private String serializeWithObjectMapper(Object object, Class view, ObjectMapper mapper ) throws IOException { return mapper.writerWithView(view).writeValueAsString(object); } }ViewsWithSchemaTest.java000066400000000000000000000042561325620701100364240ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/databind/viewspackage com.fasterxml.jackson.databind.views; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsonFormatVisitors.*; public class ViewsWithSchemaTest extends BaseMapTest { interface ViewBC { } interface ViewAB { } @JsonPropertyOrder({ "a", "b", "c" }) static class POJO { @JsonView({ ViewAB.class }) public int a; @JsonView({ ViewAB.class, ViewBC.class }) public int b; @JsonView({ ViewBC.class }) public int c; } static class ListingVisitor extends JsonFormatVisitorWrapper.Base { public final List names = new ArrayList(); @Override public JsonObjectFormatVisitor expectObjectFormat(JavaType type) { return new JsonObjectFormatVisitor.Base() { @Override public void optionalProperty(BeanProperty writer) { names.add(writer.getName()); } @Override public void optionalProperty(String name, JsonFormatVisitable handler, JavaType propertyTypeHint) { names.add(name); } }; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSchemaWithViews() throws Exception { ListingVisitor v = new ListingVisitor(); MAPPER.writerWithView(ViewBC.class) .acceptJsonFormatVisitor(POJO.class, v); assertEquals(Arrays.asList("b", "c"), v.names); v = new ListingVisitor(); MAPPER.writerWithView(ViewAB.class) .acceptJsonFormatVisitor(POJO.class, v); assertEquals(Arrays.asList("a", "b"), v.names); } public void testSchemaWithoutViews() throws Exception { ListingVisitor v = new ListingVisitor(); MAPPER.acceptJsonFormatVisitor(POJO.class, v); assertEquals(Arrays.asList("a", "b", "c"), v.names); } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failing/000077500000000000000000000000001325620701100304255ustar00rootroot00000000000000AnyPropSorting518Test.java000066400000000000000000000024371325620701100352530ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; public class AnyPropSorting518Test extends BaseMapTest { @JsonPropertyOrder(alphabetic = true) static class Bean { public int b; protected Map extra = new HashMap<>(); public int a; public Bean(int a, int b, Map x) { this.a = a; this.b = b; extra = x; } @JsonAnyGetter public Map getExtra() { return extra; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testAnyBeanWithSort() throws Exception { Map extra = new LinkedHashMap<>(); extra.put("y", 4); extra.put("x", 3); String json = MAPPER.writeValueAsString(new Bean(1, 2, extra)); assertEquals(aposToQuotes("{'a':1,'b':2,'x':3,'y':4}"), json); } } BackReference1516Test.java000066400000000000000000000050711325620701100350500ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.beans.ConstructorProperties; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; public class BackReference1516Test extends BaseMapTest { static class ParentWithCreator { String id, name; @JsonManagedReference ChildObject1 child; @ConstructorProperties({ "id", "name", "child" }) public ParentWithCreator(String id, String name, ChildObject1 child) { this.id = id; this.name = name; this.child = child; } } static class ChildObject1 { public String id, name; @JsonBackReference public ParentWithCreator parent; @ConstructorProperties({ "id", "name", "parent" }) public ChildObject1(String id, String name, ParentWithCreator parent) { this.id = id; this.name = name; this.parent = parent; } } static class ParentWithoutCreator { public String id, name; @JsonManagedReference public ChildObject2 child; } static class ChildObject2 { public String id, name; @JsonBackReference public ParentWithoutCreator parent; @ConstructorProperties({ "id", "name", "parent" }) public ChildObject2(String id, String name, ParentWithoutCreator parent) { this.id = id; this.name = name; this.parent = parent; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); private final String PARENT_CHILD_JSON = aposToQuotes( "{ 'id': 'abc',\n"+ " 'name': 'Bob',\n"+ " 'child': { 'id': 'def', 'name':'Bert' }\n"+ "}"); public void testWithParentCreator() throws Exception { ParentWithCreator result = MAPPER.readValue(PARENT_CHILD_JSON, ParentWithCreator.class); assertNotNull(result); assertNotNull(result.child); assertSame(result, result.child.parent); } public void testWithParentNoCreator() throws Exception { ParentWithoutCreator result = MAPPER.readValue(PARENT_CHILD_JSON, ParentWithoutCreator.class); assertNotNull(result); assertNotNull(result.child); assertSame(result, result.child.parent); } } BuilderDeserializationTest921.java000066400000000000000000000055411325620701100367470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.List; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class BuilderDeserializationTest921 extends BaseMapTest { public static class MyPOJO { public String x; public String y; @JsonCreator public MyPOJO(@JsonProperty("x") String x, @JsonProperty("y") String y) { this.x = x; this.y = y; } } @JsonDeserialize(builder = MyGenericPOJO.Builder.class) public static class MyGenericPOJO { private List data; private MyGenericPOJO(List d) { data = d; } public List getData() { return data; } public static class Builder { private List data; public Builder withData(List d) { data = d; return this; } public MyGenericPOJO build() { return new MyGenericPOJO(data); } } } public static class MyGenericPOJOWithCreator { private List data; private MyGenericPOJOWithCreator(List d) { data = d; } @JsonCreator public static MyGenericPOJOWithCreator create(@JsonProperty("data") List data) { return new MyGenericPOJOWithCreator.Builder().withData(data).build(); } public List getData() { return data; } public static class Builder { private List data; public Builder withData(List d) { data = d; return this; } public MyGenericPOJOWithCreator build() { return new MyGenericPOJOWithCreator(data); } } } public void testWithBuilder() throws Exception { final ObjectMapper mapper = new ObjectMapper(); final String json = aposToQuotes("{ 'data': [ { 'x': 'x', 'y': 'y' } ] }"); final MyGenericPOJO deserialized = mapper.readValue(json, new TypeReference>() {}); assertEquals(1, deserialized.data.size()); Object ob = deserialized.data.get(0); assertNotNull(ob); assertEquals(MyPOJO.class, ob.getClass()); } public void testWithCreator() throws Exception { final ObjectMapper mapper = new ObjectMapper(); final String json = aposToQuotes("{ 'data': [ { 'x': 'x', 'y': 'y' } ] }"); final MyGenericPOJOWithCreator deserialized = mapper.readValue(json, new TypeReference>() {}); assertEquals(1, deserialized.data.size()); Object ob = deserialized.data.get(0); assertNotNull(ob); assertEquals(MyPOJO.class, ob.getClass()); } } BuilderWithIgnored1214Test.java000066400000000000000000000025171325620701100361200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class BuilderWithIgnored1214Test extends BaseMapTest { @JsonDeserialize(builder = TestObject1214.Builder.class) @JsonIgnoreProperties(ignoreUnknown = true) static class TestObject1214 { final String property1; private TestObject1214(Builder builder) { property1 = builder.property1; } public static Builder builder() { return new Builder(); } public String getProperty1() { return property1; } static class Builder { private String property1; public Builder withProperty1(String p1) { property1 = p1; return this; } public TestObject1214 build() { return new TestObject1214(this); } } } public void testUnknown1214() throws Exception { ObjectMapper mapper = new ObjectMapper(); TestObject1214 value = mapper.readValue(aposToQuotes ("{'property1':'a', 'property2':'b'}"), TestObject1214.class); assertEquals("a", value.property1); } } CreatorProperties1401Test.java000066400000000000000000000022311325620701100360310ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // for [databind#1401]: should allow "Any Setter" to back up otherwise // problematic Creator properties? public class CreatorProperties1401Test extends BaseMapTest { // for [databind#1401] static class NoSetter1401 { int _a; @JsonCreator public NoSetter1401(@JsonProperty("a") int a) { _a = a; } @JsonAnySetter public void any(String key, Object value) { } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); // [databind#1401] public void testCreatorNoSetter() throws Exception { NoSetter1401 b = MAPPER.readValue(aposToQuotes("{'a':1,'b':2}"), NoSetter1401.class); assertEquals(1, b._a); NoSetter1401 b2 = MAPPER.readerForUpdating(new NoSetter1401(1)) .readValue(aposToQuotes("{'a':1}")); assertEquals(1, b2._a); } } DefaultTypingOverride1391Test.java000066400000000000000000000021221325620701100366430ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; // for [databind#1391]: should allow disabling of default typing // via explicit {@link JsonTypeInfo} public class DefaultTypingOverride1391Test extends BaseMapTest { static class ListWrapper { /* 03-Oct-2016, tatu: This doesn't work because it applies to contents * (elements), NOT the container. But there is no current mechanism * to change that; need to add a new feature or properties in 2.9 */ @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) public Collection stuff = Collections.emptyList(); } public void testCollectionWithOverride() throws Exception { final ObjectMapper mapper = new ObjectMapper() .enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, "$type"); String json = mapper.writeValueAsString(new ListWrapper()); assertEquals(aposToQuotes("{'stuff':[]}"), json); } } EnumDeserialization1626Test.java000066400000000000000000000051771325620701100363550ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.List; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; /** * NOTE: not assumed to be actual bug -- real numbers are not coerced into * Strings, and are instead assumed to always mean index numbers. * But test retained in case there might be ways to improve support * here: as is, one MUST use Creator method to resolve from number to * enum. */ public class EnumDeserialization1626Test extends BaseMapTest { static class JsonResponseEnvelope { @JsonProperty("d") public T data; } static class ShippingMethodInfo { @JsonProperty("typeId") public int typeId; @JsonProperty("value") private ShippingMethods value; @JsonProperty("coverage") public int coverage; } enum ShippingMethods { @JsonProperty("0") SHIPPING_METHODS_UNSPECIFIED(0), @JsonProperty("10") SHIPPING_METHODS_FED_EX_PRIORITY_OVERNIGHT(10), @JsonProperty("17") SHIPPING_METHODS_FED_EX_1DAY_FREIGHT(17), ; private final int shippingMethodId; ShippingMethods(final int shippingMethodId) { this.shippingMethodId = shippingMethodId; } public int getShippingMethodId() { return shippingMethodId; } } /* /********************************************************** /* Test methods /********************************************************** */ protected final ObjectMapper MAPPER = new ObjectMapper(); // [databind#1626] public void testSparseNumericEnum626() throws Exception { String jsonResponse = "{\n" + " \"d\": [\n" + " {\n" + " \"typeId\": 0,\n" + // NOTE! Only real number fails; quoted-as-String is bound as expected " \"value\": 17,\n" + " \"coverage\": 1"+ " }\n" + " ]\n" + "}"; JsonResponseEnvelope> mappedResponse = MAPPER.readValue(jsonResponse, new TypeReference>>() { }); List shippingMethods = mappedResponse.data; assertEquals(ShippingMethods.SHIPPING_METHODS_FED_EX_1DAY_FREIGHT, shippingMethods.get(0).value); } } ExternalTypeId96Test.java000066400000000000000000000043651325620701100351410ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; // Tests for External type id, one that exists at same level as typed Object, // that is, property is not within typed object but a member of its parent. public class ExternalTypeId96Test extends BaseMapTest { // for [databind#96] static class ExternalBeanWithDefault { @JsonTypeInfo(use=Id.CLASS, include=As.EXTERNAL_PROPERTY, property="extType", defaultImpl=ValueBean.class) public Object bean; public ExternalBeanWithDefault() { } public ExternalBeanWithDefault(int v) { bean = new ValueBean(v); } } @JsonTypeName("vbean") static class ValueBean { public int value; public ValueBean() { } public ValueBean(int v) { value = v; } } /* /********************************************************** /* Unit tests, deserialization /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); // For [databind#96]: should allow use of default impl, if property missing /* 18-Jan-2013, tatu: Unfortunately this collides with [databind#118], and I don't * know what the best resolution is. For now at least */ public void testWithDefaultAndMissing() throws Exception { ExternalBeanWithDefault input = new ExternalBeanWithDefault(13); // baseline: include type, verify things work: String fullJson = MAPPER.writeValueAsString(input); ExternalBeanWithDefault output = MAPPER.readValue(fullJson, ExternalBeanWithDefault.class); assertNotNull(output); assertNotNull(output.bean); // and then try without type info... ExternalBeanWithDefault defaulted = MAPPER.readValue("{\"bean\":{\"value\":13}}", ExternalBeanWithDefault.class); assertNotNull(defaulted); assertNotNull(defaulted.bean); assertSame(ValueBean.class, defaulted.bean.getClass()); } } ImplicitParamsForCreator806Test.java000066400000000000000000000034061325620701100372170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class ImplicitParamsForCreator806Test extends BaseMapTest { @SuppressWarnings("serial") static class MyParamIntrospector extends JacksonAnnotationIntrospector { @Override public String findImplicitPropertyName(AnnotatedMember param) { if (param instanceof AnnotatedParameter) { AnnotatedParameter ap = (AnnotatedParameter) param; return "paramName"+ap.getIndex(); } return super.findImplicitPropertyName(param); } } static class XY { protected int x, y; // annotation should NOT be needed with 2.6 any more (except for single-arg case) //@com.fasterxml.jackson.annotation.JsonCreator public XY(int x, int y) { this.x = x; this.y = y; } } /* /********************************************************** /* Test methods /********************************************************** */ // for [databind#806] public void testImplicitNameWithNamingStrategy() throws Exception { ObjectMapper mapper = new ObjectMapper() .setAnnotationIntrospector(new MyParamIntrospector()) .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE) ; XY value = mapper.readValue(aposToQuotes("{'param_name0':1,'param_name1':2}"), XY.class); assertNotNull(value); assertEquals(1, value.x); assertEquals(2, value.y); } } InnerClassNonStaticCore384Test.java000066400000000000000000000133321325620701100370070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertThat; import com.fasterxml.jackson.databind.*; // see [https://github.com/FasterXML/jackson-core/issues/384]: most likely // can not be fixed, but could we improve error message to indicate issue // with non-static type of `Car` and `Truck`, which prevent instantiation? public class InnerClassNonStaticCore384Test extends BaseMapTest { static class Fleet { private List vehicles; public List getVehicles() { return vehicles; } public void setVehicles(List vehicles) { this.vehicles = vehicles; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Fleet fleet = (Fleet) o; return Objects.equals(vehicles, fleet.vehicles); } @Override public int hashCode() { return Objects.hash(vehicles); } } static abstract class Vehicle { private String make; private String model; protected Vehicle(String make, String model) { this.make = make; this.model = model; } public Vehicle() { } public String getMake() { return make; } public void setMake(String make) { this.make = make; } public String getModel() { return model; } public void setModel(String model) { this.model = model; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Vehicle)) return false; Vehicle vehicle = (Vehicle) o; return Objects.equals(make, vehicle.make) && Objects.equals(model, vehicle.model); } @Override public int hashCode() { return Objects.hash(make, model); } } class Car extends Vehicle { private int seatingCapacity; private double topSpeed; public Car(String make, String model, int seatingCapacity, double topSpeed) { super(make, model); this.seatingCapacity = seatingCapacity; this.topSpeed = topSpeed; } public Car() { } public int getSeatingCapacity() { return seatingCapacity; } public void setSeatingCapacity(int seatingCapacity) { this.seatingCapacity = seatingCapacity; } public double getTopSpeed() { return topSpeed; } public void setTopSpeed(double topSpeed) { this.topSpeed = topSpeed; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; Car car = (Car) o; return seatingCapacity == car.seatingCapacity && Double.compare(car.topSpeed, topSpeed) == 0; } @Override public int hashCode() { return Objects.hash(super.hashCode(), seatingCapacity, topSpeed); } } class Truck extends Vehicle { private double payloadCapacity; public Truck(String make, String model, double payloadCapacity) { super(make, model); this.payloadCapacity = payloadCapacity; } public Truck() { } public double getPayloadCapacity() { return payloadCapacity; } public void setPayloadCapacity(double payloadCapacity) { this.payloadCapacity = payloadCapacity; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; Truck truck = (Truck) o; return Double.compare(truck.payloadCapacity, payloadCapacity) == 0; } @Override public int hashCode() { return Objects.hash(super.hashCode(), payloadCapacity); } } /* /********************************************************************** /* Test methods /********************************************************************** */ public void testHierarchy() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(); Fleet fleet = initVehicle(); /* for (Vehicle v : fleet.vehicles) { System.out.println("Vehicle, type: "+v.getClass()); } */ String serializedFleet = mapper .writerWithDefaultPrettyPrinter() .writeValueAsString(fleet); //System.out.println(serializedFleet); Fleet deserializedFleet = mapper.readValue(serializedFleet, Fleet.class); assertThat(deserializedFleet.getVehicles().get(0), instanceOf(Car.class)); assertThat(deserializedFleet.getVehicles().get(1), instanceOf(Truck.class)); assertEquals(fleet, deserializedFleet); } private Fleet initVehicle() { Car car = new Car("Mercedes-Benz", "S500", 5, 250.0); Truck truck = new Truck("Isuzu", "NQR", 7500.0); List vehicles = new ArrayList<>(); vehicles.add(car); vehicles.add(truck); Fleet serializedFleet = new Fleet(); serializedFleet.setVehicles(vehicles); return serializedFleet; } } KevinFail1410Test.java000066400000000000000000000045471325620701100342410ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class KevinFail1410Test extends BaseMapTest { enum EnvironmentEventSource { BACKEND; } @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="source") @JsonSubTypes({ @JsonSubTypes.Type(value = BackendEvent.class, name = "BACKEND") }) static abstract class EnvironmentEvent { private String environmentName; private String message; protected EnvironmentEvent() { } // for deserializer protected EnvironmentEvent(String env, String msg) { environmentName = env; message = msg; } public String getEnvironmentName() { return environmentName; } public abstract EnvironmentEventSource getSource(); public String getMessage() { return message; } } static class BackendEvent extends EnvironmentEvent { private String status; private Object resultData; protected BackendEvent() {} // for deserializer public BackendEvent(String envName, String message, String status, Object results) { super(envName, message); this.status = status; resultData = results; } public static BackendEvent create(String environmentName, String message, String status, Object results) { return new BackendEvent(environmentName, message, status, results); } @Override public EnvironmentEventSource getSource() { return EnvironmentEventSource.BACKEND; } public String getStatus() { return status; } public Object getResultData() { return resultData; } @Override public String toString() { return String.format("(%s): %s", status, getMessage()); } } public void testDupProps() throws Exception { ObjectMapper mapper = new ObjectMapper(); EnvironmentEvent event = new BackendEvent("foo", "hello", "bar", null); String ser = mapper .writerWithDefaultPrettyPrinter() .writeValueAsString(event); mapper.readValue(ser, EnvironmentEvent.class); assertNotNull(ser); } } MapEntryFormat1419Test.java000066400000000000000000000025511325620701100353030ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.*; // for [databind#1419] public class MapEntryFormat1419Test extends BaseMapTest { static class BeanWithMapEntryAsObject { @JsonFormat(shape=JsonFormat.Shape.OBJECT) public Map.Entry entry; protected BeanWithMapEntryAsObject() { } public BeanWithMapEntryAsObject(String key, String value) { Map map = new HashMap<>(); map.put(key, value); entry = map.entrySet().iterator().next(); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testWrappedAsObjectRoundtrip() throws Exception { BeanWithMapEntryAsObject input = new BeanWithMapEntryAsObject("foo" ,"bar"); String json = MAPPER.writeValueAsString(input); assertEquals(aposToQuotes("{'entry':{'key':'foo','value':'bar'}}"), json); BeanWithMapEntryAsObject result = MAPPER.readValue(json, BeanWithMapEntryAsObject.class); assertEquals("foo", result.entry.getKey()); assertEquals("bar", result.entry.getValue()); } } MapInclusion1649Test.java000066400000000000000000000023631325620701100350020ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; public class MapInclusion1649Test extends BaseMapTest { @JsonInclude(value=JsonInclude.Include.NON_EMPTY, content=JsonInclude.Include.NON_EMPTY) static class Bean1649 { public Map map; public Bean1649(String key, String value) { map = new LinkedHashMap<>(); map.put(key, value); } } /* /********************************************************** /* Test methods /********************************************************** */ final private ObjectMapper MAPPER = objectMapper(); // [databind#1649] public void testNonEmptyViaClass() throws IOException { // non-empty/null, include assertEquals(aposToQuotes("{'map':{'a':'b'}}"), MAPPER.writeValueAsString(new Bean1649("a", "b"))); // null, empty, nope assertEquals(aposToQuotes("{}"), MAPPER.writeValueAsString(new Bean1649("a", null))); assertEquals(aposToQuotes("{}"), MAPPER.writeValueAsString(new Bean1649("a", ""))); } } NoTypeInfo1654Test.java000066400000000000000000000045371325620701100344340ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class NoTypeInfo1654Test extends BaseMapTest { // [databind#1654] @JsonTypeInfo(use = JsonTypeInfo.Id.NAME) static class Value1654 { public int x; protected Value1654() { } public Value1654(int x) { this.x = x; } } static class Value1654TypedContainer { public List values; protected Value1654TypedContainer() { } public Value1654TypedContainer(Value1654... v) { values = Arrays.asList(v); } } static class Value1654UntypedContainer { @JsonDeserialize(contentUsing = Value1654Deserializer.class) @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) public List values; } static class Value1654Deserializer extends JsonDeserializer { @Override public Value1654 deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { p.skipChildren(); return new Value1654(13); } } /* /********************************************************** /* Test methods /********************************************************** */ // [databind#1654] public void testNoTypeElementOverride() throws Exception { final ObjectMapper mapper = newObjectMapper(); // First: regular typed case String json = mapper.writeValueAsString(new Value1654TypedContainer( new Value1654(1), new Value1654(2), new Value1654(3) )); Value1654TypedContainer result = mapper.readValue(json, Value1654TypedContainer.class); assertEquals(3, result.values.size()); assertEquals(2, result.values.get(1).x); // and then actual failing case final String noTypeJson = aposToQuotes( "{'values':[{'x':3},{'x': 7}] }" ); Value1654UntypedContainer unResult = mapper.readValue(noTypeJson, Value1654UntypedContainer.class); assertEquals(2, unResult.values.size()); assertEquals(7, unResult.values.get(1).x); } } NumberNodes1770Test.java000066400000000000000000000015111325620701100346070ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.databind.*; /** * Basic tests for {@link JsonNode} implementations that * contain numeric values. */ public class NumberNodes1770Test extends BaseMapTest { private final ObjectMapper MAPPER = newObjectMapper(); // Related to [databind#1770] public void testBigDecimalCoercion() throws Exception { final JsonNode jsonNode = MAPPER.reader() .with(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) .readTree("7976931348623157e309"); assertTrue(jsonNode.isBigDecimal()); // the following fails with NumberFormatException, because jsonNode is a DoubleNode with a value of POSITIVE_INFINITY // Assert.assertTrue(jsonNode.decimalValue().compareTo(new BigDecimal("7976931348623157e309")) == 0); } } ObjectIdWithBuilder1496Test.java000066400000000000000000000045571325620701100362360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.concurrent.ConcurrentHashMap; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; public class ObjectIdWithBuilder1496Test extends BaseMapTest { @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id") @JsonDeserialize(builder=POJOBuilder.class) static class POJO { private long id; public long getId() { return id; } private int var; public int getVar() { return var; } private POJO (long id, int var) { this.id = id; this.var = var; } @Override public String toString() { return "id: " + id + ", var: " + var; } } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id") @JsonPOJOBuilder(withPrefix = "", buildMethodName="readFromCacheOrBuild") static final class POJOBuilder { // Standard builder stuff private long id; private int var; public POJOBuilder id(long _id) { id = _id; return this; } public POJOBuilder var(int _var) { var = _var; return this; } public POJO build() { return new POJO(id, var); } // Special build method for jackson deserializer that caches objects already deserialized private final static ConcurrentHashMap cache = new ConcurrentHashMap<>(); public POJO readFromCacheOrBuild() { POJO pojo = cache.get(id); if (pojo == null) { POJO newPojo = build(); pojo = cache.putIfAbsent(id, newPojo); if (pojo == null) { pojo = newPojo; } } return pojo; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testBuilderId1496() throws Exception { POJO input = new POJOBuilder().id(123L).var(456).build(); String json = MAPPER.writeValueAsString(input); POJO result = MAPPER.readValue(json, POJO.class); assertNotNull(result); } } ObjectIdWithInjectable639Test.java000066400000000000000000000025611325620701100366170ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class ObjectIdWithInjectable639Test extends BaseMapTest { // for [databind#639] @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) public static final class Parent2 { @JsonProperty public Child2 child; @JsonCreator public Parent2(@JacksonInject("context") String context) { } } @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) public static final class Child2 { @JsonProperty private final Parent2 parent; @JsonCreator public Child2(@JsonProperty("parent") Parent2 parent) { this.parent = parent; } } // for [databind#639] public void testObjectIdWithInjectable() throws Exception { ObjectMapper mapper = new ObjectMapper() .setInjectableValues(new InjectableValues.Std(). addValue("context", "Stuff")); Parent2 parent2 = new Parent2("foo"); Child2 child2 = new Child2(parent2); parent2.child = child2; String json2 = mapper.writeValueAsString(parent2); parent2 = mapper.readValue(json2, Parent2.class); assertNotNull(parent2); assertNotNull(parent2.child); } } ReadOnlyDeser1382Test.java000066400000000000000000000044041325620701100350710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.*; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; public class ReadOnlyDeser1382Test extends BaseMapTest { static class Foo { @JsonProperty(access = JsonProperty.Access.READ_ONLY) private List list = new ArrayList<>(); List getList() { return list; } public Foo setList(List list) { this.list = list; return this; } } // [databind#1805] static class UserWithReadOnly { public String name; @JsonProperty(access = JsonProperty.Access.READ_ONLY) public List getRoles() { return Arrays.asList("admin", "monitor"); } } // [databind#1805] @JsonIgnoreProperties(value={ "roles" }, allowGetters=true) static class UserAllowGetters { public String name; public List getRoles() { return Arrays.asList("admin", "monitor"); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = newObjectMapper(); public void testReadOnly1382() throws Exception { String payload = "{\"list\":[1,2,3,4]}"; Foo foo = MAPPER.readValue(payload, Foo.class); assertTrue("List should be empty", foo.getList().isEmpty()); } // [databind#1805] public void testViaReadOnly() throws Exception { UserWithReadOnly user = new UserWithReadOnly(); user.name = "foo"; String json = MAPPER.writeValueAsString(user); UserWithReadOnly result = MAPPER.readValue(json, UserWithReadOnly.class); assertNotNull(result); } // [databind#1805] public void testUsingAllowGetters() throws Exception { UserAllowGetters user = new UserAllowGetters(); user.name = "foo"; String json = MAPPER.writeValueAsString(user); assertTrue(json.contains("roles")); UserAllowGetters result = MAPPER.readValue(json, UserAllowGetters.class); assertNotNull(result); } } RequireSetterForGetter736Test.java000066400000000000000000000024401325620701100367360ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.*; public class RequireSetterForGetter736Test extends BaseMapTest { public static class DataB { private int readonly; private int readwrite; public DataB() { readonly = 1; readwrite = 2; } public int getReadwrite() { return readwrite; } public void setReadwrite(int readwrite) { this.readwrite = readwrite; } public int getReadonly() { return readonly; } } // for [databind#736] public void testNeedForSetters() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY); mapper.setVisibility(PropertyAccessor.SETTER, Visibility.PUBLIC_ONLY); mapper.enable(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS); DataB dataB = new DataB(); String json = mapper.writeValueAsString(dataB); assertEquals(aposToQuotes("{'readwrite':2}"), json); } } SkipInjectableIntrospection962Test.java000066400000000000000000000031461325620701100377660ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.JacksonInject; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.OptBoolean; import com.fasterxml.jackson.databind.*; public class SkipInjectableIntrospection962Test extends BaseMapTest { static class InjectMe { private String a; public InjectMe(boolean dummy) { } public void setA(Integer a) { this.a = a.toString(); } public void setA(InjectMe a) { this.a = String.valueOf(a); } public String getA() { return a; } } static class Injectee { private String b; // Important! Prevent binding from data @JsonCreator public Injectee(@JacksonInject(useInput=OptBoolean.FALSE) InjectMe injectMe, @JsonProperty("b") String b) { this.b = b; } public String getB() { return b; } } // 14-Jun-2016, tatu: For some odd reason, this test sometimes fails, other times not... // possibly related to unstable ordering of properties? public void testInjected() throws Exception { InjectMe im = new InjectMe(true); ObjectMapper mapper = new ObjectMapper() .setInjectableValues(new InjectableValues.Std().addValue(InjectMe.class, im)); String test = "{\"b\":\"bbb\"}"; Injectee actual = mapper.readValue(test, Injectee.class); assertEquals("bbb", actual.getB()); } } StaticTyping1515Test.java000066400000000000000000000043511325620701100350120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class StaticTyping1515Test extends BaseMapTest { static abstract class Base { public int a = 1; } static class Derived extends Base { public int b = 2; } @JsonSerialize(typing = JsonSerialize.Typing.DYNAMIC) static abstract class BaseDynamic { public int a = 3; } static class DerivedDynamic extends BaseDynamic { public int b = 4; } @JsonPropertyOrder({ "value", "aValue", "dValue" }) static class Issue515Singles { public Base value = new Derived(); @JsonSerialize(typing = JsonSerialize.Typing.DYNAMIC) public Base aValue = new Derived(); public BaseDynamic dValue = new DerivedDynamic(); } @JsonPropertyOrder({ "list", "aList", "dList" }) static class Issue515Lists { public List list = new ArrayList<>(); { list.add(new Derived()); } @JsonSerialize(typing = JsonSerialize.Typing.DYNAMIC) public List aList = new ArrayList<>(); { aList.add(new Derived()); } public List dList = new ArrayList<>(); { dList.add(new DerivedDynamic()); } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper STAT_MAPPER = newObjectMapper(); { STAT_MAPPER.enable(MapperFeature.USE_STATIC_TYPING); } public void testStaticTypingForProperties() throws Exception { String json = STAT_MAPPER.writeValueAsString(new Issue515Singles()); assertEquals(aposToQuotes("{'value':{'a':1},'aValue':{'a':1,'b':2},'dValue':{'a':3,'b':4}}"), json); } public void testStaticTypingForLists() throws Exception { String json = STAT_MAPPER.writeValueAsString(new Issue515Lists()); assertEquals(aposToQuotes("{'list':[{'a':1}],'aList':[{'a':1,'b':2}],'dList:[{'a':3,'b':4}]}"), json); } } TestNonStaticInnerClassInList32.java000066400000000000000000000024771325620701100372370ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.*; public class TestNonStaticInnerClassInList32 extends BaseMapTest { public static class Dog2 { public String name; public List legs; // NOTE: non-static on purpose! public class Leg { public int length; } } /* /********************************************************** /* Tests /********************************************************** */ // core/[Issue#32] public void testInnerList() throws Exception { Dog2 dog = new Dog2(); dog.name = "Spike"; dog.legs = new ArrayList(); dog.legs.add(dog.new Leg()); dog.legs.add(dog.new Leg()); dog.legs.get(0).length = 5; dog.legs.get(1).length = 4; ObjectMapper mapper = new ObjectMapper(); String dogJson = mapper.writeValueAsString(dog); // System.out.println(dogJson); // output: {"name":"Spike","legs":[{length: 5}, {length: 4}]} // currently throws JsonMappingException Dog2 dogCopy = mapper.readValue(dogJson, Dog2.class); assertEquals(dogCopy.legs.get(1).length, 4); // prefer fully populated Dog instance } } TestObjectIdDeserialization.java000066400000000000000000000113241325620701100366040ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.objectid.TestObjectId.Employee; import com.fasterxml.jackson.failing.TestObjectIdDeserialization.EnumMapCompany.FooEnum; /** * Unit test to verify handling of Object Id deserialization. *

* NOTE: only tests that still fail, even with initial forward-ref-handling * code (2.4), are included here. Other cases moved to successfully * passing tests. */ public class TestObjectIdDeserialization extends BaseMapTest { static class ArrayCompany { public Employee[] employees; } static class ArrayBlockingQueueCompany { public ArrayBlockingQueue employees; } static class EnumMapCompany { public EnumMap employees; static enum FooEnum { A, B } } static class DefensiveCompany { public List employees; static class DefensiveEmployee extends Employee { public void setReports(List reports) { this.reports = new ArrayList(reports); } } } private final ObjectMapper mapper = new ObjectMapper(); /* /***************************************************** /* Unit tests, external id deserialization /***************************************************** */ public void testForwardReferenceInArray() throws Exception { String json = "{\"employees\":[" + "{\"id\":1,\"name\":\"First\",\"manager\":null,\"reports\":[2]}," + "2," +"{\"id\":2,\"name\":\"Second\",\"manager\":1,\"reports\":[]}" + "]}"; ArrayCompany company = mapper.readValue(json, ArrayCompany.class); assertEquals(3, company.employees.length); Employee firstEmployee = company.employees[0]; Employee secondEmployee = company.employees[1]; assertEmployees(firstEmployee, secondEmployee); } // Do a specific test for ArrayBlockingQueue since it has its own deser. public void testForwardReferenceInQueue() throws Exception { String json = "{\"employees\":[" + "{\"id\":1,\"name\":\"First\",\"manager\":null,\"reports\":[2]}," + "2," +"{\"id\":2,\"name\":\"Second\",\"manager\":1,\"reports\":[]}" + "]}"; ArrayBlockingQueueCompany company = mapper.readValue(json, ArrayBlockingQueueCompany.class); assertEquals(3, company.employees.size()); Employee firstEmployee = company.employees.take(); Employee secondEmployee = company.employees.take(); assertEmployees(firstEmployee, secondEmployee); } public void testForwardReferenceInEnumMap() throws Exception { String json = "{\"employees\":{" + "\"A\":{\"id\":1,\"name\":\"First\",\"manager\":null,\"reports\":[2]}," + "\"B\": 2," + "\"C\":{\"id\":2,\"name\":\"Second\",\"manager\":1,\"reports\":[]}" + "}}"; EnumMapCompany company = mapper.readValue(json, EnumMapCompany.class); assertEquals(3, company.employees.size()); Employee firstEmployee = company.employees.get(FooEnum.A); Employee secondEmployee = company.employees.get(FooEnum.B); assertEmployees(firstEmployee, secondEmployee); } public void testForwardReferenceWithDefensiveCopy() throws Exception { String json = "{\"employees\":[" + "{\"id\":1,\"name\":\"First\",\"manager\":null,\"reports\":[2]}," + "{\"id\":2,\"name\":\"Second\",\"manager\":1,\"reports\":[]}" + "]}"; DefensiveCompany company = mapper.readValue(json, DefensiveCompany.class); assertEquals(2, company.employees.size()); Employee firstEmployee = company.employees.get(0); Employee secondEmployee = company.employees.get(1); assertEmployees(firstEmployee, secondEmployee); } private void assertEmployees(Employee firstEmployee, Employee secondEmployee) { assertEquals(1, firstEmployee.id); assertEquals(2, secondEmployee.id); assertEquals(1, firstEmployee.reports.size()); assertSame(secondEmployee, firstEmployee.reports.get(0)); // Ensure that forward reference was properly resolved and in order. assertSame(firstEmployee, secondEmployee.manager); // And that back reference is also properly resolved. } } TestObjectIdWithInjectables639.java000066400000000000000000000053451325620701100370050ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; // This is probably impossible to handle, in general case, since // there is a cycle for Parent2/Child2... unless special handling // could be made to ensure that public class TestObjectIdWithInjectables639 extends BaseMapTest { public static final class Context { } @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) public static final class Parent1 { public Child1 child; public Parent1() { } } @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) public static final class Child1 { @JsonProperty private final Parent1 parent; @JsonCreator public Child1(@JsonProperty("parent") Parent1 parent) { this.parent = parent; } } @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) public static final class Parent2 { protected final Context context; public Child2 child; @JsonCreator public Parent2(@JacksonInject Context context) { this.context = context; } } @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) public static final class Child2 { protected final Context context; @JsonProperty protected Parent2 parent; @JsonCreator public Child2(@JacksonInject Context context, @JsonProperty("parent") Parent2 parent) { this.context = context; this.parent = parent; } } public void testObjectIdWithInjectables() throws Exception { ObjectMapper mapper = new ObjectMapper(); Context context = new Context(); InjectableValues iv = new InjectableValues.Std(). addValue(Context.class, context); mapper.setInjectableValues(iv); Parent1 parent1 = new Parent1(); Child1 child1 = new Child1(parent1); parent1.child = child1; Parent2 parent2 = new Parent2(context); Child2 child2 = new Child2(context, parent2); parent2.child = child2; String json = mapper.writeValueAsString(parent1); parent1 = mapper.readValue(json, Parent1.class); // System.out.println("This works: " + json); json = mapper.writeValueAsString(parent2); //System.out.println("This fails: " + json); parent2 = mapper.readValue(json, Parent2.class); } } TestObjectIdWithUnwrapping1298.java000066400000000000000000000052321325620701100367710ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; // Test case for https://github.com/FasterXML/jackson-databind/issues/1298 public class TestObjectIdWithUnwrapping1298 extends BaseMapTest { private static Long nextId = 1L; public static final class ListOfParents{ public List parents = new ArrayList<>(); public void addParent( Parent parent) { parents.add(parent);} } @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Parent.class) public static final class Parent { public Long id; @JsonUnwrapped public Child child; public Parent() { this.id = nextId++;} } @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Child.class) public static final class Child { public Long id; public final String name; public Child(@JsonProperty("name") String name) { this.name = name; this.id = TestObjectIdWithUnwrapping1298.nextId++; } } public void testObjectIdWithRepeatedChild() throws Exception { ObjectMapper mapper = new ObjectMapper(); // to keep output faithful to original, prevent auto-closing... mapper.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT); // Equivalent to Spring _embedded for Bean w/ List property ListOfParents parents = new ListOfParents(); //Bean with Relationship Parent parent1 = new Parent(); Child child1 = new Child("Child1"); parent1.child = child1; parents.addParent(parent1); // serialize parent1 and parent2 String json = mapper .writerWithDefaultPrettyPrinter() .writeValueAsString(parents); assertNotNull(json); // System.out.println("This works: " + json); // Add parent3 to create ObjectId reference // Bean w/ repeated relationship from parent1, should generate ObjectId Parent parent3 = new Parent(); parent3.child = child1; parents.addParent(parent3); StringWriter sw = new StringWriter(); try { mapper // .writerWithDefaultPrettyPrinter() .writeValue(sw, parents); } catch (Exception e) { fail("Failed with "+e.getClass().getName()+", output so far: " + sw); } } } TestSetterlessProperties501.java000066400000000000000000000037011325620701100365120ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; public class TestSetterlessProperties501 extends BaseMapTest { static class Poly { public int id; public Poly(int id) { this.id = id; } protected Poly() { this(0); } } static class Issue501Bean { protected Map m = new HashMap(); protected List l = new ArrayList(); protected Issue501Bean() { } public Issue501Bean(String key, Poly value) { m.put(key, value); l.add(value); } @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) public List getList(){ return l; } @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) public Map getMap() { return m; } // public void setMap(Map m) { this.m = m; } // public void setList(List l) { this.l = l; } } /* /********************************************************** /* Unit tests /********************************************************** */ // For [Issue#501] public void testSetterlessWithPolymorphic() throws Exception { Issue501Bean input = new Issue501Bean("a", new Poly(13)); ObjectMapper m = new ObjectMapper(); assertTrue(m.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS)); m.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); String json = m.writerWithDefaultPrettyPrinter().writeValueAsString(input); Issue501Bean output = m.readValue(json, Issue501Bean.class); assertNotNull(output); assertEquals(1, output.l.size()); assertEquals(1, output.m.size()); assertEquals(13, output.l.get(0).id); Poly p = output.m.get("a"); assertNotNull(p); assertEquals(13, p.id); } } TestSubtypes1311.java000066400000000000000000000025141325620701100341770ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.databind.ObjectMapper; // Not sure if this is valid, but for what it's worth, shows // the thing wrt [databind#1311]. May be removed if we can't find // improvements. public class TestSubtypes1311 extends com.fasterxml.jackson.databind.BaseMapTest { // [databind#1311] @JsonTypeInfo(property = "type", use = JsonTypeInfo.Id.NAME, defaultImpl = Factory1311ImplA.class) interface Factory1311 { } @JsonTypeName("implA") static class Factory1311ImplA implements Factory1311 { } @JsonTypeName("implB") static class Factory1311ImplB implements Factory1311 { } /* /********************************************************** /* Unit tests /********************************************************** */ // [databind#1311] public void testSubtypeAssignmentCheck() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.registerSubtypes(Factory1311ImplA.class, Factory1311ImplB.class); Factory1311ImplB result = mapper.readValue("{\"type\":\"implB\"}", Factory1311ImplB.class); assertNotNull(result); assertEquals(Factory1311ImplB.class, result.getClass()); } } TestUnknownProperty426.java000066400000000000000000000024601325620701100355130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for checking handling of unknown properties */ public class TestUnknownProperty426 extends BaseMapTest { // For [databind#426] @JsonIgnoreProperties({ "userId" }) static class User { public String firstName; Integer userId; public void setUserId(CharSequence id) { // 21-Dec-2015, tatu: With a fix in 2.7, use of String would not // trigger the problem, so use CharSequence... setUserId(new Integer(id.toString())); } public Integer getUserId() { return userId; } public void setUserId(Integer v) { this.userId = v; } } /* /********************************************************** /* Test methods /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testIssue426() throws Exception { final String JSON = aposToQuotes("{'userId': 9, 'firstName': 'Mike' }"); User result = MAPPER.readerFor(User.class).readValue(JSON); assertNotNull(result); assertEquals("Mike", result.firstName); } } TestUnwrappedMap171.java000066400000000000000000000027551325620701100347160ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import java.util.Collections; import java.util.Map; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; // Tests for [#171] public class TestUnwrappedMap171 extends BaseMapTest { static class MapUnwrap { public MapUnwrap() { } public MapUnwrap(String key, Object value) { map = Collections.singletonMap(key, value); } @JsonUnwrapped(prefix="map.") public Map map; } // // // Reuse mapper to keep tests bit faster private final ObjectMapper MAPPER = new ObjectMapper(); /* /********************************************************** /* Tests, serialization /********************************************************** */ public void testMapUnwrapSerialize() throws Exception { String json = MAPPER.writeValueAsString(new MapUnwrap("test", 6)); assertEquals("{\"map.test\": 6}", json); } /* /********************************************************** /* Tests, deserialization /********************************************************** */ public void testMapUnwrapDeserialize() throws Exception { MapUnwrap root = MAPPER.readValue("{\"map.test\": 6}", MapUnwrap.class); assertEquals(1, root.map.size()); assertEquals(6, ((Number)root.map.get("test")).intValue()); } } TestUnwrappedWithUnknown650.java000066400000000000000000000015551325620701100364730ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/fasterxml/jackson/failingpackage com.fasterxml.jackson.failing; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.*; public class TestUnwrappedWithUnknown650 extends BaseMapTest { static class A { @JsonUnwrapped public B b; } static class B { public String field; } private final ObjectMapper MAPPER = new ObjectMapper(); public void testFailOnUnknownPropertyUnwrapped() throws Exception { assertTrue(MAPPER.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); final String JSON = "{'field': 'value', 'bad':'bad value'}"; try { MAPPER.readValue(aposToQuotes(JSON), A.class); fail("Exception was not thrown on unkown property"); } catch (JsonMappingException e) { verifyException(e, "Unrecognized field"); } } } jackson-databind-jackson-databind-2.9.5/src/test/java/com/mchange/000077500000000000000000000000001325620701100247615ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/mchange/v2/000077500000000000000000000000001325620701100253105ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/mchange/v2/c3p0/000077500000000000000000000000001325620701100260555ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/mchange/v2/c3p0/jacksontest/000077500000000000000000000000001325620701100304055ustar00rootroot00000000000000ComboPooledDataSource.java000066400000000000000000000001641325620701100353470ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/com/mchange/v2/c3p0/jacksontestpackage com.mchange.v2.c3p0.jacksontest; // test class for [databind#1931] public class ComboPooledDataSource { } jackson-databind-jackson-databind-2.9.5/src/test/java/org/000077500000000000000000000000001325620701100233705ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/org/springframework/000077500000000000000000000000001325620701100266105ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/org/springframework/jacksontest/000077500000000000000000000000001325620701100311405ustar00rootroot00000000000000AbstractApplicationContext.java000066400000000000000000000001271325620701100372200ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/org/springframework/jacksontestpackage org.springframework.jacksontest; public class AbstractApplicationContext { } AbstractPointcutAdvisor.java000066400000000000000000000001241325620701100365420ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/org/springframework/jacksontestpackage org.springframework.jacksontest; public class AbstractPointcutAdvisor { } BogusApplicationContext.java000066400000000000000000000004431325620701100365350ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/org/springframework/jacksontestpackage org.springframework.jacksontest; //Made-up test class that should trigger checks for [databind#1855] public class BogusApplicationContext extends AbstractApplicationContext { public BogusApplicationContext(String s) { super(); throw new Error("Wrong!"); } } BogusPointcutAdvisor.java000066400000000000000000000004331325620701100360610ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/org/springframework/jacksontestpackage org.springframework.jacksontest; // Made-up test class that should trigger checks for [databind#1855] public class BogusPointcutAdvisor extends AbstractPointcutAdvisor { public BogusPointcutAdvisor(String s) { super(); throw new Error("Wrong!"); } } GrantedAuthority.java000066400000000000000000000001211325620701100352130ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/org/springframework/jacksontestpackage org.springframework.jacksontest; public interface GrantedAuthority { } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/000077500000000000000000000000001325620701100235355ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManualReadPerfUntyped.java000066400000000000000000000023341325620701100306010ustar00rootroot00000000000000package perf; import java.util.Map; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; public class ManualReadPerfUntyped extends ObjectReaderTestBase { @Override protected int targetSizeMegs() { return 10; } public static void main(String[] args) throws Exception { if (args.length != 1) { System.err.println("Usage: java [input]"); System.exit(1); } byte[] data = readAll(args[0]); JsonFactory f = new JsonFactory(); boolean doIntern = true; f.configure(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES, doIntern); f.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, doIntern); ObjectMapper m = new ObjectMapper(); // Either Object or Map final Class UNTYPED = Map.class; Object input1 = m.readValue(data, UNTYPED); JsonNode input2 = m.readTree(data); new ManualReadPerfUntyped() .testFromBytes( // .testFromString( m, "JSON-as-Object", input1, UNTYPED ,m, "JSON-as-Object2", input2, UNTYPED // ,m, "JSON-as-Node", input2, JsonNode.class ); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManualReadPerfUntypedReader.java000066400000000000000000000042131325620701100317220ustar00rootroot00000000000000package perf; import java.io.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; public class ManualReadPerfUntypedReader extends ObjectReaderTestBase { @Override protected int targetSizeMegs() { return 15; } public static void main(String[] args) throws Exception { if (args.length != 1) { System.err.println("Usage: java [input]"); System.exit(1); } byte[] data = readAll(args[0]); JsonFactory f = new JsonFactory(); boolean doIntern = true; f.configure(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES, doIntern); f.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, doIntern); ObjectMapper m = new ObjectMapper(); Object input1 = m.readValue(data, Object.class); JsonNode input2 = m.readTree(data); new ManualReadPerfUntypedReader() .testFromString( m, "JSON-as-Object", input1, Object.class ,m, "JSON-as-Object2", input2, Object.class ); } // When comparing to simple streaming parsing, uncomment: @Override protected double testDeser1(int reps, String input, ObjectReader reader) throws IOException { return _testRawDeser(reps, input, reader); } @Override protected double testDeser2(int reps, String input, ObjectReader reader) throws IOException { return _testRawDeser(reps, input, reader); } protected final double _testRawDeser(int reps, String json, ObjectReader reader) throws IOException { long start = System.nanoTime(); final JsonFactory f = reader.getFactory(); while (--reps >= 0) { JsonParser p = f.createParser(json); JsonToken t; while ((t = p.nextToken()) != null) { if (t == JsonToken.VALUE_STRING) { p.getText(); } else if (t.isNumeric()) { p.getNumberValue(); } ; } p.close(); } hash = f.hashCode(); return _msecsFromNanos(System.nanoTime() - start); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManualReadPerfUntypedStream.java000066400000000000000000000043061325620701100317560ustar00rootroot00000000000000package perf; import java.io.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; public class ManualReadPerfUntypedStream extends ObjectReaderTestBase { @Override protected int targetSizeMegs() { return 15; } public static void main(String[] args) throws Exception { if (args.length != 1) { System.err.println("Usage: java [input]"); System.exit(1); } byte[] data = readAll(args[0]); JsonFactory f = new JsonFactory(); boolean doIntern = true; f.configure(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES, doIntern); f.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, doIntern); ObjectMapper m = new ObjectMapper(); Object input1 = m.readValue(data, Object.class); JsonNode input2 = m.readTree(data); new ManualReadPerfUntypedStream() .testFromBytes( // .testFromString( m, "JSON-as-Object", input1, Object.class ,m, "JSON-as-Object2", input2, Object.class // ,m, "JSON-as-Node", input2, JsonNode.class ); } @Override protected double testDeser1(int reps, byte[] input, ObjectReader reader) throws IOException { return _testRawDeser(reps, input, reader); } @Override protected double testDeser2(int reps, byte[] input, ObjectReader reader) throws IOException { return _testRawDeser(reps, input, reader); } protected final double _testRawDeser(int reps, byte[] json, ObjectReader reader) throws IOException { long start = System.nanoTime(); final JsonFactory f = reader.getFactory(); while (--reps >= 0) { JsonParser p = f.createParser(new ByteArrayInputStream(json)); JsonToken t; while ((t = p.nextToken()) != null) { if (t == JsonToken.VALUE_STRING) { p.getText(); } else if (t.isNumeric()) { p.getNumberValue(); } ; } p.close(); } hash = f.hashCode(); return _msecsFromNanos(System.nanoTime() - start); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManualReadPerfWithMedia.java000066400000000000000000000035561325620701100310330ustar00rootroot00000000000000package perf; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class ManualReadPerfWithMedia extends ObjectReaderTestBase { @Override protected int targetSizeMegs() { return 8; } public static void main(String[] args) throws Exception { if (args.length != 0) { System.err.println("Usage: java ..."); System.exit(1); } MediaItem.Content content = new MediaItem.Content(); content.setTitle("Performance micro-benchmark, to be run manually"); content.addPerson("William"); content.addPerson("Robert"); content.setWidth(900); content.setHeight(120); content.setBitrate(256000); content.setDuration(3600 * 1000L); content.setCopyright("none"); content.setPlayer(MediaItem.Player.FLASH); content.setUri("http://whatever.biz"); MediaItem input = new MediaItem(content); input.addPhoto(new MediaItem.Photo("http://a.com", "title1", 200, 100, MediaItem.Size.LARGE)); input.addPhoto(new MediaItem.Photo("http://b.org", "title2", 640, 480, MediaItem.Size.SMALL)); ObjectMapper m1 = new ObjectMapper(); m1.setAnnotationIntrospector(new NoFormatIntrospector()); ObjectMapper m2 = new ObjectMapper(); new ManualReadPerfWithRecord().testFromBytes(m1, "JSON-as-Object", input, MediaItem.class, m2, "JSON-as-Array", input, MediaItem.class); } final static class NoFormatIntrospector extends JacksonAnnotationIntrospector { private static final long serialVersionUID = 1L; @Override public JsonFormat.Value findFormat(Annotated a) { return null; } } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManualReadPerfWithRecord.java000066400000000000000000000015261325620701100312250ustar00rootroot00000000000000package perf; import com.fasterxml.jackson.databind.*; /** * Simple manually run micro-benchmark for checking effects of (de)serializer * pre-fetching */ public class ManualReadPerfWithRecord extends ObjectReaderTestBase { @Override protected int targetSizeMegs() { return 8; } public static void main(String[] args) throws Exception { if (args.length != 0) { System.err.println("Usage: java ..."); System.exit(1); } Record input = new Record(44, "BillyBob", "Bumbler", 'm', true); RecordAsArray input2 = new RecordAsArray(44, "BillyBob", "Bumbler", 'm', true); ObjectMapper m = new ObjectMapper(); new ManualReadPerfWithRecord().testFromBytes(m, "JSON-as-Object", input, Record.class, m, "JSON-as-Array", input2, RecordAsArray.class); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManualReadPerfWithUUID.java000066400000000000000000000036021325620701100305520ustar00rootroot00000000000000package perf; import java.io.IOException; import java.util.UUID; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer; public class ManualReadPerfWithUUID extends ObjectReaderTestBase { static class UUIDNative { public UUID[] ids; public UUIDNative() { } public UUIDNative(UUID[] ids) { this.ids = ids; } } @Override protected int targetSizeMegs() { return 8; } @SuppressWarnings("serial") static class SlowDeser extends FromStringDeserializer { public SlowDeser() { super(UUID.class); } @Override protected UUID _deserialize(String id, DeserializationContext ctxt) throws IOException, JsonProcessingException { return UUID.fromString(id); } } static class UUIDWithJdk { @JsonDeserialize(contentUsing=SlowDeser.class) public UUID[] ids; public UUIDWithJdk() { } public UUIDWithJdk(UUID[] ids) { this.ids = ids; } } public static void main(String[] args) throws Exception { if (args.length != 0) { System.err.println("Usage: java ..."); System.exit(1); } UUID[] uuids = new UUID[8]; for (int i = 0; i < uuids.length; ++i) { uuids[i] = UUID.randomUUID(); } UUIDNative input1 = new UUIDNative(uuids); UUIDWithJdk input2 = new UUIDWithJdk(uuids); ObjectMapper m = new ObjectMapper(); new ManualReadPerfWithRecord().testFromBytes( m, "JSON-as-Object", input1, UUIDNative.class, m, "JSON-as-Array", input2, UUIDWithJdk.class); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManualReadWithTypeResolution.java000066400000000000000000000110331325620701100321710ustar00rootroot00000000000000package perf; import java.io.*; import java.util.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; /** * Variant that uses hard-coded input but compares cost of generic type * resolution to that of passing raw (type-erased) Class. * * @since 2.8 */ public class ManualReadWithTypeResolution { private final String _desc1, _desc2; private final byte[] _input; private final Class _inputType; private final TypeReference _inputTypeRef; private final ObjectMapper _mapper; private final int REPS; protected int hash; // wait for 3 seconds protected long startMeasure = System.currentTimeMillis() + 3000L; protected int roundsDone = 0; private double[] timeMsecs; public static void main(String[] args) throws Exception { new ManualReadWithTypeResolution().doTest(); } private ManualReadWithTypeResolution() throws IOException { _desc1 = "Raw type"; _desc2 = "Generic type"; _mapper = new ObjectMapper(); _input = "[\"value\",\"123\"]".getBytes("UTF-8"); _inputType = List.class; _inputTypeRef = new TypeReference>() { }; /* _input = "{\"id\":124}".getBytes("UTF-8"); _inputType = Map.class; _inputTypeRef = new TypeReference>() { }; */ REPS = (int) ((double) (15 * 1000 * 1000) / (double) _input.length); } // When comparing to simple streaming parsing, uncomment: private void doTest() throws Exception { System.out.printf("Read %d bytes to bind; will do %d repetitions\n", _input.length, REPS); System.out.print("Warming up"); int i = 0; final int TYPES = 2; timeMsecs = new double[TYPES]; while (true) { Thread.sleep(100L); final int type = (i++ % TYPES); String msg; double msesc; switch (type) { case 0: msesc = testDeser(REPS, _input, _mapper, _inputType); msg = _desc1; break; case 1: msesc = testDeser(REPS, _input, _mapper, _inputTypeRef); msg = _desc2; break; default: throw new Error(); } updateStats(type, (i % 17) == 0, msg, msesc); } } protected final double testDeser(int reps, byte[] json, ObjectMapper mapper, Class type) throws IOException { long start = System.nanoTime(); Object result = null; while (--reps >= 0) { result = mapper.readValue(json, type); } hash = result.hashCode(); return _msecsFromNanos(System.nanoTime() - start); } protected final double testDeser(int reps, byte[] json, ObjectMapper mapper, TypeReference type) throws IOException { long start = System.nanoTime(); Object result = null; while (--reps >= 0) { result = mapper.readValue(json, type); } hash = result.hashCode(); return _msecsFromNanos(System.nanoTime() - start); } private void updateStats(int type, boolean doGc, String msg, double msecs) throws Exception { final boolean lf = (type == (timeMsecs.length - 1)); if (startMeasure == 0L) { // skip first N seconds timeMsecs[type] += msecs; } else { if (lf) { if (System.currentTimeMillis() >= startMeasure) { startMeasure = 0L; System.out.println(" complete!"); } else { System.out.print("."); } } return; } System.out.printf("Test '%s' [hash: 0x%s] -> %.1f msecs\n", msg, Integer.toHexString(hash), msecs); if (lf) { ++roundsDone; if ((roundsDone % 3) == 0 ) { double den = (double) roundsDone; System.out.printf("Averages after %d rounds (%s/%s): %.1f / %.1f msecs\n", (int) den, _desc1, _desc2, timeMsecs[0] / den, timeMsecs[1] / den); } System.out.println(); } if (doGc) { System.out.println("[GC]"); Thread.sleep(100L); System.gc(); Thread.sleep(100L); } } protected final double _msecsFromNanos(long nanos) { return (nanos / 1000000.0); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManualWritePerfUntyped.java000066400000000000000000000034311325620701100310170ustar00rootroot00000000000000package perf; import java.io.File; import java.util.*; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; /* Test modified from json-parsers-benchmark, to be able to profile * Jackson implementation. */ public class ManualWritePerfUntyped extends ObjectWriterTestBase { @Override protected int targetSizeMegs() { return 15; } public static void main(String[] args) throws Exception { if (args.length != 1) { System.err.println("Usage: java [input]"); System.exit(1); } ObjectMapper mapper = new ObjectMapper(); Map stuff = mapper.readValue(new File(args[0]), Map.class); new ManualWritePerfUntyped().test(mapper, "Untyped-1", stuff, Object.class, "Untyped-2", stuff, Object.class); } @SuppressWarnings("resource") @Override protected double testSer(int REPS, Object value, ObjectWriter writer) throws Exception { long start = System.nanoTime(); // As Bytes /* // byte[] output = null; NopOutputStream out = new NopOutputStream(); while (--REPS >= 0) { // output = writer.writeValueAsBytes(value); writer.writeValue(out, value); } long nanos = System.nanoTime() - start; hash = out.size; out.close(); */ // As String // String output = null; NopWriter w = new NopWriter(); while (--REPS >= 0) { // output = writer.writeValueAsString(value); writer.writeValue(w, value); } long nanos = System.nanoTime() - start; // hash = output.length(); hash = w.size(); return _msecsFromNanos(nanos); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManualWritePerfWithAllTypes.java000066400000000000000000000101431325620701100317560ustar00rootroot00000000000000package perf; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; /* Test modified from json-parsers-benchmark, to be able to profile * Jackson implementation. */ public class ManualWritePerfWithAllTypes extends ObjectWriterTestBase { @Override protected int targetSizeMegs() { return 15; } public static void main(String[] args) throws Exception { if (args.length != 0) { System.err.println("Usage: java ..."); System.exit(1); } ObjectMapper m = new ObjectMapper(); AllTypes input1 = AllTypes.bigObject(); AllTypes input2 = AllTypes.bigObject(); new ManualWritePerfWithAllTypes().test(m, "AllTypes/small-1", input1, AllTypes.class, "AllTypes/small-2", input2, AllTypes.class); } @Override protected double testSer(int REPS, Object value, ObjectWriter writer) throws Exception { final NopOutputStream out = new NopOutputStream(); long start = System.nanoTime(); byte[] output = null; while (--REPS >= 0) { output = writer.writeValueAsBytes(value); } hash = output.length; long nanos = System.nanoTime() - start; out.close(); return _msecsFromNanos(nanos); } // Value type for test public static class AllTypes { enum FooEnum { FOO, BAR; } protected String ignoreMe; public String ignoreMe2; public String ignoreMe3; public int myInt; public boolean myBoolean; public short myShort; public long myLong; public String string; public String string2; public BigDecimal bigDecimal; public BigInteger bigInteger; public Date date; public float myFloat; public double myDouble; public byte myByte; public FooEnum foo; public FooEnum bar; public long someDate = new Date().getTime (); public AllTypes allType; public List allTypes = new ArrayList(); static AllTypes _small() { AllTypes small = new AllTypes(); small.ignoreMe = "THIS WILL NOT PASS"; small.ignoreMe2 = "THIS WILL NOT PASS EITHER"; small.ignoreMe3 = "THIS WILL NOT PASS TOO"; small.bigDecimal = new BigDecimal("1.235678900"); small.date = new Date(); small.bar = FooEnum.BAR; small.foo = FooEnum.FOO; small.string = "Hi Mom"; small.myDouble = 1.2345d; small.myFloat = 1.0f; small.myShort = (short)1; small.myByte = (byte)1; return small; } public static AllTypes smallObject() { AllTypes small = _small(); small.allType = _small(); small.allType.string = "Hi Dad"; small.allTypes = Arrays.asList(_small(), _small()); return small; } public static AllTypes bigObject() { AllTypes big = new AllTypes(); final List list = new ArrayList(); for (int index = 0; index < 10000; index++) { AllTypes item = new AllTypes(); item.ignoreMe = "THIS WILL NOT PASS"; item.ignoreMe2 = "THIS WILL NOT PASS EITHER"; item.ignoreMe3 = "THIS WILL NOT PASS TOO"; item.bigDecimal = new BigDecimal("1.235678900"); item.date = new Date (); item.bar = FooEnum.BAR; item.foo = FooEnum.FOO; item.string = "Hi Mom" + System.currentTimeMillis(); item.myDouble = 1.2345d; item.myFloat = 1.0f; item.myShort = (short)1; item.myByte = (byte)1; list.add(item); } big.allTypes = list; return big; } } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManualWritePerfWithRecord.java000066400000000000000000000014371325620701100314450ustar00rootroot00000000000000package perf; import com.fasterxml.jackson.databind.ObjectMapper; public class ManualWritePerfWithRecord extends ObjectWriterTestBase { @Override protected int targetSizeMegs() { return 10; } public static void main(String[] args) throws Exception { if (args.length != 0) { System.err.println("Usage: java ..."); System.exit(1); } Record input1 = new Record(44, "BillyBob", "Bumbler", 'm', true); RecordAsArray input2 = new RecordAsArray(44, "BillyBob", "Bumbler", 'm', true); ObjectMapper m = new ObjectMapper(); new ManualWritePerfWithRecord().test(m, "JSON-as-Object", input1, Record.class, "JSON-as-Array", input2, RecordAsArray.class); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ManulWritePerfWithUUID.java000066400000000000000000000033011325620701100306240ustar00rootroot00000000000000package perf; import java.io.IOException; import java.util.UUID; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; public class ManulWritePerfWithUUID extends ObjectWriterTestBase { @Override protected int targetSizeMegs() { return 10; } public static void main(String[] args) throws Exception { if (args.length != 0) { System.err.println("Usage: java ..."); System.exit(1); } UUID[] uuids = new UUID[8]; for (int i = 0; i < uuids.length; ++i) { uuids[i] = UUID.randomUUID(); } ObjectMapper m = new ObjectMapper(); new ManulWritePerfWithUUID().test(m, "faster-UUID", new UUIDFast(uuids), UUIDFast.class, "JDK-UUID", new UUIDSlow(uuids), UUIDSlow.class); } } class UUIDFast { public final UUID[] values; public UUIDFast(UUID[] v) { values = v; } } class UUIDSlow { @JsonSerialize(contentUsing=SlowSer.class) public final UUID[] values; public UUIDSlow(UUID[] v) { values = v; } } @SuppressWarnings("serial") class SlowSer extends StdScalarSerializer { public SlowSer() { super(UUID.class); } @Override public void serialize(UUID value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { jgen.writeString(value.toString()); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/MediaItem.java000066400000000000000000000100021325620701100262270ustar00rootroot00000000000000package perf; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder({"content", "images"}) 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 /********************************************************** */ @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder({"uri","title","width","height","size"}) 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; } } @JsonFormat(shape=JsonFormat.Shape.ARRAY) @JsonPropertyOrder({"uri","title","width","height","format","duration","size","bitrate","persons","player","copyright"}) 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; } } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/NopOutputStream.java000066400000000000000000000007641325620701100275400ustar00rootroot00000000000000package perf; import java.io.IOException; import java.io.OutputStream; public class NopOutputStream extends OutputStream { protected int size = 0; public NopOutputStream() { } @Override public void write(int b) throws IOException { ++size; } @Override public void write(byte[] b) throws IOException { size += b.length; } @Override public void write(byte[] b, int offset, int len) throws IOException { size += len; } public int size() { return size; } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/NopWriter.java000066400000000000000000000010671325620701100263350ustar00rootroot00000000000000package perf; import java.io.*; public class NopWriter extends Writer { protected int size = 0; public NopWriter() { } @Override public void write(int b) throws IOException { ++size; } @Override public void write(char[] b) throws IOException { size += b.length; } @Override public void write(char[] b, int offset, int len) throws IOException { size += len; } public int size() { return size; } @Override public void close() throws IOException { } @Override public void flush() throws IOException { } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ObjectReaderTestBase.java000066400000000000000000000204751325620701100303740ustar00rootroot00000000000000package perf; import java.io.*; import com.fasterxml.jackson.databind.*; abstract class ObjectReaderTestBase { protected final static int WARMUP_ROUNDS = 5; protected String _desc1, _desc2; protected int hash; protected long startMeasure = System.currentTimeMillis() + 5000L; protected int roundsDone = 0; protected int REPS; private double[] timeMsecs; protected abstract int targetSizeMegs(); protected void testFromBytes(ObjectMapper mapper1, String desc1, Object inputValue1, Class inputClass1, ObjectMapper mapper2, String desc2, Object inputValue2, Class inputClass2) throws Exception { final byte[] byteInput1 = mapper1.writeValueAsBytes(inputValue1); final byte[] byteInput2 = mapper2.writeValueAsBytes(inputValue2); // Let's try to guestimate suitable size... to get to N megs to process REPS = (int) ((double) (targetSizeMegs() * 1000 * 1000) / (double) byteInput1.length); // sanity check: /*T1 back1 =*/ mapper1.readValue(byteInput1, inputClass1); /*T2 back2 =*/ mapper2.readValue(byteInput2, inputClass2); System.out.println("Input successfully round-tripped for both styles..."); _desc1 = String.format("%s (%d bytes)", desc1, byteInput1.length); _desc2 = String.format("%s (%d bytes)", desc2, byteInput2.length); doTest(mapper1, byteInput1, inputClass1, mapper2, byteInput2, inputClass2); } protected void testFromString(ObjectMapper mapper1, String desc1, Object inputValue1, Class inputClass1, ObjectMapper mapper2, String desc2, Object inputValue2, Class inputClass2) throws Exception { final String input1 = mapper1.writeValueAsString(inputValue1); final String input2 = mapper2.writeValueAsString(inputValue2); // Let's try to guestimate suitable size... to get to N megs to process REPS = (int) ((double) (targetSizeMegs() * 1000 * 1000) / (double) input1.length()); _desc1 = String.format("%s (%d chars)", desc1, input1.length()); _desc2 = String.format("%s (%d chars)", desc2, input2.length()); // sanity check: /*T1 back1 =*/ mapper1.readValue(input1, inputClass1); /*T2 back2 =*/ mapper2.readValue(input2, inputClass2); System.out.println("Input successfully round-tripped for both styles..."); doTest(mapper1, input1, inputClass1, mapper2, input2, inputClass2); } protected void doTest(ObjectMapper mapper1, byte[] byteInput1, Class inputClass1, ObjectMapper mapper2, byte[] byteInput2, Class inputClass2) throws Exception { System.out.printf("Read %d bytes to bind (%d as array); will do %d repetitions\n", byteInput1.length, byteInput2.length, REPS); System.out.print("Warming up"); final ObjectReader jsonReader = mapper1.reader() .forType(inputClass1); final ObjectReader arrayReader = mapper2.reader() .forType(inputClass2); int i = 0; final int TYPES = 2; timeMsecs = new double[TYPES]; while (true) { Thread.sleep(100L); final int type = (i++ % TYPES); String msg; double msesc; switch (type) { case 0: msg = _desc1; msesc = testDeser1(REPS, byteInput1, jsonReader); break; case 1: msg = _desc2; msesc = testDeser2(REPS, byteInput2, arrayReader); break; default: throw new Error(); } updateStats(type, (i % 17) == 0, msg, msesc); } } protected void doTest(ObjectMapper mapper1, String input1, Class inputClass1, ObjectMapper mapper2, String input2, Class inputClass2) throws Exception { System.out.printf("Read %d bytes to bind (%d as array); will do %d repetitions\n", input1.length(), input2.length(), REPS); System.out.print("Warming up"); final ObjectReader jsonReader = mapper1.reader() .with(DeserializationFeature.EAGER_DESERIALIZER_FETCH) .forType(inputClass1); final ObjectReader arrayReader = mapper2.reader() .with(DeserializationFeature.EAGER_DESERIALIZER_FETCH) .forType(inputClass2); int i = 0; final int TYPES = 2; timeMsecs = new double[TYPES]; while (true) { Thread.sleep(100L); int type = (i++ % TYPES); String msg; double msecs; switch (type) { case 0: msg = _desc1; msecs = testDeser1(REPS, input1, jsonReader); break; case 1: msg = _desc2; msecs = testDeser2(REPS, input2, arrayReader); break; default: throw new Error(); } updateStats(type, (i % 17) == 0, msg, msecs); } } private void updateStats(int type, boolean doGc, String msg, double msecs) throws Exception { final boolean lf = (type == (timeMsecs.length - 1)); if (startMeasure == 0L) { // skip first N seconds timeMsecs[type] += msecs; } else { if (lf) { if (System.currentTimeMillis() >= startMeasure) { startMeasure = 0L; System.out.println(" complete!"); } else { System.out.print("."); } } return; } System.out.printf("Test '%s' [hash: 0x%s] -> %.1f msecs\n", msg, Integer.toHexString(hash), msecs); if (lf) { ++roundsDone; if ((roundsDone % 3) == 0 ) { double den = (double) roundsDone; System.out.printf("Averages after %d rounds (%s/%s): %.1f / %.1f msecs\n", (int) den, _desc1, _desc2, timeMsecs[0] / den, timeMsecs[1] / den); } System.out.println(); } if (doGc) { System.out.println("[GC]"); Thread.sleep(100L); System.gc(); Thread.sleep(100L); } } protected double testDeser1(int reps, byte[] input, ObjectReader reader) throws Exception { return _testDeser(reps, input, reader); } protected double testDeser2(int reps, byte[] input, ObjectReader reader) throws Exception { return _testDeser(reps, input, reader); } protected final double _testDeser(int reps, byte[] input, ObjectReader reader) throws Exception { long start = System.nanoTime(); Object result = null; while (--reps >= 0) { result = reader.readValue(input); } hash = result.hashCode(); // return microseconds return _msecsFromNanos(System.nanoTime() - start); } protected double testDeser1(int reps, String input, ObjectReader reader) throws Exception { return _testDeser(reps, input, reader); } protected double testDeser2(int reps, String input, ObjectReader reader) throws Exception { return _testDeser(reps, input, reader); } protected final double _testDeser(int reps, String input, ObjectReader reader) throws Exception { long start = System.nanoTime(); Object result = null; while (--reps >= 0) { result = reader.readValue(input); } hash = result.hashCode(); return _msecsFromNanos(System.nanoTime() - start); } protected final double _msecsFromNanos(long nanos) { return (nanos / 1000000.0); } protected static byte[] readAll(String filename) throws IOException { File f = new File(filename); ByteArrayOutputStream bytes = new ByteArrayOutputStream((int) f.length()); byte[] buffer = new byte[4000]; int count; FileInputStream in = new FileInputStream(f); while ((count = in.read(buffer)) > 0) { bytes.write(buffer, 0, count); } in.close(); return bytes.toByteArray(); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/ObjectWriterTestBase.java000066400000000000000000000077211325620701100304450ustar00rootroot00000000000000package perf; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializationFeature; abstract class ObjectWriterTestBase { protected int hash; protected abstract int targetSizeMegs(); protected void test(ObjectMapper mapper, String desc1, T1 inputValue1, Class inputClass1, String desc2, T2 inputValue2, Class inputClass2) throws Exception { final int REPS; { final byte[] input1 = mapper.writeValueAsBytes(inputValue1); final byte[] input2 = mapper.writeValueAsBytes(inputValue2); // Let's try to guestimate suitable size, N megs of output REPS = (int) ((double) (targetSizeMegs() * 1000 * 1000) / (double) input1.length); System.out.printf("Read %d bytes to bind (%d as array); will do %d repetitions\n", input1.length, input2.length, REPS); } final ObjectWriter writer0 = mapper.writer().with(SerializationFeature.EAGER_SERIALIZER_FETCH); final ObjectWriter writer1 = writer0.forType(inputClass1); final ObjectWriter writer2 = writer0.forType(inputClass2); int i = 0; int roundsDone = 0; final int TYPES = 2; // Skip first 5 seconds long startMeasure = System.currentTimeMillis() + 5000L; System.out.print("Warming up"); final double[] timesMsec = new double[TYPES]; while (true) { final int round = (i % TYPES); final boolean lf = (++i % TYPES) == 0; String msg; ObjectWriter writer; Object value; switch (round) { case 0: msg = desc1; writer = writer1; value = inputValue1; break; case 1: msg = desc2; writer = writer2; value = inputValue2; break; default: throw new Error(); } double msecs = testSer(REPS, value, writer); // skip first N seconds to let results stabilize if (startMeasure > 0L) { if ((round != 0) || (System.currentTimeMillis() < startMeasure)) { System.out.print("."); continue; } startMeasure = 0L; System.out.println(); System.out.println("Starting measurements..."); Thread.sleep(250L); System.out.println(); } timesMsec[round] += msecs; if ((i % 17) == 0) { System.out.println("[GC]"); Thread.sleep(100L); System.gc(); Thread.sleep(100L); } System.out.printf("Test '%s' [hash: 0x%s] -> %.1f msecs\n", msg, hash, msecs); Thread.sleep(50L); if (!lf) { continue; } if ((++roundsDone % 3) == 0) { double den = (double) roundsDone; System.out.printf("Averages after %d rounds (%s/%s): %.1f / %.1f msecs\n", roundsDone, desc1, desc2, timesMsec[0] / den, timesMsec[1] / den); } System.out.println(); } } protected double testSer(int REPS, Object value, ObjectWriter writer) throws Exception { final NopOutputStream out = new NopOutputStream(); long start = System.nanoTime(); while (--REPS >= 0) { writer.writeValue(out, value); } hash = out.size(); long nanos = System.nanoTime() - start; out.close(); return _msecsFromNanos(nanos); } protected final double _msecsFromNanos(long nanos) { return (nanos / 1000000.0); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/Record.java000066400000000000000000000003611325620701100256160ustar00rootroot00000000000000package perf; /** * Simple test class */ final class Record extends RecordBase { protected Record() { super(); } public Record(int a, String fn, String ln, char g, boolean ins) { super(a, fn, ln, g, ins); } }jackson-databind-jackson-databind-2.9.5/src/test/java/perf/RecordAsArray.java000066400000000000000000000005101325620701100270750ustar00rootroot00000000000000package perf; import com.fasterxml.jackson.annotation.JsonFormat; @JsonFormat(shape=JsonFormat.Shape.ARRAY) final class RecordAsArray extends RecordBase { protected RecordAsArray() { super(); } public RecordAsArray(int a, String fn, String ln, char g, boolean ins) { super(a, fn, ln, g, ins); } } jackson-databind-jackson-databind-2.9.5/src/test/java/perf/RecordBase.java000066400000000000000000000005741325620701100264170ustar00rootroot00000000000000package perf; public class RecordBase { public int age; public String firstName, lastName; public char gender; public boolean insured; protected RecordBase() { } protected RecordBase(int a, String fn, String ln, char g, boolean ins) { age = a; firstName = fn; lastName = ln; gender = g; insured = ins; } } jackson-databind-jackson-databind-2.9.5/src/test/resources/000077500000000000000000000000001325620701100236725ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/resources/data/000077500000000000000000000000001325620701100246035ustar00rootroot00000000000000jackson-databind-jackson-databind-2.9.5/src/test/resources/data/citm_catalog.json000066400000000000000000064553441325620701100301510ustar00rootroot00000000000000{ "areaNames": { "205705993": "Arrière-scène central", "205705994": "1er balcon central", "205705995": "2ème balcon bergerie cour", "205705996": "2ème balcon bergerie jardin", "205705998": "1er balcon bergerie jardin", "205705999": "1er balcon bergerie cour", "205706000": "Arrière-scène jardin", "205706001": "Arrière-scène cour", "205706002": "2ème balcon jardin", "205706003": "2ème balcon cour", "205706004": "2ème Balcon central", "205706005": "1er balcon jardin", "205706006": "1er balcon cour", "205706007": "Orchestre central", "205706008": "Orchestre jardin", "205706009": "Orchestre cour", "342752287": "Zone physique secrète" }, "audienceSubCategoryNames": { "337100890": "Abonné" }, "blockNames": {}, "events": { "138586341": { "description": null, "id": 138586341, "logo": null, "name": "30th Anniversary Tour", "subTopicIds": [ 337184269, 337184283 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604 ] }, "138586345": { "description": null, "id": 138586345, "logo": "/images/UE0AAAAACEKo6QAAAAZDSVRN", "name": "Berliner Philharmoniker", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586349": { "description": null, "id": 138586349, "logo": "/images/UE0AAAAACEKo7QAAAAZDSVRN", "name": "Berliner Philharmoniker", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586353": { "description": null, "id": 138586353, "logo": "/images/UE0AAAAACEKo8QAAAAZDSVRN", "name": "Pittsburgh Symphony Orchestra", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586357": { "description": null, "id": 138586357, "logo": "/images/UE0AAAAACEKo9QAAAAhDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586361": { "description": null, "id": 138586361, "logo": "/images/UE0AAAAACEKo+QAAAAVDSVRN", "name": "WDR Sinfonieorchester Köln", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586365": { "description": null, "id": 138586365, "logo": "/images/UE0AAAAACEKo/QAAAAVDSVRN", "name": "Alessandro - G.F. Haendel", "subTopicIds": [ 337184284, 337184263, 337184298, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586369": { "description": null, "id": 138586369, "logo": "/images/UE0AAAAACEKpAQAAAAVDSVRN", "name": "Orchestre Colonne", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586373": { "description": null, "id": 138586373, "logo": "/images/UE0AAAAACEKpBQAAAAdDSVRN", "name": "Christophe", "subTopicIds": [ 337184280, 337184297, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586377": { "description": null, "id": 138586377, "logo": "/images/UE0AAAAACEKpCQAAAAVDSVRN", "name": "Joshua Redman Quartet", "subTopicIds": [ 337184269, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586381": { "description": null, "id": 138586381, "logo": "/images/UE0AAAAACEKpDQAAAAVDSVRN", "name": "Orchestre Symphonique d'Etat de São Paulo", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586385": { "description": null, "id": 138586385, "logo": "/images/UE0AAAAACEKpEQAAAAVDSVRN", "name": "Le génie italien", "subTopicIds": [ 337184284, 337184298, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586389": { "description": null, "id": 138586389, "logo": "/images/UE0AAAAACEKpFQAAAAVDSVRN", "name": "Les Noces de Figaro - W.A. Mozart (version de concert)", "subTopicIds": [ 337184284, 337184298, 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586393": { "description": null, "id": 138586393, "logo": "/images/UE0AAAAACEKpGQAAAAhDSVRN", "name": "Orchestre Pasdeloup", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586397": { "description": null, "id": 138586397, "logo": null, "name": "The Saxophone Summit", "subTopicIds": [ 337184269, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586401": { "description": null, "id": 138586401, "logo": "/images/UE0AAAAACEKpIQAAAAVDSVRN", "name": "Patricia Petibon - Nouveau Monde", "subTopicIds": [ 337184263, 337184298, 337184283, 337184292 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586405": { "description": null, "id": 138586405, "logo": "/images/UE0AAAAACEKpJQAAAAVDSVRN", "name": "Russian National Orchestra", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586409": { "description": null, "id": 138586409, "logo": "/images/UE0AAAAACEKpKQAAAAZDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586413": { "description": null, "id": 138586413, "logo": "/images/UE0AAAAACEKpLQAAAAVDSVRN", "name": "Evgeny Kissin", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586417": { "description": null, "id": 138586417, "logo": "/images/UE0AAAAACEKpMQAAAAZDSVRN", "name": "Bach, concertos pour piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586421": { "description": null, "id": 138586421, "logo": "/images/UE0AAAAACEKpNQAAAAVDSVRN", "name": "Bach, concertos pour piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586425": { "description": null, "id": 138586425, "logo": null, "name": "Orchestre National d'Île-de-France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586429": { "description": null, "id": 138586429, "logo": "/images/UE0AAAAACEKpPQAAAAVDSVRN", "name": "Gewandhausorchester Leipzig", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586433": { "description": null, "id": 138586433, "logo": "/images/UE0AAAAACEKpQQAAAAVDSVRN", "name": "Gewandhausorchester Leipzig", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586437": { "description": null, "id": 138586437, "logo": "/images/UE0AAAAACEKpRQAAAAVDSVRN", "name": "Budapest Festival Orchestra", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586441": { "description": null, "id": 138586441, "logo": "/images/UE0AAAAACEKpSQAAAAVDSVRN", "name": "Orchestre National du Capitole de Toulouse", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586445": { "description": null, "id": 138586445, "logo": "/images/UE0AAAAACEKpTQAAAAVDSVRN", "name": "Gewandhausorchester Leipzig", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586449": { "description": null, "id": 138586449, "logo": "/images/UE0AAAAACEKpUQAAAAVDSVRN", "name": "Gewandhausorchester Leipzig", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586453": { "description": null, "id": 138586453, "logo": "/images/UE0AAAAACEKpVQAAAAVDSVRN", "name": "Remember Shakti", "subTopicIds": [ 337184269, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586457": { "description": null, "id": 138586457, "logo": "/images/UE0AAAAACEKpWQAAAAVDSVRN", "name": "Menahem Pressler - Quatuor Ebène", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586461": { "description": null, "id": 138586461, "logo": "/images/UE0AAAAACEKpXQAAAAZDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586465": { "description": null, "id": 138586465, "logo": "/images/UE0AAAAACEKpYQAAAAVDSVRN", "name": "Orquesta Buena Vista Social Club", "subTopicIds": [ 337184279, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586469": { "description": null, "id": 138586469, "logo": "/images/UE0AAAAACEKpZQAAAAVDSVRN", "name": "The Cleveland Orchestra", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586473": { "description": null, "id": 138586473, "logo": "/images/UE0AAAAACEKpaQAAAAVDSVRN", "name": "The Cleveland Orchestra", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586477": { "description": null, "id": 138586477, "logo": "/images/UE0AAAAACEKpbQAAAAZDSVRN", "name": "Orchestre Philharmonique du Luxembourg", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586481": { "description": null, "id": 138586481, "logo": "/images/UE0AAAAACEKpcQAAAAVDSVRN", "name": "Maurizio Pollini, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586485": { "description": null, "id": 138586485, "logo": "/images/UE0AAAAACEKpdQAAAAZDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586501": { "description": null, "id": 138586501, "logo": "/images/UE0AAAAACEKphQAAAAVDSVRN", "name": "Antonio Meneses - Maria-João Pires", "subTopicIds": [ 337184268, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586505": { "description": null, "id": 138586505, "logo": "/images/UE0AAAAACEKpiQAAAAVDSVRN", "name": "Musiques pour la reine Caroline", "subTopicIds": [ 337184284, 337184263, 337184298, 337184283, 337184292 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586509": { "description": null, "id": 138586509, "logo": null, "name": "Orchestre National d'Île-de-France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586513": { "description": null, "id": 138586513, "logo": "/images/UE0AAAAACEKpkQAAAAVDSVRN", "name": "Les Mystères d'Isis - W.A. Mozart (cersion de concert)", "subTopicIds": [ 337184284, 337184298, 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586517": { "description": null, "id": 138586517, "logo": "/images/UE0AAAAACEKplQAAAAdDSVRN", "name": "Martha Argerich - Gidon Kremer", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586521": { "description": null, "id": 138586521, "logo": "/images/UE0AAAAACEKpmQAAAAVDSVRN", "name": "Cecilia Bartoli - Mozart et la Vienne classique", "subTopicIds": [ 337184298, 337184268, 337184283, 337184292 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586525": { "description": null, "id": 138586525, "logo": "/images/UE0AAAAACEKpnQAAAAVDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586529": { "description": null, "id": 138586529, "logo": null, "name": "Orchestre Pasdeloup", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586533": { "description": null, "id": 138586533, "logo": "/images/UE0AAAAACEKppQAAAAVDSVRN", "name": "Orchestre du Théâtre Mariinsky", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586537": { "description": null, "id": 138586537, "logo": "/images/UE0AAAAACEKpqQAAAAVDSVRN", "name": "Orchestre du Théâtre Mariinsky", "subTopicIds": [ 337184298, 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586541": { "description": null, "id": 138586541, "logo": "/images/UE0AAAAACEKprQAAAAVDSVRN", "name": "Orchestre du Théâtre Mariinsky", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586545": { "description": null, "id": 138586545, "logo": "/images/UE0AAAAACEKpsQAAAAVDSVRN", "name": "Academy of Saint Martin in the Fields", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586549": { "description": null, "id": 138586549, "logo": "/images/UE0AAAAACEKptQAAAAVDSVRN", "name": "Quatuor Hagen", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586553": { "description": null, "id": 138586553, "logo": "/images/UE0AAAAACEKpuQAAAAVDSVRN", "name": "Quatuor Hagen", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586557": { "description": null, "id": 138586557, "logo": "/images/UE0AAAAACEKpvQAAAAVDSVRN", "name": "Quatuor Hagen", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586561": { "description": null, "id": 138586561, "logo": "/images/UE0AAAAACEKpwQAAAAVDSVRN", "name": "Sunwook Kim, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586565": { "description": null, "id": 138586565, "logo": null, "name": "Orchestre Colonne", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586569": { "description": null, "id": 138586569, "logo": "/images/UE0AAAAACEKpyQAAAAVDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586581": { "description": null, "id": 138586581, "logo": null, "name": "Orchestre National de France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586585": { "description": null, "id": 138586585, "logo": "/images/UE0AAAAACEKp2QAAAAVDSVRN", "name": "Messe en si mineur - J.S. Bach", "subTopicIds": [ 337184296, 337184263, 337184298, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586589": { "description": null, "id": 138586589, "logo": null, "name": "Le Messie - G.F. Haendel", "subTopicIds": [ 337184263, 337184298, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586593": { "description": null, "id": 138586593, "logo": "/images/UE0AAAAACEKp4QAAAAdDSVRN", "name": "Orchestre National d'Île-de-France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586597": { "description": null, "id": 138586597, "logo": "/images/UE0AAAAACEKp5QAAAAVDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586601": { "description": null, "id": 138586601, "logo": "/images/UE0AAAAACEKp6QAAAAdDSVRN", "name": "Orchestre Pasdeloup", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586605": { "description": null, "id": 138586605, "logo": null, "name": "Orchestre Colonne", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586609": { "description": null, "id": 138586609, "logo": null, "name": "Ciné-concert - Le Cuirassé Potemkine", "subTopicIds": [ 337184267, 337184262, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 107888604, 324846100 ] }, "138586613": { "description": null, "id": 138586613, "logo": "/images/UE0AAAAACEKp9QAAAAVDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586617": { "description": null, "id": 138586617, "logo": "/images/UE0AAAAACEKp+QAAAAVDSVRN", "name": "London Symphony Orchestra", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586625": { "description": null, "id": 138586625, "logo": null, "name": "Orchestre National d'Île-de-France", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586629": { "description": null, "id": 138586629, "logo": "/images/UE0AAAAACEKqBQAAAAVDSVRN", "name": "Orquesta Sinfonica Simón Bolívar de Venezuela", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586633": { "description": null, "id": 138586633, "logo": "/images/UE0AAAAACEKqCQAAAAVDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184298, 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586641": { "description": null, "id": 138586641, "logo": "/images/UE0AAAAACEKqEQAAAAVDSVRN", "name": "Edita Gruberova - Airs de concert", "subTopicIds": [ 337184284, 337184298, 337184283, 337184292 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586645": { "description": null, "id": 138586645, "logo": "/images/UE0AAAAACEKqFQAAAAdDSVRN", "name": "Orchestre National d'Île-de-France", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586649": { "description": null, "id": 138586649, "logo": "/images/UE0AAAAACEKqGQAAAAZDSVRN", "name": "Alexei Volodin, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586653": { "description": null, "id": 138586653, "logo": null, "name": "Sonya Yoncheva - Diva !", "subTopicIds": [ 337184284, 337184263, 337184298, 337184283, 337184292 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586657": { "description": null, "id": 138586657, "logo": "/images/UE0AAAAACEKqIQAAAAVDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586661": { "description": null, "id": 138586661, "logo": null, "name": "Le Ramayana balinais - L'Enlèvement de Sita", "subTopicIds": [ 337184279, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586667": { "description": null, "id": 138586667, "logo": null, "name": "Dave Holland & friends", "subTopicIds": [ 337184269, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586671": { "description": null, "id": 138586671, "logo": "/images/UE0AAAAACEKqLwAAAAlDSVRN", "name": "Boris Godounov - M.Moussorgski (version de concert)", "subTopicIds": [ 337184284, 337184298, 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586675": { "description": null, "id": 138586675, "logo": "/images/UE0AAAAACEKqMwAAAAVDSVRN", "name": "Insula orchestra - Accentus", "subTopicIds": [ 337184298, 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586679": { "description": null, "id": 138586679, "logo": "/images/UE0AAAAACEKqNwAAAAVDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586687": { "description": null, "id": 138586687, "logo": "/images/UE0AAAAACEKqPwAAAAVDSVRN", "name": "Bryn Terfel - Héros légendaires", "subTopicIds": [ 337184284, 337184298, 337184283, 337184292 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586691": { "description": null, "id": 138586691, "logo": null, "name": "Les Siècles", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586695": { "description": null, "id": 138586695, "logo": "/images/UE0AAAAACEKqRwAAAAVDSVRN", "name": "Gautier Capuçon - Frank Braley", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586699": { "description": null, "id": 138586699, "logo": null, "name": "Festival Présences 2014 \"Paris Berlin\"", "subTopicIds": [ 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586703": { "description": null, "id": 138586703, "logo": "/images/UE0AAAAACEKqTwAAAAZDSVRN", "name": "Autour de Tristan", "subTopicIds": [ 337184284, 337184298, 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586707": { "description": null, "id": 138586707, "logo": "/images/UE0AAAAACEKqUwAAAAVDSVRN", "name": "Orchestre du Théâtre Mariinsky", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586711": { "description": null, "id": 138586711, "logo": "/images/UE0AAAAACEKqVwAAAAVDSVRN", "name": "Orchestre du Théâtre Mariinsky", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586715": { "description": null, "id": 138586715, "logo": "/images/UE0AAAAACEKqWwAAAAVDSVRN", "name": "Orchestre du Théâtre Mariinsky", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586719": { "description": null, "id": 138586719, "logo": "/images/UE0AAAAACEKqXwAAAAVDSVRN", "name": "Etienne Daho et invités", "subTopicIds": [ 337184280, 337184297, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586723": { "description": null, "id": 138586723, "logo": null, "name": "Fantasia in concert", "subTopicIds": [ 337184299, 337184268, 337184267, 337184275, 337184282 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846098, 324846099, 107888604, 324846100 ] }, "138586731": { "description": null, "id": 138586731, "logo": "/images/UE0AAAAACEKqawAAAAVDSVRN", "name": "Khatia Buniatishvili, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586735": { "description": null, "id": 138586735, "logo": "/images/UE0AAAAACEKqbwAAAAVDSVRN", "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586743": { "description": null, "id": 138586743, "logo": null, "name": "Guy Braunstein - Zvi Plesser - Sunwook Kim", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586747": { "description": null, "id": 138586747, "logo": "/images/UE0AAAAACEKqewAAAAVDSVRN", "name": "Janine Jansen and friends", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586751": { "description": null, "id": 138586751, "logo": "/images/UE0AAAAACEKqfwAAAAVDSVRN", "name": "Elena Bashkirova, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586755": { "description": null, "id": 138586755, "logo": null, "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184284, 337184298, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586759": { "description": null, "id": 138586759, "logo": null, "name": "San Francisco Symphony", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586771": { "description": null, "id": 138586771, "logo": null, "name": "Passion selon saint Jean - J.S. Bach", "subTopicIds": [ 337184296, 337184263, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586775": { "description": null, "id": 138586775, "logo": null, "name": "Yundi Li , piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586779": { "description": null, "id": 138586779, "logo": null, "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586783": { "description": null, "id": 138586783, "logo": null, "name": "Orchestre Pasdeloup", "subTopicIds": [ 337184268, 337184269, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586787": { "description": null, "id": 138586787, "logo": null, "name": "Orchestre du Conservatoire de Paris", "subTopicIds": [ 337184284, 337184298, 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586795": { "description": null, "id": 138586795, "logo": null, "name": "Orchestre National d'Île-de-France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586799": { "description": null, "id": 138586799, "logo": null, "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586803": { "description": null, "id": 138586803, "logo": null, "name": "Royal Concertgebouw Orchestra Amsterdam", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586807": { "description": null, "id": 138586807, "logo": null, "name": "Royal Concertgebouw Orchestra Amsterdam", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586811": { "description": null, "id": 138586811, "logo": null, "name": "Royal Concertgebouw Orchestra Amsterdam", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586815": { "description": null, "id": 138586815, "logo": null, "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586823": { "description": null, "id": 138586823, "logo": null, "name": "London Symphony Orchestra", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586827": { "description": null, "id": 138586827, "logo": null, "name": "London Symphony Orchestra", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586831": { "description": null, "id": 138586831, "logo": null, "name": "Le Concert des Nations - Jordi Savall", "subTopicIds": [ 337184263, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586835": { "description": null, "id": 138586835, "logo": null, "name": "Leonidas Kavakos - Yuja Wang", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586839": { "description": null, "id": 138586839, "logo": null, "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586843": { "description": null, "id": 138586843, "logo": null, "name": "Quatuor Artemis - Gautier Capuçon", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586847": { "description": null, "id": 138586847, "logo": null, "name": "Quatuor Artemis - Quatuor Ébène", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586851": { "description": null, "id": 138586851, "logo": null, "name": "Quatuor Artemis - Elisabeth Leonskaja", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586855": { "description": null, "id": 138586855, "logo": null, "name": "Russian National Orchestra", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586859": { "description": null, "id": 138586859, "logo": null, "name": "Passion selon saint Matthieu", "subTopicIds": [ 337184296, 337184263, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586863": { "description": null, "id": 138586863, "logo": null, "name": "Les Arts Florissants - Concert de Pâques", "subTopicIds": [ 337184263, 337184298, 337184283, 337184292 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586867": { "description": null, "id": 138586867, "logo": null, "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586871": { "description": null, "id": 138586871, "logo": null, "name": "Leylâ et Majnûn ou L'Amour mystique", "subTopicIds": [ 337184279, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586875": { "description": null, "id": 138586875, "logo": null, "name": "Stephen Kovacevich, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586879": { "description": null, "id": 138586879, "logo": null, "name": "Orchestra Mozart Bologna - Mahler Chamber Orchestra", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586883": { "description": null, "id": 138586883, "logo": null, "name": "Ballet Royal du Cambodge", "subTopicIds": [ 337184279, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586889": { "description": null, "id": 138586889, "logo": null, "name": "MDR Sinfonieorchester Leipzig", "subTopicIds": [ 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586893": { "description": null, "id": 138586893, "logo": null, "name": "Orchestre Colonne", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586897": { "description": null, "id": 138586897, "logo": null, "name": "Elisabeth Leonskaja, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586901": { "description": null, "id": 138586901, "logo": null, "name": "Yuja Wang, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586905": { "description": null, "id": 138586905, "logo": null, "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586909": { "description": null, "id": 138586909, "logo": null, "name": "Anne-Sophie Mutter - Lambert Orkis", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586917": { "description": null, "id": 138586917, "logo": null, "name": "Orchestre National d'Île-de-France", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586921": { "description": null, "id": 138586921, "logo": null, "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586929": { "description": null, "id": 138586929, "logo": null, "name": "Orchestre Pasdeloup", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586933": { "description": null, "id": 138586933, "logo": null, "name": "Gilberto Gil", "subTopicIds": [ 337184279, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586937": { "description": null, "id": 138586937, "logo": null, "name": "Nelson Freire, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586941": { "description": null, "id": 138586941, "logo": null, "name": "Orchestre Philharmonique de Radio France", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586945": { "description": null, "id": 138586945, "logo": null, "name": "Orfeo - C. Monteverdi (version de concert)", "subTopicIds": [ 337184284, 337184263, 337184298, 337184283, 337184292 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586949": { "description": null, "id": 138586949, "logo": null, "name": "Bamberger Symphoniker", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586953": { "description": null, "id": 138586953, "logo": null, "name": "Murray Perahia, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586957": { "description": null, "id": 138586957, "logo": null, "name": "Orchestre National du Capitole de Toulouse", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586961": { "description": null, "id": 138586961, "logo": null, "name": "Krystian Zimerman, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586965": { "description": null, "id": 138586965, "logo": null, "name": "Rafal Blechacz, piano", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586969": { "description": null, "id": 138586969, "logo": null, "name": "Les Voyages musicaux de Marco Polo", "subTopicIds": [ 337184279, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586973": { "description": null, "id": 138586973, "logo": null, "name": "Orchestre National de Lyon", "subTopicIds": [ 337184298, 337184268, 337184283, 337184292, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586977": { "description": null, "id": 138586977, "logo": null, "name": "Guy Braunstein - Zvi Plesser - Sunwook Kim", "subTopicIds": [ 337184281, 337184283, 337184273 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586981": { "description": null, "id": 138586981, "logo": null, "name": "La Bohème - G. Puccini (version de concert)", "subTopicIds": [ 337184284, 337184298, 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586989": { "description": null, "id": 138586989, "logo": null, "name": "Otello - G. Verdi (version de concert)", "subTopicIds": [ 337184284, 337184298, 337184268, 337184283, 337184292 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586993": { "description": null, "id": 138586993, "logo": null, "name": "Staatskapelle Berlin", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "138586997": { "description": null, "id": 138586997, "logo": null, "name": "Staatskapelle Berlin", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "151183114": { "description": null, "id": 151183114, "logo": null, "name": "San Francisco Symphony", "subTopicIds": [ 337184298, 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "339420802": { "description": null, "id": 339420802, "logo": null, "name": "Lou Doillon", "subTopicIds": [ 337184280, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "339420805": { "description": null, "id": 339420805, "logo": null, "name": "Patrick Watson & Orchestre National d'Ile-de-France", "subTopicIds": [ 337184280, 337184283, 337184262 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341069930": { "description": null, "id": 341069930, "logo": "/images/UE0AAAAAFFRQagAAAAlDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181232": { "description": null, "id": 341181232, "logo": null, "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181233": { "description": null, "id": 341181233, "logo": "/images/UE0AAAAAFFYDMQAAAAhDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181234": { "description": null, "id": 341181234, "logo": "/images/UE0AAAAAFFYDMgAAAAdDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181235": { "description": null, "id": 341181235, "logo": "/images/UE0AAAAAFFYDMwAAAAZDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181236": { "description": null, "id": 341181236, "logo": "/images/UE0AAAAAFFYDNAAAAAZDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181237": { "description": null, "id": 341181237, "logo": "/images/UE0AAAAAFFYDNQAAAAhDSVRN", "name": "Paavo Järvi, direction", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181238": { "description": null, "id": 341181238, "logo": "/images/UE0AAAAAFFYDNgAAAAdDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181239": { "description": null, "id": 341181239, "logo": "/images/UE0AAAAAFFYDNwAAAAdDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181240": { "description": null, "id": 341181240, "logo": "/images/UE0AAAAAFFYDOAAAAAhDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181241": { "description": null, "id": 341181241, "logo": "/images/UE0AAAAAFFYDOQAAAAZDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181242": { "description": null, "id": 341181242, "logo": "/images/UE0AAAAAFFYDOgAAAAdDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181243": { "description": null, "id": 341181243, "logo": "/images/UE0AAAAAFFYDOwAAAAdDSVRN", "name": "Concert anniversaire des 90 ans de Menahem Pressler", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181244": { "description": null, "id": 341181244, "logo": "/images/UE0AAAAAFFYDPAAAAAZDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181245": { "description": null, "id": 341181245, "logo": "/images/UE0AAAAAFFYDPQAAAAZDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181246": { "description": null, "id": 341181246, "logo": null, "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181247": { "description": null, "id": 341181247, "logo": null, "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181248": { "description": null, "id": 341181248, "logo": "/images/UE0AAAAAFFYDQAAAAAZDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181249": { "description": null, "id": 341181249, "logo": "/images/UE0AAAAAFFYDQQAAAAdDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181250": { "description": null, "id": 341181250, "logo": "/images/UE0AAAAAFFYDQgAAAAdDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181251": { "description": null, "id": 341181251, "logo": null, "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181252": { "description": null, "id": 341181252, "logo": "/images/UE0AAAAAFFYDRAAAAAdDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181253": { "description": null, "id": 341181253, "logo": null, "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181254": { "description": null, "id": 341181254, "logo": "/images/UE0AAAAAFFYDRgAAAAlDSVRN", "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181255": { "description": null, "id": 341181255, "logo": null, "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181256": { "description": null, "id": 341181256, "logo": null, "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181257": { "description": null, "id": 341181257, "logo": null, "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181258": { "description": null, "id": 341181258, "logo": null, "name": "Orchestre de Paris", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "341181259": { "description": null, "id": 341181259, "logo": null, "name": "14052122 JARVI / GOERNE / SOLBERG / CHŒUR", "subTopicIds": [ 337184268, 337184288, 337184283, 337184275 ], "subjectCode": null, "subtitle": null, "topicIds": [ 324846099, 107888604, 324846100 ] }, "342742592": { "description": null, "id": 342742592, "logo": null, "name": "event secret 2", "subTopicIds": [], "subjectCode": null, "subtitle": null, "topicIds": [] }, "342742593": { "description": null, "id": 342742593, "logo": null, "name": "event secret 3", "subTopicIds": [], "subjectCode": null, "subtitle": null, "topicIds": [] }, "342742594": { "description": null, "id": 342742594, "logo": null, "name": "event secret 4", "subTopicIds": [], "subjectCode": null, "subtitle": null, "topicIds": [] }, "342742595": { "description": null, "id": 342742595, "logo": null, "name": "event secret 5", "subTopicIds": [], "subjectCode": null, "subtitle": null, "topicIds": [] }, "342742596": { "description": null, "id": 342742596, "logo": null, "name": "event secret 6", "subTopicIds": [], "subjectCode": null, "subtitle": null, "topicIds": [] } }, "performances": [ { "eventId": 138586341, "id": 339887544, "logo": null, "name": null, "prices": [ { "amount": 90250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937295 }, { "amount": 66500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937296 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937295 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937296 } ], "seatMapImage": null, "start": 1372701600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 339420802, "id": 339430296, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937295 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937296 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937295 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937296 } ], "seatMapImage": null, "start": 1372788000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 339420805, "id": 339430301, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937295 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937296 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937295 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937296 } ], "seatMapImage": null, "start": 1373220000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586345, "id": 138586347, "logo": "/images/UE0AAAAACEKo6QAAAAZDSVRN", "name": null, "prices": [ { "amount": 152000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 104500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1377972000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586349, "id": 138586351, "logo": "/images/UE0AAAAACEKo7QAAAAZDSVRN", "name": null, "prices": [ { "amount": 152000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 104500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1378044000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586353, "id": 138586355, "logo": "/images/UE0AAAAACEKo8QAAAAZDSVRN", "name": null, "prices": [ { "amount": 90250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 71250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1378490400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341069930, "id": 341070133, "logo": "/images/UE0AAAAAFFRQagAAAAlDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 } ], "seatMapImage": null, "start": 1378922400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341069930, "id": 341070132, "logo": "/images/UE0AAAAAFFRQagAAAAlDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 } ], "seatMapImage": null, "start": 1379008800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586357, "id": 138586359, "logo": "/images/UE0AAAAACEKo9QAAAAhDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1379095200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586361, "id": 138586363, "logo": "/images/UE0AAAAACEKo+QAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1379440800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586365, "id": 138586367, "logo": "/images/UE0AAAAACEKo/QAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1379959200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181254, "id": 341181470, "logo": "/images/UE0AAAAAFFYDRgAAAAlDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 } ], "seatMapImage": null, "start": 1380132000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181254, "id": 341181469, "logo": "/images/UE0AAAAAFFYDRgAAAAlDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 } ], "seatMapImage": null, "start": 1380218400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586369, "id": 138586371, "logo": "/images/UE0AAAAACEKpAQAAAAVDSVRN", "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1380650400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181252, "id": 341181467, "logo": "/images/UE0AAAAAFFYDRAAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1380736800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586373, "id": 138586375, "logo": "/images/UE0AAAAACEKpBQAAAAdDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1380996000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586377, "id": 138586379, "logo": "/images/UE0AAAAACEKpCQAAAAVDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1381082400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586381, "id": 138586383, "logo": "/images/UE0AAAAACEKpDQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1381168800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586385, "id": 138586387, "logo": "/images/UE0AAAAACEKpEQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1381255200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181234, "id": 341181437, "logo": "/images/UE0AAAAAFFYDMgAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1381341600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181234, "id": 341181436, "logo": "/images/UE0AAAAAFFYDMgAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1381428000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586389, "id": 138586391, "logo": "/images/UE0AAAAACEKpFQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1381512600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586393, "id": 138586395, "logo": "/images/UE0AAAAACEKpGQAAAAhDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937241 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937242 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937244 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937245 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937246 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937241 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937242 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937244 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937245 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937246 } ], "seatMapImage": null, "start": 1381586400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586397, "id": 138586399, "logo": null, "name": null, "prices": [ { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1381672800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586401, "id": 138586403, "logo": "/images/UE0AAAAACEKpIQAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1381773600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586405, "id": 138586407, "logo": "/images/UE0AAAAACEKpJQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1381860000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181233, "id": 341181435, "logo": "/images/UE0AAAAAFFYDMQAAAAhDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1381946400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181237, "id": 341181442, "logo": "/images/UE0AAAAAFFYDNQAAAAhDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1382032800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586409, "id": 138586411, "logo": "/images/UE0AAAAACEKpKQAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1382119200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586413, "id": 138586415, "logo": "/images/UE0AAAAACEKpLQAAAAVDSVRN", "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1382277600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586417, "id": 138586419, "logo": "/images/UE0AAAAACEKpMQAAAAZDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1382378400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586421, "id": 138586423, "logo": "/images/UE0AAAAACEKpNQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1382464800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181238, "id": 341181444, "logo": "/images/UE0AAAAAFFYDNgAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1382551200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181238, "id": 341181443, "logo": "/images/UE0AAAAAFFYDNgAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1382637600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586425, "id": 138586427, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937235 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937236 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937238 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937239 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937240 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937235 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937236 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937238 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937239 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937240 } ], "seatMapImage": null, "start": 1382724000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586429, "id": 138586431, "logo": "/images/UE0AAAAACEKpPQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1382810400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586433, "id": 138586435, "logo": "/images/UE0AAAAACEKpQQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1382886000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586437, "id": 138586439, "logo": "/images/UE0AAAAACEKpRQAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1383073200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586441, "id": 138586443, "logo": "/images/UE0AAAAACEKpSQAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1383246000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586445, "id": 138586447, "logo": "/images/UE0AAAAACEKpTQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1383332400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586449, "id": 138586451, "logo": "/images/UE0AAAAACEKpUQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1383418800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742592, "id": 342742708, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1383555600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742592, "id": 342742709, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1383562800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586453, "id": 138586455, "logo": "/images/UE0AAAAACEKpVQAAAAVDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937295 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937296 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937295 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937296 } ], "seatMapImage": null, "start": 1383591600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742592, "id": 342742710, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1383642000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742592, "id": 342742711, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1383649200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742592, "id": 342742712, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1383728400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742592, "id": 342742713, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1383735600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742592, "id": 342742714, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1383814800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742592, "id": 342742715, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1383822000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586457, "id": 138586459, "logo": "/images/UE0AAAAACEKpWQAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1383850800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586461, "id": 138586463, "logo": "/images/UE0AAAAACEKpXQAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1383937200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586465, "id": 138586467, "logo": "/images/UE0AAAAACEKpYQAAAAVDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1384110000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586469, "id": 138586471, "logo": "/images/UE0AAAAACEKpZQAAAAVDSVRN", "name": null, "prices": [ { "amount": 90250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937289 }, { "amount": 71250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937290 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937292 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937293 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937289 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937290 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937292 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937293 } ], "seatMapImage": null, "start": 1384196400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586473, "id": 138586475, "logo": "/images/UE0AAAAACEKpaQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1384282800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586477, "id": 138586479, "logo": "/images/UE0AAAAACEKpbQAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1384369200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586481, "id": 138586483, "logo": "/images/UE0AAAAACEKpcQAAAAVDSVRN", "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1384455600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586485, "id": 138586487, "logo": "/images/UE0AAAAACEKpdQAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1384542000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586501, "id": 138586503, "logo": "/images/UE0AAAAACEKphQAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1384801200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586505, "id": 138586507, "logo": "/images/UE0AAAAACEKpiQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1384887600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586509, "id": 138586511, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937235 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937236 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937238 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937239 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937240 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937235 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937236 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937238 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937239 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937240 } ], "seatMapImage": null, "start": 1385146800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586513, "id": 138586515, "logo": "/images/UE0AAAAACEKpkQAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1385231400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586517, "id": 138586519, "logo": "/images/UE0AAAAACEKplQAAAAdDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1385305200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586521, "id": 138586523, "logo": "/images/UE0AAAAACEKpmQAAAAVDSVRN", "name": null, "prices": [ { "amount": 152000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 104500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1385492400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181235, "id": 341181439, "logo": "/images/UE0AAAAAFFYDMwAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826019 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826019 } ], "seatMapImage": null, "start": 1385665200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586525, "id": 138586527, "logo": "/images/UE0AAAAACEKpnQAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1385751600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586529, "id": 138586531, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937241 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937242 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937244 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937245 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937246 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937241 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937242 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937244 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937245 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937246 } ], "seatMapImage": null, "start": 1385823600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181235, "id": 341181438, "logo": "/images/UE0AAAAAFFYDMwAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826019 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826019 } ], "seatMapImage": null, "start": 1385838000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586533, "id": 138586535, "logo": "/images/UE0AAAAACEKppQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1385910000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586537, "id": 138586539, "logo": "/images/UE0AAAAACEKpqQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1386010800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586541, "id": 138586543, "logo": "/images/UE0AAAAACEKprQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1386097200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181236, "id": 341181440, "logo": "/images/UE0AAAAAFFYDNAAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1386183600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181236, "id": 341181441, "logo": "/images/UE0AAAAAFFYDNAAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1386270000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586545, "id": 138586547, "logo": "/images/UE0AAAAACEKpsQAAAAVDSVRN", "name": null, "prices": [ { "amount": 104500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1386356400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586549, "id": 138586551, "logo": "/images/UE0AAAAACEKptQAAAAVDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1386428400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586553, "id": 138586555, "logo": "/images/UE0AAAAACEKpuQAAAAVDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1386442800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586557, "id": 138586559, "logo": "/images/UE0AAAAACEKpvQAAAAVDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1386514800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742593, "id": 342742716, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1386579600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742593, "id": 342742717, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1386586800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586561, "id": 138586563, "logo": "/images/UE0AAAAACEKpwQAAAAVDSVRN", "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1386615600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742593, "id": 342742718, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1386666000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742593, "id": 342742719, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1386673200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586565, "id": 138586567, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1386702000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742593, "id": 342742720, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1386752400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742593, "id": 342742721, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1386759600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181241, "id": 341181449, "logo": "/images/UE0AAAAAFFYDOQAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1386788400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742593, "id": 342742722, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1386838800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742593, "id": 342742723, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1386846000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181241, "id": 341181450, "logo": "/images/UE0AAAAAFFYDOQAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1386874800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586569, "id": 138586571, "logo": "/images/UE0AAAAACEKpyQAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1386961200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742594, "id": 342742724, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387184400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742594, "id": 342742725, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387191600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586581, "id": 138586583, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264860 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264861 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264863 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264864 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264860 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264861 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264863 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264864 } ], "seatMapImage": null, "start": 1387220400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742594, "id": 342742726, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387270800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742594, "id": 342742727, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387278000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586585, "id": 138586587, "logo": "/images/UE0AAAAACEKp2QAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1387306800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742594, "id": 342742728, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387357200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742594, "id": 342742729, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387364400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181250, "id": 341181465, "logo": "/images/UE0AAAAAFFYDQgAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1387393200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742594, "id": 342742730, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387443600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742594, "id": 342742731, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387450800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586589, "id": 138586591, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1387566000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586593, "id": 138586595, "logo": "/images/UE0AAAAACEKp4QAAAAdDSVRN", "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937235 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937236 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937238 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937239 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937240 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937235 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937236 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937238 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937239 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937240 } ], "seatMapImage": null, "start": 1387724400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742595, "id": 342742732, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387789200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742595, "id": 342742733, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387796400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742595, "id": 342742734, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387875600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742595, "id": 342742735, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387882800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742595, "id": 342742736, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387962000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742595, "id": 342742737, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1387969200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742595, "id": 342742738, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1388048400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742595, "id": 342742739, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1388055600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742596, "id": 342742740, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1388998800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742596, "id": 342742741, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1389006000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742596, "id": 342742742, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1389085200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742596, "id": 342742743, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1389092400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742596, "id": 342742744, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1389171600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742596, "id": 342742745, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1389178800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181245, "id": 341181458, "logo": "/images/UE0AAAAAFFYDPQAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1389207600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742596, "id": 342742746, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1389258000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 342742596, "id": 342742747, "logo": null, "name": null, "prices": [ { "amount": 180500, "audienceSubCategoryId": 337100890, "seatCategoryId": 342752792 } ], "seatCategories": [ { "areas": [ { "areaId": 342752287, "blockIds": [] } ], "seatCategoryId": 342752792 } ], "seatMapImage": null, "start": 1389265200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181245, "id": 341181457, "logo": "/images/UE0AAAAAFFYDPQAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1389294000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586597, "id": 138586599, "logo": "/images/UE0AAAAACEKp5QAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1389380400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586601, "id": 138586603, "logo": "/images/UE0AAAAACEKp6QAAAAdDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937241 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937242 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937244 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937245 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937246 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937241 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937242 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937244 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937245 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937246 } ], "seatMapImage": null, "start": 1389452400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586605, "id": 138586607, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1389538800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586609, "id": 138586611, "logo": null, "name": null, "prices": [ { "amount": 15000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937314 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937314 } ], "seatMapImage": null, "start": 1389726000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181242, "id": 341181451, "logo": "/images/UE0AAAAAFFYDOgAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1389812400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181242, "id": 341181452, "logo": "/images/UE0AAAAAFFYDOgAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1389898800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586613, "id": 138586615, "logo": "/images/UE0AAAAACEKp9QAAAAVDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086215 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086215 } ], "seatMapImage": null, "start": 1389985200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586617, "id": 138586619, "logo": "/images/UE0AAAAACEKp+QAAAAVDSVRN", "name": null, "prices": [ { "amount": 90250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 71250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1390071600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586625, "id": 138586627, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937235 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937236 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937238 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937239 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937240 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937235 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937236 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937238 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937239 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937240 } ], "seatMapImage": null, "start": 1390143600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586629, "id": 138586631, "logo": "/images/UE0AAAAACEKqBQAAAAVDSVRN", "name": null, "prices": [ { "amount": 90250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937271 }, { "amount": 71250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937272 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937274 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937275 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937271 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937272 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937274 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937275 } ], "seatMapImage": null, "start": 1390159800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181239, "id": 341181446, "logo": "/images/UE0AAAAAFFYDNwAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826019 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826019 } ], "seatMapImage": null, "start": 1390417200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181239, "id": 341181445, "logo": "/images/UE0AAAAAFFYDNwAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826019 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826019 } ], "seatMapImage": null, "start": 1390503600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586633, "id": 138586635, "logo": "/images/UE0AAAAACEKqCQAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1390590000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586641, "id": 138586643, "logo": "/images/UE0AAAAACEKqEQAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1390676400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586645, "id": 138586647, "logo": "/images/UE0AAAAACEKqFQAAAAdDSVRN", "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937235 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937236 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937238 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937239 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937240 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937235 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937236 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937238 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937239 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937240 } ], "seatMapImage": null, "start": 1390748400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586649, "id": 138586651, "logo": "/images/UE0AAAAACEKqGQAAAAZDSVRN", "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1390849200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586653, "id": 138586655, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1390935600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181243, "id": 341181453, "logo": "/images/UE0AAAAAFFYDOwAAAAdDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 } ], "seatMapImage": null, "start": 1391022000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181243, "id": 341181454, "logo": "/images/UE0AAAAAFFYDOwAAAAdDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 } ], "seatMapImage": null, "start": 1391108400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586657, "id": 138586659, "logo": "/images/UE0AAAAACEKqIQAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1391194800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586661, "id": 138586663, "logo": null, "name": null, "prices": [ { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1391353200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586661, "id": 138586665, "logo": null, "name": null, "prices": [ { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1391367600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586667, "id": 138586669, "logo": null, "name": null, "prices": [ { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937295 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937296 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937295 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937296 } ], "seatMapImage": null, "start": 1391540400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586671, "id": 138586673, "logo": "/images/UE0AAAAACEKqLwAAAAlDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937289 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937290 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937292 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937293 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937289 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937290 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937292 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937293 } ], "seatMapImage": null, "start": 1391626800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586675, "id": 138586677, "logo": "/images/UE0AAAAACEKqMwAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1391713200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586679, "id": 138586681, "logo": "/images/UE0AAAAACEKqNwAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1391799600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586687, "id": 138586689, "logo": "/images/UE0AAAAACEKqPwAAAAVDSVRN", "name": null, "prices": [ { "amount": 90250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 71250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1391886000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586691, "id": 138586693, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1391958000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586695, "id": 138586697, "logo": "/images/UE0AAAAACEKqRwAAAAVDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1392145200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181240, "id": 341181448, "logo": "/images/UE0AAAAAFFYDOAAAAAhDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1392231600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181240, "id": 341181447, "logo": "/images/UE0AAAAAFFYDOAAAAAhDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1392318000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586699, "id": 138586701, "logo": null, "name": null, "prices": [ { "amount": 15000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264872 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264872 } ], "seatMapImage": null, "start": 1392404400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586703, "id": 138586705, "logo": "/images/UE0AAAAACEKqTwAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1392490800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586707, "id": 138586709, "logo": "/images/UE0AAAAACEKqUwAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1392562800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586711, "id": 138586713, "logo": "/images/UE0AAAAACEKqVwAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1392663600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586715, "id": 138586717, "logo": "/images/UE0AAAAACEKqWwAAAAVDSVRN", "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1392750000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181248, "id": 341181462, "logo": "/images/UE0AAAAAFFYDQAAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1392836400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586719, "id": 138586721, "logo": "/images/UE0AAAAACEKqXwAAAAVDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1393095600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586723, "id": 138586729, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937307 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937308 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937310 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937311 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937312 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937307 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937308 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937310 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937311 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937312 } ], "seatMapImage": null, "start": 1393678800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586723, "id": 138586725, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937307 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937308 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937310 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937311 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937312 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937307 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937308 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937310 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937311 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937312 } ], "seatMapImage": null, "start": 1393693200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586723, "id": 138586727, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937307 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937308 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937310 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937311 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937312 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937307 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937308 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937310 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937311 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937312 } ], "seatMapImage": null, "start": 1393754400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586731, "id": 138586733, "logo": "/images/UE0AAAAACEKqawAAAAVDSVRN", "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1393959600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181249, "id": 341181463, "logo": "/images/UE0AAAAAFFYDQQAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826019 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826019 } ], "seatMapImage": null, "start": 1394046000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181249, "id": 341181464, "logo": "/images/UE0AAAAAFFYDQQAAAAdDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826019 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826019 } ], "seatMapImage": null, "start": 1394132400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586735, "id": 138586737, "logo": "/images/UE0AAAAACEKqbwAAAAVDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1394218800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586743, "id": 138586745, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1394305200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586747, "id": 138586749, "logo": "/images/UE0AAAAACEKqewAAAAVDSVRN", "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1394377200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586751, "id": 138586753, "logo": "/images/UE0AAAAACEKqfwAAAAVDSVRN", "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1394478000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181244, "id": 341181455, "logo": "/images/UE0AAAAAFFYDPAAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1394650800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181244, "id": 341181456, "logo": "/images/UE0AAAAAFFYDPAAAAAZDSVRN", "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1394737200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586755, "id": 138586757, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264866 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264867 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264869 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264870 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264866 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264867 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264869 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264870 } ], "seatMapImage": null, "start": 1394823600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586759, "id": 138586761, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1395082800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 151183114, "id": 151183116, "logo": null, "name": null, "prices": [ { "amount": 90250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937289 }, { "amount": 71250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937290 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937292 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937293 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937289 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937290 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937292 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937293 } ], "seatMapImage": null, "start": 1395169200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586771, "id": 138586773, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1395255600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586775, "id": 138586777, "logo": null, "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1395342000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586779, "id": 138586781, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1395428400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586783, "id": 138586785, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937241 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937242 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937244 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937245 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937246 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937241 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937242 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937244 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937245 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937246 } ], "seatMapImage": null, "start": 1395500400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586787, "id": 138586789, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1395514800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586795, "id": 138586797, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937235 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937236 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937238 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937239 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937240 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937235 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937236 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937238 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937239 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937240 } ], "seatMapImage": null, "start": 1395586800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181246, "id": 341181459, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826019 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826019 } ], "seatMapImage": null, "start": 1395860400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181246, "id": 341181460, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826019 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826019 } ], "seatMapImage": null, "start": 1395946800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586799, "id": 138586801, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1396033200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586803, "id": 138586805, "logo": null, "name": null, "prices": [ { "amount": 90250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 71250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1396191600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586807, "id": 138586809, "logo": null, "name": null, "prices": [ { "amount": 104500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1396288800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586811, "id": 138586813, "logo": null, "name": null, "prices": [ { "amount": 90250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 71250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1396375200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181255, "id": 341181472, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 } ], "seatMapImage": null, "start": 1396461600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181255, "id": 341181471, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 } ], "seatMapImage": null, "start": 1396548000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586815, "id": 138586817, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1396634400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586823, "id": 138586825, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1396720800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586827, "id": 138586829, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1396792800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586831, "id": 138586833, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1396893600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586835, "id": 138586837, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1396980000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181256, "id": 341181473, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1397066400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181256, "id": 341181474, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1397152800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586839, "id": 138586841, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264866 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264867 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264869 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264870 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264866 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264867 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264869 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264870 } ], "seatMapImage": null, "start": 1397239200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586843, "id": 138586845, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1397311200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586847, "id": 138586849, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1397325600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586851, "id": 138586853, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1397397600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586855, "id": 138586857, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1397498400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586859, "id": 138586861, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1397584800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586863, "id": 138586865, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1397930400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181251, "id": 341181466, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 } ], "seatMapImage": null, "start": 1398276000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181253, "id": 341181468, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 } ], "seatMapImage": null, "start": 1398362400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586867, "id": 138586869, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1398448800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586871, "id": 138586873, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1398607200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586875, "id": 138586877, "logo": null, "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1398708000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586879, "id": 138586881, "logo": null, "name": null, "prices": [ { "amount": 171000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 123500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 66500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1398794400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586883, "id": 138586887, "logo": null, "name": null, "prices": [ { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1399125600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586883, "id": 138586885, "logo": null, "name": null, "prices": [ { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1399140000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586889, "id": 138586891, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937307 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937308 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937310 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937311 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937307 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937308 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937310 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937311 } ], "seatMapImage": null, "start": 1399312800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586893, "id": 138586895, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1399399200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181232, "id": 341181434, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1399485600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586897, "id": 138586899, "logo": null, "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1399917600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586901, "id": 138586903, "logo": null, "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1400176800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586905, "id": 138586907, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1400263200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586909, "id": 138586911, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1400349600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586917, "id": 138586919, "logo": null, "name": null, "prices": [ { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937235 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937236 }, { "amount": 19000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937238 }, { "amount": 14250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937239 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937240 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937235 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937236 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937238 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937239 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937240 } ], "seatMapImage": null, "start": 1400421600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181259, "id": 341181480, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 } ], "seatMapImage": null, "start": 1400695200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181259, "id": 341181479, "logo": null, "name": null, "prices": [ { "amount": 80750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826016 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826017 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826015 }, { "amount": 28500, "audienceSubCategoryId": 337100890, "seatCategoryId": 340826018 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826016 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826017 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 340826015 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 340826018 } ], "seatMapImage": null, "start": 1400781600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586921, "id": 138586923, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086210 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086211 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086213 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086214 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086210 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086211 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086214 } ], "seatMapImage": null, "start": 1400868000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586929, "id": 138586931, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937241 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937242 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937244 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937245 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937246 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937241 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937242 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937244 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937245 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937246 } ], "seatMapImage": null, "start": 1400940000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586933, "id": 138586935, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1401026400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586937, "id": 138586939, "logo": null, "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1401127200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586941, "id": 138586943, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264860 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264861 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264863 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341264864 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264860 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264861 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264863 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341264864 } ], "seatMapImage": null, "start": 1401472800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586945, "id": 138586947, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1401730200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586949, "id": 138586951, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1401818400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586953, "id": 138586955, "logo": null, "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1401904800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586957, "id": 138586959, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 } ], "seatMapImage": null, "start": 1401991200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586961, "id": 138586963, "logo": null, "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1402077600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586965, "id": 138586967, "logo": null, "name": null, "prices": [ { "amount": 95000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1402423200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181258, "id": 341181477, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1402509600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181258, "id": 341181478, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1402596000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586969, "id": 138586971, "logo": null, "name": null, "prices": [ { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086196 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 339086197 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086196 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 339086197 } ], "seatMapImage": null, "start": 1402768800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586973, "id": 138586975, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 } ], "seatMapImage": null, "start": 1402840800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586977, "id": 138586979, "logo": null, "name": null, "prices": [ { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 33250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 23750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 16150, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1402941600000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586981, "id": 138586983, "logo": null, "name": null, "prices": [ { "amount": 123500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937289 }, { "amount": 85500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937290 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937292 }, { "amount": 38000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937293 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937294 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937289 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937290 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937292 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937293 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937294 } ], "seatMapImage": null, "start": 1403028000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181257, "id": 341181475, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1403114400000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181257, "id": 341181476, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1403200800000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 341181247, "id": 341181461, "logo": null, "name": null, "prices": [ { "amount": 57000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179212 }, { "amount": 42750, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179213 }, { "amount": 32300, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179214 }, { "amount": 20900, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179215 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 341179216 } ], "seatCategories": [ { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179212 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179213 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179214 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] } ], "seatCategoryId": 341179215 }, { "areas": [ { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 341179216 } ], "seatMapImage": null, "start": 1403719200000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586989, "id": 138586991, "logo": null, "name": null, "prices": [ { "amount": 152000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937284 }, { "amount": 104500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937285 }, { "amount": 76000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937287 }, { "amount": 52250, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937288 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937283 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937284 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937285 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937287 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937288 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937283 } ], "seatMapImage": null, "start": 1403892000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586993, "id": 138586995, "logo": null, "name": null, "prices": [ { "amount": 123500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 85500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 38000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1404324000000, "venueCode": "PLEYEL_PLEYEL" }, { "eventId": 138586997, "id": 138586999, "logo": null, "name": null, "prices": [ { "amount": 123500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937277 }, { "amount": 85500, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937278 }, { "amount": 61750, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937280 }, { "amount": 38000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937281 }, { "amount": 10000, "audienceSubCategoryId": 337100890, "seatCategoryId": 338937282 } ], "seatCategories": [ { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937277 }, { "areas": [ { "areaId": 205705999, "blockIds": [] }, { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937278 }, { "areas": [ { "areaId": 205705998, "blockIds": [] }, { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205705995, "blockIds": [] }, { "areaId": 205705996, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205705993, "blockIds": [] }, { "areaId": 205706007, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937280 }, { "areas": [ { "areaId": 205705994, "blockIds": [] }, { "areaId": 205706006, "blockIds": [] }, { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706001, "blockIds": [] }, { "areaId": 205706000, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937281 }, { "areas": [ { "areaId": 205706005, "blockIds": [] }, { "areaId": 205706004, "blockIds": [] }, { "areaId": 205706003, "blockIds": [] }, { "areaId": 205706002, "blockIds": [] }, { "areaId": 205706009, "blockIds": [] }, { "areaId": 205706008, "blockIds": [] } ], "seatCategoryId": 338937282 } ], "seatMapImage": null, "start": 1404410400000, "venueCode": "PLEYEL_PLEYEL" } ], "seatCategoryNames": { "338937235": "1ère catégorie", "338937236": "2ème catégorie", "338937238": "3ème catégorie", "338937239": "4ème catégorie", "338937240": "5ème catégorie", "338937241": "1ère catégorie", "338937242": "2ème catégorie", "338937244": "3ème catégorie", "338937245": "4ème catégorie", "338937246": "5ème catégorie", "338937271": "1ère catégorie", "338937272": "2ème catégorie", "338937274": "3ème catégorie", "338937275": "4ème catégorie", "338937277": "1ère catégorie", "338937278": "2ème catégorie", "338937280": "3ème catégorie", "338937281": "4ème catégorie", "338937282": "5ème catégorie", "338937283": "5ème catégorie", "338937284": "1ère catégorie", "338937285": "2ème catégorie", "338937287": "3ème catégorie", "338937288": "4ème catégorie", "338937289": "1ère catégorie", "338937290": "2ème catégorie", "338937292": "3ème catégorie", "338937293": "4ème catégorie", "338937294": "5ème catégorie", "338937295": "1ère catégorie", "338937296": "2ème catégorie", "338937307": "1ère catégorie", "338937308": "2ème catégorie", "338937310": "3ème catégorie", "338937311": "4ème catégorie", "338937312": "5ème catégorie", "338937314": "Catégorie unique", "339086196": "1ère catégorie", "339086197": "2ème catégorie", "339086210": "1ère catégorie", "339086211": "2ème catégorie", "339086213": "3ème catégorie", "339086214": "4ème catégorie", "339086215": "5ème catégorie", "340826015": "Catégorie 3", "340826016": "Catégorie 1", "340826017": "Catégorie 2", "340826018": "Catégorie 4", "340826019": "Catégorie 5", "341179212": "CAT1", "341179213": "CAT2", "341179214": "CAT3", "341179215": "CAT4", "341179216": "CAT5", "341264860": "1ère catégorie", "341264861": "2ème catégorie", "341264863": "3ème catégorie", "341264864": "4ème catégorie", "341264866": "1ère catégorie", "341264867": "2ème catégorie", "341264869": "3ème catégorie", "341264870": "4ème catégorie", "341264872": "1ère catégorie", "342752792": "catétgorie unique" }, "subTopicNames": { "337184262": "Musique amplifiée", "337184263": "Musique baroque", "337184267": "Ciné-concert", "337184268": "Musique classique", "337184269": "Jazz", "337184273": "Musique de chambre", "337184275": "Musique dirigée", "337184279": "Musique du monde", "337184280": "Pop/rock", "337184281": "Musique de chambre", "337184282": "Famille", "337184283": "Concert", "337184284": "Opéra (version de concert)", "337184288": "Musique contemporaine", "337184292": "Musique vocale", "337184296": "Musique ancienne", "337184297": "Chanson", "337184298": "Voix", "337184299": "famille" }, "subjectNames": {}, "topicNames": { "107888604": "Activité", "324846098": "Type de public", "324846099": "Genre", "324846100": "Formations musicales" }, "topicSubTopics": { "107888604": [ 337184283, 337184267 ], "324846098": [ 337184299 ], "324846099": [ 337184268, 337184288, 337184284, 337184263, 337184298, 337184269, 337184280, 337184297, 337184281, 337184296, 337184279 ], "324846100": [ 337184275, 337184262, 337184292, 337184273, 337184282 ] }, "venueNames": { "PLEYEL_PLEYEL": "Salle Pleyel" } }