這裏是我的關於問題解決的想法:
問題:
JSON。 Net的自定義反序列化api不透明,即影響我的類層次結構。
實際上,如果您的項目中有10-20個類,那麼這並不是問題,但如果您擁有數千個類的大型項目,那麼您對於需要遵從OOP設計和Json的事實並不是特別滿意.Net要求。
Json.Net與POCO對象很好,它們在創建後被填充(初始化)。但在所有情況下都不是事實,有時你會在構造函數中初始化你的對象。爲了進行初始化,您需要傳遞「正確的」參數。這些'正確的'參數可以在序列化文本中,或者可以在一段時間之前被創建和初始化。不幸的是,在反序列化過程中,Json.Net將默認值傳遞給他不明白的參數,在我的情況下,它總是導致ArgumentNullException。
解決辦法:
這裏是方法,允許使用任何一組參數或者串行化或非序列化反序列化過程真實自定義對象的創建,主要的問題是,該方法最優化的,它需要的2個相每個對象的反序列化,需要定製反序列化,但它的工作原理,並允許反序列化對象,你需要的方式,所以這裏有雲:
首先,我們重新組裝CustomCreationConverter類的方式如下:
public class FactoryConverter<T> : Newtonsoft.Json.JsonConverter
{
/// <summary>
/// Writes the JSON representation of the object.
/// </summary>
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotSupportedException("CustomCreationConverter should only be used while deserializing.");
}
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
/// <param name="objectType">Type of the object.</param>
/// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
T value = CreateAndPopulate(objectType, serializer.Deserialize<Dictionary<String, String>>(reader));
if (value == null)
throw new JsonSerializationException("No object created.");
return value;
}
/// <summary>
/// Creates an object which will then be populated by the serializer.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns></returns>
public abstract T CreateAndPopulate(Type objectType, Dictionary<String, String> jsonFields);
/// <summary>
/// Determines whether this instance can convert the specified object type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
/// </returns>
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
/// <summary>
/// Gets a value indicating whether this <see cref="JsonConverter"/> can write JSON.
/// </summary>
/// <value>
/// <c>true</c> if this <see cref="JsonConverter"/> can write JSON; otherwise, <c>false</c>.
/// </value>
public override bool CanWrite
{
get
{
return false;
}
}
}
接下來,我們創建工廠類,將創建富:
public class FooFactory : FactoryConverter<Foo>
{
public FooFactory(Bar bar)
{
this.Bar = bar;
}
public Bar Bar { get; private set; }
public override Foo Create(Type objectType, Dictionary<string, string> arguments)
{
return new Foo(Bar, arguments["X"], arguments["Y"]);
}
}
下面是示例代碼:
var bar = new Bar("BarObject");
var fooSrc = new Foo
(
bar,
"A", "B"
);
var str = JsonConvert.SerializeObject(fooSrc);
var foo = JsonConvert.DeserializeObject<Foo>(str, new FooFactory(bar));
Console.WriteLine(str);
在這種情況下,FOO包含了我們需要在傳遞給一個Foo構造函數的參數反序列化。
來源
2011-11-29 14:05:00
Lu4
不知道爲什麼串行器編寫者認爲這個優先級低。我一直認爲能夠構建不變的對象,而不需要低級別的基於公共接口的序列化器應該具有的基本功能之一。 – CodesInChaos
@CodeInChaos protobuf-net支持列出的所有4個選項,*和*至少一個其他(代理變換)...只是說' –
@CodeInChaos至於爲什麼:簡單地說,這真的很難 –