共计 8559 个字符,预计需要花费 22 分钟才能阅读完成。
JSON 简介
1. 什么是 JSON?
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它的语法基于 JavaScript 对象表示法,简单、易读,同时被许多编程语言支持。尽管它来源于 JavaScript,但它并不依赖于 JavaScript,许多语言(如 Python、Java、C#、PHP 等)都能够解析和生成 JSON。
常见用途:
API 数据交互:在客户端和服务器之间传递数据时,JSON 是常用格式,特别是前后端交互时.
配置文件:许多应用程序使用 JSON 来保存配置文件(例如 .json 文件)。
数据持久化:在数据库或文件系统中使用 JSON 来存储结构化数据。
2. JSON 的基本语法结构
JSON 的数据结构非常简单,主要包括以下两种类型:
对象(Object):由花括号 {} 包围的一组键值对,键是字符串,值可以是任何合法的 JSON 数据类型。
数组(Array):由方括号 [] 包围的一组值,值可以是任意 JSON 类型。
示例:
{
"name": "John",
"age": 30,
"isStudent": false,
"courses": ["Math", "Science"],
"address": {
"city": "New York",
"zipcode": "10001"
}
}
JSON 的基本元素:
字符串:用双引号包裹,如 “name”: “John”
数字:可以是整数或浮点数,如 “age”: 30
布尔值:true 或 false
数组:一个有序的值列表,用方括号 [] 包裹
对象:一个无序的键值对集合,用花括号 {} 包裹
空值:null
你不难看出 JSON 本质上由三种主要元素构成:
对象(Object):键值对的集合,类似于字典。JSON 对象用 {} 表示,包含键值对(key-value pairs),键必须是字符串,值可以是任意合法的 JSON 元素(如数组、对象或基本值)。
数组(Array):有序的元素集合,类似于列表或数组(不代表 C# 的数组, 只是体现一个有序集合)。JSON 数组用 [] 表示,数组中的每个元素可以是任意合法的 JSON 元素(如对象、数组或基本值)。
基本值(Value):JSON 的最基础元素,可以是字符串、数字、布尔值或 null。这部分数据不能再包含其他子元素。
这很重要: 因为充分分析这三种元素自身以及他们之间的关系是 JSON 处理的关键. 很多 JSON 库也是考虑了这三种概念实现的.
3. JSON 的优势(作用)
JSON 之所以成为数据交换的首选格式,离不开它的诸多优势:
轻量级:相比于 XML 等格式,JSON 占用的体积更小,结构更为简洁。
可读性好:人类易读,同时解析程序也易于编写。
支持数据类型丰富:可以直接表示对象、数组、字符串、数字、布尔值等常见的数据结构。
广泛支持:几乎所有编程语言都提供了用于解析和生成 JSON 的库或内置函数。
标准化格式:JSON 的格式有明确的标准,确保了跨语言、跨平台的兼容性。
灵活性高:可以嵌套任意复杂的对象和数组,适合复杂的数据结构。
4. JSON 的常见使用场景
API 通信
在现代 Web 开发中,前后端的通信常常依赖于 JSON。客户端发送 HTTP 请求时,通常使用 JSON 格式来传递数据,服务器也通过 JSON 格式返回数据。下面是一个简单的例子:
请求体(客户端向服务器发送的数据):
{
"username": "john_doe",
"password": "123456"
}
响应体(服务器返回的数据):
{
"status": "success",
"message": "Login successful",
"token": "abcdef123456"
}
配置文件
JSON 格式经常用于存储配置数据,因为它易于阅读和修改。例如,一个应用程序的配置文件可能如下:
{
"app_name": "MyApp",
"version": "1.0.0",
"settings": {
"theme": "dark",
"language": "en"
}
}
本地数据存储
前端开发中,JSON 常被用来在本地存储数据(如浏览器的 localStorage 或 sessionStorage)。
数据序列化
当将对象或数据结构保存到文件或数据库时,通常需要将其序列化为字符串格式,JSON 就是常用的序列化格式之一。
5.JSON 和 C# 类型之间的映射关系
在 C# 中,JSON 的基本元素与相应的数据类型有直接的对应关系。
1. 字符串
JSON:字符串用双引号包裹,表示文本数据。
示例:”name”: “John”
C# 对应类型:string
在 C# 中,JSON 的字符串类型直接映射为 string 类型。
示例:
string name = "John";
2. 数字
JSON:数字可以是整数或浮点数,表示数值类型的数据。
示例:”age”: 30
C# 对应类型:int、float、double
在 C# 中,整数可以映射为 int,浮点数可以映射为 float 或 double,根据具体需要选择类型。
示例:
int age = 30;
float price = 29.99f;
double pi = 3.14159;
3. 布尔值
JSON:布尔值表示为 true 或 false。
示例:”isStudent”: false
C# 对应类型:bool
在 C# 中,布尔值映射为 bool 类型。
示例:
bool isStudent = false;
4. 数组
JSON:数组是一个有序的值列表,用方括号 [] 包裹,数组中的每个元素可以是任意 JSON 类型。
示例:”courses”: [“Math”, “Science”]
C# 对应类型:List
在 C# 中,JSON 数组可以映射为 List
示例:
List courses = new List {"Math", "Science"};
// 或者
string[] coursesArray = { "Math", "Science"};
5. 对象
JSON:对象是一个无序的键值对集合,用花括号 {} 包裹,每个键必须是字符串,值可以是任意 JSON 类型。
示例:”address”: {“city”: “New York”, “zipcode”: “10001”}
C# 对应类型:自定义类或 Dictionary
在 C# 中,JSON 对象可以映射为自定义类,类中的属性对应 JSON 对象中的键值对。也可以使用 Dictionary
示例(使用自定义类):
class Address
{public string City { get; set;}
public string Zipcode {get; set;}
}
Address address = new Address {City = "New York", Zipcode = "10001"};
示例(使用字典):
Dictionary address = new Dictionary
{{ "city", "New York"},
{"zipcode", "10001"}
};
6. 空值
JSON:空值表示为 null。
示例:”middleName”: null
C# 对应类型:null
在 C# 中,JSON 的 null 对应 C# 中的 null 值。它可以应用于任何可空类型(如引用类型和 Nullable
在 C# 中,JSON 的基本元素可以映射为相应的 C# 数据类型。这种映射使得我们可以轻松处理 JSON 数据,并与 C# 中的对象和类型进行交互。
6. 如何处理 JSON 数据
什么是序列化 / 反序列化
我们首先要先铺垫一下什么是序列化 / 反序列化
序列化 和反序列化 是将对象和数据在不同格式之间转换的过程,主要用于数据持久化、网络传输等场景. 在 C# 中我们的数据一般以对象形式存储在内存中, 但是内存数据不能持久保存, 你关机后或者程序关闭时数据就没了, 那我们怎么把数据保存下来呢?
答案就是序列化, 我们常用的就是将对象序列化为 JSON(当然不止 JSON, 只是 JSON 更常用), 这样我们再将其 (这个 其说的更清晰点就是字符串,JSON 绝大多数情况是以字符串形式出现的, 只不过你可以理解为是一种有一定格式或一定规则的字符串)保存在磁盘或者通过网络传递给其他人都很方便.
理所当然的 JSON 转换为内存中的对象就是反序列化, 常见的情景就是读取 JSON 格式的配置文件, 先从磁盘读取出来再反序列化为对象, 我们就可以十分方便的操作这个对象了.
怎么做?
大多数编程语言都提供了用于解析(反序列化)和生成(序列化)JSON 数据的库或内置函数。
C# 提供了 System.Text.Json 和 Newtonsoft.Json(第三方库)来处理 JSON。
我建议使用 Newtonsoft.Json(NuGet Gallery | Newtonsoft.Json 13.0.3), 这可以说是 C# 环境里最流行, 最强大的一个库, 经过二十年左右的发展支持绝大多数.net 环境, 目前在所有 nuget 包中下载量中排名第一.
常见用法
1. 使用 JsonConvert.SerializeObject 方法可以将 C# 对象转换为 JSON 字符串。
using Newtonsoft.Json;
public class Person
{public string Name { get; set;}
public int Age {get; set;}
public bool IsStudent {get; set;}
}
Person person = new Person {Name = "John", Age = 30, IsStudent = false};
// 序列化为 JSON
string json = JsonConvert.SerializeObject(person);
Console.WriteLine(json);
得到 (这就是一个字符串, 包括首尾的花括号在内, 前面提到{} 代表一个对象, 里面是无序的键值对)
{"Name":"John","Age":30,"IsStudent":false}
2. 使用 JsonConvert.DeserializeObject
// 这里的是转义符, 不是字符串自身的内容
string json = "{"Name":"John","Age":30,"IsStudent":false}";
// 反序列化为对象
Person person = JsonConvert.DeserializeObject(json);
Console.WriteLine(person.Name); // 输出 "John"
Console.WriteLine(person.Age); // 输出 30
3. 将 JSON 数组转换为 C# 集合(如 List
string jsonArray = "[{"Name":"John","Age":30},{"Name":"Jane","Age":25}]";
// 反序列化为 List
List people = JsonConvert.DeserializeObject>(jsonArray);
foreach (var person in people)
{Console.WriteLine($"{person.Name}, {person.Age}");
}
John, 30
Jane, 25
4. 处理嵌套对象
如果 JSON 中包含嵌套对象,Newtonsoft.Json 可以自动反序列化嵌套结构。
public class Address
{public string City { get; set;}
public string Zipcode {get; set;}
}
public class Person
{public string Name { get; set;}
public Address Address {get; set;}
}
string nestedJson = "{"Name":"John","Address":{"City":"New York","Zipcode":"10001"}}";
// 反序列化嵌套的 JSON
Person person = JsonConvert.DeserializeObject(nestedJson);
Console.WriteLine($"{person.Name} lives in {person.Address.City}, {person.Address.Zipcode}");
5.JToken,JObject,JArray,JValue
上面提到 JSON 的基本组成元素: 对象, 数组, 基本值, 这对应看 newtonjson 提供的 JObject,JArray,JValue 三种类型, 哪还有一个 JToken, 这个 JToken 是三种类型抽象类型, 后三者继承自前者.
为什么提到这些类呢? 因为更灵活!
你注意上面例子, 我们处理一个 JSON 需要先声明一个类型, 有的时候我们声明了这个类型可能极少使用, 那么这个时候我们声明一个类型似乎就有些没必要了.
或者这个 JSON 数据的结构不是固定的, 或是动态的的情况下. 所以我们使用上面的类型.
string jsonString = "{"name":"Alice","age": 25}";
// 使用 JObject 解析
JObject obj = JObject.Parse(jsonString);
// 动态访问字段
string name = (string)obj["name"];
int age = (int)obj["age"];
Console.WriteLine($"Name: {name}, Age: {age}");
请看 JSON 代表一个对象, 如果不常用这个类型, 那么我们直接认为它是一个 JObject 类型. 这样我们转为 JObject 类型, 再使用索引器直接拿到我们需要的数据.
上述我们知道这是一个对象, 所以我们使用 JObject 类型, 那么我们连这个也不知道呢? 无妨! 掏出我们的 JToken 类型, 这个类型是三个子类的父类, 包含所有子类的行为, 能够代表所有的 JSON 概念, 无论它是对象, 数组, 还是基本值.
using Newtonsoft.Json.Linq;
string jsonString = @"{'person': {'name':'Alice','age': 25,'address': {'city':'Wonderland','zipcode':'12345'},'phones': ['123-456-7890','987-654-3210']
}
}";
// 解析为 JToken
JToken token = JToken.Parse(jsonString);
// 动态访问嵌套字段
string name = (string)token["person"]["name"];
string city = (string)token["person"]["address"]["city"];
string phone = (string)token["person"]["phones"][0];
Console.WriteLine($"Name: {name}, City: {city}, First Phone: {phone}");
using Newtonsoft.Json.Linq;
string jsonString = @"{'name':'Alice','age': 25,'address': {'city':'Wonderland','zipcode':'12345'},'hobbies': ['reading','chess','running']
}";
// 使用 JToken 解析
JToken token = JToken.Parse(jsonString);
// 动态访问对象中的字段
string name = (string)token["name"];
int age = (int)token["age"];
// 动态访问嵌套对象
string city = (string)token["address"]["city"];
string zipcode = (string)token["address"]["zipcode"];
// 动态访问数组中的元素
string firstHobby = (string)token["hobbies"][0];
string secondHobby = (string)token["hobbies"][1];
// 输出结果
Console.WriteLine($"Name: {name}, Age: {age}");
Console.WriteLine($"City: {city}, Zipcode: {zipcode}");
Console.WriteLine($"First Hobby: {firstHobby}, Second Hobby: {secondHobby}");
类型转换(对于 JToken 或它的子类)
Newtonsoft.Json 不仅支持通过类型强制转换访问 JSON 数据,还提供了更加便捷的方法来进行类型转换。这些方法能够避免类型强制转换时潜在的异常风险,并提供更清晰的代码表达。
Newtonsoft.Json 提供了以下常用的类型转换方法
1.Value
Value
适用于想要避免显式的类型强制转换,并且希望代码更简洁、安全的场景。
JToken token = JToken.Parse(@"{'name':'Alice','age': 25}");
string name = token["name"].Value(); // 安全的类型转换
int age = token["age"].Value(); // 转换为 int
Console.WriteLine($"Name: {name}, Age: {age}");
使用 Value
2.ToObject
ToObject
ToObject
// 定义一个类与 JSON 数据对应
public class Person
{public string Name { get; set;}
public int Age {get; set;}
}
JToken token = JToken.Parse(@"{'name':'Alice','age': 25}");
// 将 JToken 反序列化为具体的 Person 对象
Person person = token.ToObject();
Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
适合处理复杂的 JSON 数据结构,能够将整个 JSON 结构直接转换为一个 C# 对象。
它的灵活性使得你可以轻松地从 JSON 数据中创建 C# 类对象,而不用手动提取每一个字段。
3.TryGetValue
这是一个较为安全的访问方式,TryGetValue 尝试从 JToken 中获取指定类型的值,并通过返回布尔值来指示是否成功获取。
它适合在不确定 JSON 数据结构或类型时,安全地进行转换操作,避免抛出异常。
JToken token = JToken.Parse(@"{'name':'Alice','age':'not an integer'}");
// 尝试安全获取值
int age;
bool success = token["age"].TryGetValue(out age);
if (success)
{Console.WriteLine($"Age: {age}");
}
else
{Console.WriteLine("Failed to get a valid integer for age.");
}
安全的类型转换方式,适合在 JSON 数据不可靠或结构复杂时使用。
它通过 out 参数来返回结果,能够避免异常。
强制类型转换 vs 提供的方法
强制类型转换(Explicit Casting)
允许直接进行强制类型转换,比如 (string)token[“name”] 或 (int)token[“age”]。这种方式比较简洁,但是如果类型不匹配或值不存在,会抛出异常。
总结
Value
ToObject
TryGetValue
原文地址: 在 C# 中使用 JSON