是否有一个 XML 或 JSON 序列化器知道使用哪个构造函数来填充不可变对象并序列化 IEnumerable<> 属性? [关闭]

Posted

技术标签:

【中文标题】是否有一个 XML 或 JSON 序列化器知道使用哪个构造函数来填充不可变对象并序列化 IEnumerable<> 属性? [关闭]【英文标题】:Is there an XML or JSON Serializer that knows which Constructor to use to Populate an Immutable Object and also Serialize IEnumerable<> Properties? [closed] 【发布时间】:2021-02-16 08:02:23 【问题描述】:

假设我有这个不可变的结构:

public struct LogGroup

    public Log<LowResolutionLogData> LowResolutionLog  get; 

    public IEnumerable<Log<MediumResolutionLogData>> MediumResolutionLogs  get; 

    public IEnumerable<Log<HighResolutionLogData>> HighResolutionLogs  get; 

    public LogGroup
    (
        Log<LowResolutionLogData> lowResolutionLog,
        IEnumerable<Log<MediumResolutionLogData>> mediumResolutionLogs,
        IEnumerable<Log<HighResolutionLogData>> highResolutionLogs
    )
    
        LowResolutionLog = lowResolutionLog;
        MediumResolutionLogs = mediumResolutionLogs;
        HighResolutionLogs = highResolutionLogs;
    

我如何序列化它而不必将IEnumerable&lt;&gt; 属性设置为某种具体类型(例如数组或列表)?

我如何反序列化到它而不必使所有属性都可设置(我希望它调用我创建的赋值构造函数)?

对象上的复杂类型也可能有自己的复杂类型和IEnumerable&lt;&gt;s 作为不可变属性。 Log&lt;&gt;class,而它采用的类型都是 structs,因此使用赋值构造函数的反序列化需要对两者都有效。其中一种类型具有大量属性,因此我想避免样板代码并尽可能动态处理序列化/反序列化。

【问题讨论】:

我相信 Newtonsoft JSON 可以开箱即用地处理这个问题,只要构造函数参数名称与您应该可以使用的属性名称匹配。 很好,我只是尝试了 JSON.NET,但在获取读取/写入文件所需的正确对象时遇到了麻烦。你能举个简单的例子吗? 同意,Json.NET 可以使用非默认构造函数进行反序列化。有关选择构造函数的精确算法,请参见:How does JSON deserialization in C# work。但是,如果有 多个 参数化构造函数,则 Json.NET 没有内置方法可以知道使用哪个不存在标记一个 [JsonConstructor]。 IE。您的 LogGroup 应该可以很好地反序列化,但更复杂的不可变类型可能不会。 我刚刚尝试过 JSON.NET,但在获取读取/写入文件所需的正确对象时遇到了麻烦 -- 那么请分享minimal reproducible example。 Json.NET 当然可以从文件反序列化,参见newtonsoft.com/json/help/html/… 和newtonsoft.com/json/help/html/… 【参考方案1】:

非常感谢 JSteward 为我指明了正确的方向。我所需要的只是序列化我的LogGroup 并将其写入文件。

using (var streamWriter = File.CreateText(filePath))
    new JsonSerializer().Serialize(streamWriter, myLogGroup);

然后从文件中读取它并将其转回LogGroup

using (var streamReader = File.OpenText(filePath))
    var myLogGroup = (LogGroup)new JsonSerializer().Deserialize(streamReader, typeof(LogGroup));

我还必须用[JsonConstructor] 标记每个结构的赋值构造函数,以便Deserialize 使用它(否则属性将接收它们的默认值)。

所有类型抽象都被处理以进行序列化。

作为旁注,我使用 .tt 设计时模板来创建我的每个对象,以减少使用赋值构造函数的维护开销(我从一个源生成属性、构造函数参数和属性赋值)。

【讨论】:

将文件加载到字符串中,然后从字符串中反序列化,当文件很大时可能会对性能产生负面影响。相反,您可以直接从流中反序列化,如 Performance Tips: Optimize Memory Usage、Deserialize JSON from a file 和 Serialize JSON to a file 所示。 代码已根据之前的评论更改。

以上是关于是否有一个 XML 或 JSON 序列化器知道使用哪个构造函数来填充不可变对象并序列化 IEnumerable<> 属性? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

PHP:JSON 或 XML 解析器更快吗?

Git 日志输出到 XML、JSON 还是 YAML?

Java 序列化 vs JSON vs XML

是否有任何引擎用于获取 twitter xml 或 json 输出? [关闭]

Json或XML快速反序列化类(Visual Studio 2012以上)

Json 编码或序列化 XML