Newtonsoft.Json (Json.NET)使用笔记

Newtonsoft.Json

简单介绍

最常用的 JSON 处理库,功能丰富且经过广泛测试,支持复杂的序列化、反序列化、LINQ to JSON 等功能。它是.NET 项目中处理 JSON 的标准工具之一。

许可证

MIT 许可证(开源、免费,可用于商用)。

功能特点

  1. 支持复杂类型、动态类型和匿名类型。
  2. 支持数据验证、格式化、类型转换等。
  3. 支持高性能的流式 JSON 读取和写入。
  4. 提供与 .NET 类库的良好兼容性。

代码示例

基本类型的序列化和反序列化

cs 复制代码
int number = 100;
string jsonNumber = JsonConvert.SerializeObject(number);
number = JsonConvert.DeserializeObject<int>(jsonNumber);

对象与集合的序列化和反序列化

定义一个简单的类:

cs 复制代码
public class Product
{
    public int ProductID { get; set; }
    public string ProductName { get; set; }
    public decimal Price { get; set; }
}

对象的序列化与反序列化

cs 复制代码
Product product = new Product
{
    ProductID = 1,
    ProductName = "Laptop",
    Price = 999.99m
};

string json = JsonConvert.SerializeObject(product, Formatting.Indented);
product = JsonConvert.DeserializeObject<Product>(json);

集合的序列化和反序列化

cs 复制代码
List<Product> products = new List<Product>
{
    new Product { ProductID = 1, ProductName = "Laptop", Price = 999.99m },
    new Product { ProductID = 2, ProductName = "Smartphone", Price = 499.99m },
    new Product { ProductID = 3, ProductName = "Tablet", Price = 299.99m }
};

string json = JsonConvert.SerializeObject(products, Formatting.Indented);
products = JsonConvert.DeserializeObject<List<Product>>(json);

自定义转换器的使用

自定义日期格式

假设有一个类,其中包含日期类型:

cs 复制代码
public class Event
{
    public string EventName { get; set; }
    public DateTime EventDate { get; set; }
}

默认情况下,日期会序列化为 ISO 8601 格式。
如果想使用自定义格式,例如 yyyy-MM-dd,可以使用 JsonSerializerSettings。

cs 复制代码
Event ev = new Event
{
    EventName = "Conference",
    EventDate = new DateTime(2023, 10, 1)
};

JsonSerializerSettings settings = new JsonSerializerSettings
{
    DateFormatString = "yyyy-MM-dd"
};

string json = JsonConvert.SerializeObject(ev, Formatting.Indented, settings);
ev = JsonConvert.DeserializeObject<Event>(json, settings);

自定义转换器处理特殊类型

假设有一个类,包含 TimeSpan 类型,而默认的序列化可能不满足需求。

cs 复制代码
public class Task
{
    public string TaskName { get; set; }
    public TimeSpan Duration { get; set; }
}

创建自定义转换器:

cs 复制代码
public class TimeSpanConverter : JsonConverter<TimeSpan>
{
    public override void WriteJson(JsonWriter writer, TimeSpan value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString());
    }

    public override TimeSpan ReadJson(JsonReader reader, Type objectType, TimeSpan existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        return TimeSpan.Parse((string)reader.Value);
    }
}

使用自定义转换器进行序列化和反序列化

cs 复制代码
Task task = new Task
{
    TaskName = "Write Code",
    Duration = new TimeSpan(2, 30, 0) // 2 小时 30 分钟
};

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new TimeSpanConverter());

string json = JsonConvert.SerializeObject(task, Formatting.Indented, settings);
task = JsonConvert.DeserializeObject<Task>(json, settings);

动态类型和 LINQ to JSON

使用动态类型解析未知结构的 JSON

当处理的 JSON 结构未知或动态变化时,可以使用 dynamic 类型。

示例 JSON:

json 复制代码
{
  "Name": "Alice",
  "Age": 30,
  "Skills": ["C#", "WPF", "JSON"]
}

解析动态 JSON:

cs 复制代码
string json = @"{
  ""Name"": ""Alice"",
  ""Age"": 30,
  ""Skills"": [""C#"", ""WPF"", ""JSON""]
}";

dynamic obj = JsonConvert.DeserializeObject<dynamic>(json);
Console.WriteLine($"Name: {obj.Name}");
Console.WriteLine($"Age: {obj.Age}");
Console.WriteLine("Skills:");
foreach (var skill in obj.Skills)
{
    Console.WriteLine($"- {skill}");
}

使用 JObject 和 JToken

cs 复制代码
using Newtonsoft.Json.Linq;

string json = @"{
  ""Name"": ""Alice"",
  ""Age"": 30,
  ""Skills"": [""C#"", ""WPF"", ""JSON""]
}";

JObject obj = JObject.Parse(json);

// 读取值
string name = (string)obj["Name"];
int age = (int)obj["Age"];
JArray skills = (JArray)obj["Skills"];

// 添加新属性
obj["Country"] = "China";

// 删除属性
obj.Property("Age").Remove();

// 遍历所有属性
foreach (var property in obj.Properties())
{
    Console.WriteLine($"{property.Name}: {property.Value}");
}

// 输出修改后的 JSON
string modifiedJson = obj.ToString();
Console.WriteLine(modifiedJson);

输出:

json 复制代码
Name: Alice
Skills: ["C#","WPF","JSON"]
Country: China
{
  "Name": "Alice",
  "Skills": [
    "C#",
    "WPF",
    "JSON"
  ],
  "Country": "China"
}

忽略属性、更改属性名称、设置全局序列化选项

忽略某些属性

使用 [JsonIgnore] 特性可以在序列化和反序列化时忽略某些属性。

定义一个简单的类:

csharp 复制代码
public class User
{
    public string UserName { get; set; }

    [JsonIgnore]
    public string Password { get; set; }
}

示例:

csharp 复制代码
User user = new User
{
    UserName = "Alice",
    Password = "secret"
};

string json = JsonConvert.SerializeObject(user, Formatting.Indented);
Console.WriteLine(json);

输出的 JSON(Password 被忽略):

json 复制代码
{
  "UserName": "Alice"
}

更改属性名称

使用 [JsonProperty] 特性可以更改序列化时的属性名称。

定义一个简单的类:

csharp 复制代码
public class User
{
    [JsonProperty("user_name")]
    public string UserName { get; set; }

    public string Email { get; set; }
}

示例:

csharp 复制代码
User user = new User
{
    UserName = "Alice",
    Email = "alice@example.com"
};

string json = JsonConvert.SerializeObject(user, Formatting.Indented);
Console.WriteLine(json);

输出的 JSON(UserName 被更改为 user_name):

json 复制代码
{
  "user_name": "Alice",
  "Email": "alice@example.com"
}

设置全局序列化选项

可以通过 JsonSerializerSettings 设置全局的序列化和反序列化选项。

定义一个简单的类:

csharp 复制代码
public class User
{
    public string UserName { get; set; }

    public string Email { get; set; }
}

示例:忽略空值

csharp 复制代码
User user = new User
{
    UserName = "Alice",
};

JsonSerializerSettings settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore
};

string json = JsonConvert.SerializeObject(user, Formatting.Indented, settings);
Console.WriteLine(json);

输出的 JSON(Email 被忽略了):

json 复制代码
{
  "UserName": "Alice"
}
相关推荐
Jack___Xue15 分钟前
LangGraph学习笔记(六)---LangGraph ReAct应用
笔记·学习·react.js
呱呱巨基1 小时前
Linux 第一个系统程序 进度条
linux·c++·笔记·学习
林深现海1 小时前
【刘二大人】PyTorch深度学习实践笔记 —— 第二集:线性模型(凝练版)
pytorch·笔记·深度学习
历程里程碑1 小时前
Linux 16 环境变量
linux·运维·服务器·开发语言·数据库·c++·笔记
横木沉1 小时前
Opencode启动时内置Bun段错误的解决笔记
人工智能·笔记·bun·vibecoding·opencode
-Springer-2 小时前
STM32 学习 —— 个人学习笔记1(STM32简介)
笔记·stm32·学习
林深现海3 小时前
【刘二大人】PyTorch深度学习实践笔记 —— 第三集:梯度下降(凝练版)
pytorch·笔记·深度学习
悠哉悠哉愿意3 小时前
【物联网学习笔记】按键
笔记·单片机·嵌入式硬件·物联网·学习
三水不滴3 小时前
对比一下RabbitMQ和RocketMQ
经验分享·笔记·分布式·rabbitmq·rocketmq
困死,根本不会3 小时前
OpenCV摄像头实时处理:九宫格棋盘检测与棋子识别
笔记·opencv·学习