C# – Get and send JSON with HttpClient

The simplest way to get and send JSON with HttpClient is to use the GetFromJsonAsync() and PostAsJsonAsync() extension methods found in System.Net.Http.Json, like this:

using System.Net.Http.Json;

//Get JSON
var stock = await httpClient.GetFromJsonAsync<Stock>($"https://localhost:12345/stocks/{symbol}");

stock.Price = 121.10m;

//Send JSON
await httpClient.PostAsJsonAsync<Stock>("https://localhost:12345/stocks/", stock);
Code language: C# (cs)

Note: You have to install the System.Net.Http.Json nuget package if you’re using a framework version before .NET 5.

These extension methods use System.Text.Json for serialization. They simplify things by abstracting away the common steps involved in sending and getting JSON. Compare this approach with the manual way of doing it (see the What if you want to use Newtonsoft? section below).

To customize serialization, you can pass in a JsonSerializerOptions object. I’ll show an example of that below.

If you’re using a version before .NET 5, install the System.Net.Http.Json nuget package

Microsoft added System.Net.Http.Json to the framework starting in .NET 5. If you’re using a framework version before .NET 5, you’ll have to install the nuget package to get it.

Install it using the Package Manager Console with this command (or just use the nuget manager UI):

Install-Package System.Net.Http.Json
Code language: PowerShell (powershell)

Note: View > Other Windows > Package Manager Console.

Customize JSON serialization when using HttpClient

To customize serialization, you can pass in a JsonSerializerOptions object. If you need to customize something that the default options don’t support, then you can create a custom converter. Note: To maximize performance, make sure to reuse the JsonSerializerOptions object.

Here’s an example.

By default, System.Text.Json serializes enum values instead of names, like this:

{
	"symbol": "VTSAX",
	"price": 106.5,
	"quoteTime": "2021-07-20T14:04:00.3381111-04:00",
	"fundType": 1
}
Code language: JSON / JSON with Comments (json)

Let’s say you want to make it serialize the enum name instead. You can do that by passing in a JsonSerializerOptions object with a JsonStringEnumConverter object, like this:

using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;

var stock = new Stock()
{
	Symbol = "VTSAX",
	FundType = FundTypes.MutualFund,
	Price = 106.5m,
	QuoteTime = DateTimeOffset.Now
};

var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
options.Converters.Add(new JsonStringEnumConverter());

await httpClient.PostAsJsonAsync<Stock>("https://localhost:12345/stocks/", stock, options);
Code language: C# (cs)

This generates the following JSON. Notice the FundType property is using the enum name instead of the value:

{
	"symbol": "VTSAX",
	"price": 106.5,
	"quoteTime": "2021-07-20T15:18:39.7460603-04:00",
	"fundType": "MutualFund"
}
Code language: JSON / JSON with Comments (json)

Use JsonSerializerDefaults.Web

If you don’t pass in a JsonSerializerOptions object, then System.Net.Http.Json uses an options object with the following definition:

new JsonSerializerOptions(JsonSerializerDefaults.Web)
Code language: C# (cs)

This creates the options object with “web defaults,” which is equivalent to creating the options object with the following settings:

var options = new JsonSerializerOptions()
{
	PropertyNameCaseInsensitive = true,
	PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
	NumberHandling = JsonNumberHandling.AllowReadingFromString
};
Code language: C# (cs)

When you’re creating your own options object to customize serialization, you’ll need to pass in the JsonSerializerDefaults.Web constructor parameter if you want to use the “web defaults.”

What if you want to use Newtonsoft?

The System.Net.Http.Json extension methods provide a nice, convenient way to deal with JSON when you’re using HttpClient. The downside is that it forces you to use System.Text.Json. What if you want to use Newtonsoft instead (or just want to handle this manually)?

Here’s an example of getting JSON with HttpClient and deserializing it with Newtonsoft:

using Newtonsoft.Json;

var symbol = "VTSAX";
var response = await httpClient.GetAsync($"https://localhost:12345/stocks/{symbol}");

response.EnsureSuccessStatusCode();

var json = await response.Content.ReadAsStringAsync();

var stock = JsonConvert.DeserializeObject<Stock>(json);

Console.WriteLine($"Stock {stock.Symbol} ({stock.FundType}) = {stock.Price}");
Code language: C# (cs)

Note: Compare this with the one-liner httpClient.GetFromJsonAsync<Stock>(url);

This outputs:

Stock VTSAX (MutualFund) = 107Code language: plaintext (plaintext)

Here’s an example of serializing an object into JSON with Newtonsoft and then sending it with HttpClient:

using Newtonsoft.Json;

var stock = new Stock()
{
	Symbol = "VTSAX",
	FundType = FundTypes.MutualFund,
	Price = 106.5m,
	QuoteTime = DateTimeOffset.Now
};

var json = JsonConvert.SerializeObject(stock);

var response = await httpClient.PostAsync("https://localhost:12345/stocks/", 
	new StringContent(json, Encoding.UTF8, "application/json"));

response.EnsureSuccessStatusCode();
Code language: C# (cs)

Note: Compare this with the one-liner httpClient.PostAsJsonAsync<Stock>(url, stock);

Leave a Comment