Как отдать Json из файла?
я хочу научиться обрабатывать данные, которые мне будет выдавать еще не написанный сервис.
То есть, у меня есть схема json-ответов.
Пускай это для определенности будет класс Person:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Phone { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}
я могу "руками" написать json-файл.
Теперь мне надо сделать сервис, который берет этот json, сохраненный в виде файла, и отдаёт его точно так же, как это сделал бы настоящий сервис.
И тут я столкнулся вот с какой проблемой:
Шаг 1. Создаю класс Person, возвращаю экземпляр. Всё прекрасно!
Простым созданием webapi-проекта и написанием контроллера
using Microsoft.AspNetCore.Mvc;
namespace MyJsonApp.Controllers
{
[ApiController]
[Route("[controller]")]
public class UTypeController : ControllerBase
{
private readonly ILogger<UTypeController> _logger;
public UTypeController(ILogger<UTypeController> logger)
{
_logger = logger;
}
/// <summary>
/// Возвращает мой тип как json
/// </summary>
[HttpGet(Name = "GetPerson")]
public ActionResult<Person> Get()
{
Person person = new Person()
{
Name = "Elena Samoylova",
Description = "ready for companyonship",
Age = 39,
Gender = "Female",
Id = 112,
Phone = "+7 999 8559911"
};
return person;
}
}
}
я получаю вот что: по URL
http://localhost:5000/UType
мне возвращается ответ, и это настоящий json: я его вижу на экране, могу нажать на галочку Pretty-print и т.п.:
Шаг 2.
я беру json, полученный на предыдущем шаге. Сохраняю его в файл src/source.json.
Переписываю контроллер как
namespace MyJsonApp.Controllers
{
[ApiController]
[Route("[controller]")]
public class JFileController : ControllerBase
{
private readonly ILogger<JFileController> _logger;
public JFileController(ILogger<JFileController> logger)
{
_logger = logger;
}
/// <summary>
/// Возвращает содержимое статического JSON файла
/// </summary>
[HttpGet(Name = "GetData")]
public IActionResult Get()
{
try
{
// Путь к файлу относительно текущего каталога
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "src/source.json");
if (!System.IO.File.Exists(filePath))
return NotFound("Файл 'source.json' не найден.");
string jsonContent = System.IO.File.ReadAllText(filePath);
jsonContent = jsonContent.Replace("\r\n", "");
// Установка правильного типа содержимого
Response.ContentType = "application/json";
return Ok(jsonContent); // Ответ с успешным статусом 200 OK
}
catch (IOException ex)
{
_logger.LogError(ex.Message, ex.StackTrace);
return StatusCode(StatusCodes.Status500InternalServerError, $"Ошибка при чтении файла: {ex.Message}");
}
}
}
}
Тогда по URL
http://localhost:5000/JFile
я получаю... как будто бы json, но "разбавленный" обратными косыми чертами, и видно, что это "ненастоящий" json:
Причем, в исходном json'е этих обратных косых черт - нет!
Ну и, например, "Pretty-print" больше не работает.
я попробовал всякие модификации, например, читать файл как бинарный, но это не помогло.
Исходник:
https://github.com/junecat/SoQuestions/tree/main/MyJsonApp
Вопрос: так как можно переписать код так, чтобы вывод файла не отличался от вывода "истинного json'а"?
Ответы (2 шт):
Вообще вроде бы можно вот так:
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
return response;
Ok(data) он же OkObjectResult(data) - то есть сериализует data в жсон. В вашем случае data строка с кавычками, которая и сериализуется. На выходе получается строка в кавычках и экранированные кавычки внутри.
Поэтому нужно использовать return Content(jsonContent, "application/json");
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "src/source.json");
if (!System.IO.File.Exists(filePath))
return NotFound("Файл 'source.json' не найден.");
string jsonContent = System.IO.File.ReadAllText(filePath);
return Content(jsonContent, "application/json");
Также можно напрямую выдать файл без чтения в память.
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "src/source.json");
if (!System.IO.File.Exists(filePath))
return NotFound("Файл 'source.json' не найден.");
var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
return new FileStreamResult(stream, "application/json");
ну и, конечно же, можно просто напрямую писать в выходной поток (хотя при наличии FileStreamResult в этом нет смысла)
Response.ContentType = "application/json";
await using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
await fileStream.CopyToAsync(Response.Body);
return new EmptyResult();

