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

in some cases serialization of option is not working #398

Open
oshai opened this issue Feb 12, 2019 · 17 comments
Open

in some cases serialization of option is not working #398

oshai opened this issue Feb 12, 2019 · 17 comments
Labels
need-test For resolution, reproduction (ideally a test case) is needed

Comments

@oshai
Copy link

oshai commented Feb 12, 2019

We are using jackson 2.9.8.

Sometimes (we couldn't find any consistent case) it ignore option (like scala module is unaware of option and just writing a json like this:
{"x":1,"empty":false,"defined":true}
(in this case this is an option of int).

@nbauernfeind
Copy link
Member

Is there any chance you teased out what kind of types (static inner classes, anonymous inner classes, etc) it fails to serialize?

@oshai
Copy link
Author

oshai commented Mar 25, 2019

It was simple types like Boolean and Int (Option of them)

@nbauernfeind
Copy link
Member

I doubt it is that simple. We have tests that pass on all released versions of this module that specifically serialize Option[Int].

See: https://github.com/FasterXML/jackson-module-scala/blob/master/src/test/scala/com/fasterxml/jackson/module/scala/ser/OptionSerializerTest.scala#L69

Is there any chance you were using an ObjectMapper that did not have the proper scala modules registered?

@oshai
Copy link
Author

oshai commented Mar 25, 2019

I don't think so. It looked like a race condition, because it didn't happen to the type on all mapping but only on specific methods.

@nbauernfeind
Copy link
Member

Race condition, in that sometimes a singular code path would serialize correctly and other times it would not?

What version of scala are you using? Do you still observe this issue?

@oshai
Copy link
Author

oshai commented Mar 25, 2019

It's more looks like a race condition on construction time because when it fails for a specific endpoint it will constantly fail on that. However, it wasn't failing on all entities with that type and we also have few instances of the service and it failed only on a couple of them. Scala version is 2.11.7.

@nbauernfeind
Copy link
Member

If you can tease out a toy program that (when run enough times) will eventually fail, then I would be happy to investigate further. Otherwise, I am not aware of any inherent race conditions in scala 2.11.x - so I'm not even sure what would be an appropriate scenario to try.

@oshai
Copy link
Author

oshai commented Mar 25, 2019

Unfortunately, we didn't manage to reproduce it.

@nbauernfeind
Copy link
Member

@plokhotnyuk, I see your +1 -- any chance you have a different use case or a repeatable issue?

@oshai
Copy link
Author

oshai commented Mar 25, 2019

One thing that might help is that we reverted to 2.6.5 and don't see the issue anymore.

@nbauernfeind
Copy link
Member

That slightly helps ... in that the code paths for Option before and after 2.7.4 are completely different.

@plokhotnyuk
Copy link

plokhotnyuk commented Apr 10, 2019

@nbauernfeind the working w/a for me is using jsoniter-scala instead - it generates codecs at compile time and can print their sources for validation, like here

@karlroberts
Copy link

Hi guys I have the same problem, not had time to extract it to a simple test yet as gotta just revert the version bump to get into prod, but this is what I know so far.

The bug can manifest rendering a simple DTO that contains two scala Option[Long] both Some(..)'s
the first option renders as a Number the second as a an Option rendered by the Bean Mapper showing it's properties , eg value, empty and defined

A simple test of my WebRestObjectMapper (see below) does not have a problem.

class WebRestObjectMapper extends ObjectMapper { registerModule(new DefaultScalaModule) registerModule(new JodaModule) configure(WRITE_DATES_AS_TIMESTAMPS, false) configure(FAIL_ON_UNKNOWN_PROPERTIES, false) this.setSerializationInclusion(JsonInclude.Include.NON_NULL) this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY) this.setSerializationInclusion(JsonInclude.Include.NON_ABSENT) }

the FunSpec test looks like

`/** test for Bug ParentId is an Option[Long] but sometimes represents like
*
* "parentId": {
* "value": 11,
* "empty": false,
* "defined": true
* }
*
*/
describe("WebRestObjectMapper for EntityCategoryDto") {

it("should writeEntityCategoryDto non-empty parentId Option[Long] as a simple Number") {
  new Fixtures {
    val dto1 = EntityCategoryDto(Some(22), "Number 22", "testing", Some(22L))
    mapper.writeValueAsString(dto1) should be("""{"id":22,"name":"Number 22","type":"testing","parentId":22}""")
  }
}

}`

However when using Spring WebMVC (version 4.3.5.RELEASE ) vial a Controller the error manifests.
debugging by placing a breakpoint at BeanPropertyWriter.java.702 to watch the _dynamicSeralizers Map be a different instance for first Option and second Option in EntityCategoryDto The first time the _dynamicSeralizers is the Single instance which works matching “scala.Some” with “scala.Some” in

if (type == _type)

on line PropertySerializerMap.java:279

the second time it is the Double and the equivalent if(type = type) on line 310 compares “scala.Some” with “scala.None” so doesn’t match and falls back to the _serializer2 which is a the BeanMapper which renders the Options properties.

I do not know why the _dynamicSeralizers are different each time while running through the my EntityCategoryDto case class.

Hope this helps someone to fix it.

Cheers

@galando
Copy link

galando commented Aug 20, 2019

Hey guys,

We would like to upgrade to scala 2.13 and use the latest jackson-module-scala version which supports it.

Any news about this issue? we are in concern about upgrading to the latest version when this issue still exists.

Thanks a lot!

@cowtowncoder
Copy link
Member

@galando Github issues are not good discussion forum: please use mailing list:

https://groups.google.com/forum/#!forum/jackson-user

for questions like this.

@galando
Copy link

galando commented Sep 2, 2019

Thanks @cowtowncoder for the clarification.

@cowtowncoder cowtowncoder added the need-test For resolution, reproduction (ideally a test case) is needed label Sep 4, 2019
@cowtowncoder
Copy link
Member

I noticed the email so maybe others can comment there, but 2 other things:

  1. Looks like there is no reliable reproduction (unless I missed it from above): one is needed to show what exactly is wrong -- and especially on Jackson side. It is possible issue is with framework(s), not Jackson, since they typically do not pass fully resolve type information (mostly fault of JDK lacking good mechanisms, but that's longer discussion)
  2. We have a new co-owner of this module, @pjfanning, who might be able to have a look at this issue, so cc:ing him.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
need-test For resolution, reproduction (ideally a test case) is needed
Projects
None yet
Development

No branches or pull requests

6 participants