on master help sign in
Merge pull request #155 from gabemc/master

Adding functions to TH to make CamelCase to under_score easier.

commitcf8f509885340e96760fa7b7173db282d31e15fe authorBryan O'Sullivan <bos@serpentine.com> dateThu 2 Jan 2014, 15:32 (13 years ago) parenta3039453b19200
3 files changed+39−1
.gitignore+3−1 Data/Aeson/Types/Internal.hs+27 tests/Properties.hs+9
.gitignore+3−1
@@ -1,4 +1,6 @@
11dist
2+.cabal-sandbox/
3+cabal.sandbox.config
24
35*.o
46*.hi
@@ -7,4 +9,4 @@ benchmarks/AesonEncode
79
810tests/qc
911
10−cabal.sandbox.config
12+cabal.sandbox.config
Data/Aeson/Types/Internal.hs+27
@@ -36,13 +36,18 @@ module Data.Aeson.Types.Internal
3636 , defaultOptions
3737 , defaultTaggedObject
3838
39+ -- * Used for changing CamelCase names into something else.
40+ , camelTo
41+
3942 -- * Other types
4043 , DotNetTime(..)
4144 ) where
4245
46+
4347import Control.Applicative
4448import Control.Monad
4549import Control.DeepSeq (NFData(..))
50+import Data.Char (toLower, isUpper)
4651import Data.Scientific (Scientific)
4752import Data.Hashable (Hashable(..))
4853import Data.Data (Data)
@@ -346,3 +351,25 @@ defaultTaggedObject = TaggedObject
346351 { tagFieldName = "tag"
347352 , contentsFieldName = "contents"
348353 }
354+
355+-- | Converts from CamelCase to another lower case, interspersing
356+-- the character between all capital letters and their previous
357+-- entries, except those capital letters that appear together,
358+-- like 'API'.
359+--
360+-- For use by Aeson template haskell calls.
361+--
362+-- > camelTo '_' 'CamelCaseAPI' == "camel_case_api"
363+camelTo :: Char -> String -> String
364+camelTo c = lastWasCap True
365+ where
366+ lastWasCap :: Bool -- ^ Previous was a capital letter
367+ -> String -- ^ The remaining string
368+ -> String
369+ lastWasCap _ [] = []
370+ lastWasCap prev (x : xs) = if isUpper x
371+ then if prev
372+ then toLower x : lastWasCap True xs
373+ else c : toLower x : lastWasCap True xs
374+ else x : lastWasCap False xs
375+
tests/Properties.hs+9
@@ -22,6 +22,11 @@ import Data.Int
2222import qualified Data.Map as Map
2323#endif
2424
25+roundTripCaml :: String -> Bool
26+roundTripCaml s = s == (camlFrom '_' $ camlTo '_' s)
27+ where
28+ camlFrom :: Char -> String -> String
29+ camlFrom c = concatMap capitalize $ split c
2530
2631encodeDouble :: Double -> Double -> Bool
2732encodeDouble num denom
@@ -101,6 +106,10 @@ tests = [
101106 testProperty "encodeDouble" encodeDouble
102107 , testProperty "encodeInteger" encodeInteger
103108 ],
109+ testGroup "camlCase" [
110+ testProperty "camlTo" $ roundTripCaml "AnApiMethod"
111+ , testProperty "camlTo" $ roundTripCaml "anotherMethodType"
112+ ],
104113 testGroup "roundTrip" [
105114 testProperty "Bool" $ roundTripEq True
106115 , testProperty "Double" $ roundTripEq (1 :: Approx Double)