Skip to main content

URL Form serialisation

The smithy4s-core module provides a smithy4s.http.UrlForm data-type, along with encoders and decoders that can read/write generated data-types from/to the application/x-www-form-urlencoded format. This serialisation is what powers the AWS query protocol implementation in Smithy4s.

UrlForm is a case class wrapping a list of key/value pairs. It can be rendered to a String via .render, and parsed back with UrlForm.parse.

import smithy4s.example.hello.Person

import smithy4s.http.UrlForm

val personEncoder = UrlForm
.Encoder(capitalizeStructAndUnionMemberNames = false)
.fromSchema(Person.schema)
// personEncoder: UrlForm.Encoder[Person] = smithy4s.http.UrlForm$Encoder$$anon$2$$anonfun$fromSchema$8@49a276a3

val personUrlForm = personEncoder.encode(Person(name = "John Doe"))
// personUrlForm: UrlForm = UrlForm(
// values = List(
// FormData(
// path = PayloadPath(segments = List(Label(label = "name"))),
// maybeValue = Some(value = "John Doe")
// )
// )
// )
val personString = personUrlForm.render
// personString: String = "name=John+Doe"

val personDecoder = UrlForm
.Decoder(
ignoreUrlFormFlattened = false,
capitalizeStructAndUnionMemberNames = false
)
.fromSchema(Person.schema)
// personDecoder: UrlForm.Decoder[Person] = smithy4s.http.UrlForm$Decoder$$anon$1$$anonfun$fromSchema$2@5abdf61c

val maybePerson = UrlForm.parse(personString).flatMap(personDecoder.decode)
// maybePerson: Either[smithy4s.http.UrlFormDecodeError, Person] = Right(
// value = Person(name = "John Doe", town = None)
// )

Configuration

Both UrlForm.Encoder and UrlForm.Decoder take a capitalizeStructAndUnionMemberNames flag. When true, member names are capitalised in the output (and expected to be capitalised on input) - this matches the convention used by the AWS query protocol.

UrlForm.Decoder additionally accepts an ignoreUrlFormFlattened flag, which disables special handling of the @alloy#urlFormFlattened trait when decoding.

UrlForm.Encoder has an overload with an alwaysSkipEmptyLists flag, which omits empty lists from the encoded output regardless of any other configuration.

Supported traits

By default, UrlForm codecs honour the following alloy traits:

  • @alloy#urlFormName - changes the serialised key of a structure, union, or member. This is analogous to @jsonName for JSON serialisation.
  • @alloy#urlFormFlattened - unwraps the values of a list, set, or map into the containing structure or union, rather than nesting them under the member's key.

For example, given the following Smithy definition:

use alloy#urlFormName
use alloy#urlFormFlattened

structure Order {
@urlFormName("order-id")
@required
id: String

@urlFormFlattened
items: ItemList
}

list ItemList {
member: String
}

an Order("123", List("a", "b")) value would encode to order-id=123&items.1=a&items.2=b, with the list members flattened directly under the items key.