aeson-qq icon indicating copy to clipboard operation
aeson-qq copied to clipboard

Pattern matching quasi-quoter

Open ethercrow opened this issue 10 years ago • 3 comments

I'm very happy with aeson-qq for my quite simple serializing needs along the lines of:

recordToJSON (Person name age) =
    [aesonQQ| { name: #{name}, age: #{age} |]

However, reverse transformation is now looking pretty ugly in comparison with all that pattern-matching on Aeson.Values and descending into arrays and values. I can't help but wonder if it's possible to have a dual quasiquoter so you could write something like this:

jsonToRecord data =
    let [unaesonQQ| { name: #{name}, age: #{age} } |] = data
    in Person name age

ethercrow avatar Jan 02 '15 17:01 ethercrow

@ethercrow If you have a data type, you can use GHCs generics to get instances for free:

{-# LANGUAGE DeriveGeneric #-}
module Person where

import GHC.Generics
import Data.Aeson

data Person = Person {
  name :: String
, age :: Int
} deriving (Eq, Show, Generic)

instance ToJSON Person
instance FromJSON Person

sol avatar Jan 06 '15 03:01 sol

Yeah, that helps in some, probably most, situations. But when you're not controlling json structure and field names (and they contain dashes or spaces for example), this method doesn't really work.

ethercrow avatar Jan 06 '15 10:01 ethercrow

If you can define a mapping from record field names to JSON names (e.g. striping a prefix or converting CamelCase to snake_case) you can still use genericToJSON/genericParseJSON with custom options.

Regarding your question for a dual quasiquoter, in general it is possible to use QuasiQuoters as patterns. I haven't looked into it, but it may be possible to achieve this by defining quotePat for aesonQQ.

Patches welcome ;)

sol avatar Jan 07 '15 01:01 sol