aeson-qq (empty) → 0.4.0
raw patch · 4 files changed
+165/−0 lines, 4 filesdep +aesondep +basedep +haskell-src-metasetup-changed
Dependencies added: aeson, base, haskell-src-meta, json-qq, parsec, template-haskell
Files
- COPYING.txt +14/−0
- Setup.hs +2/−0
- aeson-qq.cabal +34/−0
- src/Data/Aeson/QQ.hs +115/−0
+ COPYING.txt view
@@ -0,0 +1,14 @@+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE+ Version 2, December 2004++ Copyright (C) 2010 Oscar Finnsson++ Everyone is permitted to copy and distribute verbatim or modified+ copies of this license document, and changing it is allowed as long+ as the name is changed.++ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++ 0. You just DO WHAT THE FUCK YOU WANT TO.+
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ aeson-qq.cabal view
@@ -0,0 +1,34 @@+name: aeson-qq+version: 0.4.0+synopsis: Json Quasiquatation for Haskell.++-- A longer description of the package.+description: + @aeson-qq@ provides json quasiquatation for Haskell.+ .+ This package expose the function @aesonQQ@ that compile time converts json code into a @Data.Aeson.Value@.+ @aesonQQ@ got the signature+ .+ > aesonQQ :: QuasiQuoter.+ .+ Consult documentation in the module @Data.Aeson.QQ@.++homepage: http://github.com/finnsson/aeson-qq+license: OtherLicense+license-file: COPYING.txt+author: Oscar Finnsson+maintainer: oscar.finnsson@gmail.com+category: JSON+build-type: Simple+cabal-version: >=1.6++library+ hs-source-dirs: src+ exposed-modules: Data.Aeson.QQ+ build-depends: base >= 4.3 && < 5, aeson, parsec >= 2 && < 3, json-qq, template-haskell, haskell-src-meta >= 0.1.0++source-repository head+ type: git+ location: https://github.com/finnsson/aeson-qq/++
+ src/Data/Aeson/QQ.hs view
@@ -0,0 +1,115 @@+{-# OPTIONS_GHC -XTemplateHaskell -XQuasiQuotes -XUndecidableInstances #-}++-- | This package expose the function @aesonQQ@ that compile time converts json code into a @Data.Aeson.Value@.+-- @aesonQQ@ got the signature+-- +-- > aesonQQ :: QuasiQuoter+-- +-- and is used like+-- +-- > myCode = [aesonQQ| {age: 23, name: "Pelle", likes: ["mac","Haskell"] } |]+-- +-- where it is important that+-- +-- * you got no space in @[aesonQQ|@ and+-- +-- * no additional code after @|]@.+-- +-- The quasiquatation can also bind to variables like+-- +-- > myCode = [aesonQQ| {age: <|age|>, name: <|name|>} |]+-- > where age = 34 :: Integer+-- > name = "Pelle"+-- +-- where the function @toJSON@ will be called on @age@ and @name@ runtime.+--+-- You can also insert Haskell code: +--+-- > myCode = [aesonQQ| {age: <|age + 34 :: Integer|>, name: <|map toUpper name|>} |]+-- > where age = 34 :: Integer+-- > name = "Pelle"+-- +-- You can use a similar syntax if you want to insert a value of type Data.Aeson.Value like+-- +-- > myCode = [aesonQQ| {"age": <<age>>} |]+-- +-- If you want to replace the name of the key in a hash you'll use the $-syntax:+-- +-- > foo = [aesonQQ| {$bar: 42} |]+-- > bar = "age"+-- ++module Data.Aeson.QQ (+ aesonQQ+) where++import Language.Haskell.TH+import Language.Haskell.TH.Quote++import Data.Data+import Data.Maybe++import Data.JSON.QQ as QQ++import Data.Aeson as A+import Data.Aeson.Generic++import Data.Ratio+import Text.ParserCombinators.Parsec+import Text.ParserCombinators.Parsec.Error++import Language.Haskell.Meta.Parse++aesonQQ :: QuasiQuoter+aesonQQ = QuasiQuoter { + quoteExp = jsonExp, + quotePat = \s -> error "No quotePat defined for jsonQQ",+ quoteType = \s -> error "No quoteType defined for jsonQQ",+ quoteDec = \s -> error "No quoteDec defined for jsonQQ"+}+++jsonExp :: String -> ExpQ+jsonExp txt =+ case parsed' of + Left err -> error $ "Error in aesonExp: " ++ show err+ Right val -> return $ toExp val+ where+ parsed' = QQ.parsedJson txt++----+-- JSValue etc to ExpQ+---------+toExp :: QQ.JsonValue -> Exp++toExp (JsonString str) = + AppE (ConE $ mkName "Data.Aeson.Types.String") (packE (LitE (StringL $ str)))++toExp (JsonNull) = ConE $ mkName "Data.Aeson.Types.Null"++toExp (JsonObject objs) = + (AppE (VarE $ mkName "Data.Aeson.Types.object") (ListE $ jsList ))+ where+ jsList :: [Exp] -- [(String,JSValue)]+ jsList = map objs2list (objs)+ objs2list :: (HashKey,JsonValue) -> Exp+ objs2list (HashStringKey k,v) = TupE [packE (LitE (StringL k)), toExp v]+ objs2list (HashVarKey k,v) = TupE [packE (VarE $ mkName k), toExp v]++toExp (JsonArray arr) =+ AppE (ConE $ mkName "Data.Aeson.Types.Array") (AppE (VarE $ mkName "Data.Vector.fromList") (ListE $ map toExp arr))++toExp (JsonNumber b rat) =+ AppE (ConE $ mkName "Data.Aeson.Types.Number") (AppE (ConE $ mkName "Data.Attoparsec.Number.D") (LitE (RationalL rat))) +toExp (JsonIdVar v) =+ VarE $ mkName v++toExp (JsonBool b) =+ AppE (ConE $ mkName "Data.Aeson.Types.Bool") (ConE $ mkName (if b then "True" else "False"))++toExp (JsonCode exp) =+ AppE (VarE $ mkName "Data.Aeson.Generic.toJSON") exp++-- Helpers+packE = AppE (VarE $ mkName "Data.Text.pack")+