Parsing a simple string parameter with Url.Parser

I’ll have to admit that the documentation to Url.Parser is completely impenetrable to me. What I’m trying to do is get a simple query parameter from a URL, while ignoring the path. But what is a Parser a b even? The best hint I’m getting from the documentation is that I should read those Haskell/Ocaml blog posts linked from the README, but surely I’m missing something? My best guess so far is something along the lines of:

ignorePath : Parser a a
ignorePath = custom "IGNORE_PATH" noIdeaWhatGoesHere

getId : Url -> Maybe String
getId url = parse (ignorePath <?> Query.string "id") url

Any hints?

This seems to work, but not particularly satisfying:

getId : Url -> Maybe String
getId url =
  let
    anyPath : Parser (String -> a) a
    anyPath = custom "ANY_PATH" Just

    flatten v = case v of (Just x) -> x
                          Nothing -> Nothing
  in
    flatten <|
    parse
      (map (\p i -> i) (anyPath <?> Query.string "id"))
      url

Is there a more elegant/intuitive way to do this?

I’ve Settled on this utility function for my needs thus far, which did indeed take a lot of reading, pondering, and experimenting to figure out. Looks like it is roughly equivalent to what you have, except for using location update to take care of the any path part.

extractSearchArgument : String -> Url -> Maybe String
extractSearchArgument key location =
  { location | path = "" }
    |> Url.Parser.parse (Url.Parser.query (Url.Parser.Query.string key))
    |> Maybe.withDefault Nothing
4 Likes

I think what you are looking for is Url.Parser.Query. Url.Parser is used to “analyze” the entire path, as you would want to do in an SPA where the URL changed and you need to decide what to do next. Your case is different, as you seem to just be interested in the query and don’t care about the path.

Therefore your function could be implemented similar to this:

getId : Url -> Maybe String
getId url =
    let idParser = Url.Parser.query Url.Parser.Query.string "id"
    in
    Url.Parser.parse idParser url

So Url.Parser.Query.string "id" makes a query parser (not a url parser) that parses the string in the query field id. We need to convert that to a url parser, in order to be able to parse it, so we feed that through Url.Parser.query. The resulting parser is passed with the url to Url.Parser.parse.

I have to agree that I also find it a bit confusing that you have no way of using the Url.Parser.Query.Parser other than with Url.Parser.parse, for which it needs to be converted. I would have liked something like Url.Parser.Query.parse : Url.Parser.Query.Parser a -> Url -> Maybe a.

But this way also ended up being quite readable and I think once you see it, it’s also understandable.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.