Hi, what is the recommended way to catch JSON parse errors when using Babashka? I tried (catch JsonParseException _ ...) but trying to import that class throws an exception:
> (import '[com.fasterxml.jackson.core JsonParseException])
java.lang.Exception: Unable to resolve classname: com.fasterxml.jackson.core.JsonParseException
Am I doing something silly? Of course I could just catch Exception but I'd like to be more specific.A possible workaround is:
(def -json-parse-ex (Class/forName "com.fasterxml.jackson.core.JsonParseException"))
(try (json/decode "not json") (catch Exception e (instance? -json-parse-ex e)))Thank you, I'll try that.
The error you pasted says that the Jackson you tried importing wasn't foundβnot exactly a parse error.
Yes, I might not have explained myself very well, but the work-around suggested by @doppiaelle1999 works for me. I wanted to do something like this:
(try
(json/parse-string s)
(catch JsonParseException _ nil))...which works in Clojure, but in Babashka I was not able to import that Java exception class.
Got it! Babashka only has certain java classes available, and can't load new java classes at runtime.
A quick test,
1. I can get com.fasterxml.jackson.core.JsonParseException listed as an ancestor class of the exception thrown when I give cheshire.core/parse-string invalid input,
2. β¦ but I can't import that class.
So, Cheshire is included with Babashka, but the Jackson classes aren't included in https://github.com/babashka/babashka/blob/7f280ef7b66d12fa1640ec98f66d73927d382f2e/src/babashka/impl/classes.clj.
Yes, that's the problem I ran into. But using Class/forName and asking instance? as suggested by @doppiaelle1999 is a good-enough solution for me right now.
@teodorlu thank you for the pointer to impl/classes.clj, that might come in handy again!
https://clojurians.slack.com/archives/C8NUSGWG6/p1777747432504649
I was trying to get /proc/meminfo with slurp to check memory stats, but I'm getting this error:
user=> (slurp "/proc/meminfo")
java.io.IOException: Invalid argument [at <repl>:1:1]
files in less protected areas load fine:
user=> (slurp "/tmp/test.txt")
"test\n"
I assume it's a permission issue? but the error wasn't what I'd expect in that casethanks guys, fs/read-all-lines does seem cleaner, I'll probably switch to that.
A very superficial answer would be that bb ostensibly uses clojure's slurp, and so that would raise the question of whether clojure behaves the same way, and (at least on my machine), it does. So, this could be described as bb behaving the same as clojure, which is generally kind of the goal.
I can read the file with jshell (and cat), though, so I don't think it's strictly a permissions issue - there might be more digging to do, but I wonder if it might have to do with the file being in the /proc fs.
This seems to work:
(fs/read-all-lines "/proc/meminfo")Indeed, a google search turns up this quite telling comment: <https://clojuredocs.org/clojure.core/slurp#example-542692d5c026201cdc327086>
;; On Linux, some JVMs have a bug where they cannot read a file in the /proc
;; filesystem as a buffered stream or reader. A workaround to this JVM issue
;; is to open such a file as unbuffered:
(slurp (java.io.FileReader. "/proc/cpuinfo"))
Because slurp uses a buffered read, it ends up calling available() on the file (to see how many bytes can be read) and that can't work on virtual files like this.
(or at least slurp uses a BufferedInputStream if you give it a string and coerces it to a reader that way)
(slurp (io/reader "/proc/meminfo")) doesn't work either (because it creates a BufferedReader). Interesting edge case.
I ended up doing:
(:out (babashka.process/shell {:out :string} "cat" "/proc/meminfo"))
not sure which option is most reliable@lee's suggestion seems to be less involved?
also doesn't need to call out to an external binary