Purescript:如何解析查询字符串(在 url/uri 中)

Purescript: how to parse a query string (in a url/uri)

Purescript 有一个带有 URI.Query 模块的贡献包:https://pursuit.purescript.org/packages/purescript-uri/8.0.1/docs/URI.Query 用于解析它建议使用 Text.Parsing.Parser.

有人可以通过代码示例解释如何解析这样的查询字符串:"s=str&i=1&b=true"

进入记录{s :: String, i :: Int, b :: Maybe Boolean }(假设第三个参数b是可选的,可能存在也可能不存在)

这是一个基本版本,仅使用 URI.Extra.QueryPair 和一些助手来解析内容:

module Main where

import Prelude

import Data.Either (hush)
import Data.Foldable (lookup)
import Data.Int (fromString)
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Class.Console (logShow)
import URI.Extra.QueryPairs (QueryPairs(..))
import URI.Extra.QueryPairs as QP
import URI.Query as Q

main :: Effect Unit
main = do
  logShow $ parseQuery "s=str&i=1&b=true"
  logShow $ parseQuery "s=abc&i=42&b=false"
  logShow $ parseQuery "s=str&i=1"

type Query = { s :: String, i :: Int, b :: Maybe Boolean }

parseQuery :: String -> Maybe Query
parseQuery = Q.fromString >>> QP.parse (QP.keyToString >>> pure) (QP.valueToString >>> pure) >>> hush >=> fromPairs

fromPairs :: QueryPairs String String -> Maybe Query
fromPairs (QueryPairs pairs) = do
  s <- join $ lookup "s" pairs
  i <- join (lookup "i" pairs) >>= fromString
  let b = join (lookup "b" pairs) >>= parseBool
  pure { s, i , b}
  where
  parseBool "true" = Just true
  parseBool "false" = Just false
  parseBool _ = Nothing

这将输出

(Just { b: (Just true), i: 1, s: "str" })
(Just { b: (Just false), i: 42, s: "abc" })
(Just { b: Nothing, i: 1, s: "str" })

示例。


代码本身应该相当简单。 请注意 QueryPair String String ~ Array String (Maybe String),因此值的 提取 有点乏味 (join)


使用routing-duplex

的版本

如果您对安装 purescript-routing-duplex 没问题,您可以使用其中的解析器来帮助您解决很多问题 - 这就是我要使用的那个(尤其是当您可能想要解析带有参数的路由时):

module Main where

import Prelude

import Data.Either (hush)
import Data.Maybe (Maybe)
import Effect (Effect)
import Effect.Class.Console (logShow)
import Routing.Duplex as R

main :: Effect Unit
main = do
  logShow $ parseQuery "s=str&i=1&b=true"
  logShow $ parseQuery "s=abc&i=42&b=false"
  logShow $ parseQuery "s=str&i=1"

type Query = { s :: String, i :: Int, b :: Maybe Boolean }

parseQuery :: String -> Maybe Query
parseQuery s = hush $ R.parse parser ("?" <> s)
  where
    parser =
      R.params
        { s: R.string
        , i: R.int
        , b: R.optional <<< R.boolean
        }