Giter VIP home page Giter VIP logo

jackson-databind's Introduction

Overview

This project contains the general-purpose data-binding functionality and tree-model for Jackson Data Processor. It builds on Streaming API (stream parser/generator) package, and uses Jackson Annotations for configuration. Project is licensed under Apache License 2.0.

While the original use case for Jackson was JSON data-binding, it can now be used to read content encoded in 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.

Status

Type Status
Build (CI) Build (github)
Artifact Maven Central
OSS Sponsorship Tidelift
Javadocs Javadoc
Code coverage (2.18) codecov.io
OpenSSF Score OpenSSF  Scorecard

Get it!

Maven

Functionality of this package is contained in Java package com.fasterxml.jackson.databind, and can be used using following Maven dependency:

<properties>
  ...
  <!-- Use the latest version whenever possible. -->
  <jackson.version>2.17.1</jackson.version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
  </dependency>
  ...
</dependencies>

Package also depends on jackson-core and jackson-annotations packages, but when using build tools like Maven or Gradle, dependencies are automatically included. You may, however, want to use jackson-bom to ensure compatible versions of dependencies. If not using build tool that can handle dependencies using project's pom.xml, you will need to download and include these 2 jars explicitly.

Non-Maven dependency resolution

For use cases that do not automatically resolve dependencies from Maven repositories, you can still download jars from Central Maven repository.

Databind jar is also a functional OSGi bundle, with proper import/export declarations, so it can be use on OSGi container as is.

Jackson 2.10 and above include module-info.class definitions so the jar is also a proper Java Module (JPMS).

Jackson 2.12 and above include additional Gradle 6 Module Metadata for version alignment with Gradle.


Compatibility

JDK

Jackson-databind package baseline JDK requirements are as follows:

  • Versions 2.0 - 2.7 require JDK 6
  • Versions 2.8 - 2.12 require JDK 7 to run (but 2.11 - 2.12 require JDK 8 to build)
  • Versions 2.13 and above require JDK 8

Android

List is incomplete due to compatibility checker addition being done for Jackson 2.13.

  • 2.13: Android SDK 24+
  • 2.14: Android SDK 26+
  • 2.15: Android SDK 26+
  • 2.16: Android SDK 26+
  • 2.17: Android SDK 26+
  • 2.18: (planned) Android SDK 26+

for information on Android SDK versions to Android Release names see [https://en.wikipedia.org/wiki/Android_version_history]


Use It!

More comprehensive documentation can be found from Jackson-docs repository; as well as from 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:

// 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:

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:

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:

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 Lists, Maps:

Map<String, Integer> scoreByName = mapper.readValue(jsonSource, Map.class);
List<String> 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):

Map<String, ResultValue> results = mapper.readValue(jsonSource,
   new TypeReference<Map<String, ResultValue>>() { } );
// 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!

(enters Tree Model...)

Tree Model

While dealing with Maps, Lists and other "simple" Object types (Strings, Numbers, Booleans) can be simple, Object traversal can be cumbersome. This is where Jackson's Tree model can come in handy:

// 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:
JsonNode root = mapper.readTree("{ \"name\": \"Joe\", \"age\": 13 }");
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.withObject("/other").put("type", "student");
String json = mapper.writeValueAsString(root); // prints below

/*
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.

Finally, feel free to mix and match, and even in the same json document (useful when only part of the document is known and modeled in your code)

// Some parts of this json are modeled in our code, some are not
JsonNode root = mapper.readTree(complexJson);
Person p = mapper.treeToValue(root.get("person"), Person.class); // known single pojo
Map<String, Object> dynamicmetadata = mapper.treeToValue(root.get("dynamicmetadata"), Map.class); // unknown smallish subfield, convert all to collections
int singledeep = root.get("deep").get("large").get("hiearchy").get("important").intValue(); // single value in very deep optional subfield, ignoring the rest
int singledeeppath = root.at("/deep/large/hiearchy/important").intValue(); // json path
int singledeeppathunique = root.findValue("important").intValue(); // by unique field name

// Send an aggregate json from heterogenous sources
ObjectNode root = mapper.createObjectNode();
root.putPOJO("person", new Person("Joe")); // simple pojo
root.putPOJO("friends", List.of(new Person("Jane"), new Person("Jack"))); // generics
Map<String, Object> dynamicmetadata = Map.of("Some", "Metadata");
root.putPOJO("dynamicmetadata", dynamicmetadata);  // collections
root.putPOJO("dynamicmetadata", mapper.valueToTree(dynamicmetadata)); // same thing
root.set("dynamicmetadata", mapper.valueToTree(dynamicmetadata)); // same thing
root.withObject("deep").withObject("large").withObject("hiearchy").put("important", 42); // create as you go
root.withObject("/deep/large/hiearchy").put("important", 42); // json path
mapper.writeValueAsString(root);

Supported for Jackson 2.16+ versions

// generics
List<Person> friends = mapper.treeToValue(root.get("friends"), new TypeReference<List<Person>>() { });
// create as you go but without trying json path
root.withObjectProperty("deep").withObjectProperty("large").withObjectProperty("hiearchy").put("important", 42);

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. But let's look at a simple teaser to whet your appetite.

ObjectMapper mapper = ...;
// First: write simple JSON output
File jsonFile = new File("test.json");
// note: method added in Jackson 2.11 (earlier would need to use
// mapper.getFactory().createGenerator(...)
JsonGenerator g = f.createGenerator(jsonFile, JsonEncoding.UTF8);
// write JSON: { "message" : "Hello world!" }
g.writeStartObject();
g.writeStringField("message", "Hello world!");
g.writeEndObject();
g.close();

// Second: read file back
try (JsonParser p = mapper.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);
}

10 minute tutorial: configuration

There are two entry-level configuration mechanisms you are likely to use: Features and 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.

// 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:

// 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 page.

Annotations: changing property names

The simplest annotation-based approach is to use @JsonProperty annotation like so:

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, including use of "Naming Strategy" (via @JsonNaming annotation).

You can use Mix-in Annotations to associate any and all Jackson-provided annotations.

Annotations: Ignoring properties

There are two main annotations that can be used to ignore properties: @JsonIgnore for individual properties; and @JsonIgnoreProperties for per-class definition

// 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:

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" 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:

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.

Alternatively, you can also define "factory methods":

public class FactoryBean
{
    // fields etc omitted for brevity

    @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:

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 a couple of potentially useful use cases:

// Convert from List<Integer> to int[]
List<Integer> sourceList = ...;
int[] ints = mapper.convertValue(sourceList, int[].class);
// Convert a POJO into Map!
Map<String,Object> 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).

Tutorial: Builder design pattern + Jackson

The Builder design pattern is a creational design pattern and can be used to create complex objects step by step. If we have an object that needs multiple checks on other dependencies, In such cases, it is preferred to use builder design pattern.

Let's consider the person structure, which has some optional fields

public class Person {
    private final String name;
    private final Integer age;
 
    // getters
}

Letโ€™s see how we can employ its power in deserialization. First of all, letโ€™s declare a private all-arguments constructor, and a Builder class.

private Person(String name, Integer age) {
    this.name = name;
    this.age = age;
}
 
static class Builder {
    String name;
    Integer age;
    
    Builder withName(String name) {
        this.name = name;
        return this;
    }
    
    Builder withAge(Integer age) {
        this.age = age;
        return this;
    }
    
    public Person build() {
        return new Person(name, age);
    } 
}

First of all, we need to mark our class with @JsonDeserialize annotation, passing a builder parameter with a fully qualified domain name of a builder class. After that, we need to annotate the builder class itself as @JsonPOJOBuilder.

@JsonDeserialize(builder = Person.Builder.class)
public class Person {
    //...
    
    @JsonPOJOBuilder
    static class Builder {
        //...
    }
}

A simple unit test will be:

String json = "{\"name\":\"Hassan\",\"age\":23}";
Person person = new ObjectMapper().readValue(json, Person.class);
 
assertEquals("Hassan", person.getName());
assertEquals(23, person.getAge().intValue());

If your builder pattern implementation uses other prefixes for methods or uses other names than build() for the builder method Jackson also provide a handy way for you.

For example, if you have a builder class that uses the "set" prefix for its methods and use the create() method instead of build() for building the whole class, you have to annotate your class like:

@JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")
static class Builder {
    String name;
    Integer age;
    
    Builder setName(String name) {
        this.name = name;
        return this;
    }
    
    Builder setAge(Integer age) {
        this.age = age;
        return this;
    }
    
    public Person create() {
        return new Person(name, age);
    } 
}

To deserialize JSON fields under a different name than their object counterparts, the @JsonProperty annotation can be used within the builder on the appropriate fields.

@JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")
static class Builder {
    @JsonProperty("known_as")
    String name;
    Integer age;
    //...
}

This will deserialize the JSON property known_as into the builder field name. If a mapping like this is not provided (and further annotations aren't supplied to handle this), an Unrecognized field "known_as" exception will be thrown during deserialization if the field is provided anyways.

If you wish to refer to properties with more than one alias for deserialization, the @JsonAlias annotation can be used.

@JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")
static class Builder {
    @JsonProperty("known_as")
    @JsonAlias({"identifier", "first_name"})
    String name;
    Integer age;
    //...
}

This will deserialize JSON fields with known_as, as well as identifer and first_name into name. Rather than an array of entries, a single alias can be used by specifying a string as such JsonAlias("identifier").
Note: to use the @JsonAlias annotation, a @JsonProperty annotation must also be used.

Overall, Jackson library is very powerful in deserializing objects using builder pattern.

Contribute!

We would love to get your contribution, whether it's in form of bug reports, Requests for Enhancement (RFE), documentation, or code patches.

See CONTRIBUTING for details on things like:

  • Community, ways to interact (mailing lists, gitter)
  • Issue tracking (GitHub Issues)
  • Paperwork: CLA (just once before the first merged contribution)

Limitation on Dependencies by Core Components

One additional limitation exists for so-called core components (streaming api, jackson-annotations and jackson-databind): no additional dependencies are allowed beyond:

  • Core components may rely on any methods included in the supported JDK
    • Minimum Java version is Java 7 for Jackson 2.7 - 2.12 of jackson-databind and most non-core components
    • Minimum Java version is Java 8 for Jackson 2.13 and later
  • 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.

Branches

master branch is for developing the next major Jackson version -- 3.0 -- but there are active maintenance branches in which much of development happens:

  • 2.16 is the branch for "next" minor version to release (as of July 2023)
  • 2.15 is the current stable minor 2.x version
  • 2.14 is for selected backported fixes

Older branches are usually not maintained after being declared as closed on Jackson Releases page, but exist just in case a rare emergency patch is needed. All released versions have matching git tags (e.g. jackson-dataformats-binary-2.12.3).


Differences from Jackson 1.x

Project contains versions 2.0 and above: source code for last (1.x) release, 1.9, is available at Jackson-1 repo.

Main differences compared to 1.x "mapper" jar are:

  • Maven build instead of Ant
  • Java package is now com.fasterxml.jackson.databind (instead of org.codehaus.jackson.map)

Support

Community support

Jackson components are supported by the Jackson community through mailing lists, Gitter forum, Github issues. See Participation, Contributing for full details.

Enterprise support

Available as part of the Tidelift Subscription.

The maintainers of jackson-databind and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.


Further reading

Related:

jackson-databind's People

Contributors

airborn avatar benson-basis avatar bhamiltoncx avatar brenuart avatar carstenwickner avatar carterkozak avatar catanm avatar christophercurrie avatar cowtowncoder avatar dependabot[bot] avatar felixvaughan01 avatar fge avatar hgwood avatar iprodigy avatar jdmichal avatar joohyukkim avatar k163377 avatar kamil-benedykcinski avatar lokeshn avatar michaelhixson avatar msteiger avatar mukham12 avatar pjfanning avatar saurabh-shetty avatar swankjesse avatar tatu-at-salesforce avatar vjkoskela avatar yawkat avatar yihtserns avatar yinzara avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jackson-databind's Issues

Why is @JsonTypeResolver separate from @JsonTypeInfo ?

It seems in JacksonAnnotationIntrospector that @JsonTypeResolver cannot exist without @JsonTypeInfo

protected TypeResolverBuilder<?> _findTypeResolver(MapperConfig<?> config,
            Annotated ann, JavaType baseType)
    {
...
JsonTypeInfo info = ann.getAnnotation(JsonTypeInfo.class);
JsonTypeResolver resAnn = ann.getAnnotation(JsonTypeResolver.class);
if (resAnn != null) {
            if (info == null) {
                return null;
            }

Unless I misunderstood this, I think it is unnecessary and confusing.

Allow serialization of Enums as JSON Objects

Hi,

Any way to treat enums as pojos when serializing them as json? Right now i have to implement yet another class to do the mapping for each enum. Was looking for a jsonmapper.writeValueasString(enum.values()) type of solution...

No such support, except for custom serializers.

So far I hadn't thought it useful to treat enums as POJOs (wrt
serializing properties), mostly because deserialization would be hard
to make work right. But now that I think about it, serialization-only
use case may make some sense.

There is actually even an annotation that could be used to define
this: @jsonformat.
Maybe something like:

@jsonformat(shape=Shape.OBJECT)
public enum MyEnum { .... }

so that all that is needed is... well, checking that annotation,
constructing BeanSerializer.

If this would work, can you add a github issue for this? It is in fact
kind of use case for which this annotation was added (currently only
used for configuring Date/Time types in 2.0)

-+ Tatu +-

Change OSGi bundle name to be fully-qualified

(also: use 'oss-parent' parent pom to simplify pom.xml)

Currently (2.0), OSGi bundle name is artifact id, but standard suggests use of fully-qualified (group and artifact id) name instead.
We can do this for 2.1.

ValueInstantiator and property-based creation cannot co-exist

This is a follow-up to the mailing list discussion at: http://markmail.org/thread/g7he2ktbpz4oumtc

Currently, it seems to be impossible to use a ValueInstantiator and property-based creation for the same class if registering the ValueInstantiator via a SimpleModule's addValueInstantiator method as the ValueInstantiator's configureFromObjectSettings method never gets called (it gets called for the default ValueInstantiator before it gets replaced, though).

In the end this results in the following exception as the ValueInstantiator is lacking the defaultCreator required for properety-based creation:

com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.example.model.Cluster]: can not instantiate from JSON object (need to add/enable type information?) at [Source: org.apache.catalina.connector.CoyoteInputStream@2c0bdfc; line: 1, column: 2]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:163)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObjectUsingNonDefault(BeanDeserializer.java:381)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:271)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:112)
    at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:900)
    at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:471)
    at com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:443)
    at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:474)
    at com.sun.jersey.server.impl.model.method.dispatch.EntityParamDispatchProvider$EntityInjectable.getValue(EntityParamDispatchProvider.java:123)
    at com.sun.jersey.server.impl.inject.InjectableValuesProvider.getInjectableValues(InjectableValuesProvider.java:46)
    at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$EntityParamInInvoker.getParams(AbstractResourceMethodDispatchProvider.java:153)
    at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:183)
    at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
    at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288)
    at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
    at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1483)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1414)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1363)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1353)
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:414)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:708)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    [...]

As a workaround, one can expose the StdValueInstantiators's copy constructor (both *ValueInstantiator classes in the code sample below are derived from StdValueInstantiators) to retrieve the pre-configured defaultCreator from within a BeanDeserializerModifier, but this involves some ugly type-casting:

    @Override
    public void setupModule(SetupContext context) {
        context.addBeanDeserializerModifier(new BeanDeserializerModifier() {
            @Override
            public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) {
                if (beanDesc.getBeanClass() == Cluster.class)
                    builder.setValueInstantiator(new ClusterValueInstantiator((StdValueInstantiator) builder.getValueInstantiator(), clusterService));
                else if (beanDesc.getBeanClass() == Node.class)
                    builder.setValueInstantiator(new NodeValueInstantiator((StdValueInstantiator) builder.getValueInstantiator(), nodeService));
                return super.updateBuilder(config, beanDesc, builder);
            }
        });

        super.setupModule(context);
    }

A more elegant solution that can be used within SimpleModule without the use of a BeanDeserializerModifier would be welcome.

Type Autodection via ObjectReader

jackson has a nice ability to sniff the datataype it is looking at, but it is cumbersome to use this. I'd really like soemthign like:

  new ObjectMapper(new AutoDetectingJsonFactory(new JsonFactory(), new YAMLFactory()));

Yeah, that'd rock.

Problem with JsonFilter on 2.0

(from jackson-users.ning.com, buy Nir Shemy, see [jackson-users.ning.com/forum/topics/problems-using-filterprovider-with-jackson-2-0])

I followed the wiki example using Jackson 2.0 and wrote the following code:

ObjectMapper mapper = new ObjectMapper();


// first, construct filter provider to exclude all properties but 'name', bind it as 'myFilter'
FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept("name"));


// and then serialize using that filter provider:
String json = mapper.writer(filters).writeValueAsString(new Object() {
  public String name = "a";
  public int num = 2;
});


System.out.println(json);

I had to change "filterWriter(filters)" to "writer(filters)" due to API change from Jackson 1.* to 2.0.

The output I get is:

{"name":"a","num":2}

I expected to get:

{"name":"a"}

without the "num" property.

What am I missing here? Do I use it wrong?

I used FilterProvider in Jackson 1.* and it seemed to work as expected.

Add 'JsonNode.hasNonNull()' method

Since 'JsonNode.has(...)' will return 'true' for NullNodes (nulls added explictly), it will not work for many cases where users would expect it to. At the risk of ballooning Tree Model API even more, I suggest adding methods:

boolean hasNonNull(String fieldName)
boolean hasNonNull(int index)

methods that will only return true if property/element has a value that is not an explicit null.

Support @JsonValue for key serialization

Currently Map key types support a subset of annotations, such as:

  • JsonSerialize and JsonDeserialize properties keyAs and keyUsing work
  • @JsonCreator works for indicating single-String-arg constructors, factory methods

But one annotation that would seem like an obvious addition, @JsonValue, is not yet supported.
It should.

Allow serializing, deserializing POJOs as JSON Arrays

It would be nice to be able to serialize POJOs in "tabular" format, not unlike done with formats like CSV, as JSON Arrays where order indicates which property maps to/from which array element.
Use of such 'style' can be indicated by:

  • Locally on per-property basis using @JsonFormat.shape=ARRAY
  • As default style for types using same annotation on class(es)
  • Possibly allow defaulting to this representation with a new feature.

Excepted benefits are reduced size (more compact serialization) as well as performance improvements.

@JsonProperty declares "value" as optional but for constructor arguments it is obligatory

Javadoc for @JsonProperty says "Default value ("") indicates that the field name is used as the property name without any modifications", however for POJO with initializing constructor

public class MyBean {
    @JsonCreator
    public MyBean(@JsonProperty URL url, @JsonProperty String comment) {
        ...
    }
}

the following exception is thrown:

com.fasterxml.jackson.databind.JsonMappingException: Argument #0 of constructor [constructor for ..., annotations: {interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator()}] has no property name annotation; must have name when multiple-paramater constructor annotated as Creator
    at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._addDeserializerConstructors(BasicDeserializerFactory.java:450)
    at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:352)
    at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:293)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:260)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:168)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:363)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:247)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:252)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:227)
    at com.fasterxml.jackson.databind.deser.DeserializerCache.hasValueDeserializerFor(DeserializerCache.java:174)
    at com.fasterxml.jackson.databind.DeserializationContext.hasValueDeserializerFor(DeserializationContext.java:302)
    at com.fasterxml.jackson.databind.ObjectMapper.canDeserialize(ObjectMapper.java:1747)
    at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.canRead(MappingJackson2HttpMessageConverter.java:103)

The name of the argument can be resolved by looking at constructor signature (this should be applied to BasicDeserializerFactory._addDeserializerConstructors(), line 428).

Also above exception was suppressed in DeserializerCache.hasValueDeserializerFor(), line 176. Exception should be logged with WARN error level.

Workaround: @JsonCreator public MyBean(@JsonProperty("url") URL url, @JsonProperty("comment") String comment).

Jackson version: 2.0.5.

Map serialization should expose the mapping of any Map.Entry

I want to serialize a map as an array of { key: $KEY, value: $VALUE} objects, but currently mapSerializer has entry serialization possibly called from different places. I think better would be to orient around the serialization of a Map.Entry, or at least to encapsulate the entry parsing in a common method.

For 2.1: add 'createParser', 'createGenerator' methods in factory

One naming change that should have gone in 2.0, but was sadly forgotten is that of making JsonFactory's factory methods more generic. There is no need to emphasize "json" in methods to begin with; and with 2.0, there are many non-JSON backends, so this is becoming bit of an eyesore.

So, with 2.1, we should add methods:

  • JsonFactory.createParser(...) to replace 'creteJsonParser(...) methods
  • JsonFactory.createGenerator(...) to replace 'createJsonGenerator(...) methods

and deprecate old variants. We will not be able to remove the old methods until 3.0 (if ever), but while this is bit of nuisance, I think readability of sample code will improve. Too bad we didn't do this for 2.0 to eliminate the issue, but better late than never.

ObjectMapper.setPropertyNamingStrategy() doesn't have any effect when parsing JSON

In v2.0.5 from Maven, I'm having problems using the PropertyNamingStrategy when trying to parse JSON and bind it to a set of POJOs. The property names in the JSON I'm parsing are in PascalCase (i.e., first letter capitalized), and I want to use the PropertyNamingStrategy to systematically change the first letter to lowercase (i.e., to camelCase).

When I set the ObjectMapper with the class extending the PropertyNamingStrategyBase, it doesn't seem to have any effect on the parsing, and I still get the same error as when I'm not using the PropertyNamingStrategyBase:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "ServiceDelivery" (class uk.org.siri.siri.Siri)

Here's my class extending PropertyNamingStrategyBase:

public class PascalCaseStrategy extends PropertyNamingStrategyBase {

/**
 * Converts PascalCase to camelCase
 * 
 * For example, "ResponseTimestamp" would be converted to
 * "responseTimestamp".
 * 
 * @param input PascalCase string
 * @return input converted to camelCase
 */
@Override
public String translate(String input) {
    // Replace first capital letter with lower-case equivalent
    return input.substring(0, 1).toLowerCase() + input.substring(1);
}   

}

And my code to parse the JSON from a file (the file path is passed in via argument in main):

public static void main(String[] args) {

    //Get JSON example from file
    try {                   
        File file = new File(args[0]);
                    ObjectMapper mapper = new ObjectMapper();
                    mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);   
                    mapper.setPropertyNamingStrategy(new PascalCaseStrategy());
                    Siri siri = mapper.readValue(file, Siri.class);

            } catch (IOException e) {
        System.err.println("Error reading JSON input file" + e);
    }

Here's the JSON file I'm using:
https://docs.google.com/open?id=0B8oU647elPShbHVlZzlOdVUxSVU

I can provide the POJO classes if needed.

Thanks,
Sean

Allow setting different Base64Variants

It is currently not possible to set different Base64Variants when using the ObjectMapper because the default variant is hard-coded into DeserializationConfig.getBase64Variant() which calls Base64Variants.getDefaultVariant(). For serialization even the SerializationConfig does not provide a way to set a custom Base64Variant.

Support De/Serialize Collection as json object

see the following for the original comments: http://jackson-users.ning.com/forum/topics/issue-when-implementing-collection-on-grid-object-using-jackson?commentId=5286555%3AComment%3A23488&xg_source=msg_com_forum

The idea is to allow a Collection to be handled as a pojo, instead of some form of array/list. The use case is an implementation of Collection that is done as a tree node. Serialized currently, this gives a dfs representation as an array. It would be nice to be able to indicate that this should be serialized as it's properties (pojo style). This would allow for a nested json object structure that matches the collection's tree structure.

Support polymorphism on schema generation

It would be nice to support polymorphism on schema generation.
Currently, the generated schema doesn't provides information on subtypes with the above case .

@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@type(value = subtypeA.class, name = "A"),
@type(value = subtypeB.class, name = "B"),
@type(value = subtypeC.class, name = "C")
})
public abstract class ParentType {
}

Add PropertyNamingStrategy subclass supporting PascalCase

Jackson should be able to parse JSON in PascalCase, where the JSON element names have a capital first letter (e.g., UserName) instead of the normal Java camelCase convention where the first letter is lower-case (e.g., userName.

Add a "freezeConfiguration()" method to ObjectMapper

A "freezeConfiguration()" method in ObjectMapper would be useful for cases where you want to share a common ObjectMapper amongst many classes but want to make sure that its configuration will not be changed after creation. Any call to change the configuration could throw an IllegalStateException.

Runtime error passing multiple injected values to a constructor marked as JsonCreator

I have a scenario where I am marking a class's public constructor with @JsonCreator, and want to pass multiple injected values as constructor parameters. The reason for passing the items in via the constructor is that I want the constructors for creating objects 'by hand', so intended using them for that and for Jackson to use.

However, Jackson complains (within com.fasterxml.jackson.databind.deser.impl.CreatorCollector.addPropertyCreator) that there are duplicate creator properties because there are multiple unnamed properties (the injectable values) passed to the constructor. I've looked at the documentation and the databind tests, and there's no mention of a requirement that a Json property name be linked to an injectable value, so this would seem to be a bug?

Code is attached that reproduces what I see - the creation of CtorBean in the attached code. One workaround I've found is to annotate the injected value with a JsonProperty annotation - see Ctorbean2 in the attached code.

import com.fasterxml.jackson.annotation.JacksonInject;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.ObjectMapper;


public class test2 {
    static class CtorBean {
        public Long heightInCm;
        public String name;
        public int age;

        @JsonCreator
        public CtorBean(
                @JacksonInject("name") String n, 
                @JsonProperty("age") int a,
                @JacksonInject("height") Long l)
        {
            name = n;
            age = a;
            heightInCm = l;
        }
    }

    static class CtorBean2 {
        public Long heightInCm;
        public String name;
        public int age;

        @JsonCreator
        public CtorBean2(
                @JacksonInject("name") @JsonProperty("name") String n, 
                @JsonProperty("age") int a,
                @JacksonInject("height") @JsonProperty("height") Long l)
        {
            name = n;
            age = a;
            heightInCm = l;
        }
    }

    private static ObjectMapper mapper;

    public static void main(String[] args) {
        mapper = new ObjectMapper(); // create once, reuse
        try {
            InjectableValues injectableValues = new InjectableValues.Std()
            .addValue("name", "test")
            .addValue("height", 200L);

            // This one succeeds
            CtorBean2 item2 = 
                mapper.reader(new TypeReference<CtorBean2>() {})
                .with(injectableValues)
                .readValue("{ \"age\" : 123 }");
            System.out.println(item2.toString());

            // This one fails with a JsonMappingException
            CtorBean item = 
                mapper.reader(new TypeReference<CtorBean>() {})
                .with(injectableValues)
                .readValue("{ \"age\" : 123 }");
            System.out.println(item.toString());
        }
        catch (Exception e) {
            System.out.println("Caught exception..." + e.toString());
        }
    }
}

Add ObjectWriter.withDeclaredType() method

Currently ObjectWriter.withType() method forces specific type to be used both as full type for choosing serializer and equivalent of declared (static) type needed for determining polymorphic type handling. This makes it difficult to properly indicate generic typing; or force type information for things that need to be considered java.lang.Object for "default" typing.

To resolve this problem, we probably need a separate setting that will only affect type serialization aspect, and not value serialization.

Make ObjectReader/ObjectWriter pre-fetch root (de)serializer

From performance perspective it would make sense that ObjectReader and ObjectWriter would pre-fetch root-level serializer/deserializer, if they have enough information to do so. This could improve performance slightly, depending on relative cost of lookup.

Add support for per-class annotatable naming strategy?

(suggested by Mark Wolfe)


It would be nice to be able to indicate naming strategy to use on per-POJO basis, by using hypothetical annotation like:

@JsonNaming(SnakeCaseStrategy.class)
public class MyClass { ... }

(where SnakeCaseStrategy would implement PropertyNamingStrategy)

Improve @JsonView flexibility

I'm struggling with a problem that is probably common for people that extensively use @JSONVIEW. Since only one view can be active at any one time, and jsonview classes are singly-inherited, the facility is very tightly constrained. There are a lot of cases where I need to define multiple views: "Show me the properties relevant to green administrators and the fields relevant to blue administrators", where these are not perfect subsets.

From an API perspective, one solution would be to allow json views to be defined by interfaces and thus enable multiple inheritance. Alternatively, just allow multiple views to be specified - although this raises the question of AND vs OR.

This has been moved from FasterXML/jackson-core#3

asText(): NullNode vs. MissingNode

scala> MissingNode.getInstance().asText()
res12: java.lang.String = ""

scala> NullNode.instance.asText()
res13: java.lang.String = null

Is it expected that MissingNode returns ""?

Inconsistencies between ObjectMapper#writeValue(File/Writer/OutputStream, Object) variants and #writeValue(JsonGenerator, Object) variant

The following methods:
ObjectMapper#writeValue(OutputStream, Object)
ObjectMapper#writeValue(File, Object)
ObjectMapper#writeValue(Writer, Object)
ObjectMapper#writeValueAsString(Object)
ObjectMapper#writeValueAsBytes(Object)

all call _configAndWriteValue(JsonGenerator jgen, Object value) internally. This internal method applies several "Features" such as pretty printing and closeable support that are configurable at the root ObjectMapper level via ObjectMapper#configure(...).

Unfortunately, when calling:
ObjectMapper#writeValue(JsonGenerator, Object)

.... which is necessary when supporting the different JsonEncoding options, _configAndWriteValue is NOT called and any configured ObjectMapper features such as pretty printing are not applied.

This may be by design, but it is somewhat confusing since I used the ObjectMapper to get the JsonFactory that constructed the JsonGenerator. Given that, I expect when I set the following option:

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);

... that JsonGenerators created by the ObjectMapper would have the feature applied. I agree it should be possible to override a custom JsonGenerator's properties externally, but I would still expect the initial values to match what was configured on the root ObjectMapper.

You can see this causing some confusion in a Spring MVC context here:
http://stackoverflow.com/questions/6541757/when-using-spring-mvc-for-rest-how-do-you-enable-jackson-to-pretty-print-render

Divergence between JacksonV1 and JacksonV2 about Root Name (especially for Lists)

I migrated my project to jackson 1.9.9 to jackson 2.0.5

before i expected for a list, something like that.

{ "myObjectBean" : [ {-myObjectBean-}, {-myObjectBean-} ] }

after migrating, i had

[ {-myObjectBean-}, {-myObjectBean-} ]

so i added com.fasterxml.jackson.databind.SerializationFeature.WRAP_ROOT_VALUE

and now, i have

{ "ArrayList" : [ {-myObjectBean-}, {-myObjectBean} ] }

i look the source code, and unfortunately i can't change "ArrayList" to "myObjectBean".

Obviously, "ArrayList" is a wrong name ... my function returns a List of MyObjectBean.

Please provide a way to clone an ObjectMapper

We need a way to clone an ObjectMapper. The user case is:
At some times we need a ObjectMapper which has a slightly different configuration that the one that we use though the system.

In Jackson 1.9.1 we did this by
ObjectMapper o1= new ObjectMapper()
.setSerializationConfig(objectMapper.getSerializationConfig()
.with(SerializationConfig.Feature.INDENT_OUTPUT));

I couldn't find a way to reproduce this in Jackson 2.

We cannot use ObjectReader/ObjectWriter for this, since we use both databinding and the TreeModel and ObjectWriter doesn't have support for TreeModel.

Serialization should occur in a serializer not a SimpleBeanPropertyFilter

It seems that BeanPropertyFilter.serializeAsField is only ever called in BeanSerializerBase(555) and serialization is delegated to the filter. I suggest that the beanserializer should only consult the filter for whether the property is block or permitted, and let the serialization remain in the serializer.
I want to reuse filtering in getSchema in BeanSerializerBase because I have a deeply nested object hierarchy(which currently yields a stack overflow when I call getSchema), but my effective json schema is really determined by the filters I apply. So, I need to decouple filtering from field serialization.

Consider adding support for binding data from Form parameters

(and perhaps query params as well)

One potential starting point is code contribution by a Restlet collaborator:

http://tembrel.blogspot.fr/2012/03/converting-forms-in-restlet-to-pojos.html

One limiting factor is the form of input, that is, is there some standard input object that we could assume as the base.
If not, needs to be a module to contain external dependency; and possibly even either multiple modules, or just multiple dependencies, depending on details. For example, deps to J2EE APIs are simpler to deal with than deps to frameworks.

RFE: convertValue() could check for simple casts?

As a minor improvement, convertValue() could see if simple cast suffices; that is, can just return input value as is.
A user pointed out the (s)he expected this behavior; and it seems reasonable enough, possibly simplifying some use cases.

ObjectReader.readValues() confusing wrt whether START_ARRAY is skipped or not

With Jackson 1.9 and 2.0, behavior of ObjectReader.readValues() (and ObjectMapper.readValues()) is confusing, with respect to handling of case whether JsonParser points to START_ARRAY. While heuristics were added to try to support the common case, they are not well documented or necessarily even defined.

So, for 2.1, we should simplify behavior and use a two-part definition:

  • For cases where JsonParser is passed as argument, no skipping is done: parser MUST either point to the first token of the first element; or not point to any token (in which case JsonParser.nextToken() will be called to point to the first token of the first element). Value of token parser points to has no effect on behavior.
  • For cases where JsonParser is constructed by ObjectReader, type of the first token (of the document) is checked: if it is START_ARRAY, token will be skipped assuming that sequence is wrapped in a JSON array, and the token following is assumed to be the first token of the first element.

The benefits of this definition over earlier (2.0) functioning are:

  • Allows binding of all kinds of wrapped/unwrapped sequences, regardless of JSON structures of individual elements, and their mapping to Java types.
  • Simple definition; no auto-magical determination

The main downside is that functionality will not be 100% backwards compatible; this is unfortunate, but given that the definition of behavior earlier was not fully documented, earlier functioning can not be considered as correct (that is: this is a bug fix; defining formerly unspecific behavior).

Exception serializing JDK Dynamic Proxy

As discussed on stackoverflow board http://stackoverflow.com/questions/12112564/json-serializing-jdk-dynamic-proxy-with-jackson-library seems that Jackson not properly handles the serialization of a proxied objects treating them as normal beans:

public interface IPlanet {
    String getName();
}

Planet implements IPlanet {
    private String name;
    public String getName(){return name;}
    public String setName(String iName){name = iName;}
}

...
IPlanet ip = ObjectsUtil.getProxy(IPlanet.class, p);
ObjectMapper mapper = new ObjectMapper();
mapper.writeValueAsString(ip);

The proxy generation utility is implemented in this way:

/**
 * Create new proxy object that give the access only to the method of the specified
 * interface.
 * 
 * @param type
 * @param obj
 * @return
 */
public static <T> T getProxy(Class<T> 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;
        }
    }
    // TODO: The suppress warning is needed cause JDK class java.lang.reflect.Proxy
    // needs generics
    @SuppressWarnings("unchecked")
    T proxy = (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type },
            new ProxyUtil(obj));
    return proxy;
}

Tryng to serialize the resulting exception is

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class $Proxy11 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.SerializationFeature.FAIL_ON_EMPTY_BEANS) )

MixIn inheritance fails.

Given:

@JsonAutoDetect(fieldVisibility = Visibility.ANY) 
public interface CommonFilter {
   @JsonView(Unrestricted.class)
   @JsonProperty
   Long getId();

   @JsonView(Unrestricted.class)
   @JsonProperty
   String getName();
}

@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public interface SomeFilter extends CommonFilter {
   @JsonView(Unrestricted.class)
   @JsonProperty
   String getSomeField();
} 

...
mapper.addMixInAnnotations(SomeClass.class, SomeFilter.class);
...
mapper.writerWithView(Unrestricted.class).withDefaultPrettyPrinter();
...
writer.writeValueAsString(...)

This doesn't write id and name, just someField.

Provide getters for some protected properties (improvement)

Not so important, but still it would be nice to have some public getters to be able to retrieve current factory configurations:

SerializerFactory ObjectMapper.getSerializerFactory() { return _serializerFactory; }
DefaultDeserializationContext ObjectMapper.getDeserializationContext() { return _deserializationContext; }

SerializerFactoryConfig BasicSerializerFactory.getFactoryConfig { return _factoryConfig; }
DeserializerFactoryConfig BasicDeserializerFactory.getFactoryConfig() { return _factoryConfig; }

Deprecate com.fasterxml.jackson.databind.jsonschema

Deprecate com.fasterxml.jackson.databind.jsonschema along with:
the generateJsonSchema method in objectmapper and defaultserializerprovider,
methods which create nodes in stdserializer,
and potentially deprecate getSchema in a lot of serializers

Allow access and manipulation of json schema as a schema type

I tentatively added a schema type with a hierarchy of subtypes that outline, as well as I could interpret it, the json schema draft. I'll make a pull request so that you can see the changes.
I'm not sure what the smartest way to go connect a schema java type to json and the java it represents.

Add new mapping exception type for format exceptions

Referencing this thread:
http://jackson-users.ning.com/forum/topics/avoid-exposing-implementation-details-in-jsonmappingexeption

Here's the situation:

A user gives my application JSON w/ an improperly formatted Date string. This generates an IllegalArgumentException in DateTime, which is then wrapped in a JsonMappingException with a message like the following:

Invalid format: "badDateString" (through reference chain: com.example.MyPojo["date"]).

I'd like to provide the user an informative error message that gives some idea of the cause, however I don't want to expose the internal details of my POJO. There doesn't seem to be a good way to do this currently.

It would be ideal if Jackson provided additional subclasses of JsonMappingException (as has been done with UnrecognizedPropertyException) that could provide additional contextual details that would allow the exception to be better handled and reported. (E.g. it can be difficult to determine if the exception is the result of unexpected JSON or JSON->POJO coding errors).

Thanks!

Handle possible security problem with ObjectNode, HashMap, String.hashCode()

(see [https://github.com/FasterXML/jackson-core/issues/21] for related problem)

Given that it is easy to fabricate collisions for String.hashCode() (since JDK's impl allows substring-replacement style attacks very easily), ObjectNode is prone to attacks.
Since JsonParser use has been fixed (Issue-21), it is necessary to simialrly address the issue of use of HashMap with default String hashCode().

The big problem here is the performance: not so much that of cost of calculating hashCode() alone, but lack of caching of that value (JDK aggressively caches hashCode on first access).

We should probably do similar two-part solution here as earlier: make it possible to detect abnormal (super high collision list) cases and error out; but also improve hash code used as much as possible.

JSON schema generation with Jackson goes into infinite loop

It might be that I'm missing an obvious annotation in Jackson but I have following class

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.jsonschema.JsonSchema;

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class Loop {

  private String name;
  private Loop otherLoop;

  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  public Loop getOtherLoop() { return otherLoop; }
  public void setOtherLoop(Loop otherLoop) { this.otherLoop = otherLoop; }

  public static void main(String[] args) throws Exception {
    Loop parent = new Loop();
    parent.setName("parent");

    Loop child = new Loop();
    child.setName("child");
    child.setOtherLoop(parent);

    ObjectMapper mapper = new ObjectMapper();
    System.out.println(mapper.writeValueAsString(child));

    JsonSchema jsonSchema = mapper.generateJsonSchema(Loop.class);
    System.out.println(mapper.writeValueAsString(jsonSchema));
  }
}

and when I run it using Jackson 2 it goes into an infinite loop

{"name":"child","otherLoop":{"name":"parent"}}
Exception in thread "main" java.lang.StackOverflowError
at com.fasterxml.jackson.databind.cfg.MapperConfig.isEnabled(MapperConfig.java:106)
at com.fasterxml.jackson.databind.SerializationConfig.getAnnotationIntrospector(SerializationConfig.java:382)
at com.fasterxml.jackson.databind.SerializerProvider.getAnnotationIntrospector(SerializerProvider.java:307)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.createContextual(BeanSerializerBase.java:318)
at com.fasterxml.jackson.databind.SerializerProvider._handleContextual(SerializerProvider.java:971)
at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:447)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:619)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:621)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:621)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:621)

Any ideas, workarounds?!

Issue with JsonTypeInfo and Lists

When I try and serialize a list of objects that have JsonTypeInfo defined, the objects in the list do not have the JsonTypeInfo property set. I am having problems with this against both 1.9.4 and 2.0.2, if there is a way to do this that I missed in the documentation, please let me know.

diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestAbstractTypeNames.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestAbstractTypeNames.java
index 5a257a1..57213b4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestAbstractTypeNames.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestAbstractTypeNames.java
@@ -9,6 +9,8 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;

 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;

 /**
  * Unit tests for checking how combination of interfaces, implementation
@@ -93,6 +95,21 @@ public class TestAbstractTypeNames  extends BaseMapTest
     /**********************************************************
      */

+    public void testCollection() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        List<DefaultEmployee> friends = new ArrayList<DefaultEmployee>();
+        friends.add(new DefaultEmployee("Joe Hildebrandt", null, "MDA"));
+
+        String singleObject = mapper.writeValueAsString(friends.get(0));
+        ObjectNode output = mapper.readValue(singleObject, ObjectNode.class);
+        assertEquals("Employee", output.get("userType").asText());
+
+        String list = mapper.writeValueAsString(friends);
+        ArrayNode listOutput = mapper.readValue(list, ArrayNode.class);
+        assertNotNull("Expected " + listOutput.get(0) + " to include userType", listOutput.get(0).get("userType"));
+    }
+
     // Testing [JACKSON-498], partial fix
     public void testEmptyCollection() throws Exception
     {

Serialization of root primitive objects causes invalid JSON

When Jackson serializer is passed a wrapped primitive for serialization, this primitive is serialized as is, for example:

objectMapper = new ObjectMapper();

StringWriter w = new StringWriter();
objectMapper.writeValue(w, Integer.valueOf(10));
System.out.println(w.toString());

produces 10 as output. However 10 is not a valid JSON (according to jsonlint) and should be wrapped either in square brackets (i.e. [10], so it will be a single-element array) or in curly brackets (i.e. {value:10}, so it will be an object with dummy property). The problem affects numbers, java.lang.String, java.util.Date, ...

The problem is originally posted to stackoverflow.

Add 'ObjectNode.set(String,JsonNode)' for consistent entry manipulation semantics for ObjectNode

As discussed on the users group (http://jackson-users.ning.com/forum/topics/method-chaining-is-this-by-design): JsonNode has many .put() methods on ObjectNode, but their behaviour is inconsistent. On a given ObjectNode:

  • .put("somekey", any(JsonNode.class)) will return the old value for key "somekey" if any, null otherwise;
  • .put("somekey", anythingBut(JsonNode.class)) will return the ObjectNode being manipulated.

Quoting:

It is by design, in the sense that original idea was to model the way java.util.Map works; but then later additions > (adding Java values, not JsonNode) chose to instead return ObjectNode to allow chaining.

Later on in the thread, it was acknowledged that allowing chaining was a better model on the whole, but that changing .put() behavior was too late for 2.x; and that another set of methods could possibly be added for 2.1.x.

Note: I haven't looked at ArrayNode, maybe it could do with something like this too.

Proposal (for ObjectNode): .addMember()/.removeMember(), or maybe .withMember()/.withoutMember(), with the consistent behavior throughout that they return the manipulated ObjectNode; and for 3.x, mark these as deprecated and unify .put() behavior, since it is a better name anyway, to allow chaining.

There is also the question of .remove(), though.

Add option to resolve type from multiple existing properties (`@JsonTypeInfo(use=DEDUCTION)`)

Rather than forcing the creation of an additional typeId property, or class info, determine the type by its natural properties. Possible As.EXISTING_PROPERTIES, and register a TypeResolver that returns the JavaType by inspecting the object.

Given a type hierarchy, naturally subtypes have additional fields and their type can likely be determined simply by inspecting the fields.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.