Easiest way to have a server return JSON by default?

168 views
Skip to first unread message

Adam Jones

unread,
May 10, 2010, 4:22:15 PM5/10/10
to Compojure
For the project I'm working on, the server will almost exclusively
emit JSON. It's not intended for normal web traffic, just write & read
JSON with a REST interface. I already have something like this:


(defn emit-json
"Turn the object into json as normal, then set the map to emit
correct content types"
([x]
(emit-json x (hash-map)))
([x m]
(merge
{:headers {"Content-Type" "application/json"}
:body (json-str x)}
m)))

Which lets me just dump a map and have things work, however that means
explicitly calling emit-json for each function. Is there any simple
way to set things up so this is always run and other content types are
the special case?

--
You received this message because you are subscribed to the Google Groups "Compojure" group.
To post to this group, send email to comp...@googlegroups.com.
To unsubscribe from this group, send email to compojure+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/compojure?hl=en.

James Reeves

unread,
May 10, 2010, 5:21:15 PM5/10/10
to comp...@googlegroups.com
Which version of Compojure are you using?

- James

Adam Jones

unread,
May 10, 2010, 6:09:20 PM5/10/10
to Compojure
This is with 0.3.2. I can move to the 0.4.0rc if needed, just tend to
avoid doing so unless necessary.

On May 10, 2:21 pm, James Reeves <jree...@weavejester.com> wrote:
> Which version of Compojure are you using?
>
> - James
>
> On 10 May 2010 21:22, Adam Jones <ajon...@gmail.com> wrote:
>
>
>
>
>
> > For the project I'm working on, the server will almost exclusively
> > emit JSON. It's not intended for normal web traffic, just write & read
> > JSON with a REST interface. I already have something like this:
>
> > (defn emit-json
> >  "Turn the object into json as normal, then set the map to emit
> >   correct content types"
> >  ([x]
> >     (emit-json x (hash-map)))
> >  ([x m]
> >     (merge
> >      {:headers {"Content-Type" "application/json"}
> >       :body (json-str x)}
> >      m)))
>
> > Which lets me just dump a map and have things work, however that means
> > explicitly calling emit-json for each function. Is there any simple
> > way to set things up so this is always run and other content types are
> > the special case?
>
> > --
> > You received this message because you are subscribed to the Google Groups "Compojure" group.
> > To post to this group, send email to comp...@googlegroups.com.
> > To unsubscribe from this group, send email to compojure+...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/compojure?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups "Compojure" group.
> To post to this group, send email to comp...@googlegroups.com.
> To unsubscribe from this group, send email to compojure+...@googlegroups.com.
> For more options, visit this group athttp://groups.google.com/group/compojure?hl=en.

James Reeves

unread,
May 10, 2010, 7:49:43 PM5/10/10
to comp...@googlegroups.com
On 10 May 2010 23:09, Adam Jones <ajo...@gmail.com> wrote:
> This is with 0.3.2. I can move to the 0.4.0rc if needed, just tend to
> avoid doing so unless necessary.

If you're using 0.3.2, you can override the
compojure.http.resource/update-response methodmethod.

In 0.4.0 the compojure.response/render does the same thing, but is
somewhat simpler.

Of course, if you override the multimethod for Map, be aware you'll
need an alternative way of handling redirects and so forth.

- James

Adam Jones

unread,
May 10, 2010, 8:31:21 PM5/10/10
to Compojure
I think one of those should work, or I may look into other options.
(e.g. a 'defnjs' function that pipes the original output through emit-
json) Thanks for the help.

Slightly off topic for this conversation, but what do you think of the
idea of having render (IFn) look up a :headers key in the function
metadata and merge anything there with the function return? That gives
a relatively straightforward way of handling this issue:

(with-meta index-page {:headers {"Content-Type" "application/json"}}
(defroutes example
(ANY "*" index-page)))

Obviously abstractions would follow from there. Kind of new to Clojure
(or just returning from a very very long break), am I missing
somewhere that this would be a problem?

-Adam

On May 10, 4:49 pm, James Reeves <jree...@weavejester.com> wrote:

James Reeves

unread,
May 10, 2010, 8:46:58 PM5/10/10
to comp...@googlegroups.com
On 11 May 2010 01:31, Adam Jones <ajo...@gmail.com> wrote:
> Slightly off topic for this conversation, but what do you think of the
> idea of having render (IFn) look up a :headers key in the function
> metadata and merge anything there with the function return? That gives
> a relatively straightforward way of handling this issue:
>
> (with-meta index-page {:headers {"Content-Type" "application/json"}}
>  (defroutes example
>    (ANY "*" index-page)))

Personally, I'd use some middleware:

(defn wrap-headers [handler headers]
(fn [request]
(let [response (handler request)]
(update-in response [:headers] merge headers))))

(wrap! example
(:headers {"Content-Type" "application/json"}))

Or perhaps a binding. I probably wouldn't use metadata in this case.
Reply all
Reply to author
Forward
0 new messages