fasterxml / jackson-module-kotlin Goto Github PK
View Code? Open in Web Editor NEWModule that adds support for serialization/deserialization of Kotlin (http://kotlinlang.org) classes and data classes.
License: Apache License 2.0
Module that adds support for serialization/deserialization of Kotlin (http://kotlinlang.org) classes and data classes.
License: Apache License 2.0
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.
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"
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.
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.
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
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.
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.
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)
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())
}
did i do something wrong???
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)
I am experiencing a NoClassDefFoundError
exception when attempting to deserialize JSON to object using Android, Kotlin 1.0.5 and kotlin jackson module.
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'
}
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)
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.
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!
Maybe my eyes are just missing it, but I don't see a license listed or mentioned anywhere. Is this software licensed?
Thanks.
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
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.
`
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.
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
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]
It seems like it's impossible to use the "@JsonIgnore" annotation on delegated properties.
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)
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?
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.
Ready for first snapshot release.
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.
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.
A unit test is disabled, because absence of @JsonCreator does the wrong thing:
in the failure case instead of getting an exception " No suitable constructor found for type " you end up with " Argument #0 of constructor ... has no property name annotation; must have name when multiple-parameter constructor annotated as Creator"
see https://github.com/FasterXML/jackson-module-paranamer/issues/11
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?
Library needs to be rebuilt with Kotlin M12. My IntelliJ Kotlin plugin complains about incompatible binaries.
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?
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 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.
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.
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?
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'
}
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.
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.
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
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
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
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"
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
@JsonUnwrapped annotations are not working for data classes failing with not find creator property with name 'propertyname'
.
Same structure with a regular class seems to work fine.
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())
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
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?
Hello,
The @JsonProperty
annotation doesn't work as expected for Boolean properties.
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
}
@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?
Will jackson work with Either class?
This little test shows the situation:
https://github.com/nwolff/jackson-module-kotlin/commit/7fdd4556d99d8e8f07251dd641455c3669c1c5f7
When I try to read an object with more than 31 properties with default values, jackson ignores the value for the very last property. The reason may be how Kotlin compiler transforms such classes to bytecode, but I am not sure. The following test demonstrates the bug:
https://gist.github.com/dstarcev/a829685618d3c638f462028e48690ce8
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.