No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2025-04-16 19:27:12 -04:00
.github/workflows Update CI matrix 2024-03-18 12:32:10 -04:00
src push update (#3) 2025-04-16 19:27:12 -04:00
test Update for modern Gleam 2024-03-18 12:26:57 -04:00
.gitignore Initial commit 2022-02-03 01:09:57 -05:00
gleam.toml push update (#3) 2025-04-16 19:27:12 -04:00
LICENSE Initial commit 2022-02-03 01:09:57 -05:00
manifest.toml push update (#3) 2025-04-16 19:27:12 -04:00
README.md Update for modern Gleam 2024-03-18 12:26:57 -04:00

form_coder

A Gleam library to encode and decode x-www-form-urlencoded data.

This data is a superset of your traditional GET query parameter format; e.g. foo=bar&baz=qux. While there's no established standard for conveying data structures such as lists and maps, form_coder follows the format used by both Rails and Plug. Namely:

  • A list like [#("foo", ["bar", "baz"])] is encoded to foo[]=bar&foo[]=baz
  • A map like [#("foo", %{"bar" => "qux"})] (map in Elixir syntax for brevity) is encoded as foo[bar]=qux.

Examples

Encoding

> form_coder.encode([#("foo", QStr("bar")), #("baz", QStr("qux"))])
"foo=bar&baz=qux"
> form_coder.encode([#("user_ids", QList([QStr("1"), QStr("2")]))])
"user_ids[]=1&user_ids[]=2"
> form_coder.encode([#("person", QMap(dict.from_list([#("name", QStr("Joe")), #("age", QStr("71"))])))])
"person[age]=71&person[name]=Joe"

What's with QStr, QList, and QMap?

Well, in the type specification, the argument must take the form List(#(String, _)), where I can choose what to replace _ with. Choosing any one of String, List, or Dict would make using the other two very inconvenient. Using some type variable a would enforce that all "values" have the same type (i.e. you can't have some values as strings and others as lists) and form_coder would have to know how to encode your arbitrary a and that doesn't seem possible.

Since Gleam doesn't have union types, I created an algebraic type with variants to wrap each supported type; hence QStr, QList, and QMap.

Decoding

> form_coder.decode("foo=bar&baz=qux", dynamic.list(of: dynamic.tuple2(dynamic.string, dynamic.string)))
[#("foo", "bar"), #("baz", "qux")]

Support for decoding the more sophisticated types (List, Map) is planned, but not yet implemented.

Quick start

gleam build # Compile the project
gleam test  # Run the tests
gleam shell # Run an Erlang shell

Installation

gleam add form_coder