question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

public val/var in constructor produces 'No String-argument constructor/factory method to deserialize from String value'

See original GitHub issue

As per https://github.com/FasterXML/jackson-dataformat-xml/issues/254, I have a very similar problem. I’m on 2.9.1. The case is so simple that I’m not sure my usage is correct, but the functioning workaround suggests it’s legitimate.

The following should serve as a self-contained example.

package com.robpridham.jsonexample

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.junit.Assert.assertEquals
import org.junit.Test

class DataClassTest {

    data class DataClass1(val name: String, val content: DataClass2)

    data class DataClass2(val content: String)

    private val jsonData = """
        {
            "name": "my name",
            "content": "some value"
        }
        """

    @Test
    fun testJsonParsing() {
        val mapper = jacksonObjectMapper()
        val dataClass1 = mapper.readValue<DataClass1>(jsonData)
        assertEquals(DataClass2("some value"), dataClass1.content)
    }
}

This fails with the following:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.robpridham.jsonexample.DataClassTest$DataClass2` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('some value')
 at [Source: (String)"
{
            "name": "my name",
            "content": "some value"
        }
        "; line: 4, column: 24] (through reference chain: com.robpridham.jsonexample.DataClassTest$DataClass1["content"])

	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1329)
	at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1031)
	at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:370)
	at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:314)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1351)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:170)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
	at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:519)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:527)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:416)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1265)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:325)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3011)
	at com.robpridham.jsonexample.DataClassTest.testJsonParsing(DataClassTest.kt:28)
	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 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:242)
	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:498)
	at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)

If I rework DataClass2 to have private val in the constructor, or indeed no val keyword in its constructor at all, then this works.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:3
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

8reactions
Fleshgrindercommented, Mar 16, 2018

Hey @apatrida the former case you described is what I have and I’m running into exactly this issue, minimal example:

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

data class ValueObject(@JsonValue val value: String)

fun main(args: Array<String>) {
    val mapper = jacksonObjectMapper()
    val vo = mapper.readValue<ValueObject>(""""value"""")

    check(vo == ValueObject("value"))
}

Deserialization fails with:

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `ValueObject` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('value')
 at [Source: (String)""value""; line: 1, column: 1]
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)
	at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1031)
	at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
	at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1366)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3011)
	at MainKt.main(main.kt:14)

The only workaround I found so far is the following:

import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonValue
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue

data class ValueObject(@JsonValue val value: String) {
    private companion object {
        @JsonCreator
        @JvmStatic
        fun valueOf(value: String) = ValueObject(value)
    }
}

fun main(args: Array<String>) {
    val mapper = jacksonObjectMapper()
    val vo = mapper.readValue<ValueObject>(""""value"""")

    check(vo == ValueObject("value"))
}
1reaction
apatridacommented, Oct 27, 2019

I am wondering if what @robpridham-bbc is doing is instead trying to use the ideas of @JsonUnwrapped which won’t currently work since (@cowtowncoder) you get the error:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot define Creator property “content” as @JsonUnwrapped: combination not yet supported

If that is not the case, maybe is intending to use @JsonValue annotation but that succeeds in @Fleshgrinder 's case but not the case of a nested object.

But really I think he just wants the single string constructor to work as-is, so I think this is the solution here:

class Github91Test {

    data class DataClass1(val name: String, val content: DataClass2)

    data class DataClass2 @JsonCreator(mode = JsonCreator.Mode.DELEGATING) constructor (@JsonValue val content: String)

    private val jsonData = """
        {
            "name": "my name",
            "content": "some value"
        }
        """

    @Test
    fun testJsonParsing() {
        val mapper = jacksonObjectMapper()
        val dataClass1 = mapper.readValue<DataClass1>(jsonData)
        assertEquals(DataClass1("my name", DataClass2("some value")), dataClass1)
        assertEquals("{\"name\":\"my name\",\"content\":\"some value\"}", mapper.writeValueAsString(dataClass1))
    }
}

Closing this issue because nothing reported here is an actual bug.

Read more comments on GitHub >

github_iconTop Results From Across the Web

No String-argument constructor/factory method to deserialize ...
Instead of sending values for my Address bean, I'm getting just an empty string. Unfortunately, I'm receiving my data from a third party...
Read more >
No String-Argument Constructor/Factory Method To ... - ADocLib
No String-Argument Constructor/Factory Method To Deserialize From String ... work with little to no public boolean isValid(LocalDate value, ...
Read more >
Class MWStringArray - MathWorks
Creates a one-element string array that represents the java string argument. Parameters: val - The value to initialize the array element. Throws: ...
Read more >
A tour of the Dart language
Define a function. void printInteger(int aNumber) { print('The number is $aNumber. ... name contains a reference to a String object with a value...
Read more >
Java String (Methods & Constructor) with Syntax and Example
The strings in java are a collection of characters bound by double quotes(“”). They are immutable, i.e once they are declared, their values...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found