I have an application (several actually) which decode JSON data in a Map using Jackson. Data appears to either be in a Map or ArrayList (in the case of JSON arrays.) The data that comes in on these streams is unstructured, so this won't be changing.
I own some Clojure code which accesses nested properties in these objects. Ideally I'd like to extend the Associative abstraction to these Java types so that get-in
works on them. Something like the following:
(extend-protocol clojure.lang.Associative
java.util.Map
(containsKey [this k] (.containsKey this k))
(entryAt [this k] (when (.containsKey this k)
(clojure.lang.MapEntry/create k (.get this k))))
java.util.ArrayList
(containsKey [this k] (< (.size this) k))
(entryAt [this k] (when (.containsKey this k)
(clojure.lang.MapEntry/create k (.get this k)))))
There are two problems with this; The first being that Associative is not a protocol (if it were this appears it would work). The second being that the types are already defined so I cannot add Associative with deftype.
I'm pretty new to the JVM interop part of Clojure. Is there a method I'm not seeing? Or is there a protocol which wraps Associative and will work with get-in
that I've missed?
Thanks SO!
The answer is that half of the extension you want to do is already done, and the other half cannot be done. The
get-in
function callsget
, which callsclojure.lang.RT/get
, which callsclojure.lang.RT/getFrom
, which callsjava.util.Map/get
if the first argument is aMap
. So if you have any JavaMap
, thenget-in
works (I'm borrowing this example directly from thedoto
docstring):However, Clojure does not have a
get
implementation forList
s that supportRandomAccess
. You could write your ownget
that does:Example:
Then you could copy the implementation of
get-in
so it would use your customget
function.I'm pretty sure this isn't what you want, though, because then every bit of code you write would have to use your
get-in
rather than Clojure'sget-in
, and any other code that already uses Clojure'sget
would still not work withArrayList
s. I don't think there's really a good solution to your problem, unfortunately.