一、RESTful基础
RESTful是一种轻量级、跨平台的Web服务架构风格,它的核心原则是:
- 资源唯一标识:每个资源有唯一的URL
- 无状态操作:服务器不保存客户端状态
- 统一接口:用标准HTTP方法操作资源
| HTTP方法 | 操作 | 幂等 | 安全 |
|---|---|---|---|
| GET | 查询 | 是 | 是 |
| POST | 新增 | 否 | 否 |
| PUT | 更新 | 是 | 否 |
| DELETE | 删除 | 是 | 否 |
RESTful vs 传统API:
- 传统:
/user/query/1 - RESTful:
/user/1
二、调用RESTful API的通用流程
cs
// 1. 获取数据 - HttpClient最佳实践
using var httpClient = new HttpClient();
var response = await httpClient.GetAsync("https://api.example.com/data");
var jsonString = await response.Content.ReadAsStringAsync();
// 2. 解析JSON - 两种常用方式
// 方式一:动态解析(快速提取少量字段)
var jsonDoc = JsonDocument.Parse(jsonString);
string name = jsonDoc.RootElement.GetProperty("user").GetProperty("name").GetString();
// 方式二:强类型解析(推荐!)
public class User {
public string Name { get; set; }
public int Age { get; set; }
public DateTime RegisterDate { get; set; }
}
var user = JsonSerializer.Deserialize<User>(jsonString, new JsonSerializerOptions {
PropertyNameCaseInsensitive = true // 忽略大小写
});
// 3. 使用解析后的数据
Console.WriteLine($"欢迎,{user.Name}!您已注册于{user.RegisterDate:yyyy-MM-dd}");
三、JSON解析的实用技巧
3.1 推荐方案
使用System.Text.Json(.NET Core 3.0+)
优势:
- 微软原生,性能更好
- 编译时检查 + 智能提示 + 高可维护性
- 支持异步操作
3.2 常见坑点及解决方案
| 问题 | 解决方案 | 代码示例 |
|---|---|---|
| 字段大小写不一致 | PropertyNameCaseInsensitive = true |
new JsonSerializerOptions { PropertyNameCaseInsensitive = true } |
| 日期格式问题 | 添加日期转换器 | options.Converters.Add(new DateTimeConverter("yyyy-MM-dd")); |
| JSON中有注释 | 忽略注释 | options.ReadCommentHandling = JsonCommentHandling.Skip; |
| 空字段导致异常 | 设置默认值 | public string Name { get; set; } = string.Empty; |
四、完整实战示例
cs
using System;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
public class WeatherApiService
{
public async Task<WeatherData> GetWeatherAsync(string location)
{
using var httpClient = new HttpClient();
// 获取天气数据
var response = await httpClient.GetAsync(
$"https://api.weather.com/v3?location={location}");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
// 强类型解析(推荐方式)
return JsonSerializer.Deserialize<WeatherData>(json, new JsonSerializerOptions {
PropertyNameCaseInsensitive = true,
NumberHandling = JsonNumberHandling.AllowReadingFromString
});
}
}
public class WeatherData
{
public string City { get; set; }
public string Condition { get; set; }
public int Temperature { get; set; }
public DateTime ForecastDate { get; set; }
}
五、为什么推荐System.Text.Json?
- 性能更好:比Newtonsoft.Json快约20-30%
- 原生集成:.NET Core 3.0+默认包含
- 安全:不依赖第三方库,减少安全风险
- 现代化:支持最新的JSON特性
六、进阶建议
- 创建通用API服务类:把HttpClient封装起来,避免重复代码
- 处理错误:添加try-catch块处理网络异常
- 缓存:对频繁请求的API添加缓存机制
- 异步:始终使用异步方法,提升应用性能
七、处理JSON嵌套复杂结构
三步搞定嵌套JSON处理(推荐System.Text.Json)
7.1 第一步:定义强类型模型(关键!)
cs
// 定义嵌套结构
public class ApiResponse
{
public string Status { get; set; }
public Data Data { get; set; }
}
public class Data
{
public List<User> Users { get; set; }
public Meta Meta { get; set; }
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
}
public class Meta
{
public int TotalCount { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
}
7.2 第二步:解析嵌套JSON(一行代码搞定!)
cs
// 获取API返回的JSON字符串
string json = await httpClient.GetStringAsync("https://api.example.com/data");
// 一行代码解析嵌套结构(这才是真正的"快速"!)
var response = JsonSerializer.Deserialize<ApiResponse>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true, // 忽略大小写
NumberHandling = JsonNumberHandling.AllowReadingFromString // 处理数字字符串
});
7.3 第三步:安全访问嵌套数据
cs
// 安全访问嵌套数据
if (response != null && response.Data != null && response.Data.Users != null)
{
foreach (var user in response.Data.Users)
{
Console.WriteLine($"用户: {user.Name}, 城市: {user.Address.City}");
}
// 也可以直接访问
Console.WriteLine($"总用户数: {response.Data.Meta.TotalCount}");
}
- 强类型安全:编译时检查,不会等到运行时才发现错误
- 代码可读性高 :一目了然,不需要写一堆
doc["data"]["users"][0]["address"]["city"] - 性能更好:比Newtonsoft.Json快20-30%(.NET Core 3.0+)
- 自动处理嵌套:不需要手动遍历每一层
八、实用技巧:处理常见嵌套问题
8.1 嵌套层级太深,字段可能为空
cs
// 安全访问嵌套字段(避免NullReferenceException)
var city = response?.Data?.Users?[0]?.Address?.City ?? "N/A";
Console.WriteLine($"城市: {city}");
8.2 JSON字段名大小写不一致
cs
new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true // 关键!忽略大小写
}
8.3 嵌套结构中可能有额外字段
cs
// 忽略未知字段
new JsonSerializerOptions
{
IgnoreUnknown = true
}
8.4 处理嵌套数组
cs
// 获取所有用户的姓名
var userNames = response.Data.Users
.Where(u => u.Id > 100)
.Select(u => u.Name)
.ToList();
一个真实案例:处理天气API的嵌套JSON
cs
public class WeatherResponse
{
public CurrentWeather Current { get; set; }
public Forecast Forecast { get; set; }
}
public class CurrentWeather
{
public string City { get; set; }
public int Temperature { get; set; }
public string Condition { get; set; }
}
public class Forecast
{
public List<DailyForecast> Days { get; set; }
}
public class DailyForecast
{
public DateTime Date { get; set; }
public int HighTemp { get; set; }
public int LowTemp { get; set; }
}
// 使用方式
var weather = JsonSerializer.Deserialize<WeatherResponse>(json);
Console.WriteLine($"当前城市: {weather.Current.City}, 温度: {weather.Current.Temperature}°C");
Console.WriteLine($"明天最高温: {weather.Forecast.Days[0].HighTemp}°C");