Skip to content

Commit

Permalink
Better java.time support.
Browse files Browse the repository at this point in the history
  • Loading branch information
cnuernber committed Aug 23, 2021
1 parent e47fe95 commit c67f446
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 19 deletions.
54 changes: 41 additions & 13 deletions src/tech/v3/libs/cljs_ajax.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,61 @@
[ajax.interceptors :as ajax-interceptors]
[ajax.transit :as ajax-transit]
[tech.v3.dataset :as ds]
[cognitect.transit :as transit]))
[tech.v3.datatype.datetime :as dtype-dt]
[java.time :refer [LocalDate Instant]]
[cognitect.transit :as t]))


(def ^{:doc "Transit writer used for writing transit-json datasets and uses
`ds/transit-write-handler-map`" }
writer (transit/writer :json {:handlers (ds/transit-write-handler-map)}))
(defonce write-handlers* (atom (ds/transit-write-handler-map)))
(defonce read-handlers* (atom (ds/transit-read-handler-map)))


(def ^{:doc "cljs-ajax interceptor that hardwires content-type to application/transit+json
and uses `ds/transit-read-handler-map`." }
response-format
(defn add-transit-io-handlers!
[datatype tag read-fn write-fn]
(swap! write-handlers* assoc datatype (t/write-handler (constantly tag) write-fn))
(swap! read-handlers* assoc tag read-fn))


(defn add-java-time-handlers!
"Add handlers for java.time.LocalDate and java.time.Instant"
[]
(add-transit-io-handlers! LocalDate "java.time.LocalDate"
dtype-dt/epoch-days->local-date
dtype-dt/local-date->epoch-days)
(add-transit-io-handlers! Instant "java.time.Instant"
dtype-dt/epoch-milliseconds->instant
dtype-dt/instant->epoch-milliseconds))


(defn writer
"Transit writer used for writing transit-json datasets and uses
`ds/transit-write-handler-map`"
[]
(t/writer :json {:handlers @write-handlers*}))


(defn response-format
"cljs-ajax interceptor that hardwires content-type to application/transit+json
and uses `ds/transit-read-handler-map`."
[& [content-type]]
(ajax-interceptors/map->ResponseFormat
{:content-type ["application/transit+json"]
{:content-type (or content-type ["application/transit+json"])
:description "Transit response"
:read (ajax-transit/transit-read-fn {:handlers (ds/transit-read-handler-map)})}))
:read (ajax-transit/transit-read-fn {:handlers @read-handlers*})}))


(def ^{:doc "Options map that must be included in the cljs-ajax request in order
to activate dataset->transit pathways."} opt-map
{:writer writer :response-format response-format})
(defn opt-map
"Options map that must be included in the cljs-ajax request in order
to activate dataset->transit pathways."
[]
{:writer (writer) :response-format (response-format)})


(defn transit-request
"Perform a cljs-ajax request using the select cljs-ajax.core method and merging
[[opt-map]] first into the options."
[method url options]
(method url (merge opt-map options)))
(method url (merge (opt-map) options)))


(defn GET
Expand Down
8 changes: 8 additions & 0 deletions src/tech/v3/libs/muuntaja.clj
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,11 @@
* `:read-handlers` - transit handler-map of extra handlers to use when reading data."
[handler & [options]]
(muuntaja-middle/wrap-format handler (muuntaja options)))


(defn wrap-format-java-time
"Wrap-format support datasets and scalar java.time.LocalDate and java.time.Instant objects."
[handler & [options]]
(wrap-format handler (assoc options
:write-handlers tech-transit/java-time-write-handlers
:read-handlers tech-transit/java-time-read-handlers)))
12 changes: 11 additions & 1 deletion src/tech/v3/libs/transit.clj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
(:import [tech.v3.dataset.impl.dataset Dataset]
[tech.v3.dataset.impl.column Column]
[java.nio ByteBuffer ByteOrder]
[java.util Base64 HashMap]))
[java.util Base64 HashMap]
[java.time LocalDate Instant]))

(set! *warn-on-reflection* true)

Expand Down Expand Up @@ -204,6 +205,15 @@
(def write-handlers {Dataset (t/write-handler "tech.v3.dataset" dataset->data)})
(def read-handlers {"tech.v3.dataset" (t/read-handler data->dataset)})

(def java-time-write-handlers
{LocalDate (t/write-handler "java.time.LocalDate" dtype-dt/local-date->days-since-epoch)
Instant (t/write-handler "java.time.Instant" dtype-dt/instant->milliseconds-since-epoch)})

(def java-time-read-handlers
{"java.time.LocalDate" dtype-dt/days-since-epoch->local-date
"java.time.Instant" dtype-dt/milliseconds-since-epoch->instant})


(defn dataset->transit
"Convert a dataset into transit"
[ds out & [format handlers]]
Expand Down
2 changes: 1 addition & 1 deletion testapp/deps.edn
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{:paths ["src" "resources"]
:deps {com.cnuernber/tmdjs {:mvn/version "1.000-beta-6"}
:deps {com.cnuernber/tmdjs {:mvn/version "1.000-beta-15-SNAPSHOT"}
http-kit/http-kit {:mvn/version "2.5.3"}
hiccup/hiccup {:mvn/version"1.0.5"}
bidi/bidi {:mvn/version "2.1.6"}
Expand Down
16 changes: 13 additions & 3 deletions testapp/src/testapp/main.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
[ring.middleware.resource :refer [wrap-resource]]
[ring.middleware.content-type :refer [wrap-content-type]]
;;automatic handling of transit->dataset conversion
[tech.v3.libs.muuntaja :refer [wrap-format]]
[tech.v3.libs.muuntaja :refer [wrap-format-java-time]]
[ring.middleware.cookies :refer [wrap-cookies]]
[ring.middleware.gzip :refer [wrap-gzip]]
[bidi.ring :as bidi-ring]
[clojure.tools.logging :as log]
[tech.v3.dataset :as ds])
[tech.v3.dataset :as ds]
[tech.v3.libs.transit :as tech-transit])
(:import [java.time LocalDate Instant])
(:gen-class))


Expand Down Expand Up @@ -46,6 +48,12 @@
(response/response)))


(defn datetest
[request]
(response/response {:local-date (LocalDate/now)
:instant (Instant/now)}))


(defn stocks-data
[request]
(-> (ds/->dataset "https://github.com/techascent/tech.ml.dataset/raw/master/test/data/stocks.csv" {:key-fn keyword})
Expand All @@ -54,12 +62,14 @@

(def routes ["/" {:get [["data" #'generate-data]
["stocks" #'stocks-data]
["datetest" #'datetest]
[true #'home-page]]}])

(defn handler
[]
(-> (bidi-ring/make-handler routes)
(wrap-format)
(wrap-format-java-time {:write-handlers tech-transit/java-time-write-handlers
:read-handlers tech-transit/java-time-read-handlers})
(wrap-cookies)
(wrap-resource "public")
(wrap-content-type)
Expand Down
5 changes: 4 additions & 1 deletion testapp/src/testapp/webapp.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
(:require [goog.dom :as gdom]
[reagent.dom]
[reagent.ratom :refer [atom]]
[tech.v3.libs.cljs-ajax :refer [GET POST]]
[tech.v3.libs.cljs-ajax :refer [GET POST] :as tech-cljs-ajax]
[tech.v3.dataset :as ds]
[tech.v3.datatype.functional :as dfn]))


(defonce app* (atom {}))


Expand Down Expand Up @@ -71,4 +72,6 @@
(defn init
"Entrypoint into the application."
[]
(tech-cljs-ajax/add-java-time-handlers!)

(render))

0 comments on commit c67f446

Please sign in to comment.