7

It's not that hard to write ToJSON/FromJSON instances for the generated types but still, while you're generating code could you throw that in? Or is there an easy way to make this happen as a Yesod user? (I haven't dug too deep into how TH works...)

Update: OK, I like this suggestion but, say my persistent type is User. If I use

$(deriveJSON id ''User)

it yields

  Exception when trying to run compile-time code:
  Data.Aeson.TH.withType: Unsupported type: TySynD Model.User [] (AppT (ConT Model.UserGeneric) (ConT Database.Persist.GenericSql.Raw.SqlPersist))
  Code: deriveJSON (id) 'User

apparently because it's an alias. But

$(deriveJSON id ''UserGeneric)

yields

Kind mis-match
The first argument of `UserGeneric' should have kind `(* -> *)
                                                      -> *
                                                      -> *',
but `backend[i5XB]' has kind `*'

I've probably still got the wrong type but I can't find enough about what Persistent generates to get the right incantation.

svachalek
  • 1,166
  • 8
  • 18
  • Have you figured this out yet? Running into the exact same problem here. – Justin L. Sep 03 '13 at 01:45
  • I haven't been working with Yesod for quite a while now but I'm pretty sure I had this working using the added "json" mentioned in Michael Snoyman's link: https://github.com/yesodweb/yesod/wiki/Persistent-entity-syntax#json-instances – svachalek Sep 03 '13 at 05:55

4 Answers4

10

For anyone who doesn't notice the sub comment on Michael Snowman's post, in resent versions of persistent you can do:

Person json
    name Text
    age Int

and get ToJSON and FromJSON instances of Person.

triplepoint217
  • 462
  • 3
  • 10
6

I actually think we'll be adding this feature to Persistent 0.8 (to be released with Yesod 0.10 in a week or two). It's true what dflemstr said about dependency bloat, which is why we haven't done this in the past, but we already depend on aeson now for our configuration types (based on Yaml config files, which uses aeson's data types).

Michael Snoyman
  • 31,100
  • 3
  • 48
  • 77
  • Thanks Michael, sounds good to me. In the meantime if anyone knows the right syntax for the deriveJSON call that would also be helpful! – svachalek Feb 02 '12 at 19:15
  • 3
    This has been implemented for a while, see: https://github.com/yesodweb/yesod/wiki/Persistent-entity-syntax#json-instances – Michael Snoyman Apr 26 '13 at 05:53
  • Thanks Michael! This is awesome stuff. It would be great if you updated the online chapter of your book about RESTful content to include this fact. I'm working from the paper copy, but I check all the examples online for just this reason. – nont Jun 28 '14 at 18:58
2

You can just use the automatic deriving mechanism in Data.Aeson.TH.

{-# LANGUAGE TemplateHaskell #-}
$(deriveJSON id ''Foo)

This should work fine on both Yesod-generated data types as well as your own types.

It takes a function to customize the record field names. Here, I've just passed id to get them unchanged. See the documentation for details.

hammar
  • 138,522
  • 17
  • 304
  • 385
  • Thanks, looks like both of you had the same answer at the same time. Yesod types are aliases though so it generates an "Unsupported type" error. I tried using $(deriveJSON id ''UserGeneric) where my type is User, and got this: Kind mis-match The first argument of `UserGeneric' should have kind `(* -> *) -> * -> *', but `backend[i5XB]' has kind `*' – svachalek Feb 02 '12 at 02:19
1

The default Yesod type generators shouldn't generate ToJSON/FromJSON instances, because that would add a dependency on aeson even if you didn't want to use that package, which could lead to dependency bloat.

You can import Data.Aeson.TH and use this code to automatically create JSON instances:

data MyDataType = ...

deriveJSON id ''MyDataType

Replace id with a function that renames fields for you, if you don't want the same field names in Haskell as in the JSON file.

dflemstr
  • 25,947
  • 5
  • 70
  • 105