【问题标题】:JsonConvert.serializeObject with dataset returning unexpected result带有数据集的 JsonConvert.serializeObject 返回意外结果
【发布时间】:2020-04-07 08:38:40
【问题描述】:

我正在尝试在 .net core 2.0 中将数据集转换为 JSON,并使用下面的代码来完成此操作

return Ok(JsonConvert.SerializeObject(dataset, Formatting.Indented))

我得到的输出是

"{\n \"DataSet.RemotingVersion\": {\n \"Major\": 2,\n \"Minor\": 0,\n \"Build\": -1,\n \"Revision\": -1,\n \"MajorRevision\": -1,\n \"MinorRevision\": -1\n },\n \"XmlSchema\": \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-16\\\"?>\\n<xs:schema id=\\\"dataset\\\" xmlns=\\\"\\\" xmlns:xs=\\\"http://www.w3.org/2001/XMLSchema\\\" xmlns:msdata=\\\"urn:schemas-microsoft-com:xml-msdata\\\">\\n <xs:element name=\\\"dataset\\\" msdata:IsDataSet=\\\"true\\\" msdata:UseCurrentLocale=\\\"true\\\">\\n <xs:complexType>\\n <xs:choice minOccurs=\\\"0\\\" maxOccurs=\\\"unbounded\\\">\\n <xs:element name=\\\"datatable\\\">\\n <xs:complexType>\\n <xs:sequence>\\n <xs:element name=\\\"cvbf\\\" type=\\\"xs:string\\\" msdata:targetNamespace=\\\"\\\" minOccurs=\\\"0\\\" />\\n </xs:sequence>\\n </xs:complexType>\\n </xs:element>\\n </xs:choice>\\n </xs:complexType>\\n </xs:element>\\n</xs:schema>\",\n \"XmlDiffGram\": \"<diffgr:diffgram xmlns:msdata=\\\"urn:schemas-microsoft-com:xml-msdata\\\" xmlns:diffgr=\\\"urn:schemas-microsoft-com:xml-diffgram-v1\\\" />\"\n}"

我对 C# 开发非常陌生,

  • 如何将其转换为正确的 JSON?
  • 为什么会这样?

【问题讨论】:

  • 尝试:返回 Ok(dataset),设置您想要的序列化方法,在 Global.asax 或 WebApiConfig.cs 中全局设置
  • Newtonsoft.JSON 可以处理数据集吗?
  • @Prathik Jain 它适用于我的 REST 服务器。在某种程度上...... 2个数据集之间的一种类型的引用不会转移。我会查找它是什么并将其发布在此处以获取信息
  • 当 Json 序列化数据集时对我不起作用的是:当有 2 个数据表并在数据集上使用 DataSet.Relations.Add() 时,添加的关系在序列化/反序列化期间丢失
  • 看起来您可能正在按照JSON.NET Parser seems to be double serializing my objects 的行对您的DataSet 进行双重序列化,Ok(Object) 将对象进行序列化,而不是已经序列化的 JSON。然后它会为您序列化对象。

标签: c# .net xml asp.net-core-2.0 .net-core-2.0


【解决方案1】:

这里有两个问题:

  1. 您似乎正在以JSON.NET Parser seems to be double serializing my objects 中描述的方式对您的dataset 进行双重序列化。首先您手动将返回的对象序列化为字符串,然后调用Ok(object),它序列化传入的对象(即 JSON 字符串),从而产生嵌套序列化。

    解决方案是不要这样做。让框架为您序列化您的对象,只需执行return Ok(dataset);

  2. 更新。 Json.NET 11.0 Release 1 支持 .NET Standard 2.0,因此现在可以在 .Net 内核中使用此版本和更高版本对 DataSetDataTable 进行序列化。您需要升级到此版本或后续版本。

    原始答案。您的第二个问题是您尝试使用 Json.NET 10.0.3 或更早版本在 .Net 核心中使用 Json.NET 序列化 DataSet - 不幸的是这样做了尚不支持。正如Issue #1409: serializes a DataSet to JSON on dotnet core 2.0Issue #1383: .Net core build doesn't include DataTableConverter 中所述,此版本的Json.NET 以netstandard 1.3 为目标,而DataSetDataTable 是在netstandard 1.5 中引入的。因此,此版本没有内置逻辑来在 .Net 核心中序列化这些类型。

    那么,您有哪些选择使用此版本?首先,Json.NET 在MIT License 下获得许可,因此您可以复制其版本的DataSetConverterDataTableConverter,将它们包含在您的项目中,并将它们添加到JsonSerializerSettings.Converters。问题JsonSerializerSettings and Asp.Net Core 展示了如何在 ASP.NET Core 中自定义设置。

    其次,您可以将 DataSet 转换为 DTO 并返回它。例如,以下扩展方法将任何DataSet 转换为Dictionary<string, List<Dictionary<string, object>>>,Json.NET 可以序列化:

    public static class DataSetExtensions
    {
        public static List<Dictionary<string, object>> ToDictionaryList(this DataTable table)
        {
            if (table == null)
                return null;
            return table.Rows.Cast<DataRow>()
                .Select(r => table.Columns.Cast<DataColumn>().ToDictionary(c => c.ColumnName, c => r[c]))
                .ToList();
        }
    
        public static Dictionary<string, List<Dictionary<string, object>>> ToDictionary(this DataSet set)
        {
            if (set == null)
                return null;
            return set.Tables.Cast<DataTable>()
                .ToDictionary(t => t.TableName, t => t.ToDictionaryList());
        }
    }
    

    更好的是,创建一个强类型模型来返回。 (如果您还序列化为 XML,那么这是更好的解决方案,因为 XmlSerializer 不支持字典的序列化。)

【讨论】:

  • 非常感谢,它真的很有帮助,我终于修复了我的代码,它为我节省了大量时间和研究。尤其是价值百万的链接,谢谢。
【解决方案2】:

截至 2018 年 4 月 25 日。我有完全相同的问题。下载最新版本的 Newtonsoft。我升级到 11.0.2。它现在适用于 ASP Core 2。数据集被转换为 JSON。

【讨论】:

    猜你喜欢
    • 2020-07-17
    • 2013-01-04
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2017-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多