ASP.NET Core Web API如何导出与导入外部REST API的JSON数据?
ASP.NET Core WebAPI实现JSON数据的导出与导入
需求背景
我正在构建ASP.NET Core WebAPI,用于从外部REST API获取JSON格式的天气数据,现在需要实现这些数据的本地保存(导出)和重新加载(导入)功能。
当前获取外部API数据的代码如下:
public async Task<List<Weather>> Get(string cities) { List<Weather> weathers = new List<Weather>(); var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; foreach (var city in cities.Split(";")) { string APIURL = $"?key={this.apiKey}&q={city}"; var response = await _httpClient.GetAsync(APIURL); if (response.IsSuccessStatusCode) { var responses = await response.Content.ReadAsStreamAsync(); var weather = await JsonSerializer.DeserializeAsync<Weather>(responses, options); weathers.Add(weather); } } return weathers; }
返回的JSON格式示例:
[ { "location":{ "name":"Chennai", "region":"Tamil Nadu", ... }, "current":{ "last_updated_epoch":1663601400, "last_updated":"2022-09-19 21:00", ... } }, { "location":{ "name":"Mumbai", "region":"Maharashtra", .. }, "current":{ "last_updated_epoch":1663602300, "last_updated":"2022-09-19 21:15", .. } } ]
已实现的代码更新
我已经编写了文件操作工具类和导入导出的相关代码,具体如下:
JSON文件操作工具类
public static class JsonFileUtils { private static readonly JsonSerializerSettings _options = new() { NullValueHandling = NullValueHandling.Ignore }; public static void StreamWrite(object obj, string fileName) { using var streamWriter = File.CreateText(fileName); using var jsonWriter = new JsonTextWriter(streamWriter); JsonSerializer.CreateDefault(_options).Serialize(jsonWriter, obj); } public static async Task StreamWriteAsync(object obj, string fileName) { await Task.Run(() => StreamWrite(obj, fileName)); } }
数据导出(保存到本地文件)
在获取数据的接口中添加保存逻辑:
public async Task<List<Weather>> Get(string cities) { List<Weather> weathers = new List<Weather>(); var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; foreach (var city in cities.Split(";")) { string APIURL = $"?key={this.apiKey}&q={city}"; var response = await _httpClient.GetAsync(APIURL); if (response.IsSuccessStatusCode) { var responses = await response.Content.ReadAsStreamAsync(); var weather = await JsonSerializer.DeserializeAsync<Weather>(responses, options); weathers.Add(weather); } } var fileName = "weathers.json"; await JsonFileUtils.StreamWriteAsync(weathers, fileName); return weathers; }
数据导入(上传JSON文件并解析)
添加文件上传接口:
[HttpPost("upload", Name = "upload")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List<Weather>))] [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] public async Task<IActionResult> UploadFile( IFormFile file, CancellationToken cancellationToken) { string fileContent = null; using (var reader = new StreamReader(file.OpenReadStream())) { fileContent = reader.ReadToEnd(); } var result = JsonConvert.DeserializeObject<List<Weather>>(fileContent); return Ok(result); }
代码优化建议
统一JSON序列化库:当前代码混合使用了
System.Text.Json(获取数据时的反序列化)和Newtonsoft.Json(文件操作和上传解析),建议统一使用其中一种,避免配置不一致。比如统一用System.Text.Json重构工具类和上传接口:// 重构后的JsonFileUtils public static class JsonFileUtils { private static readonly JsonSerializerOptions _options = new() { NullValueHandling = JsonIgnoreCondition.WhenWritingNull, WriteIndented = true, PropertyNameCaseInsensitive = true }; public static void StreamWrite<T>(T obj, string fileName) { using var stream = File.Create(fileName); JsonSerializer.Serialize(stream, obj, _options); } public static async Task StreamWriteAsync<T>(T obj, string fileName) { using var stream = File.Create(fileName); await JsonSerializer.SerializeAsync(stream, obj, _options); } public static T StreamRead<T>(string fileName) { using var stream = File.OpenRead(fileName); return JsonSerializer.Deserialize<T>(stream, _options); } public static async Task<T> StreamReadAsync<T>(string fileName) { using var stream = File.OpenRead(fileName); return await JsonSerializer.DeserializeAsync<T>(stream, _options); } }// 重构后的上传接口 [HttpPost("upload", Name = "upload")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List<Weather>))] [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] public async Task<IActionResult> UploadFile( IFormFile file, CancellationToken cancellationToken) { if (file == null || file.Length == 0) { return BadRequest("上传的文件不能为空"); } var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant(); if (fileExtension != ".json") { return BadRequest("仅支持上传JSON格式文件"); } try { using var stream = file.OpenReadStream(); var result = await JsonSerializer.DeserializeAsync<List<Weather>>(stream, _options); return Ok(result); } catch (JsonException ex) { return BadRequest($"JSON格式错误:{ex.Message}"); } }规范文件存储路径:直接使用文件名会保存到程序运行目录,建议配置固定存储目录(如
wwwroot/weather-data),并确保目录存在:private static string GetStoragePath(string fileName) { var basePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "weather-data"); Directory.CreateDirectory(basePath); return Path.Combine(basePath, fileName); }增强错误处理:导出时添加异常捕获,避免保存失败影响接口返回;导入时增加文件校验和格式错误提示,提升接口健壮性。
内容的提问来源于stack exchange,提问作者One Developer
相关产品推荐
相关产品推荐

