-
-
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
Nested List and Map in Scala module #12
Comments
BackgroundThis is happening because Jackson doesn't have any information about what types you want. So it uses default representations to provide a best-effort mapping with the most functionality it can. scala> val map1 = objectMapper.readValue("""{"test":"113123","myList":[{"test2":"321323"},{"test3":"11122"}]}""", classOf[Map[String,Any]])
map1: Map[String,Any] = Map(test -> 113123, myList -> [{test2=321323}, {test3=11122}])
scala> map1("myList").getClass
res4: java.lang.Class[_] = class java.util.ArrayList
scala> val list = map1("myList").asInstanceOf[java.util.ArrayList[Any]]
list: java.util.ArrayList[Any] = [{test2=321323}, {test3=11122}]
scala> list.get(0).getClass
res6: java.lang.Class[_] = class java.util.LinkedHashMap
scala> val map2 = list.get(0).asInstanceOf[java.util.LinkedHashMap[String, Any]]
map2: java.util.LinkedHashMap[String,Any] = {test2=321323} Core Jackson is selecting the types here, not the Scala module, specifically through a class called WorkaroundsUse JavaConvertersWithout tweaking your Jackson configuration, you can always add another layer of conversion when you type match the list: scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._
scala> val list = map1("myList") match { case list: java.util.ArrayList[_] => list.asScala }
list: scala.collection.mutable.Buffer[_] = Buffer({test2=321323}, {test3=11122})
scala> val map2 = list(0) match { case map: java.util.Map[_, _] => map.asScala }
map2: scala.collection.mutable.Map[_, _] = Map(test2 -> 321323) Set
|
I think the idea is exactly to use one of Scala List/Map types for contained JSON arrays, lists, but I only now realized that since use of Scala module does not necessarily imply all-Scala, it can't by default change mapping that is used by UntypedObjectDeserializer. However, maybe I should think of ways to make behavior of UntypedObjectDeserializer configurable, so that it would be possible to force use of Scala types (or any other objects). |
Chris, thinking about this bit more, perhaps there should just be an option to override UntypedObjectDeserializer to use Scala Lists and Maps? This is legal (they are Objects after all). And should be easy to configure as well; just need a setting in module, and it could register handler for |
That's probably what I'll end up doing, and probably as the default. Most users are going to want to minimize their exposure to Java standard types anyway, and it looks like |
Makes sense to me. |
@JamiePullar, a follow-up question: is your desire to just see the returned types be Scala types, or do you want specific control over what the default types should be? In other words, for JSON arrays, must it be a List, or would any Seq be OK? |
In my particular case I needed a List, however I would think a seq could be made to work. Specific control does sound cool though.. |
For efficiency reasons, I've implemented this using The code also respects the |
I have finally had the chance to implement these changes, I got a nearly private class NestedTypeObjectDeserializer extends override def mapArray(jp: JsonParser, ctxt: DeserializationContext): override def mapObject(jp: JsonParser, ctxt: DeserializationContext): Thank you very much for your time on this. On Thu, Mar 8, 2012 at 4:09 PM, Christopher Currie <
|
I was suggested to raise this as an issue.
I wish to convert lists of json objects, which in themselves may contain Json objects, or Lists of Json objects and would like the results to be Scala Maps or Lists as appropriate, however, I can only get the top level object to convert to a Map or a List. Is there a simple way to do this?
For example in REPL
objectMapper.readValue("{"test":"113123","myList":[{"test2":"321323"},{"test3":"11122"}]}", classOf[Map[String,Any]])
Will return
res: Map[String,Any] = Map(test -> 113123, myList -> [{test2=321323}, {test3=11122}])
Where I would like
res: Map[String,Any] = Map(test -> 113123, myList -> List(Map(test2 -> 321323), Map(test3 -> 111222)))
The text was updated successfully, but these errors were encountered: