JSON and Serialization
JSON Format Basics
JSON (JavaScript Object Notation) is a lightweight data interchange format that stores and transmits structured data as plain text.
- Object: Wrapped in
{}, contains key-value pairs; keys must be strings - Array: Wrapped in
[], an ordered list of values - Data types: String, number, boolean, null, object, array
{
"name": "Zhang San",
"age": 28,
"isStudent": false,
"hobbies": ["programming", "reading"],
"address": {
"city": "Beijing",
"zip": "100000"
}
}
System.Text.Json Overview
System.Text.Json is a high-performance JSON library built into .NET Core 3.0+, requiring no third-party packages. It is recommended over Newtonsoft.Json.
using System.Text.Json;
Serialization: Object to JSON
JsonSerializer.Serialize() converts an object to a JSON string.
Example
using System;
using System.Text.Json;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public bool IsStudent { get; set; }
}
class Program
{
static void Main()
{
var person = new Person
{
Name = "Zhang San",
Age = 28,
IsStudent = false
};
string json = JsonSerializer.Serialize(person);
Console.WriteLine(json);
}
}
{"Name":"Zhang San","Age":28,"IsStudent":false}
Deserialization: JSON to Object
JsonSerializer.Deserialize<T>() converts a JSON string back to an object of the specified type.
Example
using System;
using System.Text.Json;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public bool IsStudent { get; set; }
}
class Program
{
static void Main()
{
string json = @"{""Name"":""Zhang San"",""Age"":28,""IsStudent"":false}";
Person person = JsonSerializer.Deserialize<Person>(json);
Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
}
}
Name: Zhang San, Age: 28
JsonSerializerOptions Configuration
Use JsonSerializerOptions to control serialization behavior, such as naming policy, indentation, and ignoring null values.
| Option | Description |
|---|---|
PropertyNamingPolicy |
Property naming policy, e.g. JsonNamingPolicy.CamelCase |
WriteIndented |
Whether to indent output for readability |
IgnoreNullValues |
Whether to ignore null-valued properties |
PropertyNameCaseInsensitive |
Ignore property name case during deserialization |
Example
using System;
using System.Text.Json;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
class Program
{
static void Main()
{
var person = new Person
{
Name = "Zhang San",
Age = 28,
Email = null
};
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true,
IgnoreNullValues = true
};
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json);
}
}
{
"name": "Zhang San",
"age": 28
}
Serializing Collections and Dictionaries
JsonSerializer can directly serialize collection types such as lists and dictionaries.
Example
using System;
using System.Collections.Generic;
using System.Text.Json;
public class Student
{
public string Name { get; set; }
public int Score { get; set; }
}
class Program
{
static void Main()
{
var students = new List<Student>
{
new Student { Name = "Zhang San", Score = 90 },
new Student { Name = "Li Si", Score = 85 },
new Student { Name = "Wang Wu", Score = 92 }
};
var options = new JsonSerializerOptions { WriteIndented = true };
string json = JsonSerializer.Serialize(students, options);
Console.WriteLine(json);
var scores = new Dictionary<string, int>
{
["Chinese"] = 90,
["Math"] = 95,
["English"] = 88
};
string dictJson = JsonSerializer.Serialize(scores, options);
Console.WriteLine(dictJson);
}
}
[
{
"Name": "Zhang San",
"Score": 90
},
{
"Name": "Li Si",
"Score": 85
},
{
"Name": "Wang Wu",
"Score": 92
}
]
{
"Chinese": 90,
"Math": 95,
"English": 88
}
Dynamic JSON: JsonDocument and JsonElement
When the JSON structure is uncertain, you can use JsonDocument and JsonElement for dynamic parsing without predefined classes.
Example
using System;
using System.Text.Json;
class Program
{
static void Main()
{
string json = @"{""name"":""Zhang San"",""age"":28,""hobbies"":[""programming"",""reading""]}";
using JsonDocument doc = JsonDocument.Parse(json);
JsonElement root = doc.RootElement;
string name = root.GetProperty("name").GetString();
int age = root.GetProperty("age").GetInt32();
JsonElement hobbies = root.GetProperty("hobbies");
Console.WriteLine($"Name: {name}, Age: {age}");
foreach (JsonElement hobby in hobbies.EnumerateArray())
{
Console.WriteLine($"Hobby: {hobby.GetString()}");
}
}
}
Name: Zhang San, Age: 28
Hobby: programming
Hobby: reading
Custom Serialization: JsonConverter
Inherit from JsonConverter<T> and override the Read and Write methods to implement custom serialization/deserialization logic.
Example
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
public class DateOnlyConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DateTime.ParseExact(reader.GetString(), "yyyy-MM-dd", null);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
}
}
public class Event
{
public string Title { get; set; }
[JsonConverter(typeof(DateOnlyConverter))]
public DateTime Date { get; set; }
}
class Program
{
static void Main()
{
var evt = new Event
{
Title = "Product Launch",
Date = new DateTime(2025, 6, 15)
};
string json = JsonSerializer.Serialize(evt);
Console.WriteLine(json);
Event deserialized = JsonSerializer.Deserialize<Event>(json);
Console.WriteLine($"Title: {deserialized.Title}, Date: {deserialized.Date:yyyy-MM-dd}");
}
}
{"Title":"Product Launch","Date":"2025-06-15"}
Title: Product Launch, Date: 2025-06-15
Combining JSON with LINQ
After deserializing JSON into a collection, you can use LINQ for querying, filtering, and aggregation.
Example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
public class Student
{
public string Name { get; set; }
public int Score { get; set; }
public string City { get; set; }
}
class Program
{
static void Main()
{
string json = @"[
{""Name"":""Zhang San"",""Score"":90,""City"":""Beijing""},
{""Name"":""Li Si"",""Score"":85,""City"":""Shanghai""},
{""Name"":""Wang Wu"",""Score"":92,""City"":""Beijing""},
{""Name"":""Zhao Liu"",""Score"":78,""City"":""Shanghai""},
{""Name"":""Qian Qi"",""Score"":95,""City"":""Beijing""}
]";
List<Student> students = JsonSerializer.Deserialize<List<Student>>(json);
var beijingTop = students
.Where(s => s.City == "Beijing")
.OrderByDescending(s => s.Score)
.ToList();
Console.WriteLine("Beijing students (sorted by score, descending):");
foreach (var s in beijingTop)
{
Console.WriteLine($" {s.Name}: {s.Score}");
}
var cityAvg = students
.GroupBy(s => s.City)
.Select(g => new { City = g.Key, Avg = g.Average(s => s.Score) });
Console.WriteLine("\nAverage score by city:");
foreach (var item in cityAvg)
{
Console.WriteLine($" {item.City}: {item.Avg:F1}");
}
}
}
Beijing students (sorted by score, descending):
Qian Qi: 95
Wang Wu: 92
Zhang San: 90
Average score by city:
Beijing: 92.3
Shanghai: 81.5
CSV Read/Write Introduction
CSV (Comma-Separated Values) is a text format that separates fields with commas, commonly used for data export and exchange. The C# standard library has no built-in CSV support; you can parse it manually or use a third-party library like CsvHelper.
Example
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Program
{
static void Main()
{
var records = new List<string[]>
{
new[] { "Name", "Age", "City" },
new[] { "Zhang San", "28", "Beijing" },
new[] { "Li Si", "25", "Shanghai" }
};
string csvPath = "data.csv";
File.WriteAllLines(csvPath, records.Select(r => string.Join(",", r)));
string[] lines = File.ReadAllLines(csvPath);
foreach (string line in lines)
{
string[] fields = line.Split(',');
Console.WriteLine($"{fields[0],-10} {fields[1],-4} {fields[2]}");
}
}
}
Name Age City
Zhang San 28 Beijing
Li Si 25 Shanghai
💡 Tip: For production environments, it is recommended to use CsvHelper (NuGet package), which correctly handles fields containing commas, quotes, and newlines, avoiding common pitfalls of manual parsing.
❓ FAQ
PropertyNameCaseInsensitive = true in JsonSerializerOptions to ignore case differences.[JsonIgnore] attribute to that property to skip it.JsonConverter<DateTime> and override the Write method to specify the desired date format string.📖 Summary
- JSON uses
{}for objects and[]for arrays; it is a universal data interchange format System.Text.Jsonis the built-in .NET JSON library, usingSerialize/Deserializefor conversionJsonSerializerOptionsconfigures naming policy, indentation, null-value handling, and moreJsonDocument/JsonElementare suitable for parsing JSON with uncertain structure- Custom
JsonConverter<T>controls serialization logic for specific types - JSON deserialized into collections can be combined with LINQ for querying and aggregation
- CSV can be parsed manually; for production use, the
CsvHelperlibrary is recommended
📝 Exercises
- Define a
Bookclass (Title, Author, Price, IsPublished), serialize it to an indented JSON string and output it, then deserialize it back to an object - Create a
List<Book>with at least 3 books, serialize to JSON, then use LINQ to filter books with a price greater than 50 - Write a custom
JsonConverterthat serializesDateTimein"yyyy/MM/dd"format, and verify that deserialization correctly restores it - Serialize a
Dictionary<string, string>to JSON and save it to a file, then read from the file and deserialize it back - Write manual CSV read/write logic that handles fields containing commas (wrap them in double quotes)



