I have been building more clients lately and I am curious. There seems like there would be a good use for something like JSON::Serializable
for URI::Params
. What do people normally use for this and would this be a good addition to the stdlib?
What benefits are you imagining for a URI::Params::Serializable
mixin? The main benefit I’ve noticed with constructs like JSON::Serializable
and similar constructs for other similar serialization formats is that, since the data structures are nested, you can reuse types in a lot of different places. For example, Stripe’s API embeds customer
and payment_method
objects in a lot of different responses. Since URI::Params
doesn’t allow nesting, I don’t know what the benefits would be.
Though, to be fair, Stripe’s API is a pretty interesting example for me to use here since their API receives form-encoded data and emits JSON.
I usually use them as I would a Hash(String, String | Array(String))
. In place of explicit type casting, params[key]?
returns the string (if the key exists) and params.fetch_all(key)
returns all values for that key.
For example, let’s say you’re publishing a post:
params = r.form_params
title = params["title"]?
body = params["body"]?
# Check to see that the params were provided, since the
# PostQuery#create method requires them to be strings
if title && body && valid_authenticity_token?(params, session)
case result = PostQuery.new.create(title, body)
in Validations::Success(Post)
response.redirect "/posts/#{result.object.id}"
in Validations::Failure
errors = result.errors
render "posts/errors"
render "posts/form"
end
else # Probably didn't come in via the form
response.status = :bad_request
end
And to build them to send to a remote server:
params = URI::Params{
"foo" => foo,
"bar" => bar,
}
response = http.post("/path/to/endpoint", body: params.to_s)
I think mappings to Crystal types are great for any serialization format. Even arguably simple ones.
It’s easy to use and ensures type safety.
A good role model for serialization implementations is Rust’s serde framework. And it has a plugin for URI params as well: serde_qs
.