Comments (10)
@alexwei jackson-module-scala is an ugly set of hacks around the Java-centric library 'jackson-databind'
With the endless variety of configuration that jackson allows but with Java-centric implementations in jackson-databind, jackson-module-scala simply can't keep up.
Fixing this could take days of fiddly debugging and require changes in both jackson-databind and jackson-module-scala.
My main aim is to get jackson-module-scala to handle the vanilla configuration of ObjectMapper. Once people start tweaking advanced Java-centric configs of jackson-databind - I lose interest. The cost-benefit is heavily skewed against spending time on this.
from jackson-module-scala.
The issue seems to be a serialization issue:
vanilla ObjectMapper writes:
{"a":"abc","b":1,"c":"zyx","d":[0,1,2],"e":{"a":"1","b":"2","c":"3"}}
.activateDefaultTyping(mapper.getPolymorphicTypeValidator, DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY)
causes this output with terrible class choices
["com.fasterxml.jackson.module.scala.ser.DefaultTypingSerializationTest$JacksonTestData",{"a":"abc","b":1,"c":"zyx","d":["scala.collection.immutable.$colon$colon",[0,1,2]],"e":["scala.collection.convert.JavaCollectionWrappers$MapWrapper",{"a":"1","b":"2","c":"3"}]}]
from jackson-module-scala.
I, personally, would never use a Map when dealing when serializing/deserializing data. I would try to use collections that contain strongly typed data - Seq[MyCaseClass]
or Seq[(A, B)]
or something like that.
Putting class names in JSON output doesn't feel great.
If I had to get something working with JacksonTestData, I would change the Map[String, String]
to Seq[String, String]
or java.util.Map[String, String]
Or just use a vanilla mapper instance (ie without the DefaultTyping set).
from jackson-module-scala.
Noting that this used to work in Scala 2.12 through a bit of good fortune.
AFAICT
jackon-module-scala
'sMapConverter
callsmap.asJava
to convert (well, wrap) the ScalaMap
as a JavaMap
.jackson-databind
-sMapSerializer.serializeWithType
decides what class name to emit in the JSON by callingClassNameIdResolver.idFromType
in a resolver withthis._baseType = MapLikeType("scala.collection.immutable.Map", ...)
- In Scala 2.12, the
.asJava
call gives an inner classscala.collection.convert.Wrappers$MapWrapper
. In 2.13 we get an non-inner class (as it enclosed in an scalaobject
, notclass
)scala.collection.convert.JavaCollectionWrappers$MapWrapper
. idFromType
falls back to using the base type (which is what we're after, I think), in 2.12. In 2.13 it emits the type id ofJavaCollectionWrappers$MapWrapper
, but this leads to a failure in deserializing.
A workaround would be to replace the .asJava
call with an explicit wrapping of the value in a custom class that a) implements java.util.Map, and b) is an inner class. 🤮!
from jackson-module-scala.
The big problem really is that Jackson's databind has pretty decent support for Map
and Collection
implementations, but Scala's counterparts do not implement them. As such there's much less support for "Map-like" and "Collection-like" types so implementation is by definition more involved. Although if existence of these was known at the time original Map/Collection (de)serializers were built they could probably have been implemented in a way to improve reuse.
Now doing 2-phase processing using Java Map/Collection intermediates works ok for most other aspects but NOT for polymorphic typing (esp. via Default Typing) because it by definition is very tightly coupled to implementation types -- and in this case information for Wrapper is used.
I guess I am just repeating much of what @retronym just said. :)
from jackson-module-scala.
I spent some time trying to hack a solution but I just kept hitting issues. I have many higher priority things to work on so I'm not planning to spend much time on this.
- It is very easy to workaround - don't enable default typing when deserializing such JSON
- this is not a new issue and so far only 1 person has raised an issue
- probably the best solution is #470 but that involves forking a 1000+ line Java serializer and adding tonnes of test coverage for that 1000 lines of code to cover all the various code paths through that 1000 lines
from jackson-module-scala.
Thanks for the notes.
I'm doing maintenance work across a large codebase and luckily there only seems to be one small spot using Default Typing within fairly extensive usage of jackson-scala. It looks like this was done to serialise a Scala sealed hierarchy.
I'm going to use an alternative mechanism for that instead. I believe @ JsonTypeInfo + @ JsonSubtypes should work as per https://stackoverflow.com/questions/18027233/jackson-scala-json-deserialization-to-case-classes .
from jackson-module-scala.
Thanks @retronym - JsonTypeInfo/JsonSubtypes annotations are the best way to do this.
DefaultTyping should be ok if you avoid Scala Maps.
from jackson-module-scala.
@retronym I'm not sure if it's a great idea but I have reflection based libs that extend jackson-module-scala and that auto-discover subtypes for sealed traits. You still need the JsonTypeInfo annotation (but don't need to list the sub types). I was hoping to create a jackson-databind enhancement that would allow you to avoid the JsonTypeInfo annotation too but I haven't gotten around to it.
https://github.com/FasterXML/jackson-module-scala#related-projects (separate projects for Scala 2 and Scala 3 - because the code differs quite a bit depending on which Scala version you are using).
from jackson-module-scala.
@pjfanning I finally got back to trying to work around this bug. It proved awkward so I took another look at finding a workaround in the library:. Here's my PR: #658
from jackson-module-scala.
Related Issues (20)
- Release 2.16.0 HOT 2
- release jackson-module-scala v2.12 for Scala 2.10 HOT 2
- Release 2.16.1 HOT 1
- Update `2.17` branch to `2.17.0-rc1-SNAPSHOT` HOT 2
- Release 2.15.4 HOT 1
- Release 2.17.0-rc1 HOT 1
- Release 2.16.2 HOT 2
- Release 2.17.0 HOT 2
- Performance regression with 2.17.x HOT 32
- Update 2.17 release note wiki with Scala module 2.17 fixes HOT 4
- Release 2.17.1 HOT 1
- See if there is benefit from integrating with jackson-databind better wrt detecting "canonical" Constructor for Scala (case) classes HOT 4
- Jackson Scala module build from`master` (v3) fails HOT 16
- investigate OptionSerializerTest default typing test and CaseClassSerializerTest serialize java getters test
- Release 2.17.2 HOT 2
- potentially implement annotation introspector findPrimaryCreator HOT 1
- investigate deserialization case that works in Jackson 2.18 but fails in Jackson 3
- Change to `DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES` default in 3.0 databind leads to Scala test fails
- Different handling of null and absent value during deserialization HOT 5
- Release 2.18.0-rc1 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jackson-module-scala.