c# JavaScriptConverter -如何反序列化自定义属性
本文关键字:反序列化 自定义属性 JavaScriptConverter | 更新日期: 2023-09-27 18:13:55
我有一个已序列化为JSON的类,我正试图将其反序列化为对象。
。
public class ContentItemViewModel
{
public string CssClass { get; set; }
public MyCustomClass PropertyB { get; set; }
}
简单属性(CssClass)将反序列化为:
var contentItemViewModels = ser.Deserialize<ContentItemViewModel>(contentItems);
但是PropertyB得到一个错误…
我们添加了JavaScriptConverter:
ser.RegisterConverters(new List<JavaScriptConverter>{ publishedStatusResolver});
但是当我们将'MyCustomClass'添加为'SupportedType'时,反序列化方法从未被调用。但是当我们将ContentItemViewModel作为SupportedType时,就会调用Deserialize。
我们有一个当前的解决方案,看起来像这样:
class ContentItemViewModelConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
var cssClass = GetString(dictionary, "cssClass"); //I'm ommitting the GetString method in this example...
var propertyB= GetString(dictionary, "propertyB");
return new ContentItemViewModel{ CssClass = cssClass ,
PropertyB = new MyCustomClass(propertyB)}
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
throw new Exception("Only does the Deserialize");
}
public override IEnumerable<Type> SupportedTypes
{
get
{
return new List<Type>
{
typeof(ContentItemViewModel)
};
}
}
}
但是我们更喜欢一个简单的解决方案,只反序列化MyCustomClass,因为有许多其他字段是在ViewModel上,它似乎浪费编辑这个转换器每次我们改变/添加属性....
是否有一种方法来反序列化只是PropertyB类型的MyCustomClass?
谢谢你的帮助!
是否考虑过使用DatacontractJsonSerializer
[DataContract]
public class MyCustomClass
{
[DataMember]
public string foobar { get; set; }
}
[DataContract]
public class ContentItemViewModel
{
[DataMember]
public string CssClass { get; set; }
[DataMember]
public MyCustomClass PropertyB { get; set; }
}
class Program
{
static void Main(string[] args)
{
ContentItemViewModel model = new ContentItemViewModel();
model.CssClass = "StackOver";
model.PropertyB = new MyCustomClass();
model.PropertyB.foobar = "Flow";
//Create a stream to serialize the object to.
MemoryStream ms = new MemoryStream();
// Serializer the User object to the stream.
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ContentItemViewModel));
ser.WriteObject(ms, model);
byte[] json = ms.ToArray();
ms.Close();
string s= Encoding.UTF8.GetString(json, 0, json.Length);
Console.ReadLine();
}
}
添加所有可能的类到DatacontractJsonSerializer。KnownTypes如果MyCustomClass有派生
不管它在这段时间之后是否值得,但是我遇到了同样的问题,解决方案是反序列化器没有得到关于您正在反序列化的类的线索,除非您向他提供必要的信息。
在顶层,它从Deserialize<>()的类型参数知道类型。这就是为什么你的ContentItemViewModel
转换器工作。对于嵌套对象,它需要__type属性和JavaScriptTypeResolver。
var ser = new JavaScriptSerializer(new SimpleTypeResolver());
ser.RegisterConverters(myconverters);
MyClass myObject = new MyClass();
string json = ser.Serialize(myObject);
// set a breakpoint here to see what has happened
ser.Deserialize<MyClass>(json);
TypeResolver为每个序列化对象添加__type属性。您可以编写使用短名称的自定义类型解析器。在这个示例中,我使用来自。net的SimpleTypeResolver,它"简单地"将完全限定类型名称存储为__type。当反序列化时,JavaScriptDeserializer会找到__type并向TypeResolver询问正确的类型。然后它知道一个类型,并可以调用注册的JavaScriptConverter。反序列化方法。
如果没有TypeResolver,对象将被反序列化为Dictionary,因为JavaScriptSerializer没有任何类型信息。
如果你不能在json字符串中提供__type属性,我认为你需要先反序列化到Dictionary,然后添加一个"猜测步骤"来解释字段以找到正确的类型。然后,你可以使用JavaScriptSerializer的ConvertToType方法将字典复制到对象的字段和属性中。
如果你需要使用ASP. js提供的JavaScriptSerializer。. NET并且不能自己创建,请考虑JavaScriptSerializer的. tor帮助中的这一节:
异步通信层用于从客户端脚本调用Web服务的JavaScriptSerializer实例使用一个特殊的类型解析器。该类型解析器将可以反序列化的类型限制为那些在Web服务的方法签名中定义的类型,或者应用了GenerateScriptTypeAttribute的类型。不能以编程方式修改此内置类型解析器。
也许GenerateScriptType属性可以帮助您。但是我不知道这里需要什么样的__type属性