@@ -13,10 +13,15 @@ import Data.List (List(..), (:), fromFoldable)
1313import Data.Map as M
1414import Data.Maybe (maybe , Maybe (..))
1515import Data.String (CodePoint , codePointAt )
16+ import Data.Symbol (class IsSymbol , SProxy (..), reflectSymbol )
1617import Data.Traversable (traverse )
1718import Data.TraversableWithIndex (traverseWithIndex )
1819import Data.Tuple (Tuple (..))
1920import 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 (..))
2025
2126class DecodeJson a where
2227 decodeJson :: Json -> Either String a
@@ -98,3 +103,41 @@ decodeJArray = maybe (Left "Value is not an Array") Right <<< toArray
98103
99104decodeJObject :: Json -> Either String (FO.Object Json )
100105decodeJObject = 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