-
-
Notifications
You must be signed in to change notification settings - Fork 142
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
Fail to deserialize @JsonUnwrapped
properties passed via @JsonCreator
#90
Comments
Thanks for the report, I'll look into this as soon as I can. FWIW, the |
I took some time to look at this today. Part of the process involves recreating the use case in Java, to see how the databind module is designed to work with it. The example I came up with this here: https://gist.github.com/christophercurrie/5991810 The best guidance I've found for dealing with this issue is to have a constructor that takes the individual properties as parameters. For your use case, that would (in theory) look something like:
However, due to SI-7661, it appears that this particular formulation won't compile, so you'd have to develop a different set of compiler overloads. I've raised this issue on the Jackson developers list in hopes of finding a better solution, and will provide updates here as I have them. |
The issue in databind has been filed as FasterXML/jackson-databind#265. |
Even using the approach you suggest I can't get it to recognize the @JsonUnwrapped annotation only when serializing:
How do I make this work? |
Perhaps we're making things more complex than they need to be. Since Jackson isn't doing the wrapping for us, and we have to do it by hand, then we might as well make the code adapt to the JSON: case class Person(
name: String,
address1: Option[String],
city: Option[String],
state: Option[String],
alias: Option[String]
) {
def this(name: String, a: Address, alias: String) = this(name, a.address1, a.city, a.state, alias)
@JsonIgnore
val location = Address(address1, city, state)
} This has some unfortunate wrapping/unwrapping when the constructor supporting |
Chris, This approach works on most case as long as you have no more than 22 attributes in a json object/case class. |
Also note that whether problems with combination of Above is just to suggest that to solve urgent practical problem, work-around is the way to go. |
@yunglin True, though I would find a JSON object with more than 22 properties a scary thing indeed. @lmmworko also has another restriction that his field layout is fixed because of database marshaling. I always recommend separate types for wire formats and database formats, even if they are similar today, because variations like this always happen. But writing the monkey code to convert from one to the other is no fun, so I understand why designers shy away from this (even though I would still recommend you write it anyway). As @cowtowncoder mentions, there's still no permanent fix in Jackson for class NonCreatorPerson
{
var name: String = _
@JsonUnwrapped var location: Address = _
var alias: Option[String] = _
} This works just fine for the JSON, but I don't know if it would muck with whatever database marshaling might be in play. The other way, that keeps the class more or less structurally the same, requires the fix I just made in 75d9970 for case class Person(name: String, @JsonIgnore location: Address, alias: Option[String])
{
private def this() = this("", Address(None, None, None), None)
def address1 = location.address1
private def address1_=(value: Option[String]) {
setAddressField("address1", value)
}
def city = location.city
private def city_=(value: Option[String]) {
setAddressField("city", value)
}
def state = location.state
private def state_= (value: Option[String]) {
setAddressField("state", value)
}
private def setAddressField(name: String, value: Option[String])
{
val f = location.getClass.getDeclaredField(name)
f.setAccessible(true)
f.set(location, value)
}
} This basically adds some private setters for Jackson to use to stuff the Address properties into, and some low level JVM reflection hacks to force assignments to Address's vals. It's awful stuff, but it works. However, I'm going to leave this issue as unresolved until I can either come up with better solutions for the Scala module, or a permanent fix in the databind library. |
I have stumbled across this issue too... For what it is worth, I created a simple example with just @JsonUnwrapped:
Then, create the Scala Mapper:
Finally, try to read:
Reading a Point works, but not a Circle:
I get the stack trace:
|
Thanks for your feedback. This is a known issue that requires additional work in the databind library. That work is being tracked in FasterXML/jackson-databind#265. When that issue is resolved, it's expected that this one will be resolved as well. |
I also hit this issue today... Now that FasterXML/jackson-databind#265 is fixed, maybe we can get this to work? |
I now see that scala has the same problem as Kotlin and that FasterXML/jackson-databind#1467 must be fixed.. |
@JsonUnwrapped
properties passed via @JsonCreator
I hit this issue today, any update on this as now is 2021 almost 9 years |
I presume this was closed so that discussion can continue on FasterXML/jackson-databind#1467 |
Yes; this is not Scala-specific as far as I know. |
I am trying to use @JsonUnwrapped to make a flatten json object into more structure scala object. However, jackson will throw
java.lang.IllegalStateException: Method should never be called on a com.fasterxml.jackson.databind.deser.CreatorProperty
I wrote a test case for this issue and tested on 2.2.2 release and 2.3.0-SNAPSHOT, and neither of them can pass the test.
The text was updated successfully, but these errors were encountered: