clojurecheshire

Convert from data.json to cheshire


I am completely new to Clojure. I still struggle with reading functions sometimes.

I am trying to change this function to use checkshire. Here is my attempt :

defn- json->messages [json]
(let [records          (:amazon.aws.sqs/records (cheshire/decode
                                                json
                                                :key-fn key-reader
                                                :value-fn value-reader))
    add-origin-queue (fn [record]
                       (let [event-source-arn (:amazon.aws.sqs/event-source-arn record)
                             queue-name       (arn->queue-name event-source-arn)]
                         (assoc record :amazon.aws.sqs/queue-name queue-name)))]
(map add-origin-queue records)))

The function key-reader function:

(def ^:private
key-reader
(memoize (fn [key]
         (let [kebab-key (if (= "md5OfBody" key)
                           "md5-of-body"
                           (csk/->kebab-case key))]
           (keyword "amazon.aws.sqs" kebab-key)))))

The function :

(def ^:private
value-reader
(memoize (fn [key value]
         (if (= key :amazon.aws.sqs/receipt-handle)
           value-reader
           value))))

I than call the function like so :

(json->messages msg)

msg is a json string.

However I am getting the error below with that attempt :

Execution error (ArityException) at tech.matterindustries.titan.ion.lambda.sqs-receive/json->messages (sqs_receive.clj:36). Wrong number of args (5) passed to: cheshire.core/parse-smile


Solution

  • You are sending the wrong number of args to cheshire.core/parse-smile. Do you have a piece of sample data?

    Please also keep your code clean & formatted, like this:

    (defn- json->messages
      [json]
      (let [records          (:amazon.aws.sqs/records (cheshire/decode json :key-fn key-reader :value-fn value-reader))
            add-origin-queue (fn [record]
                               (let [event-source-arn (:amazon.aws.sqs/event-source-arn record)
                                     queue-name       (arn->queue-name event-source-arn)]
                                 (assoc record :amazon.aws.sqs/queue-name queue-name)))]
        (map add-origin-queue records)))
    

    I could not find decode in the Cheshire docs, but in the source it has this:

    (def decode "Alias to parse-string for clojure-json users" parse-string)
    

    I am disappointed in their incomplete docs.

    A quick google shows the docs:

    (parse-string string & [key-fn array-coerce-fn])
    
    Returns the Clojure object corresponding to the given JSON-encoded string.
    An optional key-fn argument can be either true (to coerce keys to keywords),
    false to leave them as strings, or a function to provide custom coercion.
    
    The array-coerce-fn is an optional function taking the name of an array field,
    and returning the collection to be used for array values.
    

    This may not be clear. What it means is there are 3 legal ways to call parse-string:

    (parse-string  <json-str>)
    (parse-string  <json-str>  <key-fn>)
    (parse-string  <json-str>  <key-fn>  <array-coerce-fn>)
    

    So you can call it with 1, 2, or 3 args. You cannot add in :key-fn or :value-fn map keys, as in your example.

    Please also note that your key-reader and value-reader look like they do not match what cheshire/read-string is expecting.