我在我的WCF数据服务中使用Json.NET。
下面是我的类(简化):
[DataContract]
public class Component
{
public Component()
{
// I'm doing some magic here.
}
}
如何在不使用JsonConvert.DeserializeObject
调用构造函数情况下反序列化该类
如果不清楚,很抱歉,请随时提问。
发布于 2012-12-19 16:14:18
构造函数总是被调用。我通常有两个构造函数。一个用于序列化(默认构造函数),另一个用于所有“常规”代码:
[DataContract]
public class Component
{
// for JSON.NET
protected Component()
{
}
public Component(allMandatoryFieldsHere)
{
// I'm doing some magic here.
}
}
通过这种方式,我还可以确保dev指定所需的所有信息。
但是,我并不建议您在传输信息时使用DTO以外的任何东西,因为否则可能会绕过对象的封装(任何人都可以用任何值初始化任何字段)。井。如果你使用的不是贫血模型。
因此,使用FormatterServices.GetSafeUninitializedObject
是一种丑陋的变通办法,因为没有人知道您是以未初始化的方式创建所有对象的。构造函数初始化的存在是有原因的。更好的做法是,类可以通过提供我建议的“序列化”构造函数来告知不调用真正的构造函数是可以的。
发布于 2016-08-26 03:34:10
其他人已经提到了第二个构造函数,但使用两个属性: JsonConstructor和Obsolete,你可以做得更好,而不是让人类去记住调用哪个构造函数。
public ChatMessage()
{
MessageID = ApplicationState.GetNextChatMessageID(); // An expensive call that uses up an otherwise free ID from a limited set and does disk access in the process.
}
[JsonConstructor] // This forces JsonSerializer to call it instead of the default.
[Obsolete("Call the default constructor. This is only for JSONserializer", true)] // To make sure that calling this from your code directly will generate a compiler error. JSONserializer can still call it because it does it via reflection.
public ChatMessage(bool DO_NOT_CALL_THIS)
{
}
JsonConstructor强制JsonSerializer调用它,而不是默认的。
Obsolete("...",true)确保直接从代码中调用它会生成编译器错误。JSONserializer仍然可以调用它,因为它是通过反射来实现的。
发布于 2014-01-22 17:15:58
避免在反序列化时调用构造函数的最佳选择是创建特殊的协定解析器,它覆盖所有没有标记有JsonConstructor属性的构造函数的类的创建者函数。通过这种方式,如果你真的需要,你仍然可以强制JSON.NET调用构造函数,但是所有其他的类都会像.NET中的标准DataContract序列化程序一样被创建。代码如下:
/// <summary>
/// Special contract resolver to create objects bypassing constructor call.
/// </summary>
public class NoConstructorCreationContractResolver : DefaultContractResolver
{
/// <summary>
/// Creates a <see cref="T:Newtonsoft.Json.Serialization.JsonObjectContract"/> for the given type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// A <see cref="T:Newtonsoft.Json.Serialization.JsonObjectContract"/> for the given type.
/// </returns>
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
// prepare contract using default resolver
var objectContract = base.CreateObjectContract(objectType);
// if type has constructor marked with JsonConstructor attribute or can't be instantiated, return default contract
if (objectContract.OverrideConstructor != null || objectContract.CreatedType.IsInterface || objectContract.CreatedType.IsAbstract)
return objectContract;
// prepare function to check that specified constructor parameter corresponds to non writable property on a type
Func<JsonProperty, bool> isParameterForNonWritableProperty =
parameter =>
{
var propertyForParameter = objectContract.Properties.FirstOrDefault(property => property.PropertyName == parameter.PropertyName);
if (propertyForParameter == null)
return false;
return !propertyForParameter.Writable;
};
// if type has parameterized constructor and any of constructor parameters corresponds to non writable property, return default contract
// this is needed to handle special cases for types that can be initialized only via constructor, i.e. Tuple<>
if (objectContract.ParametrizedConstructor != null
&& objectContract.ConstructorParameters.Any(parameter => isParameterForNonWritableProperty(parameter)))
return objectContract;
// override default creation method to create object without constructor call
objectContract.DefaultCreatorNonPublic = false;
objectContract.DefaultCreator = () => FormatterServices.GetSafeUninitializedObject(objectContract.CreatedType);
return objectContract;
}
}
您只需在反序列化之前在序列化程序设置中设置此协定解析器。
https://stackoverflow.com/questions/13947997
复制相似问题