Я написал веб-API для доступа к некоторым данным JSON в файловой системе. API настроен на возврат данных в виде json клиенту. Однако, когда я пытаюсь десериализовать ответ JSON в список моих объектов, он терпит неудачу.
Я попытался очистить ответ, так как в нем, кажется, есть дополнительные символы, но, похоже, это не сработало, так как очистка имела тенденцию приводить к появлению вонючего не-JSON. Я чувствую, что делаю это сложнее, чем нужно.
Мой класс модели данных:
public abstract class CatalogueBase
{
string name;
string description;
int id;
public string Name { get => name; set => name = value; }
public string Description { get => description; set => description = value; }
public int Id { get => id; set => id = value; }
}
public class Media : CatalogueBase
{
MediaType type;
MediaRating rating;
string genre;
public MediaType Type { get => type; set => type = value; }
public MediaRating Rating { get => rating; set => rating = value; }
public string Genre { get => genre; set => genre = value; }
public Media()
{
}
}
Конечная точка веб-API, которая захватывает и отправляет данные:
[HttpGet]
[Route("GetMedia/")]
public ActionResult<string> GetAll()
{
string[] files = Directory.GetFiles(this.config.Value.JSONFileDirectory);
if (files.Length > 0)
{
try
{
List<string> jsonFiles = new List<string>();
string json;
foreach (var file in files)
{
using (StreamReader reader = new StreamReader(file))
{
json = reader.ReadToEnd();
jsonFiles.Add(Regex.Unescape(json));
}
}
return JsonConvert.SerializeObject(jsonFiles, Formatting.Indented);
}
catch (Exception e)
{
throw new Exception("Could not parse JSON file.", e);
}
}
else
{
return NotFound("No files were found in the catalog.");
}
}
Обратите внимание, что каждый файл содержит один Media
объект, ранее сериализованный как JSON.
Код на стороне клиента, который вызывает вышеуказанную конечную точку:
public async Task<List<Media>> GetAllMedia()
{
client = GetHttpClient(@"GetMedia/");
HttpResponseMessage response = await client.GetAsync("");
string content = await response.Content.ReadAsStringAsync();
var media = JsonConvert.DeserializeObject<List<Media>>(content);
return media;
}
И, наконец, образец JSONresponse, который я получаю в своем клиенте:
"\"[\\r\\n \\\"{\\\\\\\"Type\\\\\\\":0,\\\\\\\"Rating\\\\\\\":5,\\\\\\\"Genre\\\\\\\":\\\\\\\"Drama\\\\\\\",\\\\\\\"Name\\\\\\\":\\\\\\\"Memes\\\\\\\",\\\\\\\"Description\\\\\\\":\\\\\\\"A movie set during the American Civil War\\\\\\\",\\\\\\\"Id\\\\\\\":1}\\\",\\r\\n \\\"{\\\\r\\\\n\\\\\\\"Id\\\\\\\": 2,\\\\r\\\\n\\\\\\\"Name\\\\\\\": \\\\\\\"Gods and Generals\\\\\\\",\\\\r\\\\n\\\\\\\"Description\\\\\\\": \\\\\\\"A movie set during the American Civil War\\\\\\\",\\\\r\\\\n\\\\\\\"Type\\\\\\\": \\\\\\\"Movie\\\\\\\",\\\\r\\\\n\\\\\\\"Rating\\\\\\\": \\\\\\\"Excellent\\\\\\\",\\\\r\\\\n\\\\\\\"Genre\\\\\\\" : \\\\\\\"Drama\\\\\\\"\\\\r\\\\n}\\\\r\\\\n\\\",\\r\\n \\\"{\\\\r\\\\n\\\\\\\"Id\\\\\\\": 3,\\\\r\\\\n\\\\\\\"Name\\\\\\\": \\\\\\\"Avengers Endgame\\\\\\\"\\\\r\\\\n\\\\\\\"Description\\\\\\\": \\\\\\\"The end of the Avengers series.\\\\\\\",\\\\r\\\\n\\\\\\\"Type\\\\\\\": \\\\\\\"Movie\\\\\\\",\\\\r\\\\n\\\\\\\"Rating\\\\\\\": \\\\\\\"Excellent\\\\\\\",\\\\r\\\\n\\\\\\\"Genre\\\\\\\" : \\\\\\\"Action\\\\\\\"\\\\r\\\\n}\\\\r\\\\n\\\"\\r\\n]\""
Сам ответ JSON выглядит для меня проблемой, слишком много \\
и других специальных символов. Я пытался очистить его с помощью строки. Заменить вызовы, но это не сработало. Есть идеи?
Фактическое сообщение об ошибке:
System.AggregateException: 'Произошла одна или несколько ошибок. (Ошибка преобразования значения ... json string ..... в тип 'System.Collections.Generic.List`1 [CatalogManager.Models.MediaManager.Media]'. Path '', строка 1, позиция 732.) '
Редактировать: попробовал некоторые из предложений в комментариях, и я получил следующий ответ JSON:
"[\"{\\\"Type\\\":0,\\\"Rating\\\":5,\\\"Genre\\\":\\\"Drama\\\",\\\"Name\\\":\\\"Memes\\\",\\\"Description\\\":\\\"A movie set during the American Civil War\\\",\\\"Id\\\":1}\",\"{\\r\\n\\\"Id\\\": 2,\\r\\n\\\"Name\\\": \\\"Gods and Generals\\\",\\r\\n\\\"Description\\\": \\\"A movie set during the American Civil War\\\",\\r\\n\\\"Type\\\": \\\"Movie\\\",\\r\\n\\\"Rating\\\": \\\"Excellent\\\",\\r\\n\\\"Genre\\\" : \\\"Drama\\\"\\r\\n}\\r\\n\",\"{\\r\\n\\\"Id\\\": 3,\\r\\n\\\"Name\\\": \\\"Avengers Endgame\\\"\\r\\n\\\"Description\\\": \\\"The end of the Avengers series.\\\",\\r\\n\\\"Type\\\": \\\"Movie\\\",\\r\\n\\\"Rating\\\": \\\"Excellent\\\",\\r\\n\\\"Genre\\\" : \\\"Action\\\"\\r\\n}\\r\\n\"]"
И когда я пытаюсь разобрать его с JObject, я получаю следующую ошибку:
System.AggregateException
HResult=0x80131500
Message=One or more errors occurred. (Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.)
Source=System.Private.CoreLib
StackTrace:
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at CatalogManager.Pages.IndexModel.OnGet() in C:\Users\tpzap_000\source\repos\CatalogManager\Pages\Manager\Index.cshtml.cs:line 73
at Microsoft.AspNetCore.Mvc.RazorPages.Internal.ExecutorFactory.ActionResultHandlerMethod.Execute(Object receiver, Object[] arguments)
at Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.<InvokeHandlerMethodAsync>d__30.MoveNext()
Inner Exception 1:
JsonReaderException: Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.
Final Edit: я попробовал предложение dbc, и это сработало. Я думаю, что основная проблема была на моей стороне API. Я анализировал свои файлы json как строки, а не в объекте своей модели Media, а затем использовал Newtonsoft для анализа его в правильно сформированный json. Я изменил свой код стороны API на следующий:
[HttpGet]
[Route("GetMedia/")]
public ActionResult<List<Media>> GetAll()
{
string[] files = Directory.GetFiles(this.config.Value.JSONFileDirectory);
if (files.Length > 0)
{
try
{
List<Media> jsonFiles = new List<Media>();
string json;
foreach (var file in files)
{
using (StreamReader reader = new StreamReader(file))
{
json = reader.ReadToEnd();
Media currentMedia = JsonConvert.DeserializeObject<Media>(json);
//jsonFiles.Add(Regex.Unescape(json));
jsonFiles.Add(currentMedia);
}
}
return Ok(jsonFiles);
}
catch (Exception e)
{
throw new Exception("Could not parse JSON file.", e);
}
}
else
{
return NotFound("No files were found in the catalog.");
}
}
И он успешно работал на переднем конце.