-
Notifications
You must be signed in to change notification settings - Fork 0
/
JSONClass.hs
94 lines (71 loc) · 2.57 KB
/
JSONClass.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
module JSONClass where
import Control.Arrow
type JSONError = String
newtype JAry a = JAry {
fromJAry :: [a]
} deriving (Eq, Ord, Show)
newtype JObj a = JObj {
fromJObj :: [(String, a)]
} deriving (Eq, Ord, Show)
data JValue = JString String
| JNumber Double
| JBool Bool
| JNull
| JObject (JObj JValue)
| JArray (JAry JValue)
deriving (Eq, Ord, Show)
jaryFromJValue :: (JSON a) => JValue -> Either JSONError (JAry a)
jaryFromJValue (JArray (JAry a)) =
whenRight JAry (mapEithers fromJValue a)
jaryFromJValue _ = Left "not a JSON array"
whenRight :: (b -> c) -> Either a b -> Either a c
whenRight f (Right b) = Right $ f b
whenRight _ (Left t) = Left t
mapEithers :: (a -> Either b c) -> [a] -> Either b [c]
mapEithers f (x:xs) = case mapEithers f xs of
Left err -> Left err
Right ys -> case f x of
Left err -> Left err
Right t -> Right (t:ys)
mapEithers _ _ = Right []
jaryToJValue :: (JSON a) => JAry a -> JValue
jaryToJValue = JArray . JAry . map toJValue . fromJAry
instance (JSON a) => JSON (JObj a) where
toJValue = JObject . JObj . map (second toJValue) . fromJObj
fromJValue (JObject (JObj o)) = whenRight JObj (mapEithers unwrap o)
where unwrap (k, v) = whenRight ((,) k) (fromJValue v)
fromJValue _ = Left "Not a JSON object"
instance (JSON a) => JSON (JAry a) where
toJValue = jaryToJValue
fromJValue = jaryFromJValue
listToJValues :: (JSON a) => [a] -> [JValue]
listToJValues = map toJValue
jvaluesToJAry :: [JValue] -> JAry JValue
jvaluesToJAry = JAry
jaryOfJValuesToJValue :: JAry JValue -> JValue
jaryOfJValuesToJValue = JArray
class JSON a where
toJValue :: a -> JValue
fromJValue :: JValue -> Either JSONError a
instance JSON JValue where
toJValue = id
fromJValue = Right
instance JSON Bool where
toJValue = JBool
fromJValue (JBool b) = Right b
fromJValue _ = Left "not a JSON boolean"
instance JSON [Char] where
toJValue = JString
fromJValue (JString s) = Right s
fromJValue _ = Left "not a JSON string"
doubleToJValue :: (Double -> a )-> JValue -> Either JSONError a
doubleToJValue f (JNumber d) = Right (f d)
doubleToJValue _ _ = Left "not a JSON number"
instance JSON Int where
toJValue = JNumber . realToFrac
fromJValue = doubleToJValue round
instance JSON Integer where
toJValue = JNumber . realToFrac
fromJValue = doubleToJValue round