This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-10-13
Channels
- # announcements (1)
- # babashka (41)
- # beginners (194)
- # calva (14)
- # chlorine-clover (2)
- # cider (32)
- # circleci (9)
- # cljsrn (10)
- # clojure (110)
- # clojure-australia (1)
- # clojure-berlin (2)
- # clojure-dev (39)
- # clojure-europe (42)
- # clojure-france (3)
- # clojure-nl (19)
- # clojure-spec (22)
- # clojure-uk (23)
- # clojurescript (21)
- # conjure (41)
- # datomic (33)
- # depstar (16)
- # duct (46)
- # events (1)
- # fulcro (17)
- # graphql (14)
- # jobs (6)
- # jobs-discuss (9)
- # leiningen (6)
- # malli (29)
- # off-topic (21)
- # pathom (7)
- # portal (1)
- # rdf (81)
- # re-frame (3)
- # reagent (12)
- # reitit (2)
- # remote-jobs (1)
- # rum (1)
- # shadow-cljs (60)
- # specter (1)
- # sql (13)
- # tools-deps (23)
- # vrac (1)
- # yada (19)
I'm trying to parse a json message from aws cli but got stuck pretty early - what am I doing wrong?
echo '{"DecodedMessage" : "{\"allowed\":false,\"explicitDeny\":false}"}' | bb -i "(do (require '[cheshire.core :as json]) (let [{:strs [DecodedMessage] :as msg} (json/parse-string *input*)] (println DecodedMessage) ))" | bb -i "(do (require '[cheshire.core :as json])
(let [{:strs [DecodedMessage] :as msg} (json/parse-string *input*)] (println DecodedMessage) ))"
----- Error --------------------------------------------------------------------
Type: java.lang.ClassCastException
Message: clojure.lang.Cons cannot be cast to java.lang.String
Location: <expr>:2:50
----- Context ------------------------------------------------------------------
1: (do (require '[cheshire.core :as json])
2: (let [{:strs [DecodedMessage] :as msg} (json/parse-string *input*)] (println DecodedMessage) ))
^--- clojure.lang.Cons cannot be cast to java.lang.String
----- Stack trace --------------------------------------------------------------
cheshire.core/parse-string - <built-in>
user - <expr>:2:50
In the REPL, this works:
(def *input* "{\"DecodedMessage\" : \"{\\\"allowed\\\":false,\\\"explicitDeny\\\":false}\"}")
(do (require '[cheshire.core :as json])
(let [{:strs [DecodedMessage] :as msg} (json/parse-string *input*)] (println DecodedMessage) ))
;;=>
{"allowed":false,"explicitDeny":false}
I think
-i Bind *input* to a lazy seq of lines from stdi
@U06BE1L6T Can you try replacing -i
with -e
?Ah right, now I'm getting a different error 🙂
----- Error --------------------------------------------------------------------
Type: clojure.lang.EdnReader$ReaderException
Message: java.lang.RuntimeException: Invalid token: :
Location: 1:99
----- Stack trace --------------------------------------------------------------
- <expr>:1:99
cheshire.core/parse-string - <built-in>
user - <expr>:1:80
When using -i
then input becomes a lazy seq of lines. You should be aware of this. Cheshire cannot parse a lazy seq of text, it just parses text.
echo '{"DecodedMessage" : "{\"allowed\":false,\"explicitDeny\":false}"}' | bb -e "(do (require '[cheshire.core :as json]) (let [{:strs [DecodedMessage] :as msg} (json/parse-stream *in*)] (println DecodedMessage) ))"
{"allowed":false,"explicitDeny":false}
@U04V15CAJ I think forgetting -i
or using *input*
instead of *in*
are easy mistakes to make. Did you consider using something like delays to gives some user feedback here? E.g. @`*input*` could throw an error if -i
is not used. Maybe it would also be helpful if there was one var for a particular input. Now *input*
can have different shapes based on the flag. I understand something like this would be a breaking change, but I’m curious what you think
You don't need to use -i
and *input*
together, if you don't provide -i
input contains EDN from stdin
Yes I understand that reading the docs would help. I was thinking there might be a more foolproof way. But your position is clear :)
These flags were invented when babashka was more or less just for one-liners and it could not run scripts, namespaces, macros, etc, etc. I don't use these flags a lot myself. Maybe I should hide them a little bit in the README ;)
maybe hide them behind a flag --show-flags
😅
It sounds useful. I haven’t done much with input yet. The potential error cases would grow I’m guessing, maybe like the example above
Or an idea could be to not have flags, but leave it to the program? Maybe something like https://github.com/originrose/lazy-map that you would call like (:edn-stream *input*)
. It would start parsing on the first call (i.e. lazy). If the value is incorrect it would throw. If there is no input it would throw. Would this make sense?
That’s true, only benefit would be that you don’t have to have a reference somewhere. But maybe it’s too magical for little benefit
http://babashka.io helper namespace with parse-edn-stream, etc could work
Makes sense. Would also make example scripts more explicit (no need to guess the flag settings)
(http://babashka.io/edn-stream) (assumes input is in) (http://babashka.io/edn-stream reader) (explicit reader) same for json, transit
Nice 🙂 And this lib could potentially be used from the jvm as well (I guess). So would make it easier to reuse both directions
@U04V15CAJ Thanks for listening 🙂