Serialization
RestClient.Net gives you full control over how requests are serialized and responses are deserialized.
Deserializers
Deserializers convert HttpResponseMessage to your model types:
Func<HttpResponseMessage, CancellationToken, Task<TSuccess>> deserializeSuccess
Func<HttpResponseMessage, CancellationToken, Task<TError>> deserializeError
JSON Deserialization
Using System.Text.Json:
var result = await httpClient.GetAsync(
url: "https://api.example.com/users/1".ToAbsoluteUrl(),
deserializeSuccess: async (response, ct) =>
await response.Content.ReadFromJsonAsync<User>(ct)
?? throw new InvalidOperationException("Null response"),
deserializeError: async (response, ct) =>
await response.Content.ReadFromJsonAsync<ApiError>(ct)
?? new ApiError("Unknown error")
);
Reusable Deserializers
Create a static class with reusable deserializer methods:
public static class Deserializers
{
public static async Task<T> Json<T>(HttpResponseMessage response, CancellationToken ct)
where T : class =>
await response.Content.ReadFromJsonAsync<T>(ct)
?? throw new InvalidOperationException($"Failed to deserialize {typeof(T).Name}");
public static async Task<ApiError> Error(HttpResponseMessage response, CancellationToken ct) =>
await response.Content.ReadFromJsonAsync<ApiError>(ct)
?? new ApiError("Unknown error");
}
// Usage
var result = await httpClient.GetAsync(
url: "https://api.example.com/users/1".ToAbsoluteUrl(),
deserializeSuccess: Deserializers.Json<User>,
deserializeError: Deserializers.Error
);
Custom JSON Options
Configure JsonSerializerOptions for custom serialization behavior:
public static class Deserializers
{
private static readonly JsonSerializerOptions Options = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
public static async Task<T> Json<T>(HttpResponseMessage response, CancellationToken ct)
where T : class =>
await response.Content.ReadFromJsonAsync<T>(Options, ct)
?? throw new InvalidOperationException($"Failed to deserialize {typeof(T).Name}");
}
Serializers
Serializers convert your request body to HttpContent. They're used with POST, PUT, and PATCH requests.
Func<TBody, HttpContent> serializeRequest
JSON Serialization
var result = await httpClient.PostAsync(
url: "https://api.example.com/users".ToAbsoluteUrl(),
body: new CreateUserRequest("John", "john@example.com"),
serializeRequest: body => JsonContent.Create(body),
deserializeSuccess: Deserializers.Json<User>,
deserializeError: Deserializers.Error
);
Custom Content Types
Form URL Encoded
Using FormUrlEncodedContent:
serializeRequest: body => new FormUrlEncodedContent(new Dictionary<string, string>
{
["name"] = body.Name,
["email"] = body.Email
})
Multipart Form Data
Using MultipartFormDataContent for file uploads:
serializeRequest: body =>
{
var content = new MultipartFormDataContent();
content.Add(new StringContent(body.Name), "name");
content.Add(new ByteArrayContent(body.FileBytes), "file", body.FileName);
return content;
}
XML
Using XmlSerializer:
serializeRequest: body =>
{
var serializer = new XmlSerializer(typeof(TBody));
using var writer = new StringWriter();
serializer.Serialize(writer, body);
return new StringContent(writer.ToString(), Encoding.UTF8, "application/xml");
}
Stream Response
Using Stream for large files:
var result = await httpClient.GetAsync(
url: "https://api.example.com/files/large".ToAbsoluteUrl(),
deserializeSuccess: async (response, ct) => await response.Content.ReadAsStreamAsync(ct),
deserializeError: Deserializers.Error
);
See Also
- HttpClient Extensions - Extension methods using serializers
- Result Types - Understanding the return types