Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserializing @JacksonXmlText #198

Closed
harpocrates opened this issue Jun 10, 2016 · 10 comments
Closed

Deserializing @JacksonXmlText #198

harpocrates opened this issue Jun 10, 2016 · 10 comments

Comments

@harpocrates
Copy link

harpocrates commented Jun 10, 2016

Whilst there is no problem serializing a field annotated with @JacksonXmlText, deserialization always chokes up. For example (in Scala, but should be clear enough):

case class Phone (
  @JacksonXmlProperty(isAttribute = true, localName = "type") phoneType: String,
  @JacksonXmlText phoneNumber: String
)

Serializes Phone("cell","000-000-0000") into <phone type="cell">000-000-0000</phone>, but deserializing the same thing will fail with

JsonMappingException: Could not find creator property with name ''

Is there a reason this can't/shouldn't be supported, at least in restricted situations like the above? It seems like this falls under the "XML written using this module must be readable using module as well".

@cowtowncoder
Copy link
Member

That should just work. I'll see if I can creat reproduction.

I assume this is with 2.7.4.

cowtowncoder added a commit that referenced this issue Jun 10, 2016
@cowtowncoder
Copy link
Member

I can not reproduce the problem with Jackson 2.7.4.

@harpocrates
Copy link
Author

Yeah. I think I have a dependency problem that is making me use an older version of Jackson.

Sorry to have bothered you. This is a great project!

@cowtowncoder
Copy link
Member

@harpocrates Np, glad it works for you!

@Sjworks
Copy link

Sjworks commented Feb 20, 2018

I got a same issue with Jackson 2.8.10
my dependencies is

  "com.fasterxml.jackson.core" % "jackson-core" % "2.8.10",
  "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.8.10",
  "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.8.10",

code is here

@JacksonXmlRootElement(localName = "DataType")
case class DataType1 (
                       @JacksonXmlProperty(isAttribute = true, localName = "Usage")
                       usage: String,
                       @JacksonXmlProperty(isAttribute = true, localName = "IsUnsigned")
                       isUnsigned: Boolean,
                       @JacksonXmlText
                       value: String
                     )

xml is

<DataType Usage="MYSQL" IsUnsigned="True">INT</DataType>

Console

[error] application - Invalid definition for property "" (of type Lmodels/version1/DataType1;): Could not find creator property with name '' (known Creator properties: [Usage, IsUnsigned, value])
 at [Source: java.io.StringReader@6f8b3d1e; line: 1, column: 1]
com.fasterxml.jackson.databind.JsonMappingException: Invalid definition for property "" (of type Lmodels/version1/DataType1;): Could not find creator property with name '' (known Creator properties: [Usage, IsUnsigned, value])
 at [Source: java.io.StringReader@6f8b3d1e; line: 1, column: 1]
	at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)
	at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:1329)
	at com.fasterxml.jackson.databind.DeserializationContext.reportBadPropertyDefinition(DeserializationContext.java:1293)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.addBeanProps(BeanDeserializerFactory.java:600)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:269)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:184)
	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)

:(

@iteratoruk
Copy link

iteratoruk commented Aug 2, 2018

Same issue with 2.9.6:


import com.fasterxml.jackson.annotation.{JsonCreator, JsonInclude, JsonProperty}
import com.fasterxml.jackson.databind.{DeserializationFeature, SerializationFeature}
import com.fasterxml.jackson.dataformat.xml.annotation.{JacksonXmlProperty, JacksonXmlRootElement, JacksonXmlText}
import com.fasterxml.jackson.dataformat.xml.{JacksonXmlModule, XmlMapper}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import org.scalatest.{MustMatchers, WordSpec}

// fails with Jackson 2.9.6:
/*
Invalid definition for property `` (of type `MyElement`): Could not find creator property with name '' (known Creator properties: [anAttribute, theValue])
 at [Source: (StringReader); line: 1, column: 1]
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid definition for property `` (of type `MyElement`): Could not find creator property with name '' (known Creator properties: [anAttribute, theValue])
 at [Source: (StringReader); line: 1, column: 1]
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:62)
	at com.fasterxml.jackson.databind.DeserializationContext.reportBadPropertyDefinition(DeserializationContext.java:1446)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.addBeanProps(BeanDeserializerFactory.java:567)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:227)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:137)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:411)
	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:444)
	at com.fasterxml.jackson.module.scala.deser.OptionDeserializer.createContextual(OptionDeserializerModule.scala:48)
	at com.fasterxml.jackson.databind.DeserializationContext.handlePrimaryContextualization(DeserializationContext.java:651)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:484)
	at com.fasterxml.jackson.databind.deser.std.DelegatingDeserializer.resolve(DelegatingDeserializer.java:58)
	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:477)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4190)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4009)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
	at CaseClassJacksonXmlTextTest$$anonfun$1$$anonfun$apply$mcV$sp$1.apply(CaseClassJacksonXmlTextTest.scala:34)
 */
class CaseClassJacksonXmlTextTest extends WordSpec with MustMatchers {

  private val module = new JacksonXmlModule()
  module.setDefaultUseWrapper(false)
  private val mapper = new XmlMapper(module)
  mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
  mapper.configure(SerializationFeature.INDENT_OUTPUT, true)
  mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
  mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
  mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT)
  mapper.registerModule(DefaultScalaModule)

  "serialization" should {

    "be commutative" in {
      val doc = MyDocument(Some(MyElement(
        anAttribute = Some("foo"),
        theValue = Some("bar")
      )))
      val sw = new StringWriter()
      mapper.writeValue(sw, doc)
      val serialized = sw.toString
      val deserialized = mapper.readValue(serialized, classOf[MyDocument])
      deserialized must be(doc)
    }

  }

}

@JacksonXmlRootElement(localName = "MyDocument")
case class MyDocument(@JacksonXmlProperty(localName = "MyElement")
                      somethingWithXmlText: Option[MyElement] = None)


case class MyElement(@JacksonXmlProperty(localName = "anAttribute", isAttribute = true)
                     anAttribute: Option[String] = None,

                     @JacksonXmlText
                     theValue: Option[String] = None)```

@iteratoruk
Copy link

My current workaround is to use a custom deserializer:

@JsonDeserialize(using = classOf[AttributeAndTextTypeDeserializer])
case class MyElement(@JacksonXmlProperty(localName = "anAttribute", isAttribute = true)
                     anAttribute: Option[String] = None,

                     @JacksonXmlText
                     theValue: Option[String] = None)

class AttributeAndTextTypeDeserializer extends StdDeserializer[MyElement](classOf[MyElement]) {

  override def deserialize(p: JsonParser, ctx: DeserializationContext): MyElement = {
    val n: JsonNode = p.getCodec.readTree(p)
    MyElement(nonEmptyOrNone(n.get("anAttribute").asText("")), nonEmptyOrNone(n.get("").asText("")))
  }

  private def nonEmptyOrNone(str: String): Option[String] = if (str.trim.isEmpty) None else Some(str)

}

@Simon3
Copy link

Simon3 commented Nov 3, 2021

Same problem here with Jackson 2.11.4
Basically, @JacksonXmlText works for serialization, but not for deserialization.
Can we re-open this ticket or do we have to open a new one?

@cowtowncoder
Copy link
Member

2.11.4 is pretty old, so I'd want reproduction with 2.13.0.

But as to issue: yes, please file a new issue -- I don't like reopening closed issues due to complexity of version tracking (wrt release notes) and likelihood of there being different underlying issues.
Referencing older issue from new one is fine and can be useful of course, but a new issue with full reproduction makes sense here.

@Simon3
Copy link

Simon3 commented Nov 9, 2021

Actually, forget about it. My problem is related to Kotlin data classes. Works fine with normal classes.
Seems to be a known issue in jackson-module-kotlin: FasterXML/jackson-module-kotlin#138

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants