JSON与序列化
JSON格式基础
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,以纯文本存储和传输结构化数据。
- 对象:用
{}包裹,包含键值对,键必须是字符串 - 数组:用
[]包裹,有序值列表 - 数据类型:字符串、数字、布尔值、null、对象、数组
TEXT
{
"name": "张三",
"age": 28,
"isStudent": false,
"hobbies": ["编程", "阅读"],
"address": {
"city": "北京",
"zip": "100000"
}
}
System.Text.Json 概述
System.Text.Json 是 .NET Core 3.0+ 内置的高性能 JSON 库,无需安装第三方包。推荐使用它而非 Newtonsoft.Json。
CSHARP
using System.Text.Json;
序列化:对象转JSON
JsonSerializer.Serialize() 将对象转换为 JSON 字符串。
示例
CSHARP
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 = "张三",
Age = 28,
IsStudent = false
};
string json = JsonSerializer.Serialize(person);
Console.WriteLine(json);
}
}
TEXT
{"Name":"张三","Age":28,"IsStudent":false}
反序列化:JSON转对象
JsonSerializer.Deserialize<T>() 将 JSON 字符串转换回指定类型的对象。
示例
CSHARP
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"":""张三"",""Age"":28,""IsStudent"":false}";
Person person = JsonSerializer.Deserialize<Person>(json);
Console.WriteLine($"姓名: {person.Name}, 年龄: {person.Age}");
}
}
TEXT
姓名: 张三, 年龄: 28
JsonSerializerOptions 配置
通过 JsonSerializerOptions 可控制序列化行为,如命名策略、缩进格式、忽略空值等。
| 选项 | 说明 |
|---|---|
PropertyNamingPolicy |
属性命名策略,如 JsonNamingPolicy.CamelCase |
WriteIndented |
是否缩进输出,便于阅读 |
IgnoreNullValues |
是否忽略 null 值属性 |
PropertyNameCaseInsensitive |
反序列化时忽略属性名大小写 |
示例
CSHARP
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 = "张三",
Age = 28,
Email = null
};
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true,
IgnoreNullValues = true
};
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json);
}
}
TEXT
{
"name": "张三",
"age": 28
}
序列化集合与字典
JsonSerializer 可直接序列化列表、字典等集合类型。
示例
CSHARP
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 = "张三", Score = 90 },
new Student { Name = "李四", Score = 85 },
new Student { Name = "王五", Score = 92 }
};
var options = new JsonSerializerOptions { WriteIndented = true };
string json = JsonSerializer.Serialize(students, options);
Console.WriteLine(json);
var scores = new Dictionary<string, int>
{
["语文"] = 90,
["数学"] = 95,
["英语"] = 88
};
string dictJson = JsonSerializer.Serialize(scores, options);
Console.WriteLine(dictJson);
}
}
TEXT
[
{
"Name": "张三",
"Score": 90
},
{
"Name": "李四",
"Score": 85
},
{
"Name": "王五",
"Score": 92
}
]
{
"语文": 90,
"数学": 95,
"英语": 88
}
动态JSON:JsonDocument与JsonElement
当 JSON 结构不确定时,可使用 JsonDocument 和 JsonElement 进行动态解析,无需预定义类。
示例
CSHARP
using System;
using System.Text.Json;
class Program
{
static void Main()
{
string json = @"{""name"":""张三"",""age"":28,""hobbies"":[""编程"",""阅读""]}";
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}, 年龄: {age}");
foreach (JsonElement hobby in hobbies.EnumerateArray())
{
Console.WriteLine($"爱好: {hobby.GetString()}");
}
}
}
TEXT
姓名: 张三, 年龄: 28
爱好: 编程
爱好: 阅读
自定义序列化:JsonConverter
继承 JsonConverter<T> 并重写 Read 和 Write 方法,可实现自定义的序列化/反序列化逻辑。
示例
CSHARP
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 = "产品发布会",
Date = new DateTime(2025, 6, 15)
};
string json = JsonSerializer.Serialize(evt);
Console.WriteLine(json);
Event deserialized = JsonSerializer.Deserialize<Event>(json);
Console.WriteLine($"标题: {deserialized.Title}, 日期: {deserialized.Date:yyyy-MM-dd}");
}
}
TEXT
{"Title":"产品发布会","Date":"2025-06-15"}
标题: 产品发布会, 日期: 2025-06-15
JSON与LINQ结合
将 JSON 反序列化为集合后,可使用 LINQ 进行查询、筛选和统计。
示例
CSHARP
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"":""张三"",""Score"":90,""City"":""北京""},
{""Name"":""李四"",""Score"":85,""City"":""上海""},
{""Name"":""王五"",""Score"":92,""City"":""北京""},
{""Name"":""赵六"",""Score"":78,""City"":""上海""},
{""Name"":""钱七"",""Score"":95,""City"":""北京""}
]";
List<Student> students = JsonSerializer.Deserialize<List<Student>>(json);
var beijingTop = students
.Where(s => s.City == "北京")
.OrderByDescending(s => s.Score)
.ToList();
Console.WriteLine("北京学生(按分数降序):");
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("\n各城市平均分:");
foreach (var item in cityAvg)
{
Console.WriteLine($" {item.City}: {item.Avg:F1}");
}
}
}
TEXT
北京学生(按分数降序):
钱七: 95
王五: 92
张三: 90
各城市平均分:
北京: 92.3
上海: 81.5
CSV读写简介
CSV(Comma-Separated Values)是用逗号分隔字段的文本格式,常用于数据导出和交换。C# 标准库无内置CSV支持,可手动解析或使用第三方库如 CsvHelper。
示例
CSHARP
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Program
{
static void Main()
{
var records = new List<string[]>
{
new[] { "姓名", "年龄", "城市" },
new[] { "张三", "28", "北京" },
new[] { "李四", "25", "上海" }
};
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],-6} {fields[1],-4} {fields[2]}");
}
}
}
TEXT
姓名 年龄 城市
张三 28 北京
李四 25 上海
💡 提示:生产环境建议使用 CsvHelper(NuGet 包),它能正确处理含逗号、引号、换行的字段,避免手动解析的常见陷阱。
❓ 常见问题
Q System.Text.Json 和 Newtonsoft.Json 有什么区别?
A System.Text.Json 是 .NET 内置的高性能库,Newtonsoft.Json 是第三方库功能更丰富,新项目优先使用内置库。
Q 反序列化时属性名大小写不匹配怎么办?
A 设置
JsonSerializerOptions 的 PropertyNameCaseInsensitive = true 即可忽略大小写差异。Q 如何忽略某个属性不被序列化?
A 在该属性上添加
[JsonIgnore] 特性即可跳过该属性。Q JSON 中的日期格式如何控制?
A 通过自定义
JsonConverter<DateTime> 重写 Write 方法,指定所需的日期格式字符串。📖 小节
- JSON 使用
{}表示对象、[]表示数组,是通用的数据交换格式 System.Text.Json是 .NET 内置的 JSON 库,通过Serialize/Deserialize完成转换JsonSerializerOptions可配置命名策略、缩进、忽略空值等行为JsonDocument/JsonElement适合解析结构不确定的 JSON- 自定义
JsonConverter<T>可控制特定类型的序列化逻辑 - JSON 反序列化为集合后可结合 LINQ 进行查询统计
- CSV 格式可手动解析,生产环境推荐使用
CsvHelper库
📝 作业
- 定义一个
Book类(Title、Author、Price、IsPublished),序列化为缩进的 JSON 字符串并输出,再反序列化回对象 - 创建一个
List<Book>包含至少3本书,序列化为 JSON,然后用 LINQ 筛选价格大于50的书籍 - 编写一个自定义
JsonConverter,将DateTime序列化为"yyyy/MM/dd"格式,并验证反序列化可正确还原 - 将一个字典
Dictionary<string, string>序列化为 JSON 后保存到文件,再从文件读取并反序列化还原 - 手动编写 CSV 写入与读取逻辑,处理包含逗号的字段(用双引号包裹)



