module Data.Aeson.Coerce where

import Data.Aeson as Aeson (Value(..), FromJSON, fromJSON, eitherDecode, Result(..))
import Data.ByteString.Lazy (ByteString)
import Data.Text (pack, unpack)

type LazyByteString = ByteString

class Coercable a where
  -- I'd love to have
  -- coerc :: a -> a
  asString :: a -> a
  asNumber :: a -> a

instance Coercable Value where
  asString (Number n) = String (pack $ show n)
  asString (Bool b)   = String (pack $ show b)
  asString _          = error "No coercion"
  asNumber (String s) = Number (read $ unpack s)
  asNumber (Bool b)   = Number $ if b then 1 else 0
  asNumber _          = error "No coercion"

eitherDecode :: FromJSON a => (Value -> Value) -> LazyByteString -> Either String a
eitherDecode ops bs = do
  val <- Aeson.eitherDecode bs
  resultToEither . fromJSON $ ops val
  where resultToEither :: Result a -> Either String a
        resultToEither (Error e) = Left e
        resultToEither (Success s) = Right s