-
-
Notifications
You must be signed in to change notification settings - Fork 164
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
Can't parse JSON map to Map[String, T] #39
Comments
The basic problems is that |
You could probably shadow the default implementation for serializing Maps and make it drop down to json dicts if the keys are all strings. Kinda hacky but it'd work, and I suspect it'd work. |
Thanks for your reply. I've added the following instances for Maps with String keys in my project: implicit def MapWithStringKeysW[V: Writer] = Writer[Map[String, V]] {
obj => Js.Obj(obj.toSeq.map(x => (x._1, writeJs[V](x._2))): _*)
}
implicit def MapWithStringKeysR[V: Reader] = Reader[Map[String, V]] {
case json: Js.Obj => json.value.map(x => (x._1, readJs[V](x._2))).toMap
} This works for me at the moment. Would you consider adding something like this to the library? |
Yep, I'd like to do that at some point. How does this play with existing On Mon, Nov 17, 2014 at 3:40 PM, Anton Beloglazov notifications@github.com
|
Here are some examples you've given in #17 (comment): println(upickle.write(Map("hello" -> (1, "world"))))
println(upickle.write(Map((1, "hello") -> "world")))
println(upickle.write(Map(Seq(1, 2, 3) -> "world")))
println(upickle.write(Map("hello" -> Seq(1, 2, 3)))) The output is: {"hello":[1,"world"]}
[[[1,"hello"],"world"]]
[[[1,2,3],"world"]]
{"hello":[1,2,3]} Would you like me to test anything else? |
That looks perfectly reasonable. What about def func[T: Writer](t: T) = upickle.write(Map(t -> 123))
func("10")
upickle.write(Map("10" -> 123))
func(10) |
In this case the output is: [["10",123]]
{"10":123}
[[10,123]] It didn't pull the correct implicit for the first case for some reason. Do you have any ideas of how to solve this? |
I don't know if it's solvable; it's doing exactly what we're asking it to do: get a For it to be consistent, it feels to me that the only solutions would be to
Both of these feel pretty sketchy, but I'm not sure which one is less sketchy =/ Having the shape of your JSON changing unpredictably under you is sketchy, but so is having to recursively |
I see, thanks for the explanation. I've added two more instances as you suggested: implicit def MapW[K: Writer, V: Writer]: Writer[Map[K, V]] = Writer[Map[K, V]](
x => {
if (x.nonEmpty && x.head._1.isInstanceOf[String])
Js.Obj(x.toSeq.map(entry => (entry._1.asInstanceOf[String], writeJs[V](entry._2))): _*)
else
Js.Arr(x.toSeq.map(writeJs[(K, V)]): _*)
}
)
implicit def MapR[K: Reader, V: Reader]: Reader[Map[K, V]] = Reader[Map[K, V]] {
case json: Js.Obj => json.value.map(x => (x._1.asInstanceOf[K], readJs[V](x._2))).toMap
case json: Js.Arr => json.value.map(readJs[(K, V)]).toMap
} The output is now correct for the case of String keys: {"10":123}
{"10":123}
[[10,123]] |
Here's an interesting case: what if instead of checking the head of the map, we checked the implicit
|
Sorry for taking long to reply. I agree, empty string-key maps should definitely be handled consistently with non-empty ones. However, I couldn't figure out how to check if |
I was more thinking implicitly[Writer[T]] == upickle.StringRW That should work right? |
Naturally, it won't work for people who define their own Another less-hard-coded solution is to provide Writer[T].asStringKey(t: T): Option[String]
Reader[T].fromStringKey(s: String): Option[T] That will allow other non- Of course, the downside is that this doubles the API surface-area of |
Sorry, I didn't notice implicit def MapW[K: Writer, V: Writer](implicit sw: Writer[String]): Writer[Map[K, V]] = Writer[Map[K, V]](
x => {
if (implicitly[Writer[K]] == sw)
Js.Obj(x.toSeq.map(entry => (entry._1.asInstanceOf[String], writeJs[V](entry._2))): _*)
else
Js.Arr(x.toSeq.map(writeJs[(K, V)]): _*)
}
) You idea about |
On further thought, I think it'd be best to limit the weirdness of JSON objects to the |
Remember you'll need to update |
Sure, I'll try to do that soon. Thanks! |
Thanks for making these changes! Sorry, I was busy with other work. Are you going to release a new version? |
At some point; thinking of waiting for Scala.js 0.6.0 to come out. Lazy to modify and publish all my libraries more than once... |
Cool, I'm looking forward to that :) |
I think the error I'm receiving is related to this issue |
It seems the library has evolved meanwhile and the writer needs to be written differently. I think following should do the job with recent version:
|
Hi Li,
Thanks for your work on this project, it's very nice! I've faced a problem when trying to parse the following JSON (output from CouchDb):
I have the following classes:
When I'm trying to parse the JSON with something like:
upickle.read[Person](json)
I get the following exception:
As I understand, it's having problems with creating an instance of Map. Do you know any way to resolve this? Thanks!
The text was updated successfully, but these errors were encountered: