@@ -13,10 +13,15 @@ import Data.List (List(..), (:), fromFoldable)
13
13
import Data.Map as M
14
14
import Data.Maybe (maybe , Maybe (..))
15
15
import Data.String (CodePoint , codePointAt )
16
+ import Data.Symbol (class IsSymbol , SProxy (..), reflectSymbol )
16
17
import Data.Traversable (traverse )
17
18
import Data.TraversableWithIndex (traverseWithIndex )
18
19
import Data.Tuple (Tuple (..))
19
20
import Foreign.Object as FO
21
+ import Prim.Row as Row
22
+ import Prim.RowList as RL
23
+ import Record as Record
24
+ import Type.Data.RowList (RLProxy (..))
20
25
21
26
class DecodeJson a where
22
27
decodeJson :: Json -> Either String a
@@ -98,3 +103,41 @@ decodeJArray = maybe (Left "Value is not an Array") Right <<< toArray
98
103
99
104
decodeJObject :: Json -> Either String (FO.Object Json )
100
105
decodeJObject = maybe (Left " Value is not an Object" ) Right <<< toObject
106
+
107
+
108
+ instance decodeRecord :: (GDecodeJson row list , RL.RowToList row list ) => DecodeJson (Record row ) where
109
+ decodeJson json =
110
+ case toObject json of
111
+ Just object -> gDecodeJson object (RLProxy :: RLProxy list )
112
+ Nothing -> Left " Could not convert JSON to object"
113
+
114
+ class GDecodeJson (row :: # Type ) (list :: RL.RowList ) | list -> row where
115
+ gDecodeJson :: FO.Object Json -> RLProxy list -> Either String (Record row )
116
+
117
+ instance gDecodeJsonNil :: GDecodeJson () RL.Nil where
118
+ gDecodeJson _ _ = Right {}
119
+
120
+ instance gDecodeJsonCons
121
+ :: ( DecodeJson value
122
+ , GDecodeJson rowTail tail
123
+ , IsSymbol field
124
+ , Row.Cons field value rowTail row
125
+ , Row.Lacks field rowTail
126
+ )
127
+ => GDecodeJson row (RL.Cons field value tail ) where
128
+
129
+ gDecodeJson object _ = do
130
+ let sProxy :: SProxy field
131
+ sProxy = SProxy
132
+
133
+ fieldName = reflectSymbol sProxy
134
+
135
+ rest <- gDecodeJson object (RLProxy :: RLProxy tail )
136
+
137
+ case FO .lookup fieldName object of
138
+ Just jsonVal -> do
139
+ val <- decodeJson jsonVal
140
+ Right $ Record .insert sProxy val rest
141
+
142
+ Nothing ->
143
+ Left $ " JSON was missing expected field: " <> fieldName
0 commit comments