[英]How Can I Parse YAML Into a Derived Collection Using YamlDotNet?
使用YamlDotNet ,我試圖反序列化以下 YAML:
Collection:
- Type: TypeA
TypeAProperty: value1
- Type: TypeB
TypeBProperty: value2
Type
屬性是Collection
下所有對象的必需屬性。 其余屬性取決於類型。
這是我理想的對象模型:
public class Document
{
public IEnumerable<IBaseObject> Collection { get; set; }
}
public interface IBaseObject
{
public string Type { get; }
}
public class TypeAClass : IBaseObject
{
public string Type { get; set; }
public string TypeAProperty { get; set; }
}
public class TypeBClass : IBaseObject
{
public string Type { get; set; }
public string TypeBProperty { get; set; }
}
根據我的閱讀,我認為我最好的選擇是使用從INodeDeserializer
派生的自定義節點解串器。 作為概念證明,我可以這樣做:
public class MyDeserializer : INodeDeserializer
{
public bool Deserialize(IParser parser, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer, out object value)
{
if (expectedType == typeof(IBaseObject))
{
Type type = typeof(TypeAClass);
value = nestedObjectDeserializer(parser, type);
return true;
}
value = null;
return false;
}
}
我現在的問題是如何在調用nestedObjectDeserializer
之前動態確定要選擇的Type
。
當使用JSON.Net,我能夠使用CustomCreationConverter
,讀子JSON成JObject
,確定我喜歡的類型,然后創建一個新JsonReader
從JObject
並重新解析的對象。
有沒有一種方法可以讀取、回滾,然后重新讀取nestedObjectDeserializer
?
是否有另一種對象類型可以調用nestedObjectDeserializer
,然后從中讀取Type
屬性,最后繼續對派生類型進行正常的 YamlDotNet 解析?
這是不容易的。 這是一個 GitHub 問題,解釋了如何使用 YamlDotNet 進行多態序列化。
在您的情況下,一個簡單的解決方案是兩步反序列化。 首先,您將反序列化為某種中間形式,然后將其轉換為您的模型。 這相對容易,因為您限制了對 YamlDotNet 內部的挖掘:
public class Step1Document
{
public List<Step1Element> Collection { get; set; }
public Document Upcast()
{
return new Document
{
Collection = Collection.Select(m => m.Upcast()).ToList()
};
}
}
public class Step1Element
{
// Fields from TypeA and TypeB
public string Type { get; set; }
public string TypeAProperty { get; set; }
public string TypeBProperty { get; set; }
internal IBaseObject Upcast()
{
if(Type == "TypeA")
{
return new TypeAClass
{
Type = Type,
TypeAProperty = TypeAProperty
};
}
if (Type == "TypeB")
{
return new TypeBClass
{
Type = Type,
TypeBProperty = TypeBProperty
};
}
throw new NotImplementedException(Type);
}
}
然后反序列化:
var serializer = new DeserializerBuilder().Build();
var document = serializer.Deserialize<Step1Document>(data).Upcast();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.