【问题标题】:Problems roundtripping F# discriminated unions with Json.net使用 Json.net 往返 F# 可区分联合的问题
【发布时间】:2014-09-15 11:49:45
【问题描述】:

我在 F# 中有以下枚举

 type MyEnum = 
    | Value1
    | Value2
    | Value3

这是代码编译时编译器生成的内容

   [Serializable]
    [DebuggerDisplay("{__DebugDisplay(),nq}")]
    public class MyEnum : IEquatable<MyEnum>, IStructuralEquatable, IComparable<MyEnum>, IComparable, IStructuralComparable
    {
        [CompilerGenerated]
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        [DebuggerNonUserCode]
        public bool IsValue1 { get; }
        [CompilerGenerated]
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        [DebuggerNonUserCode]
        public bool IsValue2 { get; }
        [CompilerGenerated]
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        [DebuggerNonUserCode]
        public bool IsValue3 { get; }
        [CompilerGenerated]
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        [DebuggerNonUserCode]
        public int Tag { get; }
        [CompilerGenerated]
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        [DebuggerNonUserCode]
        public static MyEnum Value1 { get; }
        [CompilerGenerated]
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        [DebuggerNonUserCode]
        public static MyEnum Value2 { get; }
        [CompilerGenerated]
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        [DebuggerNonUserCode]
        public static MyEnum Value3 { get; }

        [CompilerGenerated]
        public override sealed int CompareTo(MyEnum obj);
        [CompilerGenerated]
        public override sealed int CompareTo(object obj);
        [CompilerGenerated]
        public override sealed int CompareTo(object obj, IComparer comp);
        [CompilerGenerated]
        public override sealed bool Equals(MyEnum obj);
        [CompilerGenerated]
        public override sealed bool Equals(object obj);
        [CompilerGenerated]
        public override sealed bool Equals(object obj, IEqualityComparer comp);
        [CompilerGenerated]
        public override sealed int GetHashCode();
        [CompilerGenerated]
        public override sealed int GetHashCode(IEqualityComparer comp);

        public static class Tags
        {
            public const int Value1 = 0;
            public const int Value2 = 1;
            public const int Value3 = 2;
        }
    }

问题 当上述枚举类型用于需要非静态set 的每个属性进行反序列化的序列化时,它会失败。事实上,我已经将它与RavenDBJson.Net 序列化一起使用,我得到以下内容

myenummember = {}

如何通过序列化程序有效地使用 F# 枚举类型?

【问题讨论】:

  • 这是联合类型,而不是枚举。以下是一个枚举:type MyEnum = Value1 = 0 | Value2 = 1 | Value3 = 2
  • 如果你正在尝试序列化一个 DU(示例实际上是什么),我们最近在这里遇到了一个非常相似的问题:stackoverflow.com/questions/24884814/…
  • ildjarn 所说的。在 F# 中,.NET enum typesdiscriminated union types 完全不同,尽管它们在语法上看起来非常相似。枚举只是标准的 .NET 枚举,并且与任何能够理解它们的序列化程序兼容。另一方面,DU 在内部由具有嵌套类的类表示,并且需要序列化程序的特殊支持。这是一个 good post 解释了差异。
  • 什么 json.net 版本? 6.0.(3?) 增加了支持(但有弱点,见我的回答)。顺便说一句,如果您打算将我们的编译输出大量转储,那么您真的应该在代码方面展示您正在做的事情,有用且所有这些都是

标签: serialization f# json.net ravendb


【解决方案1】:

您可以提供知道如何来回转换的 JsonConverter 实例。

【讨论】:

    【解决方案2】:

    虽然 Json.net 6.0(.1?) 为 F# DU 提供支持,但存在许多弱点(我在@John Palmer's link 的回答和评论中提到了其中一些)。

    FsUno.Prod 包含一个 Serialization.fs(由 Jérémie Chassaing 编写)解决了这些问题以及更多问题[使用@Ayende Rahien 提到的技术]。


    (此时此刻my fork, FunDomainincludes some further extensionshere。 (这些更改可能最终会回到 FsUno.Prod 中,这应该被视为权威 repo)

    【讨论】:

      【解决方案3】:

      尝试使用“Serializable”属性标记类型。还为模式标识符提供赋值可能有助于编译器推断它是枚举而不是总和类型可能会有所帮助。

      [<Serializable>]
      type x =
        ABC = 1
      | ABE = 2
      

      【讨论】:

      • -1 应该没有什么区别——我不使用任何这样的装置,而且 json.net 在处理许多不同的情况时非常彻底。 (我会向 OP 询问应该发生的事情的代码......)
      猜你喜欢
      • 2018-04-25
      • 2011-11-19
      • 1970-01-01
      • 2014-09-13
      • 1970-01-01
      • 2017-12-27
      • 1970-01-01
      • 2013-08-04
      • 2016-07-14
      相关资源
      最近更新 更多