4

I'm implementing basic end-to-end functionality from an HTML5 app to a Datomic database. The first port-of-call is to have the client make an AJAX call directly to the Datomic REST API (http://docs.datomic.com/rest.html).

The problem that needs to be solved with this approach is that the data comes back in EDN whereas the client application wants to use JSON.

I can see there are possible ways of doing it using Javascript on the client, for example, use some library code to do translate the EDN (as an example, I found jsedn - https://www.npmjs.com/package/jsedn)

Does anyone have experience of doing something that worked like this, using Javascript? Alternatively, is it more generally accepted that EDN to JSON should be done in the Clojure/Clojurescript arena (client- or server-side) such as outlined in http://swannodette.github.io/2014/07/26/transit--clojurescript/ ?

Thanks

Phil

[Edit 04-Mar-15 - a clarification: By client-side Clojurescript I'm thinking of something like taking CLJS code that transforms EDN to JSON, compiling it down to JS then using it as a client side library.]

westwell
  • 191
  • 2
  • 11

2 Answers2

3

Nothing against the jsedn project you mention, but it hasn't seen a commit in two years and has a couple long-standing issues/PR's that haven't been taken care of: I'd be weary of relying on it.

You could easily acheive what you're after by creating a new clojurescript project and ^:export-ing a single function that parses incoming edn and spits out JS objects (because there is no good reason to deserialise edn, serialize it to JSON, then deserialise it again!):

(ns app.edn (:require [cljs.reader :as r]))

(defn ^:export read-edn [s]
  (let [data (r/read-string s)]
    ; Log/prettify for JS/whatever
    (clj->js data)))

Compile it, require the file in your JS, and it'll be available at app.edn.read_edn().

SLD
  • 659
  • 4
  • 10
  • 1
    Thanks @SLD. I did what you suggested above and it worked (and provided more JSON-ey JSON than jsedn did: jsedn used names based on the Clojure names, prepending colons and including namespace paths). It took me a while to work out how to load the compiled code with RequireJS, so I've included my full steps below in case they are of use to anyone else. – westwell Mar 19 '15 at 12:47
1

As indicated in the comment, here are the full steps I took to implement @SLD's correct answer, in case anyone can benefit from the detail.

1) Take the cljs code from the answer above.

2) Create a project.clj file to use in the build. I found I had to use the option

:optimizations :whitespace

so that the generated code made sense to me (and would load in RequireJS)

3) Use command

lein cljsbuild once

to build the js files. The console out will indicate the name of the main generated file, which is the one specified in project.clj

4) (if using RequireJS) add the generated file in the "paths" of RequireJS config

5) (if using RequireJS) add a "shim" entry for the generated file, as it isn't a module. To get the correct value for exports, look in the generated js file from 3) and see what global object is being exported. Add the name of that global object as the "exports" value of the shim.

westwell
  • 191
  • 2
  • 11