【问题标题】:YamlDotNet !!binary typeYamlDotNet !!二进制类型
【发布时间】:2016-06-03 16:59:58
【问题描述】:

我正在尝试使用 yaml 发送二进制数据,即字节数组。根据 yaml 文档,Yaml Binary Type,这是支持的。在 Java 端,我使用 SnakeYaml,如果传递了 byte[] 的值,那么 yaml 会正确给出 !!binary。

YamlDotNet 似乎“开箱即用”不支持此功能。下面的代码 sn -p 创建一个整数值序列:

IDictionary<string, object> data = new Dictionary<string, object>();

        const string value = ":| value: <XML> /n\n C:\\cat";
        byte[] bytes = Encoding.UTF8.GetBytes(value);
        data.Add(ValueKey, bytes);


        // Turn the object representation into text
        using (var output = new StringWriter())
        {
            var serializer = new Serializer();
            serializer.Serialize(output, data);

            return output.ToString();
        }

输出如下:

val:\r- 58\r- 124\r- 32\r- 118\r- 97\r- 108\r- 117\r- 101\r- 58\r- 32\r- 60\r- 88\r- 77\r- 76\r- 62\r- 32\r- 47\r- 110\r- 10\r- 32\r- 67\r- 58\r- 92\r- 99\r- 97\r- 116\r

但我想要更多类似的东西:

  val: !!binary |-
OnwgdmFsdWU6IDxYTUw+IC9uCiBDOlxjYXQ=

谁能推荐一个解决方法?

【问题讨论】:

    标签: yamldotnet


    【解决方案1】:

    添加对自定义类型的支持的首选方法是使用自定义IYamlTypeConverter!!binary 类型的可能实现是:

    public class ByteArrayConverter : IYamlTypeConverter
    {
        public bool Accepts(Type type)
        {
            // Return true to indicate that this converter is able to handle the byte[] type
            return type == typeof(byte[]);
        }
    
        public object ReadYaml(IParser parser, Type type)
        {
            var scalar = (YamlDotNet.Core.Events.Scalar)parser.Current;
            var bytes = Convert.FromBase64String(scalar.Value);
            parser.MoveNext();
            return bytes;
        }
    
        public void WriteYaml(IEmitter emitter, object value, Type type)
        {
            var bytes = (byte[])value;
            emitter.Emit(new YamlDotNet.Core.Events.Scalar(
                null,
                "tag:yaml.org,2002:binary",
                Convert.ToBase64String(bytes),
                ScalarStyle.Plain,
                false,
                false
            ));
        }
    }
    

    要使用Serializer中的转换器,您只需使用以下代码注册它:

    var serializer = new Serializer();
    serializer.RegisterTypeConverter(new ByteArrayConverter());
    

    对于Deserializer,还需要注册转换器,但还需要添加标签映射,将!!binary标签解析为byte[]类型:

    var deserializer = new Deserializer();
    deserializer.RegisterTagMapping("tag:yaml.org,2002:binary", typeof(byte[]));
    deserializer.RegisterTypeConverter(new ByteArrayConverter());
    

    A fully working example can be tried here

    【讨论】:

    • 感谢 Antoine - 这似乎是一种更好的方法!
    • 这将是很棒的 YamlDotNet 文档页面。
    • 我创建了一个 BitmapConverter 因为我想读/写位图。一切正常。但我想知道如果我还想读/写另一种字节数组类型会发生什么。反序列化器如何知道一种字节数组是位图但另一种是不同类型的?我必须将“tag:yaml.org,2002:binary”的标签映射注册到 typeof(Bitmap)。这是否意味着任何字节数组都将被解释为位图?
    • deserializer.RegisterTagMapping()deserializer.RegisterTypeConverter() 标记为 Obsolete,现在无法访问 @antoine-aubry,您能否提供装饰器或其他新方法来实现这一点?
    【解决方案2】:

    对于任何感兴趣的人....我通过自己创建字符串并添加 !!binary 标记来解决此问题,并且还进行了一些清理工作。下面是代码。

    ToYaml:

    IDictionary<string, string> data = new Dictionary<string, string>();
    string byteAsBase64Fromat = Convert.ToBase64String("The string to convert");
    byteAsBase64Fromat = "!!binary |-\n" + byteAsBase64Fromat + "\n";
    
    data.Add(ValueKey, byteAsBase64Fromat);
    string yaml;
    using (var output = new StringWriter())
    {
      var serializer = new Serializer();
      serializer.Serialize(output, data);
    
       yaml = output.ToString();
    }
    string yaml = yaml.Replace(">", "");
    return yaml.Replace(Environment.NewLine + Environment.NewLine,     Environment.NewLine);
    

    然后返回:

    string binaryText = ((YamlScalarNode)data.Children[new YamlScalarNode(ValueKey)]).Value
    String value = Convert.FromBase64String(binaryText);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      • 2012-03-18
      相关资源
      最近更新 更多