Git Product home page Git Product logo

jackson-module-kotlin's Introduction

Kotlin Kotlin Slack

Overview

Module that adds support for serialization/deserialization of Kotlin classes and data classes. Previously a default constructor must have existed on the Kotlin object for Jackson to deserialize into the object. With this module, single constructor classes can be used automatically, and those with secondary constructors or static factories are also supported.

Status

  • release 2.17.0 (for Jackson 2.17.x) GitHub Actions build
  • release 2.16.2 (for Jackson 2.16.x) GitHub Actions build
  • release 2.15.3 (for Jackson 2.15.x) GitHub Actions build
  • release 2.14.3 (for Jackson 2.14.x) GitHub Actions build

Releases require that you have included Kotlin stdlib and reflect libraries already.

Gradle:

implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.17.+"

Maven:

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-kotlin</artifactId>
    <version>2.17.0</version>
</dependency>

Usage

For any Kotlin class or data class constructor, the JSON property names will be inferred from the parameters using Kotlin runtime type information.

To use, just register the Kotlin module with your ObjectMapper instance:

// With Jackson 2.12 and later
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
...
val mapper = jacksonObjectMapper()
// or
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
...
val mapper = ObjectMapper().registerKotlinModule()
// or
import com.fasterxml.jackson.module.kotlin.jsonMapper
import com.fasterxml.jackson.module.kotlin.kotlinModule
...
val mapper = jsonMapper {
  addModule(kotlinModule())
}

In 2.17 and later, the jacksonObjectMapper {} and registerKotlinModule {} lambdas allow configuration for KotlinModule.
See #Configuration for details on the available configuration items.

A simple data class example:

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue

data class MyStateObject(val name: String, val age: Int)

...
val mapper = jacksonObjectMapper()

val state = mapper.readValue<MyStateObject>(json)
// or
val state: MyStateObject = mapper.readValue(json)
// or
myMemberWithType = mapper.readValue(json)

All inferred types for the extension functions carry in full generic information (reified generics). Therefore, using readValue() extension without the Class parameter will reify the type and automatically create a TypeReference for Jackson.

Also, there are some convenient operator overloading extension functions for JsonNode inheritors.

import com.fasterxml.jackson.databind.node.ArrayNode
import com.fasterxml.jackson.databind.node.ObjectNode
import com.fasterxml.jackson.databind.node.JsonNodeFactory
import com.fasterxml.jackson.module.kotlin.*

// ...
val objectNode: ObjectNode = JsonNodeFactory.instance.objectNode()
objectNode.put("foo1", "bar").put("foo2", "baz").put("foo3", "bax")
objectNode -= "foo1"
objectNode -= listOf("foo2")
println(objectNode.toString()) // {"foo3":"bax"}

// ...
val arrayNode: ArrayNode = JsonNodeFactory.instance.arrayNode()
arrayNode += "foo"
arrayNode += true
arrayNode += 1
arrayNode += 1.0
arrayNode += "bar".toByteArray()
println(arrayNode.toString()) // ["foo",true,1,1.0,"YmFy"]

Compatibility

Kotlin

(NOTE: incomplete! Please submit corrections/additions via PRs!)

Different kotlin-core versions are supported by different Jackson Kotlin module minor versions. Here is an incomplete list of supported versions:

  • Jackson 2.17.x: Kotlin-core 1.7 - 2.0
  • Jackson 2.16.x: Kotlin-core 1.6 - 1.9
  • Jackson 2.15.x: Kotlin-core 1.5 - 1.8
  • Jackson 2.14.x: Kotlin-core 1.4 - 1.8
  • Jackson 2.13.x: Kotlin-core 1.4 - 1.7

Please note that the versions supported by 2.17 are tentative and may change depending on the release date.

Android

Supported Android SDK versions are determined by jackson-databind. Please see this link for details.

Annotations

You can intermix non-field values in the constructor and JsonProperty annotation in the constructor. Any fields not present in the constructor will be set after the constructor call. An example of these concepts:

   @JsonInclude(JsonInclude.Include.NON_EMPTY)
   class StateObjectWithPartialFieldsInConstructor(val name: String, @JsonProperty("age") val years: Int)    {
        @JsonProperty("address") lateinit var primaryAddress: String   // set after construction
        var createdDt: DateTime by Delegates.notNull()                // set after construction
        var neverSetProperty: String? = null                          // not in JSON so must be nullable with default
    }

Note that using lateinit or Delegates.notNull() will ensure that the value is never null when read, while letting it be instantiated after the construction of the class.

Caveats

  • The @JsonCreator annotation is optional unless you have more than one constructor that is valid, or you want to use a static factory method (which also must have platformStatic annotation, e.g. @JvmStatic). In these cases, annotate only one method as JsonCreator.
  • During deserialization, if the definition on Kotlin is a non-null primitive and null is entered explicitly on JSON, processing will continue with an unintended default value. This problem is fixed by enabling DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES on ObjectMapper.
  • Serializing a member or top-level Kotlin class that implements Iterator requires a workaround, see Issue #4 for easy workarounds.
  • If using proguard:
    • kotlin.Metadata annotations may be stripped, preventing deserialization. Add a proguard rule to keep the kotlin.Metadata class: -keep class kotlin.Metadata { *; }
    • If you're getting java.lang.ExceptionInInitializerError, you may also need: -keep class kotlin.reflect.** { *; }
    • If you're still running into problems, you might also need to add a proguard keep rule for the specific classes you want to (de-)serialize. For example, if all your models are inside the package com.example.models, you could add the rule -keep class com.example.models.** { *; }
    • Also, please refer to this page for settings related to jackson-databind.

Support for Kotlin Built-in classes

These Kotlin classes are supported with the following fields for serialization/deserialization (and other fields are hidden that are not relevant):

  • Pair (first, second)
  • Triple (first, second, third)
  • IntRange (start, end)
  • CharRange (start, end)
  • LongRange (start, end)

Deserialization for value class is also supported since 2.17.
Please refer to this page for more information on using value class, including serialization.

(others are likely to work, but may not be tuned for Jackson)

Sealed classes without @JsonSubTypes

Subclasses can be detected automatically for sealed classes, since all possible subclasses are known at compile-time to Kotlin. This makes com.fasterxml.jackson.annotation.JsonSubTypes redundant. A com.fasterxml.jackson.annotation.@JsonTypeInfo annotation at the base-class is still necessary.

  @JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
  sealed class SuperClass{
      class A: SuperClass()
      class B: SuperClass()
  }

...
val mapper = jacksonObjectMapper()
val root: SuperClass = mapper.readValue(json)
when(root){
    is A -> "It's A"
    is B -> "It's B"
}

Configuration

The Kotlin module may be given a few configuration parameters at construction time; see the inline documentation for details on what options are available and what they do.

val kotlinModule = KotlinModule.Builder()
    .enable(KotlinFeature.StrictNullChecks)
    .build()
val mapper = JsonMapper.builder()
    .addModule(kotlinModule)
    .build()

If your ObjectMapper is constructed in Java, there is a builder method provided for configuring these options:

KotlinModule kotlinModule = new KotlinModule.Builder()
        .enable(KotlinFeature.StrictNullChecks)
        .build();
ObjectMapper objectMapper = JsonMapper.builder()
        .addModule(kotlinModule)
        .build();

Development

Maintainers

Following developers have committer access to this project.

  • Author: Jayson Minard (@apatrida) wrote this module originally (no longer active)
  • Active Maintainers:
    • Dmitry Spikhalskiy (@Spikhalskiy) -- since 2.14
    • Drew Stephens (@dinomite)
    • Vyacheslav Artemyev (@viartemev)
    • WrongWrong (@k163377) -- since 2.15
  • Co-maintainers:
    • Tatu Saloranta (@cowtowncoder)

You may at-reference maintainers as necessary but please keep in mind that all maintenance work is strictly voluntary (no one gets paid to work on this or any other Jackson components) so there is no guarantee for timeliness of responses.

All Pull Requests should be reviewed by at least one of active maintainers; bigger architectural/design questions should be agreed upon by majority of active maintainers.

Releases & Branches

This module follows the release schedule of the rest of Jackson—the current version is consistent across all Jackson components & modules. See the jackson-databind README for details.

Contributing

We welcome any contributions—reports of issues, ideas for enhancements, and pull requests related to either of those.

See the main Jackson contribution guidelines for more details.

Branches

If you are going to write code, choose the appropriate base branch:

  • 2.17 for bugfixes against the current stable version
  • 2.18 for additive functionality & features or minor, backwards compatible changes to existing behavior to be included in the next minor version release
  • master for significant changes to existing behavior, which will be part of Jackson 3.0

Failing tests

There are a number of tests for functionality that is broken, mostly in the failing package but a few as part of other test suites. Instead of ignoring these tests (with JUnit's @Ignore annotation) or excluding them from being run as part of automated testing, the tests are written to demonstrate the failure (either making a call that throws an exception or with an assertion that fails) but not fail the build, except if the underlying issue is fixed. This allows us to know when the tested functionality has been incidentally fixed by unrelated code changes.

See the tests readme for more information.

jackson-module-kotlin's People

Contributors

apatrida avatar cowtowncoder avatar daviddenton avatar davidrigglemaninin avatar dinomite avatar elektro-wolle avatar frost13it avatar fuud avatar hiddewie avatar jarekratajski avatar jf9327 avatar jflymyx avatar joohyukkim avatar k163377 avatar kkurczewski avatar pjfanning avatar prb avatar sarbyn avatar schmist avatar sconvent avatar shartte avatar simonrolin avatar spikhalskiy avatar stephanebg avatar sylvain-maillard avatar szymonprz avatar twisterrob avatar viartemev avatar wjur avatar yorlov 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

jackson-module-kotlin's Issues

Problems deserializing object when default values for constructor parameters are used

I'm having problems deserializing object when when default values for constructor parameters are used. Jackson is attempting to set a parameter that is missing in json to null in Kotlin even though the parameter has a default value. Here's the example that fails:

class KotlinJacksonTest {
    @Test
    fun testDeserialization() {
        val mapper = ObjectMapper()
        mapper.registerModule(KotlinModule())
        val test = mapper.readValue("""{"name": "bla"}""", TestObj::class.java)
        println(test)

    }
}

data class TestObj(val name: String, val other: String = "test")

Here's the stacktrace:

com.fasterxml.jackson.databind.JsonMappingException: Instantiation of [simple type, class TestObj] value failed: Parameter specified as non-null is null: method TestObj.<init>, parameter other

    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.wrapException(StdValueInstantiator.java:399)
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromObjectWith(StdValueInstantiator.java:231)
    at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:135)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:442)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1099)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:296)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2726)
    at io.github.knes1.kotao.brew.KotlinJacksonTest.testDeserialization(KotlinJacksonTest.kt:17)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method TestObj.<init>, parameter other

Class Object factory methods do not work

In Kotlin, a class object factory method is not actually a static method. It renders into byte code as:

MyClass.object$.myMethod

Therefore the scanning from Jackson data binding does not see it and give it the chance to be used. Possibly we can return a TypeInstantiator to handle this case, but it doesn't appear easy to do at the moment. There is a chance we return one that actually can't be used if its factory methods don't exist, or have wrong parameter types. Need to see what Jackson does if we hand back the class object class as if it is valid TypeInstantiator and yet it isn't. Otherwise, find a new way to make this work, possibly adding overrides to the scanner that decides what methods to test.

Kotlin M12 support

Library needs to be rebuilt with Kotlin M12. My IntelliJ Kotlin plugin complains about incompatible binaries.

Unable to deserialize enums with constructor parameters

Getting an index out of bounds exception when trying to deserialize enums with constructor parameters. Should be able to reproduce it with the following:

enum class TestEnum(val i: Int) {
    TEST(1)
}

fun main(args: Array<String>) {
    val mapper = jacksonObjectMapper()
    val test = mapper.readValue("\"TEST\"", TestEnum::class.java)
    println(test)
}

kotlin.jvm.internal.KotlinClass does not exist anymore in Kotlin 1.0.0

Trying to use Jackson with Kotlin 1.0.0 release produces the following exception:

java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/jvm/internal/KotlinClass;
  at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findKotlinParameterName(KotlinModule.kt:99)
  at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findImplicitPropertyName(KotlinModule.kt:57)
  at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.findImplicitPropertyName(AnnotationIntrospectorPair.java:454)
  at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreatorParam(POJOPropertiesCollector.java:436)
  at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreators(POJOPropertiesCollector.java:415)
  at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:285)
  at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getPropertyMap(POJOPropertiesCollector.java:248)
  at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getProperties(POJOPropertiesCollector.java:155)
  at com.fasterxml.jackson.databind.introspect.BasicBeanDescription._properties(BasicBeanDescription.java:142)
  at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findProperties(BasicBeanDescription.java:217)
  at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._findCreatorsFromProperties(BasicDeserializerFactory.java:330)
  at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:312)
  at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:252)
  at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:221)
  at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:143)
  at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:406)
  at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:352)
  at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
  at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
  at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
  at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:444)
  at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.createContextual(ObjectArrayDeserializer.java:134)
  at com.fasterxml.jackson.databind.DeserializationContext.handleSecondaryContextualization(DeserializationContext.java:685)
  at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:482)
  at com.fasterxml.jackson.databind.ObjectReader._prefetchRootDeserializer(ObjectReader.java:1856)
  at com.fasterxml.jackson.databind.ObjectReader.<init>(ObjectReader.java:185)
  at com.fasterxml.jackson.databind.ObjectMapper._newReader(ObjectMapper.java:627)

I've checked KotlinModule code and Kotlin language code, there's no kotlin.jvm.internal.KotlinClass anymore. I guess the replacement would be KClass from reflection lib, but I'm not sure.

P.S. I'm on Android.

More meaningful exception for missing mandatory kotlin constructor params

Hi, thanks so much for the kotlin module :)

Just wondering if it would be possible for KotlinValueInstantiator to throw a more specific exception for missing mandatory fields (i.e. mandatory kotlin constructor params)?

Our use case is that we're using kotlin data classes in our Spring Boot REST APIs. We've got some basic exception handling to provide more meaningful API errors when Jackson has an issue with the JSON (e.g. invalid enum values, invalid date formats, etc), but currently there's no easy way to identify missing mandatory values (i.e. mandatory kotlin constructor params), as it just throws a generic JsonMappingException.

I can't see a good fit among the existing exceptions, so it would have to be a new one, maybe MissingKotlinParameterException?

I've created a PR, see #33

Need support for Kotlin Iterables

I just implemented custom Iterable and Iterator classes which I tried passing into a (default) mapper. It serializes it as an object rather than an array. It does, however, serialize it as an array if java.lang.Iterable and java.util.Iterator are implemented.

Java and Kotlin Iterables are pretty much the same. I believe, this module should also add serializer for Kotlin iterables.

Problem with serializing anonymous objects with assigned external values

I encountered a problem with serialization of anonymous objects when Kotlin module is active.

val externalValue = "ggg"

mapper.writeValueAsString(object {
	val value = externalValue
})

then you will get this exception:

Exception in thread "main" kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Call is not yet supported for this function: public constructor `JacksonTest3Kt$main$1`() defined in `JacksonTest3Kt$main$1`[DeserializedClassConstructorDescriptor@5609159b] (member = null)
	at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:96)
	at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:36)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
	at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(KFunctionImpl.kt)
	at kotlin.reflect.jvm.ReflectJvmMapping.getJavaConstructor(ReflectJvmMapping.kt:72)
	at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:161)
	at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findKotlinParameterName(KotlinModule.kt:145)
	at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findImplicitPropertyName(KotlinModule.kt:81)
	at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.findImplicitPropertyName(AnnotationIntrospectorPair.java:470)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreatorParam(POJOPropertiesCollector.java:497)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreators(POJOPropertiesCollector.java:477)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:320)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getJsonValueAccessor(POJOPropertiesCollector.java:185)
	at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findJsonValueAccessor(BasicBeanDescription.java:251)
	at com.fasterxml.jackson.databind.ser.BasicSerializerFactory.findSerializerByAnnotations(BasicSerializerFactory.java:345)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:222)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:171)
	at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1374)
	at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1325)
	at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:509)
	at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:710)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:308)
	at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3744)
	at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3120)

If you do the same with Kotlin module disabled then serialization works correctly.

Tested with Kotlin 1.1 and module 2.8 / 2.9.

NoClassDefFoundError in 2.6.2

Kotlin v0.13.1513 and Jackson v2.6.2 app builds (and clean builds) do not work. They always throw such exception. Last night I attempted building and rebuilding service multiple times. I was using Gradle build system.

java.lang.NoClassDefFoundError: kotlin/reflect/jvm/JvmPackage
    at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findKotlinParameterName(KotlinModule.kt:97)
    at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findImplicitPropertyName(KotlinModule.kt:59)
    at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.findImplicitPropertyName(AnnotationIntrospectorPair.java:467)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreatorParam(POJOPropertiesCollector.java:436)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreators(POJOPropertiesCollector.java:415)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:285)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getJsonValueMethod(POJOPropertiesCollector.java:169)
    at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findJsonValueMethod(BasicBeanDescription.java:222)
    at com.fasterxml.jackson.databind.ser.BasicSerializerFactory.findSerializerByAnnotations(BasicSerializerFactory.java:355)
    at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:210)
    at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:153)
    at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1199)
    at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1153)
    at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:481)
    at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:679)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:107)
    at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3554)
    at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2891)
    ...
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
    at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:125)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.utils.servlet.JdbcMySqlConnectionCleanupFilter.doFilter(JdbcMySqlConnectionCleanupFilter.java:60)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:257)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
    at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:146)
    at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:442)
    at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:437)
    at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:444)
    at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:230)
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:308)
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:300)
    at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:441)
    at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:234)
    at java.lang.Thread.run(Thread.java:745)

I am not really sure whether this is a problem with Kotlin or Jackson module.

Dropwizard javax.validation problems

I am trying to use Dropwizard with Kotlin. To deserialize my data classes I am using this module.

When declaring a simple data class

data class Test(@Length(min = 12) val arg0 : String, val arg1 : String)

Kotlin creates an immutable class and puts validation annotations on a constructor.

Whatever jackson-module-kotlin does to circumvent that constructor, these annotations are ignored by Hibernate validator.

In fact, I tried debugging jackson-module-kotlin and it seems to ignore the primary constructor even if I annotate it with @JsonCreator.

Is jackson-module-kotlin the cause of the problem, Dropwizard, Kotlin?

case insensitive fields not working when declared in constructor

I've got a mapper defined like this:

mapper = jacksonObjectMapper()
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)

When I try to deserialize an object defined like this:

class ConfigItem(
    val configItemId: String
)

using JSON that looks like this:

{
    "configItemID": "test"
}

I get an error that says something along the lines of Instantiation failed for JSON property configItemId due to missing (therefore NULL) value for creator parameter.

Provide better / more in-depth errors for @JsonCreator missing parameters

It seems when there is a missing / null param for a non-null field when using a JsonCreator that the project short circuits at the first parameter found missing.

It would be great if there was potentially an option to be able to collect all the missing parameters (at the traversable paths) and then emitted an exception with all the collected constraint errors.

I currently have been using javax.validation to do this with the NotNull annotation, but being able to use have this module collect all the errors would make that much less painful.

I'm open to doing this myself and submitting a PR if that seems like a reasonable request.

Map with Pair key can be serialized but not deserialized

Hi,

data class Test(val map: Map<Pair<String, String>, String>)

this data class will be perfectly serialized, but cannot be deserialized afterwards:

val mapper = jacksonObjectMapper()
val test = Test(mapOf(Pair(Pair("string1", "string2"), "string3")))
val jsonString = mapper.writeValueAsString(test) //works: {"map":{"(string1, string2)":"string3"}}
val parsedTest = mapper.readValue(jsonString, Test::class.java)  //exception

Stacktrace:

com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class kotlin.Pair<java.lang.String,java.lang.String>]
 at [Source: {"map":{"(string1, string2)":"string3"}}; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)
    at com.fasterxml.jackson.databind.DeserializationContext.reportMappingException(DeserializationContext.java:1234)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._handleUnknownKeyDeserializer(DeserializerCache.java:585)
    at com.fasterxml.jackson.databind.deser.DeserializerCache.findKeyDeserializer(DeserializerCache.java:168)
    at com.fasterxml.jackson.databind.DeserializationContext.findKeyDeserializer(DeserializationContext.java:499)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.createContextual(MapDeserializer.java:247)
    at com.fasterxml.jackson.databind.DeserializationContext.handleSecondaryContextualization(DeserializationContext.java:681)
    at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:445)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer.findDeserializer(StdDeserializer.java:964)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:501)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
    at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
    at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:476)
    at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3899)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3794)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2842)

@JsonUnwrapped fails if parameter is non-nullable

I've made a commit onto my fork that demonstrates an error I've been trying to resolve for the whole day. It seems that JsonUnwrapped doesn't work with non-nullable values.

If you run my commit, you'll see that the first Boom does not fail, as Bomb? allows for null values (which are needed for some reason?), while Boom2 fails, with the error:

com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.fasterxml.jackson.module.kotlin.test.TestCasesFromSlack1$Boom2] value failed for JSON property value due to missing (therefore NULL) value for creator parameter value which is a non-nullable type
 at [Source: 
           {
                "word": "HI"
            }
        ; line: 4, column: 13] (through reference chain: com.fasterxml.jackson.module.kotlin.test.TestCasesFromSlack1$Boom2["value"])

	at com.fasterxml.jackson.module.kotlin.KotlinValueInstantiator.createFromObjectWith(KotlinValueInstantiator.kt:44)
	at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:138)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeUsingPropertyBasedWithUnwrapped(BeanDeserializer.java:779)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithUnwrapped(BeanDeserializer.java:605)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:309)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3837)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2899)
	at com.fasterxml.jackson.module.kotlin.test.TestCasesFromSlack1.testCzarSpringThing1(TestCasesFromSlack.kt:87)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

In addition, I'm running a test in my code that looks like this

public class JsonDeserializationTest
{

    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

    @Test
    public void allClassesUsedByOurControllersShouldBeDeserializableByJackson() throws Exception
    {
        assertCanBeMapped(OSValueObject.class);
        ......
        assertCanBeMapped(MoreValueObject.class);
    }

    private void assertCanBeMapped(Class<?> classToTest)
    {
        String message =
                String.format("%s is not deserialisable, check the swallowed exception in StdDeserializerProvider.hasValueDeserializerFor",
                       classToTest.getSimpleName());
        converter.getObjectMapper().findAndRegisterModules();
        assertThat(message, converter.canRead(classToTest, MediaType.APPLICATION_JSON), is(true));
    }

}

which fails if I don't include @param:JsonProperty("data") on the element, like so:

data class OSValueObject(
        val oneId: OneId,
        val twoId: TwoId,
        @param:JsonProperty("details") @JsonUnwrapped val details: Details?
)

Error message:


java.lang.AssertionError: OSValueObject is not deserialisable, check the swallowed exception in StdDeserializerProvider.hasValueDeserializerFor
Expected: is <true>
     but: was <false>

	at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
	at com.company.loanapp.JsonDeserializationTest.assertCanBeMapped(JsonDeserializationTest.java:72)
	at com.company.loanapp.JsonDeserializationTest.allClassesUsedByOurControllersShouldBeDeserializableByJackson(JsonDeserializationTest.java:59)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runners.Suite.runChild(Suite.java:128)
	at org.junit.runners.Suite.runChild(Suite.java:27)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

@JsonProperty annoation not respected for booleans in constructor.

Hello,

The @JsonProperty annotation doesn't work as expected for Boolean properties.

  • When used on a constructor property, it doesn't work
  • When used on a class property, it works but the original property name is serialized too.

See example below:

fun test() {
    val mapper = jacksonObjectMapper()

    println(mapper.writeValueAsString(Test()))
    
    //output: {"is_lol":"sdf","foo":true,"bar":true,"is_foo":true}
}

class Test(
        // This gets serialized as "is_lol", as expected. No issues here.
        @JsonProperty("is_lol")
        val lol: String = "sdf",

        // This gets serialized as "bar", even though we asked for "is_bar". This is an issue.
        @JsonProperty("is_bar")
        val isBar: Boolean = true) {

    // This gets serialized as both "foo" and "is_foo", although we only asked for "is_foo". Also an issue.
    @JsonProperty("is_foo")
    val isFoo: Boolean = true
}

EDIT: It works if we use @get:JsonProperty()

So in the example above, using @get:JsonProperty("is_bar") gives me the correct results.

Therefore, maybe close this ticket but improve README by mentioning this?

Wiki error

Under the Status

compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.6.2-4"
runtime "org.jetbrains.kotlin:kotlin-reflect:1.0.0-beta-2423"

it should be

compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.6.3-4"
runtime "org.jetbrains.kotlin:kotlin-reflect:1.0.0-beta-2423"

Kotlin Reflect and Android --- Method Counts

Hello,

I'm working with Kotlin in an Android project that depends on this plugin. I'm trying to avoid the dreaded 64K method limit and between Jackson Core, Jackson Databind, and this library's dependency on kotlin-reflect I'm stuck with just over 20K methods before counting any of my other dependencies.

Kotlin Reflect takes up over half of this count with just over 16K methods. Is there some way this library could be gotten rid of or replaced with an alternative (perhaps Kotlin Reflect Lite)? I realize in the short term my best recourse is to write models in Java and forgo the Kotlin plugin entirely, but I'd really prefer to have my models in Kotlin if at all possible.

Thanks,

Mike

Kotlin 1.0

Version 2.6.5-1 is not working with kotlin-stdlib 1.0

Exception is thrown:

Caused by: java.lang.NoClassDefFoundError: kotlin/jvm/internal/KotlinClass
    at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findKotlinParameterName(KotlinModule.kt:99) ~[jackson-module-kotlin-2.6.5-1.jar:2.6.5-1]

Look at switching to Jackson Jr

Possible since Kotlin has runtime type information and therefore the module can control more about serialization/deserialization we should look at extending Jackson Jr instead. It will get worse as Kotlin removes the JetValueParameter, at which point it will be really hard to make Jackson work with its current module model. Or we need a Jackson change.

NoClassDefFoundError: kotlin/reflect/jvm/JvmPackage with M13

I'm using this module in combination with Kotlin M13 and Spring. I had a codebase that previous worked however upon upgrading Kotlin and this module (to 2.6.2) I'm now getting

NoClassDefFoundError: kotlin/reflect/jvm/JvmPackage

when trying to deserialize a simple data class

@JsonIdentityInfo and UnresolvedForwardReference exception

Hello!
I use

compile group: 'com.fasterxml.jackson.module', 
name: 'jackson-module-kotlin', 
version: '2.8.5'

I have classes structure such click, and code

fun main(args: Array<String>) {
    test()
}

fun test(){
    val mapper = jacksonObjectMapper()

    val entity2 = Entity2("test_entity2")
    val entity1 = Entity1("test_entity1")
    val rootEntity1 = Entity1("root_entity1")

    entity2.entity1 = rootEntity1
    entity1.parent = rootEntity1
    entity1.entity2 = entity2
    rootEntity1.entity2 = entity2
    val json = mapper.writeValueAsString(entity1)
    println(json)
    val result = mapper.readValue(json, Entity1::class.java)
    println(result)
}
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator::class)
class Entity1(
        var name: String = "",
        var entity2: Entity2? = null,
        var parent: Entity1? = null
){
    override fun equals(other: Any?): Boolean{
        if (this === other) return true
        if (other?.javaClass != javaClass) return false

        other as Entity1
        if (name != other.name) return false
        return true
    }
    override fun hashCode(): Int{
        return name.hashCode()
    }
    override fun toString(): String{
        return "Entity1(name='$name')"
    }

}
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator::class)
class Entity2(
        var name: String = "",
        var entity1: Entity1? = null
) {
    override fun equals(other: Any?): Boolean{
        if (this === other) return true
        if (other?.javaClass != javaClass) return false
        other as Entity2
        if (name != other.name) return false
        return true
    }

    override fun hashCode(): Int{
        return name.hashCode()
    }

    override fun toString(): String{
        return "Entity2(name='$name')"
    }
}

This code throw Exception in thread "main" com.fasterxml.jackson.databind.deser.UnresolvedForwardReference: Could not resolve Object Id [2] (for [simple type, class Entity2]) (through reference chain: Entity1["entity2"]->Entity2["entity1"]->Entity1["entity2"]) for json

{"@id":1,"name":"test_entity1","entity2":{"@id":2,"name":"test_entity2","entity1":{"@id":3,"name":"root_entity1","entity2":2,"parent":null}},"parent":3};

, but if commit //rootEntity1.entity2 = entity2 or val mapper = ObjectMapper() from #jackson-core code works fine. Its bag or I just don't understand Jackson?

Minor compatibility problems with 2.6.0-rc1 databind

Looks like some of the changes I have been making in jackson-databind cause issues with Kotlin module. I would fix them (since they are probably minor). but unfortunately I don't know Kotlin the language yet.
As soon as the isses are fixed, I can push 2.6.0-rc1 of Kotlin module, along with other components -- hoping to start Release Candidate series quite early this time, to allow for some regression testing before 2.6.0 final

Error when trying to deserialize json on Android. kotlin 1.0.2/1.0.0, module version 2.7.1-2

java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/reflect/jvm/ReflectJvmMapping; at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findKotlinParameterName(KotlinModule.kt:121) at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findImplicitPropertyName(KotlinModule.kt:61) at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.findImplicitPropertyName(AnnotationIntrospectorPair.java:454) at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreatorParam(POJOPropertiesCollector.java:436) at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreators(POJOPropertiesCollector.java:415) at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:285) at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getPropertyMap(POJOPropertiesCollector.java:248) at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getProperties(POJOPropertiesCollector.java:155) at com.fasterxml.jackson.databind.introspect.BasicBeanDescription._properties(BasicBeanDescription.java:142) at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findProperties(BasicBeanDescription.java:217) at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._findCreatorsFromProperties(BasicDeserializerFactory.java:330) at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:312) at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:252) at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:221) at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:143) at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:406) at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:352) at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264) at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244) at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142) at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:477) at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3889) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3784) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2779)

Serialization Stopped working after update to M13( && jackson 2.6.2).

I have 2 data-classes, one nests another one:

    data class WidgetShortcut(var appAction: String = "com.google.android.googlequicksearchbox.VoiceSearchActivity",
                          var appPackage: String = "com.google.android.googlequicksearchbox",
                          var icon: Int = R.drawable.icn_microphone,
                          var launchType: LaunchType = LaunchType.ACTIVITY,
                          var label: String = "Voice Search")

    data class WidgetData(var primaryColor: Int = Color.WHITE,
                          var secondaryColor: Int = Color.DKGRAY,
                          var autoTheme: Boolean = true,
                          var autoThemeReversed: Boolean = false,
                          var colorfulLogo: Boolean = false,
                          var searchAsOverlay: Boolean = true,
                          var shortcuts: ArrayList<WidgetShortcut> = arrayListOf(WidgetShortcut()))

and here's how I serialize\deserialize them:

    fun getJsonString(data: WidgetData) = jacksonObjectMapper().writeValueAsString(data)

    fun restoreJsonString(string: String) = jacksonObjectMapper().readValue(string, WidgetData::class.java)

It worked fine in M12 && 2.5 jackson-kotlin-module but after update to new version data can't be serialized anymore. I get such logcat:

09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime: FATAL EXCEPTION: main
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime: Process: com.pavelsikun.customizablesearchwidget, PID: 8256
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:115)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:  Caused by: java.lang.reflect.InvocationTargetException
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:372)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699) 
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:115) 
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:  Caused by: com.fasterxml.jackson.databind.JsonMappingException: Invalid index 0, size is 0 (through reference chain: com.pavelsikun.customizablesearchwidget.util.WidgetData["shortcuts"])
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:199)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:683)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3554)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:2925)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.pavelsikun.customizablesearchwidget.util.DataManager.saveWidgetData(DataManager.kt:67)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.pavelsikun.customizablesearchwidget.activity.WidgetConfigurationActivity$onOptionsItemSelected$1.invoke(WidgetConfigurationActivity.kt:48)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.pavelsikun.customizablesearchwidget.activity.WidgetConfigurationActivity.onOptionsItemSelected(WidgetConfigurationActivity.kt:59)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.app.Activity.onMenuItemSelected(Activity.java:3694)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:325)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:147)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.internal.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.internal.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.internal.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:73)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.widget.Toolbar$1.onMenuItemClick(Toolbar.java:180)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:761)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:811)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:153)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:948)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:619)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.support.v7.internal.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:139)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.view.View.performClick(View.java:4797)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.view.View$PerformClick.run(View.java:19899)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:739)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:95)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:135)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5374)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method) 
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:372) 
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904) 
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699) 
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:115) 
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:  Caused by: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at java.util.ArrayList.get(ArrayList.java:308)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findKotlinParameterName(KotlinModule.kt:97)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findImplicitPropertyName(KotlinModule.kt:59)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.findImplicitPropertyName(AnnotationIntrospectorPair.java:467)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:     at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreatorParam(POJOPropertiesCollector.java:436)
09-20 19:50:18.390 8256-8256/com.pavelsikun.customizablesearchwidget E/AndroidRuntime:  at com.fasterxml.jackson.databin

Is jet.runtime.typeinfo actually required as an OSGi import?

Thanks for developing the module!

It seems like I can't use this module in OSGi because I am not sure how I can satisfy this import requirement (jet.runtime.typeinfo). I can't locate if you are using it anywhere throughout the module itself, so.. is it actually necessary?

Cannot use non optional arguments

For some reason, I cannot get non-optional arguments to work properly. Judging from #32 it should be possible so I'm not sure what I'm doing wrong. I'm using spring boot and my controller looks something like this:


@RequestMapping("/a/{pathparam}/end")
@RestController
public class DocumentController extends BaseController {

    private final DocumentService documentService;

    @Autowired
    public DocumentController(DocumentService documentService) {
        this.documentService = documentService;
    }

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<RegisterDocumentResponse> createDocument(
            @PathVariable Id id,
            @RequestBody RegisterDocumentRequest request) {
        return new ResponseEntity<>(documentService.registerNewDocument(id, request),
                                    HttpStatus.CREATED);
    }
}

my object mapper config

@Configuration
public class JacksonConfiguration {

    @Bean
    public ObjectMapper getObjectMapper() {
        ObjectMapper om = new ObjectMapper();

        om.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES));
        om.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        om.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        om.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        om.registerModule(new JavaTimeModule());
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        om.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
        om.registerModule(new KotlinModule());

        return om;
    }
}

my kotlin class

data class RegisterDocumentRequest(@JsonUnwrapped var documentData: DocumentData)

and finally the error in question. It doesn't make sense, because I'm supplying every parameter! (There's only one...)

org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Instantiation of [simple type, class com.company.app.common.document.requests.RegisterDocumentRequest] value failed for JSON property documentData due to missing (therefore NULL) value for creator parameter documentData which is a non-nullable type
 at [Source: java.io.PushbackInputStream@68d57fce; line: 1, column: 217] (through reference chain: com.company.app.common.document.requests.RegisterDocumentRequest["documentData"]); nested exception is com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.company.app.common.document.requests.RegisterDocumentRequest] value failed for JSON property documentData due to missing (therefore NULL) value for creator parameter documentData which is a non-nullable type
 at [Source: java.io.PushbackInputStream@68d57fce; line: 1, column: 217] (through reference chain: com.company.app.common.document.requests.RegisterDocumentRequest["documentData"])
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:228)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:213)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:197)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:149)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:127)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:105)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at com.company.common.web.filter.ResourceExecutionContextFilter.doFilterInternal(ResourceExecutionContextFilter.java:34)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at com.company.common.web.filter.TenantValidationFilter.doFilterInternal(TenantValidationFilter.java:46)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)17:32:32.298 [http-nio-0.0.0.0-9000-exec-7]   WARN  c.p.app.common.BaseController - HttpMessageNotReadableException caught in controller; returning 400: Correlation ID: 29ae027f-d0d9-4005-8a3c-25cd8c11b818

    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:164)
    at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:107)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:522)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1110)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.company.app.common.document.requests.RegisterDocumentRequest] value failed for JSON property documentData due to missing (therefore NULL) value for creator parameter documentData which is a non-nullable type
 at [Source: java.io.PushbackInputStream@68d57fce; line: 1, column: 217] (through reference chain: com.company.app.common.document.requests.RegisterDocumentRequest["documentData"])
    at com.fasterxml.jackson.module.kotlin.KotlinValueInstantiator.createFromObjectWith(KotlinValueInstantiator.kt:53)
    at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:135)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeUsingPropertyBasedWithUnwrapped(BeanDeserializer.java:773)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithUnwrapped(BeanDeserializer.java:600)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:309)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2913)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:225)
    ... 110 more

I can't tell if this is a bug, or expected behavior.

Annotation JsonProperty working incorrectly

I have following data class for the test case:

data class Dummy(
    @JsonProperty("is_deleted") var isDeleted : Boolean = true,
    var title : String
)

I have tried to marshall it into JSON string using following object mapper setup and call:

val om = ObjectMapper()
om.registerModule(KotlinModule())
assertEquals("{\"is_deleted\":true,\"title\":\"The Dummy\"}", om.writeValueAsString(Dummy(title = "The Dummy")))

The output is {"deleted":true,"title":"The Dummy"}> though I would expect {"is_deleted":true,"title":"The Dummy"}.

When I change data class var from isDeleted to deleted then it starts to work correctly.
`

Problems with no-arg plugin + JsonIgnore + Kotlin 1.1

I tried updating an internal project to Kotlin 1.1, but I encountered an issue with one of our data classes. It seems that in some circumstances deserializing doesn't work even though it worked fine with Kotlin 1.0.6.

I uploaded a minimal example project that demonstrates the error here: https://github.com/mhlz/jackson-module-kotlin-issue

If you change the kotlin.version property in the pom.xml to 1.0.6 it works fine. But with 1.1.0 it crashes with the following exception:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Could not find creator property with name 'innerTest' (in class Test)
 at [Source: 
{
    "innerTest": {
        "str": "str",
        "otherStr": "otherStr"
    }
}
; line: 2, column: 1]
	at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)
	at com.fasterxml.jackson.databind.DeserializationContext.reportMappingException(DeserializationContext.java:1234)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.addBeanProps(BeanDeserializerFactory.java:551)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:226)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:141)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:403)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
	at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:476)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3899)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3794)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2842)
	at MainKt.main(Main.kt:36)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

I figured out that removing the @field:JsonIgnore annotation makes the exception go away. The same thing happens with @get:JsonIgnore as well.

I hope the example project gives enough info to debug this issue properly, as I have no idea what could cause this problem.

After investigating more this issue does not occur with module-kotlin 2.8.6 and databind 2.8.6. Those work fine with Kotlin 1.1.

Unsafe, not typed result of treeToValue method.

Sample code:
val listOfPojo:List<POJO> = jsonMapper.treeToValue(jsonNode)
Return List<LinkedHashMap> instead of List<POJO>. After iterration have java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to POJO.

Works OK:
val listOfPojo<POJO> = jsonMapper.readValue(jsonNode.toString())

The shorthand for readValue does not work with generics

it seems that the shorthand val str : String = mapper.readValue("") does not work if i try to do it like
val str : T = mapper.readValue("")

my code reads now like this:

    val mapper = jacksonObjectMapper()
    fun <T: Any> RoutingContext.getAsPojo(type: KClass<T>) : T = mapper.readValue(this.bodyAsString, type.java)

if it's possible to write the code like this:
val state: MyStateObject = mapper.readValue(json)

it sounds logical that it should be possible to write like that with generics as well. Would it be possible?

Cache reflection results.

I am using this in a high-throughput multi-threaded service and my service is spending almost all of its time waiting on lock on the class loader because every time an object is deserialized, it does reflection on the object being deserialized into. It appears that this is a lock on the classloader deep in the bowels of the Kotlin reflection code.

Reflection is not a fast process, and involves global locks in some cases (such as this one) so the result of the reflection should be cached in a way that allows for multi-threaded reads of the cached object. We have exactly one object that is deserialized into in our entire process, so using reflection every time to figure out what the object looks like is hugely wasteful and expensive.

could not serialize data class

hi when i serialized a data class but i only got id the code is below
here is data class

data class DXBuyGood(
        var id: Int = 0,
        private var type: GoodType = GoodType.SINGLE,
        private var price: Int = 0,
        private var num: Int = 0) {}

and here is GoodType enum class

enum class GoodType(type: String) {
    SINGLE("single"), PACKAGE("single")
}

and here is my objectMapper config

class MyObjectMapper : ObjectMapper() {
            init {
                configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true)
                configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
                dateFormat = SimpleDateFormat(DateFormatType.YYYY_MM_DD_HH_MM_SS.value)
                setSerializationInclusion(JsonInclude.Include.NON_NULL)
                registerModule(KotlinModule())
                findAndRegisterModules()
            }
        }

        @JvmStatic @JvmOverloads
        fun toJson(obj: Any): String {
            return toJson(OBJECT_MAPPER, obj)
        }
}

@JvmOverloads
fun Any.toJson(): String {
    return JsonUtil.toJson(this)
}

and the test code is here

    @Test
    fun testToJson() {
        println(DXBuyGood(24, GoodType.SINGLE, 30.0, 1).toJson())
    }

but i got the result is this
2016-07-28_01:12:02.jpg

did i do something wrong???

Polymorphic support

I have this use case: Let's say I have an interface with N data classes implementing it and a container like:

interface MyCommand {
   val commandId: String
}
data class ActivateCustomer(override val commandId: String, val credit: Long) : MyCommand
data class DeactivateCustomer(override val commandId: String, val reason: String) : MyCommand
// and other similar commands like CreateOrder, FinishOrder, etc
class MyCommandsContainer(val commands: List<MyCommand>)

How could I ser/deser MyCommandsContainer class in an idiomatic Kotlin ? Also, I would prefer to avoid to annotate MyCommand with all it's subtypes since I want my dependencies as commands -> MyCommand and not the reverse. Thanks.

Deserializing @JsonValue toString and single string constructor in data class?

Hi,

Having trouble deserializing a data class represented as a JsonValue on toString and a single string arg constructor..

Am seeing the following error:

com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class com.fasterxml.jackson.module.kotlin.test.StringValue] from String value ('test'); no single-String constructor/factory method
at [Source: "test"; line: 1, column: 1]

data class StringValue(val string: String) {
    @JsonValue override fun toString() = string
}

public class TestJsonValue {
    @Test public fun testJsonValue() {
        val expectedJson = "\"test\""
        val expectedObj = StringValue("test")

        val actualJson = jacksonObjectMapper().writeValueAsString(expectedObj)
        assertEquals(expectedJson, actualJson)

        val actualObj = jacksonObjectMapper().readValue("\"test\"", StringValue::class.java)
        assertEquals(expectedObj, actualObj)

    }
}

Have also tried with:

data class StringValue @JsonCreator constructor(val string: String) {
    @JsonValue override fun toString() = string
}

Would you mind pointing me in the right direction?
Thanks

Problems with kotlin 1.1 and data classes

SUMMARY: the problem exists, but I think cant be fixed before KT-14969

Ok, the first thing I tried is just use and got this:

java.lang.ExceptionInInitializerError
	at kotlin.reflect.jvm.internal.RuntimeTypeMapper.mapJvmClassToKotlinClassId(RuntimeTypeMapper.kt:242)
	at kotlin.reflect.jvm.internal.KClassImpl.getClassId(KClassImpl.kt:56)
	at kotlin.reflect.jvm.internal.KClassImpl.access$getClassId$p(KClassImpl.kt:40)
	at kotlin.reflect.jvm.internal.KClassImpl$descriptor_$1.invoke(KClassImpl.kt:42)
	at kotlin.reflect.jvm.internal.KClassImpl$descriptor_$1.invoke(KClassImpl.kt:40)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.KClassImpl.getDescriptor(KClassImpl.kt:52)
	at kotlin.reflect.jvm.internal.KClassImpl.getConstructorDescriptors(KClassImpl.kt:69)
	at kotlin.reflect.jvm.internal.KClassImpl.getConstructors(KClassImpl.kt:118)
	at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:158)
	at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findKotlinParameterName(KotlinModule.kt:121)
	at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findImplicitPropertyName(KotlinModule.kt:61)
	at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.findImplicitPropertyName(AnnotationIntrospectorPair.java:454)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreatorParam(POJOPropertiesCollector.java:436)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreators(POJOPropertiesCollector.java:415)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:285)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getPropertyMap(POJOPropertiesCollector.java:248)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getProperties(POJOPropertiesCollector.java:155)
	at com.fasterxml.jackson.databind.introspect.BasicBeanDescription._properties(BasicBeanDescription.java:142)
	at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findProperties(BasicBeanDescription.java:217)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._findCreatorsFromProperties(BasicDeserializerFactory.java:330)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:312)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:252)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:221)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:143)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:406)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:352)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
	at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:477)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3908)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3803)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2816)
... (private stuff)
Caused by: java.lang.IllegalStateException: @NotNull method kotlin/reflect/jvm/internal/impl/builtins/KotlinBuiltIns.getBuiltInClassByName must not return null
	at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.getBuiltInClassByName(KotlinBuiltIns.java:308)
	at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.getBuiltInClassByName(KotlinBuiltIns.java:301)
	at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.getBuiltInClassByName(KotlinBuiltIns.java:341)
	at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.getCloneable(KotlinBuiltIns.java:473)
	at kotlin.reflect.jvm.internal.impl.platform.JavaToKotlinClassMap.<init>(JavaToKotlinClassMap.java:54)
	at kotlin.reflect.jvm.internal.impl.platform.JavaToKotlinClassMap.<clinit>(JavaToKotlinClassMap.java:38)

The second, I cloned the repo and tried to build with latest version of 1.1 plugin, and got compiler error KT-14969

Deserializing kotlin class types as Object throws exception

Sample:
val result = objectMapper.writeValueAsString(Pair<Boolean,Long>(false,42))
val inflated = objectMapper.readValue(result, Object::class.java)

Throws:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property '@Class' that is to contain type id (for class java.lang.Object)

This is basically what Redisson does to deserialize types. If you specify @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS) on a mixin, everything works but it'd be nice to have some configuration to get this on the Kotlin types by default.

NoClassDefFoundError During Deserialization With Android & Kotlin 1.0.5

I am experiencing a NoClassDefFoundError exception when attempting to deserialize JSON to object using Android, Kotlin 1.0.5 and kotlin jackson module.

Gradle Build Script

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'idea'

android {
    ...
}

dependencies {
    testCompile group: 'junit',
                name: 'junit',
                version: '4.12'
    compile group: 'com.android.support',
            name: 'appcompat-v7',
            version: '25.0.0'
    compile group: 'org.jetbrains.kotlin',
            name: 'kotlin-stdlib',
            version: '1.0.5'
    compile group: 'org.jetbrains.kotlin',
            name: 'kotlin-reflect',
            version: '1.0.5'
    compile group: 'ca.violetsuntechnologies',
            name: 'archon-library',
            version: '1.0.0-12'
    compile group: 'org.jetbrains.anko',
            name: 'anko-sdk23',
            version: '0.9'
    compile group: 'org.jetbrains.anko',
            name: 'anko-appcompat-v7',
            version: '0.9'
}

Stack Trace

java.lang.ExceptionInInitializerError
	at kotlin.reflect.jvm.internal.RuntimeTypeMapper.mapJvmClassToKotlinClassId(RuntimeTypeMapper.kt:264)
	at kotlin.reflect.jvm.internal.KClassImpl.getClassId(KClassImpl.kt:55)
	at kotlin.reflect.jvm.internal.KClassImpl.access$getClassId$p(KClassImpl.kt:39)
	at kotlin.reflect.jvm.internal.KClassImpl$descriptor_$1.invoke(KClassImpl.kt:41)
	at kotlin.reflect.jvm.internal.KClassImpl$descriptor_$1.invoke(KClassImpl.kt:39)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.KClassImpl.getDescriptor(KClassImpl.kt:51)
	at kotlin.reflect.jvm.internal.KClassImpl.getConstructorDescriptors(KClassImpl.kt:68)
	at kotlin.reflect.jvm.internal.KClassImpl.getConstructors(KClassImpl.kt:117)
	at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:158)
	at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findKotlinParameterName(KotlinModule.kt:141)
	at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findImplicitPropertyName(KotlinModule.kt:77)
	at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.findImplicitPropertyName(AnnotationIntrospectorPair.java:469)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreatorParam(POJOPropertiesCollector.java:469)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreators(POJOPropertiesCollector.java:449)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:303)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getPropertyMap(POJOPropertiesCollector.java:266)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getProperties(POJOPropertiesCollector.java:158)
	at com.fasterxml.jackson.databind.introspect.BasicBeanDescription._properties(BasicBeanDescription.java:144)
	at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findProperties(BasicBeanDescription.java:219)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._findCreatorsFromProperties(BasicDeserializerFactory.java:332)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:314)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:253)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:219)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:141)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:403)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
	at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
	at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:443)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:206)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:26)
	at com.fasterxml.jackson.databind.DeserializationContext.handleSecondaryContextualization(DeserializationContext.java:681)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:481)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3899)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3794)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2861)
	at ca.violetsuntechnologies.archon.library.api.API$Companion.load(API.kt:104)
	at ca.violetsuntechnologies.archon.MainActivity$onResume$2.invoke(MainActivity.kt:39)
	at ca.violetsuntechnologies.archon.MainActivity$onResume$2.invoke(MainActivity.kt:15)
	at org.jetbrains.anko.AsyncKt$doAsync$1.invoke(Async.kt:138)
	at org.jetbrains.anko.AsyncKt$doAsync$1.invoke(Async.kt)
	at org.jetbrains.anko.AsyncKt$sam$Callable$8e819ea9.call(Async.kt)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
	at java.util.concurrent.FutureTask.run(FutureTask.java:137)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:150)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:264)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
	at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.NoClassDefFoundError: kotlin.reflect.jvm.internal.impl.resolve.jvm.JvmPrimitiveType
	at kotlin.reflect.jvm.internal.impl.platform.JavaToKotlinClassMap.<init>(JavaToKotlinClassMap.java:67)
	at kotlin.reflect.jvm.internal.impl.platform.JavaToKotlinClassMap.<clinit>(JavaToKotlinClassMap.java:39)
	at kotlin.reflect.jvm.internal.RuntimeTypeMapper.mapJvmClassToKotlinClassId(RuntimeTypeMapper.kt:264)
	at kotlin.reflect.jvm.internal.KClassImpl.getClassId(KClassImpl.kt:55)
	at kotlin.reflect.jvm.internal.KClassImpl.access$getClassId$p(KClassImpl.kt:39)
	at kotlin.reflect.jvm.internal.KClassImpl$descriptor_$1.invoke(KClassImpl.kt:41)
	at kotlin.reflect.jvm.internal.KClassImpl$descriptor_$1.invoke(KClassImpl.kt:39)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.KClassImpl.getDescriptor(KClassImpl.kt:51)
	at kotlin.reflect.jvm.internal.KClassImpl.getConstructorDescriptors(KClassImpl.kt:68)
	at kotlin.reflect.jvm.internal.KClassImpl.getConstructors(KClassImpl.kt:117)
	at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:158)
	at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findKotlinParameterName(KotlinModule.kt:141)
	at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector.findImplicitPropertyName(KotlinModule.kt:77)
	at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.findImplicitPropertyName(AnnotationIntrospectorPair.java:469)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreatorParam(POJOPropertiesCollector.java:469)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreators(POJOPropertiesCollector.java:449)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:303)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getPropertyMap(POJOPropertiesCollector.java:266)
	at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getProperties(POJOPropertiesCollector.java:158)
	at com.fasterxml.jackson.databind.introspect.BasicBeanDescription._properties(BasicBeanDescription.java:144)
	at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findProperties(BasicBeanDescription.java:219)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._findCreatorsFromProperties(BasicDeserializerFactory.java:332)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:314)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:253)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:219)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:141)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:403)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
	at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
	at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:443)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:206)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:26)
	at com.fasterxml.jackson.databind.DeserializationContext.handleSecondaryContextualization(DeserializationContext.java:681)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:481)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3899)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3794)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2861)
	at ca.violetsuntechnologies.archon.library.api.API$Companion.load(API.kt:104)
	at ca.violetsuntechnologies.archon.MainActivity$onResume$2.invoke(MainActivity.kt:39)
	at ca.violetsuntechnologies.archon.MainActivity$onResume$2.invoke(MainActivity.kt:15)
	at org.jetbrains.anko.AsyncKt$doAsync$1.invoke(Async.kt:138)
	at org.jetbrains.anko.AsyncKt$doAsync$1.invoke(Async.kt)
	at org.jetbrains.anko.AsyncKt$sam$Callable$8e819ea9.call(Async.kt)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
	at java.util.concurrent.FutureTask.run(FutureTask.java:137)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:150)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:264)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
	at java.lang.Thread.run(Thread.java:856)

It is possible to have null in non-nulls array after deserialization

Not sure it's an issue of this module, but suppose, I defined a class like this:

data class Person(val name: String, val hobbies: Array<String>)

Then, I use it like this:

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import com.fasterxml.jackson.module.kotlin.readValue

fun main(args: Array<String>) {
    val mapper: ObjectMapper = ObjectMapper().registerKotlinModule()

    // This is ok
    println(mapper.readValue<Person>("{\"name\":\"Darth Vader\", \"hobbies\": [\"Force choking\", \"Lighsabering\"]}"))

    // But this should fail as one of the strings is null
    println(mapper.readValue<Person>("{\"name\":\"Darth Vader\", \"hobbies\": [\"Force choking\", \"Lighsabering\", null]}"))

    // NPE
    mapper.readValue<Person>("{\"name\":\"Darth Vader\", \"hobbies\": [\"Force choking\", \"Lighsabering\", null]}").hobbies.forEach {
        println("$it: ${it.length()}")
    }
}

The output is:

Person(name=Darth Vader, hobbies=[Force choking, Lighsabering])
Person(name=Darth Vader, hobbies=[Force choking, Lighsabering, null])
Force choking: 13
Lighsabering: 12
Exception in thread "main" java.lang.NullPointerException
    at _DefaultPackage$main$4d2eced0.main(main.kt:15)
    at _DefaultPackage.main(main.kt:1)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

As you can see, after deserialization on of the strings in the array, that should not be null, is null. This can cause NPE.

The buildscript, with all the versions is:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:0.12.412'
    }
}

apply plugin: 'kotlin'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.jetbrains.kotlin:kotlin-stdlib:0.12.412'
    compile 'org.jetbrains.kotlin:kotlin-reflect:0.12.412'
    compile 'com.fasterxml.jackson.module:jackson-module-kotlin:2.5.4'
}

Feature Request: Support ClosedRange<Comparable<*>>

As far as I know only ranges of primitive types are supported. Please correct me if there's a way to deal with ranges of comparable.

I couldn't serialize/deserialize ranges of comparable classes (ie: LocalDate).

I made a custom serializer. But it doesn't work in collections (ie: List<ClosedRange<LocalDate>>). It would be nice to be supported directly by the Jackson module.

Anyway, if someone could point me in the right direction to make it work it would be appreciated!

Databind fails to readValue/writeValueToString

Converting a simple data class from String to Object fails,

val json = """{"key": "Key", "value": "Value"}"""
val arr: EnvironmentInfo = jacksonObjectMapper().readValue(json, EnvironmentInfo::class.java)

Definition of data class
data class EnvironmentInfo (val key: String, val value: String)

Throws,

java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.introspect.AnnotatedConstructor.getType()Lcom/fasterxml/jackson/databind/JavaType;
	at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector$hasCreatorAnnotation$1.invoke(KotlinModule.kt:98)
	at com.fasterxml.jackson.module.kotlin.KotlinNamesAnnotationIntrospector$hasCreatorAnnotation$1.invoke(KotlinModule.kt:66)

Im using
compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.8.4"

Cannot use optional primitive parameters with FAIL_ON_NULL_FOR_PRIMITIVES enabled

Use case is to enable FAIL_ON_NULL_FOR_PRIMITIVES so that non-nullable and non-optional primitive fields do not default to their platform zero value when they are excluded from the json but instead raise a json mapping exception. However enabling that feature also caused optional primitive fields with default values specified to throw the same exception.

Pull request #41 has test cases showing the problem and a fix for it.

Default values for primitive parameters

I was surprised by the behavior of Jackson+Kotlin with respect to primitive parameters that have default values. It seems like those default values are ignored, and zero is used instead.

Here's an example:

class Main private constructor() {
  compainion object {
    @JvmStatic fun main(args: Array<String>) {
      val mapper = ObjectMapper().registerModule(KotlinModule())
      val string1 = "{\"i\":3}"
      val string2 = "{}"
      val value1 = mapper.readValue(string1, Foo::class.java)
      val value2 = mapper.readValue(string2, Foo::class.java)
      println("value1: $value1")
      println("value2: $value2")
    }
  }

  data class Foo
  @JsonCreator constructor(@JsonProperty val i: Int = 5)
}

That prints:

value1: Foo(i=3)
value2: Foo(i=0)

But I wanted it to print:

value1: Foo(i=3)
value2: Foo(i=5)

Is that beyond the scope of this module? Is it impossible for some reason?

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.