1

I'm working on my first Haskell web app, and am having trouble converting a BSON document into JSON and then sending it as an API response. I'm currently using the AesonBson package to convert my BSON to an Aeson Object, but can't figure out how to send that Aeson Object as a JSON API response.

Here is an example of a route handler in my server:

{-# LANGUAGE OverloadedStrings #-}

module Web.Routes where


import Web.Scotty
import Web.Utils
import Web.Actions.Database
import Control.Monad.Trans (liftIO)
import Data.AesonBson


routes :: ScottyM ()
routes = do
  get "/databases/:db/:collection" $ do
      db <- param "db"
      collection <- param "collection"
      docs <- liftIO $ getAllDocuments "127.0.0.1" db collection
      json $ map aesonify docs

These seems like it should be simple - getAllDocuments returns IO [Document], and then I map aesonfy over my list of docs, before attempting to return them as a JSON server response.

Problem is I keep getting this No instance for ToJSON error:

No instance for (aeson-0.8.0.2:Data.Aeson.Types.Class.ToJSON
                   aeson-0.6.2.1:Data.Aeson.Types.Internal.Value)
  arising from a use of ‘Web.Scotty.json’
In the expression: Web.Scotty.json
In a stmt of a 'do' block:
  Web.Scotty.json
  GHC.Base.$ GHC.Base.map Data.AesonBson.aesonify docs
In the second argument of ‘(GHC.Base.$)’, namely
  ‘do { db <- Web.Scotty.param "db";
        collection <- Web.Scotty.param "collection";
        docs <- transformers-0.3.0.0:Control.Monad.IO.Class.liftIO
                GHC.Base.$
                  Web.Actions.Database.getAllDocuments "127.0.0.1" db collection;
        Web.Scotty.json
        GHC.Base.$ GHC.Base.map Data.AesonBson.aesonify docs }’

Any idea what I am missing? It looks like aesonify returns an Aeson Object... shouldn't that be an instace of ToJSON? Any help would be greatly appreciated, I've been spinning my wheels on this one for a while now. I've tried placing Aeson's object function in different places, manually adding documents as an instance of ToJSON, but really can't figure this out.

tydotg
  • 631
  • 4
  • 11

1 Answers1

3

You have two different versions of aeson package: aeson-0.8.0.2 and aeson-0.6.2.1. Clearly the Value from aeson-0.6.2.1 is not an instance of FromJSON from aeson-0.8.0.2.

I'd recommend you to cabalize the code and/or use cabal sandbox. Alternatively you can use ghc-pkg to unregister one of aeson versions.

ADD: you seems to have the same issue with transformers-0.3.0.0. GHC never qualifies identifiers with package name and version in error messages unless it is ambiguous. Try ghc-pkg list transformers

Yuras
  • 13,856
  • 1
  • 45
  • 58
  • Oh damn, haha, can't believe I missed that (or, well to be fair I'm still pretty bad at reading Haskell error messages, so maybe 'missed' isn't the right term). Thank you a ton for taking a look at that. I do use cabal for managing my dependencies, but probably got myself into a bad spot with reckless package install sessions. – tydotg Jun 06 '15 at 19:36
  • So simply removing `aeson 0.8` fixed the problem (`AesonBson` seems to rely on `aeson 0.6`, thanks again for the help on that one. I tried running `ghc-pkg list transformers` and got two results, but I'm not really sure what it's telling me. Do you see a problem? `/usr/local/Cellar/ghc/7.8.4/lib/ghc-7.8.4/package.conf.d transformers-0.3.0.0 /Users/tolson/.ghc/x86_64-darwin-7.8.4/package.conf.d` – tydotg Jun 06 '15 at 19:47