【问题标题】:YamlDotNet: How to handle !!setYamlDotNet:如何处理 !!set
【发布时间】:2015-09-24 08:47:03
【问题描述】:

我正在尝试反序列化一些在序列化 Java HashSet 时设置在 SnakeYaml 创建的字符串中的 YAML。不同的泛型类型被序列化,例如 HashSet 和自定义类型 HashSet。

YAML 示例:

holidays: !!set
    ? DDMMYYYY: 25/12/2042
      MMDDYYYY: 12/25/2042
      date:
        chronology: &id001
          calendarType: iso8601
          id: ISO
        dayOfMonth: 25
        dayOfWeek: THURSDAY
        dayOfYear: 359
        era: CE
        leapYear: false
        month: DECEMBER
        monthValue: 12
        year: 2042
      serialValue: 52225
    : null

我最初得到异常:

附加信息:无法加载文件或程序集“2002:set”或其依赖项之一。系统找不到指定的文件。

为了修复,我将标签映射注册到反序列化器:

{"tag:yaml.org,2002:set", typeof (HashSet<object>)}

然后我得到异常:

在 YamlDotNet.dll 中发生了“YamlDotNet.Core.YamlException”类型的第一次机会异常 附加信息:(第 4 行,第 23 列,第 23 列,第 108 行)-(第 5 行,第 9 列,第 9 列,第 122 行):预期为“SequenceStart”,得到“映射开始”(第 4 行,第 23 列,编号:108)。

我原以为处理集是 YAML 的一个非常常见的要求,但我不知道如何解决这个问题。

谁能告诉我如何处理?

【问题讨论】:

    标签: java c# serialization snakeyaml yamldotnet


    【解决方案1】:

    问题是HashSet&lt;T&gt;没有实现IDictionary&lt;TKey, TValue&gt;,然后被反序列化为序列而不是映射。

    您将需要创建自己的集合实现,可能通过扩展HashSet&lt;T&gt; 并像这样实现IDictionary&lt;T, object&gt;

    public class YamlSet<T> : HashSet<T>, IDictionary<T, object>
    {
        void IDictionary<T, object>.Add(T key, object value)
        {
            Add(key);
        }
    
        object IDictionary<T, object>.this[T key]
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                Add(key);
            }
        }
        // ...
    }
    

    IDictionary&lt;T, object&gt; 的更多成员必须实现,但这些是反序列化工作所必需的。

    See a fully working example here

    【讨论】:

    • 谢谢安托万。我尝试这样做,它通过了原始异常,但随后给出了“System.InvalidCastException”......“对象必须实现 IConvertible。”然后我更改了 YamlSet 以实现 IConvertible。似乎方法 ToType(Type conversionType, IFormatProvider provider) 是必需的。这里的conversionType 是我期望的类型的System.Collections.ISet。我在该方法中尝试了各种方法,例如返回 this、converType,但它给出了强制转换异常。你能解释一下应该在这里做什么吗?将不胜感激。
    • 你可以让YamlSet&lt;T&gt;实现ISet接口,或者使用TypeConverter注册一个可以将YamlSet&lt;T&gt;转换成ISet的转换器。
    • 对不起 Antoine,我想我遗漏了一些东西...... YamlSet 已经扩展了实现 ISet 的 HashSet,所以我认为将 YamlSet 更改为实现 ISet 没有任何作用。我尝试注册一个接受 {return type == typeof(YamlSet);} 的类型转换器,但我不确定在 ReadYaml 中放入什么。我查看了this 并执行了: public object ReadYaml(IParser parser, Type type){parser.MoveNext();var value = ((Scalar)parser.Current).Value;return new HashSet{value}; } ...
    • ...但随后我收到一条错误消息,指出 Object 必须实现 IConvertible。有什么建议吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 2015-12-20
    • 2020-01-12
    • 2015-03-24
    • 2016-01-31
    • 2017-05-31
    • 2018-09-16
    相关资源
    最近更新 更多