Clojure encode Joda DateTime with ring-json
Asked Answered
D

3

6

With the following app:

; src/webapp/core.clj
(ns webapp.core
  (:require [compojure.core :refer [defroutes GET]]
            [ring.middleware.json :as mid-json]
            [clj-time.jdbc]))

(defn foo [request]
  {:body {:now (org.joda.time.DateTime/now)}})

(defroutes routes
  (GET "/foo" [] foo))

(def app
  (-> routes
      (mid-json/wrap-json-response)))

Hitting the /foo endpoint gives me this error:

com.fasterxml.jackson.core.JsonGenerationException: Cannot JSON encode object of class: class org.joda.time.DateTime: 2017-10-21T03:38:16.207Z

Is there a simple way to get ring-json to encode the DateTime object? Do I have to write my own middleware to convert it to e.g. a string first? If so, how would I do that? (I've never written ring middleware before).

My project.clj has these dependencies FYI:

[[org.clojure/clojure "1.8.0"]
 [org.clojure/java.jdbc "0.6.1"]
 [ring/ring-jetty-adapter "1.4.0"]
 [compojure "1.4.0"]
 [ring/ring-json "0.4.0"]
 [clj-time "0.14.0"]]
Dorton answered 21/10, 2017 at 3:53 Comment(0)
F
10

If you're using Cheshire to generate JSON, you can extend its protocol to handle serialization then it should "just work":

(extend-protocol cheshire.generate/JSONable
  org.joda.time.DateTime
  (to-json [dt gen]
    (cheshire.generate/write-string gen (str dt))))
Floatage answered 21/10, 2017 at 4:0 Comment(0)
F
0

Additionally, the following modification made it work for projects that are using the time library tick.alpha.api. I was getting the error

#error {:cause Cannot JSON encode object of class:
 class java.time.Instant: 2019-10-23T00:31:40.668Z
 :via
 [{:type com.fasterxml.jackson.core.JsonGenerationException
   :message Cannot JSON encode object of class:
 class java.time.Instant: 2019-10-23T00:31:40.668Z
   :at [cheshire.generate$generate invokeStatic generate.clj 152]}]

Implementing the following in the file db/core.clj fixed the issue for me.

(extend-protocol cheshire.generate/JSONable
  java.time.Instant
  (to-json [dt gen]
    (cheshire.generate/write-string gen (str dt))))
Franciscofranciska answered 26/10, 2019 at 17:47 Comment(0)
F
0

Another way to do the same thing as Taylor Woods answer:

(cheshire.generate/add-encoder java.time.LocalDate cheshire.generate/encode-str)
Fourgon answered 27/10, 2023 at 16:41 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.