Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将JSON响应反序列化到对象列表_C#_Json_Asp.net Core_Json.net - Fatal编程技术网

C# 如何将JSON响应反序列化到对象列表

C# 如何将JSON响应反序列化到对象列表,c#,json,asp.net-core,json.net,C#,Json,Asp.net Core,Json.net,我已经编写了一个web API来访问文件系统上的一些JSON数据。API被设置为将数据作为json返回给客户端。但是,当我尝试将JSON响应反序列化到对象列表中时,它失败了 我已经尝试清理响应,因为它似乎有额外的字符,但这似乎不起作用,因为清理往往会产生不可靠的非JSON。我觉得我把事情弄得比实际需要的更复杂了 我的数据模型类: public abstract class CatalogueBase { string name; string description; i

我已经编写了一个web 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()
    {

    }
}
正在捕获和发送数据的web 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.");
    }
}
最后,我在我的客户机中得到了一个示例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响应本身在我看来是个问题,太多的
\\
和其他特殊字符。我试着用string.Replace来清理它,但是没有用。有什么想法吗

实际错误消息:

System.AggregateException:'发生了一个或多个错误。(将值…json字符串…转换为类型“System.Collections.Generic.List`1[CatalogManager.Models.MediaManager.Media]”时出错。路径“”,第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.
System.aggregateeexception
HResult=0x80131500
消息=发生了一个或多个错误。(从JsonReader读取JObject时出错。当前JsonReader项不是对象:StartArray.Path“”,第1行,位置1。)
Source=System.Private.CoreLib
堆栈跟踪:
位于System.Threading.Tasks.Task`1.GetResultCore(布尔waitCompletionNotification)
在C:\Users\tpzap\u 000\source\repos\CatalogManager\Pages\Manager\Index.cshtml.cs中的CatalogManager.Pages.IndexModel.OnGet()处:第73行
位于Microsoft.AspNetCore.Mvc.RazorPages.Internal.ExecutorFactory.ActionResultHandlerMethod.Execute(对象接收器,对象[]参数)
在Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.d_u30.MoveNext()上
内部异常1:
JsonReaderException:从JsonReader读取JObject时出错。当前JsonReader项不是对象:StartArray。路径“”,第1行,位置1。

最终编辑:我尝试了dbc的建议,效果很好。我认为核心问题在于API方面,我将json文件解析为字符串,而不是解析为媒体模型对象,然后使用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.");
    }

}
[HttpGet]
[路线(“GetMedia/”)]
公共行动结果GetAll()
{
string[]files=Directory.GetFiles(this.config.Value.JSONFileDirectory);
如果(files.Length>0)
{
尝试
{
List jsonFiles=new List();
字符串json;
foreach(文件中的var文件)
{
使用(StreamReader=新StreamReader(文件))
{
json=reader.ReadToEnd();
Media currentMedia=JsonConvert.DeserializeObject(json);
//Add(Regex.Unescape(json));
jsonFiles.Add(currentMedia);
}  
}
返回Ok(jsonFiles);
}
捕获(例外e)
{
抛出新异常(“无法解析JSON文件。”,e);
}
}
其他的
{
return NotFound(“目录中未找到任何文件”);
}
}

而且它在前端工作得很成功

您的基本问题是服务器返回一个
字符串
,但客户端希望
应用程序/json
内容包含一个序列化的
列表
,从而在反序列化过程中造成兼容性问题

确保客户端和服务器兼容的最简单方法是从服务器返回完全相同的类型,即
列表
(或者如果您希望返回错误的可能性)。这允许框架处理序列化和内容协商,因此您不必这样做。以下内容将完成此工作:

[HttpGet]
[Route("GetMedia/")]
public ActionResult<List<Media>> GetAll()
{
    string[] files = Directory.GetFiles(this.config.Value.JSONFileDirectory);
    if (files.Length > 0)
    {
        try
        {
            var serializer = JsonSerializer.CreateDefault();
            return files.Select(f =>
                {
                    using (var reader = new StreamReader(f))
                    using (var jsonReader = new JsonTextReader(reader))
                    {
                        return serializer.Deserialize<Media>(jsonReader);
                    }
                })
                .ToList();
        }
        catch (Exception e)
        {
            throw new Exception("Could not parse JSON file.", e);
        }
    }
    else
    {
        return NotFound("No files were found in the catalog.");
    }
}

asp.net将把结果转换为JSON。只要在GetAllMedia方法中返回jsonFiles(当然还要更改返回类型),尝试添加这一行,然后在调试控制台中返回结果<代码>var jobject=jobject.Parse(内容);Console.WriteLine(作业对象)。还可以更改
返回JsonConvert.serialized对象(jsonfile,Formatting.Indented)
to
returnok(jsonFiles)
尝试了您的建议,但是JObject.Parse无法解析它。用结果更新了帖子@Rufo爵士,我确实在API端的返回语句中去掉了序列化,这似乎是朝着正确方向迈出的一步。我认为json有点干净。1)您的方法具有签名
ActionResult
,但您实际想要返回什么内容类型<代码>文本/普通或
应用程序/json
?2) 响应应该包含哪些内容?3) 为什么要执行
Regex.Unescape(json)
?1)我更喜欢返回application/json。2) 就是我从文件中提取的json数据,就是这样。3) 我这样做是为了清理从文件中提取的json字符串。它似乎有一堆特殊的字符(\r、\n、\\,等等)。自从我加上鲁福爵士的建议后,我就把它删除了。
[HttpGet]
[Route("GetMedia/")]
public ActionResult<List<Media>> GetAll()
{
    string[] files = Directory.GetFiles(this.config.Value.JSONFileDirectory);
    if (files.Length > 0)
    {
        try
        {
            var serializer = JsonSerializer.CreateDefault();
            return files.Select(f =>
                {
                    using (var reader = new StreamReader(f))
                    using (var jsonReader = new JsonTextReader(reader))
                    {
                        return serializer.Deserialize<Media>(jsonReader);
                    }
                })
                .ToList();
        }
        catch (Exception e)
        {
            throw new Exception("Could not parse JSON file.", e);
        }
    }
    else
    {
        return NotFound("No files were found in the catalog.");
    }
}
return files.Select(f => JsonConvert.DeserializeObject<Media>(File.ReadAllText(f))).ToList();