Commits

Gabe McArthur  committed 2bd3570

Per @basvandijk, I've moved all of the logic into a camelTo function.

  • Participants
  • Parent commits c4e92aa

Comments (0)

Files changed (2)

File Data/Aeson/TH.hs

 
     , mkToJSON
     , mkParseJSON
-
-    -- * For the oft-conversion of CamelCase to underscore_case in JSON
-    , camelToUnderscore
-    , camelToUnderscoreDrop
-    , camelToUnderscoreDropChecked
     ) where
 
 --------------------------------------------------------------------------------
 -- from base:
 import Control.Applicative ( pure, (<$>), (<*>) )
 import Control.Monad       ( return, mapM, liftM2, fail )
-import Data.Char           ( isUpper, toLower)
 import Data.Bool           ( Bool(False, True), otherwise, (&&) )
 import Data.Eq             ( (==) )
 import Data.Function       ( ($), (.) )
 import Data.Int            ( Int )
 import Data.Either         ( Either(Left, Right) )
 import Data.List           ( (++), foldl, foldl', intercalate
-                           , length, map, zip, genericLength, all, partition, drop
+                           , length, map, zip, genericLength, all, partition
                            )
 import Data.Maybe          ( Maybe(Nothing, Just), catMaybes )
-import Prelude             ( String, (-), Integer, fromIntegral, error, const )
+import Prelude             ( String, (-), Integer, fromIntegral, error )
 import Text.Printf         ( printf )
 import Text.Show           ( show )
 #if __GLASGOW_HASKELL__ < 700
 valueConName (Number _) = "Number"
 valueConName (Bool   _) = "Boolean"
 valueConName Null       = "Null"
-
--- | Removes the first Int characters of string, then converts from
---   CamelCase to underscore_case.
---
---   For use by Aeson template haskell calls.
-camelToUnderscore :: String -> String
-camelToUnderscore = camelToUnderscoreDrop 0
-
--- | Removes the first Int characters of string, then converts from
---   CamelCase to underscore_case. Drops the first few characters from
---   the input.
---
---   For use by Aeson template haskell calls.
-camelToUnderscoreDrop :: Int -> String -> String
-camelToUnderscoreDrop i = camelToUnderscoreDropChecked (const i)
-
--- | Removes the first Int characters of string, then converts from
---   CamelCase to underscore_case. Investigates the input string to
---   see how many characters to drop.
---
---   For use by Aeson template haskell calls.
-camelToUnderscoreDropChecked :: (String -> Int) -> String -> String
-camelToUnderscoreDropChecked chk property =
-    underscore True input
-  where
-    input :: String
-    input = drop (chk property) property
-
-    underscore :: Bool    -- ^ Previous was a capital letter
-               -> String  -- ^ The remaining string
-               -> String
-    underscore _    []           = []
-    underscore prev (x : xs)     = if isUpper x
-                                      then if prev
-                                             then toLower x : underscore True xs
-                                             else '_' : toLower x : underscore True xs
-                                      else x : underscore False xs
-

File Data/Aeson/Types/Internal.hs

     , SumEncoding(..)
     , defaultOptions
     , defaultTaggedObject
+
+    -- Used for changing CamelCase names into something else.
+    , camelTo
     ) where
 
 import Control.Applicative
 import Control.Monad
-import Control.DeepSeq (NFData(..))
-import Data.Attoparsec.Char8 (Number(..))
-import Data.Hashable (Hashable(..))
-import Data.HashMap.Strict (HashMap)
-import Data.Monoid (Monoid(..))
-import Data.String (IsString(..))
-import Data.Text (Text, pack)
-import Data.Typeable (Typeable)
-import Data.Vector (Vector)
+import Control.DeepSeq        ( NFData(..) )
+import Data.Attoparsec.Char8  ( Number(..) )
+import Data.Char              ( isUpper, toLower )
+import Data.Hashable          ( Hashable(..) )
+import Data.HashMap.Strict    ( HashMap )
+import Data.Monoid            ( Monoid(..) )
+import Data.String            ( IsString(..) )
+import Data.Text              ( Text, pack )
+import Data.Typeable          ( Typeable )
+import Data.Vector            ( Vector )
 import qualified Data.HashMap.Strict as H
 import qualified Data.Vector as V
 
                       { tagFieldName      = "tag"
                       , contentsFieldName = "contents"
                       }
+
+-- | Converts from CamelCase to another lower case, interpsersing
+--   the character between all capital letters and their previous
+--   entries, except those capital letters that appear together,
+--   like 'API'.
+--
+--   For use by Aeson template haskell calls.
+--
+--   > camelTo '_' 'CamelCaseAPI' == "camel_case_api"
+camelTo :: Char -> String -> String
+camelTo c = lastWasCap True
+  where
+    lastWasCap :: Bool    -- ^ Previous was a capital letter
+              -> String  -- ^ The remaining string
+              -> String
+    lastWasCap _    []           = []
+    lastWasCap prev (x : xs)     = if isUpper x
+                                      then if prev
+                                             then toLower x : lastWasCap True xs
+                                             else c : toLower x : lastWasCap True xs
+                                      else x : lastWasCap False xs
+