从 YamlStream 发出序列化类型标签
Issue Serializing Type Tags from YamlStream
我在为 class 创建配置文件时遇到问题,其中包含在我使用 YamlStream API.
时实现相同接口的对象列表
我想保留我放在列表项上的本地标签,以便它们可以从另一个上下文正确反序列化。在我的实际项目中,我必须对 YamlNodes 进行一些预处理。但是,当我想将 YamlDocument 序列化为文件时,本地类型标签丢失了。我看到标签在转换为 YamlStream 时被解析(某些节点已正确设置标签 属性)。但是,经过处理后,它们被序列化,没有标签。
我有一些我在这个 repo 中尝试过的例子:https://github.com/mariotee/YamlDotNetIssue
var stream = new YamlStream();
stream.Load(new StringReader(yaml));
//pre processing would go here
using (var wr = new StringWriter())
{
stream.Save(wr, false);
File.WriteAllText("path", wr.ToString());
}
预期结果:
pets:
- !Cat
name: skippy
likesMilk: true
- !Cat
name: felix
likesMilk: true
- !Dog
name: ralf
likesBones: true
- !Hamster
name: Hamtaro
likesTv: true
...
实际结果:
pets:
- name: skippy
likesMilk: true
- name: felix
likesMilk: true
- name: ralf
likesBones: true
- name: Hamtaro
likesTv: true
...
正如我评论的那样,这是一个错误。但是,您可以通过提供自己的 IEmitter
实现并将 MappingStart 的 IsImplicit 属性 强制为 false:
来解决此问题
public static void Main()
{
var yaml = @"
pets:
- !Cat
name: skippy
likesMilk: true
- !Cat
name: felix
likesMilk: true
- !Dog
name: ralf
likesBones: true
- !Hamster
name: Hamtaro
likesTv: true
...
";
var stream = new YamlStream();
stream.Load(new StringReader(yaml));
stream.Save(new MappingFix(new Emitter(Console.Out)), false);
}
public class MappingFix : IEmitter
{
private readonly IEmitter next;
public MappingFix(IEmitter next)
{
this.next = next;
}
public void Emit(ParsingEvent @event)
{
var mapping = @event as MappingStart;
if (mapping != null) {
@event = new MappingStart(mapping.Anchor, mapping.Tag, false, mapping.Style, mapping.Start, mapping.End);
}
next.Emit(@event);
}
}
这会产生预期的输出:
pets:
- !Cat
name: skippy
likesMilk: true
- !Cat
name: felix
likesMilk: true
- !Dog
name: ralf
likesBones: true
- !Hamster
name: Hamtaro
likesTv: true
...
请注意,这需要最新版本 - YamlDotNet 6.1.1
我在为 class 创建配置文件时遇到问题,其中包含在我使用 YamlStream API.
时实现相同接口的对象列表我想保留我放在列表项上的本地标签,以便它们可以从另一个上下文正确反序列化。在我的实际项目中,我必须对 YamlNodes 进行一些预处理。但是,当我想将 YamlDocument 序列化为文件时,本地类型标签丢失了。我看到标签在转换为 YamlStream 时被解析(某些节点已正确设置标签 属性)。但是,经过处理后,它们被序列化,没有标签。
我有一些我在这个 repo 中尝试过的例子:https://github.com/mariotee/YamlDotNetIssue
var stream = new YamlStream();
stream.Load(new StringReader(yaml));
//pre processing would go here
using (var wr = new StringWriter())
{
stream.Save(wr, false);
File.WriteAllText("path", wr.ToString());
}
预期结果:
pets:
- !Cat
name: skippy
likesMilk: true
- !Cat
name: felix
likesMilk: true
- !Dog
name: ralf
likesBones: true
- !Hamster
name: Hamtaro
likesTv: true
...
实际结果:
pets:
- name: skippy
likesMilk: true
- name: felix
likesMilk: true
- name: ralf
likesBones: true
- name: Hamtaro
likesTv: true
...
正如我评论的那样,这是一个错误。但是,您可以通过提供自己的 IEmitter
实现并将 MappingStart 的 IsImplicit 属性 强制为 false:
public static void Main()
{
var yaml = @"
pets:
- !Cat
name: skippy
likesMilk: true
- !Cat
name: felix
likesMilk: true
- !Dog
name: ralf
likesBones: true
- !Hamster
name: Hamtaro
likesTv: true
...
";
var stream = new YamlStream();
stream.Load(new StringReader(yaml));
stream.Save(new MappingFix(new Emitter(Console.Out)), false);
}
public class MappingFix : IEmitter
{
private readonly IEmitter next;
public MappingFix(IEmitter next)
{
this.next = next;
}
public void Emit(ParsingEvent @event)
{
var mapping = @event as MappingStart;
if (mapping != null) {
@event = new MappingStart(mapping.Anchor, mapping.Tag, false, mapping.Style, mapping.Start, mapping.End);
}
next.Emit(@event);
}
}
这会产生预期的输出:
pets:
- !Cat
name: skippy
likesMilk: true
- !Cat
name: felix
likesMilk: true
- !Dog
name: ralf
likesBones: true
- !Hamster
name: Hamtaro
likesTv: true
...
请注意,这需要最新版本 - YamlDotNet 6.1.1