Function to convert parsed CSV to array of JSON objects
This commit is contained in:
@@ -3,9 +3,14 @@ module PostgREST.RequestIntent where
|
|||||||
import qualified Data.Aeson as JSON
|
import qualified Data.Aeson as JSON
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.ByteString.Lazy as BL
|
import qualified Data.ByteString.Lazy as BL
|
||||||
|
import qualified Data.Csv as CSV
|
||||||
import Data.List (find)
|
import Data.List (find)
|
||||||
|
import qualified Data.HashMap.Strict as M
|
||||||
import Data.Maybe (fromMaybe, isJust, isNothing,
|
import Data.Maybe (fromMaybe, isJust, isNothing,
|
||||||
listToMaybe)
|
listToMaybe)
|
||||||
|
import Data.String.Conversions (cs)
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Vector as V
|
||||||
import Network.Wai (Request (..))
|
import Network.Wai (Request (..))
|
||||||
import Network.Wai.Parse (parseHttpAccept)
|
import Network.Wai.Parse (parseHttpAccept)
|
||||||
import PostgREST.RangeQuery (NonnegRange, rangeRequested)
|
import PostgREST.RangeQuery (NonnegRange, rangeRequested)
|
||||||
@@ -25,8 +30,9 @@ data Target = TargetIdent QualifiedIdentifier
|
|||||||
data ContentType = ApplicationJSON | TextCSV
|
data ContentType = ApplicationJSON | TextCSV
|
||||||
-- | When Hasql supports the COPY command then we can
|
-- | When Hasql supports the COPY command then we can
|
||||||
-- have a special payload just for CSV, but until
|
-- have a special payload just for CSV, but until
|
||||||
-- then CSV is converted to a JSON array
|
-- then CSV is converted to a JSON array.
|
||||||
data Payload = PayloadJSON JSON.Array
|
data Payload = PayloadJSON JSON.Array
|
||||||
|
| PayloadParseError BS.ByteString
|
||||||
|
|
||||||
-- | Describes what the user wants to do. This data type is a
|
-- | Describes what the user wants to do. This data type is a
|
||||||
-- translation of the raw elements of an HTTP request into domain
|
-- translation of the raw elements of an HTTP request into domain
|
||||||
@@ -42,7 +48,7 @@ data Intent = Intent {
|
|||||||
, iTarget :: Maybe Target
|
, iTarget :: Maybe Target
|
||||||
-- | The content type the client most desires (or JSON if undecided)
|
-- | The content type the client most desires (or JSON if undecided)
|
||||||
, iAccepts :: Either BS.ByteString ContentType
|
, iAccepts :: Either BS.ByteString ContentType
|
||||||
-- | {foo} becomes [{foo}] and CSV is converted to JSON
|
-- | Set to Nothing when client sends no data
|
||||||
, iPayload :: Maybe Payload
|
, iPayload :: Maybe Payload
|
||||||
-- | Taken from JSON Web Token
|
-- | Taken from JSON Web Token
|
||||||
, iTrustedClaims :: Maybe JSON.Object
|
, iTrustedClaims :: Maybe JSON.Object
|
||||||
@@ -88,6 +94,8 @@ userIntent schema req _ =
|
|||||||
lookupHeader = flip lookup hdrs
|
lookupHeader = flip lookup hdrs
|
||||||
hasPrefer val = any (\(h,v) -> h == "Prefer" && v == val) hdrs
|
hasPrefer val = any (\(h,v) -> h == "Prefer" && v == val) hdrs
|
||||||
|
|
||||||
|
-- PRIVATE ---------------------------------------------------------------
|
||||||
|
|
||||||
-- | Chooses a payload from the items in an accept header.
|
-- | Chooses a payload from the items in an accept header.
|
||||||
-- When possible it picks JSON.
|
-- When possible it picks JSON.
|
||||||
pickContentType :: Maybe BS.ByteString -> Either BS.ByteString ContentType
|
pickContentType :: Maybe BS.ByteString -> Either BS.ByteString ContentType
|
||||||
@@ -102,3 +110,22 @@ pickContentType accept
|
|||||||
Just acceptH = accept
|
Just acceptH = accept
|
||||||
findInAccept = flip find $ parseHttpAccept acceptH
|
findInAccept = flip find $ parseHttpAccept acceptH
|
||||||
has = isJust . findInAccept . BS.isPrefixOf
|
has = isJust . findInAccept . BS.isPrefixOf
|
||||||
|
|
||||||
|
type CsvData = V.Vector (V.Vector BL.ByteString)
|
||||||
|
|
||||||
|
-- | Convert
|
||||||
|
-- a,b
|
||||||
|
-- 1,2
|
||||||
|
-- 3,4
|
||||||
|
--
|
||||||
|
-- into
|
||||||
|
-- [ {"a": 1, "b": 2}, {"a": 3, "b": 4} ]
|
||||||
|
csvToJson :: (CSV.Header, CsvData) -> JSON.Array
|
||||||
|
csvToJson (cols, vals) =
|
||||||
|
V.map rowToJson vals
|
||||||
|
where
|
||||||
|
cols' = V.map cs cols :: V.Vector T.Text
|
||||||
|
rowToJson :: V.Vector BL.ByteString -> JSON.Value
|
||||||
|
rowToJson val = JSON.Object $
|
||||||
|
let val' = V.map (JSON.String . cs) val in
|
||||||
|
M.fromList . V.toList $ V.zip cols' val'
|
||||||
|
|||||||
Reference in New Issue
Block a user