【问题标题】:How Do I convert my array of objects into JSON object in C# (.net core)如何在 C#(.net 核心)中将我的对象数组转换为 JSON 对象
【发布时间】:2019-11-24 22:56:22
【问题描述】:

我正在使用 MVC 模式在 .Net Core 2.2 中工作。我有一个 Web-API 控制器,在那里我使用经典的 CRUD 方法创建了一些端点。

现在我已经编译了所有内容,当我调试我的解决方案时,我得到一个包含几个 JSON 格式对象的数组 - 但系统将输出视为一个数组,而不是 JSON。

现在我希望这个数组变成 JSON。

我看过这个:https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JObject.htm

我的原始方法看起来像这样(在控制器中):

[HttpGet("/ListAllItems")]
public async Task<IEnumerable<DtoModel>> ListAllItemsFromDb()
{
    return  await _dbProvider.ListAllItemsAsync();
}

并给出以下输出:

[{"id": "GUID-STRING", "itemName": "foo"}, {"id": "GUID-STRING2", "itemName": "bar"}]

//My frontend did not recognize this as a JSON, since it is an array, and threw an exception

所以我在我的控制器中尝试了这个

  [HttpGet("/ListAllItems")]
        public async Task<JObject> ListAllItemsFromDb()
        {
            var result = await _dbProvider.ListAllItemsAsync();
            string output = result.ToString(); 
            string json = JsonConvert.SerializeObject(output);
            JObject obj = JObject.Parse(json);
            return obj; 
        }

当我运行此代码时,我的错误消息指出:“JsonReaderException:从 JsonReader 读取 JObject 时出错。当前 JsonReader 项不是对象:字符串。路径 '',第 1 行,位置 60。”

如何将对象数组转换为 JSON 对象?

【问题讨论】:

  • 但是看起来您的数据不是 JSON 对象,而是 JSON 对象数组
  • //我的前端没有将其识别为 JSON 那么问题出在您的浏览器/前端。这是 json 对象数组的正确语法。你如何在前端解析它?
  • 这有这么多糟糕的决定,我什至无法开始,你为什么使用JObject作为你的行动的结果,你为什么序列化然后序列化?为什么不声明这样的对象 var result = new { items = await _dbProvider.ListAllItemsAsync()};
  • but the system sees the output it as an array, not as JSON. 如果您像您一样传递两个对象,那么您将获得 JSON(正如您在问题中显示的那样)。它是 100% 合法的 JSON。该 JSON 在反序列化时将产生一个对象数组(这是有道理的——你有两个对象)。 如果您不希望这样,我们需要查看您的 JS 代码以了解您是如何处理这个 JSON 的。
  • @Emilia 这几乎可以肯定是一个 XY 问题 (meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。某些东西不起作用,您已经对问题的性质得出了结论。我们确实需要看一下JS代码,看看你对问题的猜测是否准确。

标签: c# json vue.js .net-core


【解决方案1】:

您的前端可能会拒绝 JSON 数组,因为它们存在一些安全问题。文章Anatomy of a Subtle JSON Vulnerability 对此进行了解释。但我认为它不再适用,参见thisthis Stack Overflow 问题

但是,您可以创建一个包装器对象以避免返回顶级 JSON 数组:

public class Wrapper<T> {
   public T Data {get; set;}
}

然后在你的控制器中:

[HttpGet("/ListAllItems")]
public async Task<Wrapper<IEnumerable<DtoModel>>> ListAllItemsFromDb()
{
    return new Wrapper<<IEnumerable<DtoModel>>() {
       Data = await _dbProvider.ListAllItemsAsync()
    };
}

MVC 基础架构将返回如下 JSON 结果:

{
   Value: [{"id": "GUID-STRING", "itemName": "foo"}, {"id": "GUID-STRING2", "itemName": "bar"}]
}

这应该会让你的前端很开心。

【讨论】:

  • 这已经超过 10 年了。 It didn’t work with IE 6, 7, 8, FireFox 3 nor Google Chrome.
  • @mjwills 是的,但仍有一些框架拒绝顶级 JSON 数组。并且有些平台(例如 SharePoint)从不返回顶级 JSON 数组。无论如何,使用包装器解决了 OP 问题,所以我猜她的问题与该漏洞或其他相关问题有关,例如 There is a second array-related vulnerability: http://haacked.com/archive/2009/06/25/json-hijacking.aspx/ This one uses Object.prototype.__defineSetter__
  • Yes, but there still are frameworks that reject top level JSON arrays 他们存在吗?当然,我毫不怀疑他们这样做。 vue.js 是其中之一吗?不,不,不是。
  • 哦,我没有意识到 OP 正在使用 Vue.js,抱歉。然后,尽管包装器解决了问题,但我们仍然不知道为什么前端拒绝原始 JSON。
【解决方案2】:

JsonConvert 将毫无问题地转换您的列表 - 在 IEnumerable&lt;DtoObject&gt; 上调用 ToString() 可能是您的问题。

将列表传递给 JsonConvert,它将正确解析。

var result = await _dbProvider.ListAllItemsAsync();
string json = JsonConvert.SerializeObject(result);

【讨论】:

    猜你喜欢
    • 2015-09-21
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多