404 Not Found

404 Not Found


nginx

JSON与序列化

JSON格式基础

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,以纯文本存储和传输结构化数据。

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 结构不确定时,可使用 JsonDocumentJsonElement 进行动态解析,无需预定义类。

示例

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> 并重写 ReadWrite 方法,可实现自定义的序列化/反序列化逻辑。

示例

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 设置 JsonSerializerOptionsPropertyNameCaseInsensitive = true 即可忽略大小写差异。
Q 如何忽略某个属性不被序列化?
A 在该属性上添加 [JsonIgnore] 特性即可跳过该属性。
Q JSON 中的日期格式如何控制?
A 通过自定义 JsonConverter<DateTime> 重写 Write 方法,指定所需的日期格式字符串。

📖 小节

📝 作业

  1. 定义一个 Book 类(Title、Author、Price、IsPublished),序列化为缩进的 JSON 字符串并输出,再反序列化回对象
  2. 创建一个 List<Book> 包含至少3本书,序列化为 JSON,然后用 LINQ 筛选价格大于50的书籍
  3. 编写一个自定义 JsonConverter,将 DateTime 序列化为 "yyyy/MM/dd" 格式,并验证反序列化可正确还原
  4. 将一个字典 Dictionary<string, string> 序列化为 JSON 后保存到文件,再从文件读取并反序列化还原
  5. 手动编写 CSV 写入与读取逻辑,处理包含逗号的字段(用双引号包裹)
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏