Working with JSON in C#
C# offers two main libraries for JSON: the built-in System.Text.Json (.NET Core 3.0+)
and the popular Newtonsoft.Json (Json.NET). This guide covers both.
System.Text.Json (Built-in)
Deserializing JSON
using System.Text.Json;
// Define a class
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public bool IsActive { get; set; }
}
// Deserialize JSON string
string json = "{\"name\": \"John\", \"age\": 30, \"email\": \"john@example.com\", \"isActive\": true}";
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
User user = JsonSerializer.Deserialize(json, options);
Console.WriteLine(user.Name); // John
Console.WriteLine(user.Age); // 30 Serializing to JSON
using System.Text.Json;
var user = new User
{
Name = "Jane",
Age = 25,
Email = "jane@example.com",
IsActive = true
};
// Basic serialization
string json = JsonSerializer.Serialize(user);
Console.WriteLine(json);
// {"Name":"Jane","Age":25,"Email":"jane@example.com","IsActive":true}
// Pretty print with options
var options = new JsonSerializerOptions
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
string prettyJson = JsonSerializer.Serialize(user, options);
Console.WriteLine(prettyJson); JsonDocument for Dynamic JSON
using System.Text.Json;
string json = "{\"name\": \"John\", \"address\": {\"city\": \"New York\"}, \"tags\": [\"developer\"]}";
using JsonDocument doc = JsonDocument.Parse(json);
JsonElement root = doc.RootElement;
// Access properties
string name = root.GetProperty("name").GetString();
string city = root.GetProperty("address").GetProperty("city").GetString();
// Access array
JsonElement tags = root.GetProperty("tags");
foreach (JsonElement tag in tags.EnumerateArray())
{
Console.WriteLine(tag.GetString());
}
// Check if property exists
if (root.TryGetProperty("email", out JsonElement email))
{
Console.WriteLine(email.GetString());
} Attributes and Customization
using System.Text.Json.Serialization;
public class User
{
// Rename property in JSON
[JsonPropertyName("user_name")]
public string Name { get; set; }
// Ignore property
[JsonIgnore]
public string Password { get; set; }
// Ignore if null
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? MiddleName { get; set; }
// Number handling
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
public int Age { get; set; }
} Newtonsoft.Json (Json.NET)
Install via NuGet: Install-Package Newtonsoft.Json
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
// Deserialize
string json = "{\"name\": \"John\", \"age\": 30}";
User user = JsonConvert.DeserializeObject(json);
// Serialize
string output = JsonConvert.SerializeObject(user);
// Pretty print
string prettyJson = JsonConvert.SerializeObject(user, Formatting.Indented); JObject for Dynamic JSON
using Newtonsoft.Json.Linq;
string json = "{\"name\": \"John\", \"address\": {\"city\": \"New York\"}}";
// Parse to JObject
JObject obj = JObject.Parse(json);
// Access values
string name = (string)obj["name"];
string city = (string)obj["address"]["city"];
// Modify
obj["age"] = 30;
// Create JObject
var newObj = new JObject
{
["name"] = "Jane",
["age"] = 25
};
Console.WriteLine(newObj.ToString()); JSON Validation
using System.Text.Json;
public class JsonValidator
{
public static bool IsValidJson(string json)
{
try
{
JsonDocument.Parse(json);
return true;
}
catch (JsonException)
{
return false;
}
}
public static ValidationResult ValidateJson(string json)
{
try
{
using var doc = JsonDocument.Parse(json);
var type = doc.RootElement.ValueKind switch
{
JsonValueKind.Object => "object",
JsonValueKind.Array => "array",
JsonValueKind.String => "string",
_ => "unknown"
};
return new ValidationResult(true, null, type);
}
catch (JsonException ex)
{
return new ValidationResult(false, ex.Message, null);
}
}
}
public record ValidationResult(bool IsValid, string? Error, string? Type); Working with Files
using System.Text.Json;
using System.IO;
// Read JSON file
string json = await File.ReadAllTextAsync("data.json");
var user = JsonSerializer.Deserialize(json);
// Write JSON file
var options = new JsonSerializerOptions { WriteIndented = true };
string output = JsonSerializer.Serialize(user, options);
await File.WriteAllTextAsync("output.json", output);
// Stream-based (memory efficient)
await using FileStream stream = File.OpenRead("data.json");
var data = await JsonSerializer.DeserializeAsync(stream); HTTP API Example
using System.Net.Http.Json;
var httpClient = new HttpClient();
// GET JSON
var user = await httpClient.GetFromJsonAsync("https://api.example.com/user");
// POST JSON
var newUser = new User { Name = "John", Email = "john@example.com" };
var response = await httpClient.PostAsJsonAsync("https://api.example.com/users", newUser);
var createdUser = await response.Content.ReadFromJsonAsync();
// ASP.NET Core Controller
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
[HttpGet("{id}")]
public ActionResult Get(int id)
{
var user = new User { Name = "John", Age = 30 };
return Ok(user);
}
[HttpPost]
public ActionResult Create([FromBody] User user)
{
return CreatedAtAction(nameof(Get), new { id = 1 }, user);
}
} Best Practices
- Use
System.Text.Jsonfor new .NET Core/.NET 5+ projects (better performance) - Use
Newtonsoft.Jsonif you need advanced features like LINQ to JSON - Cache
JsonSerializerOptionsinstances for better performance - Use
PropertyNameCaseInsensitive = truefor flexible deserialization - Handle
JsonExceptionwhen parsing untrusted input - Use source generators in .NET 6+ for better AOT compilation support