我有一个已经被序列化为JSON的类,我正在尝试将其反序列化为一个对象。
e.g。
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'时,从未调用Deserialize方法。但是,当我们将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上还有许多其他字段,每次更改/添加属性时都必须编辑此转换器。 ...
有没有办法反序列化MyCustomClass类型的JUST PropertyB?
感谢您的帮助!
答案 0 :(得分:0)
您是否考虑过使用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();
}
}
如果MyCustomClass有派生词,则将所有可能的类添加到 DatacontractJsonSerializer.KnownTypes 。
答案 1 :(得分:0)
对于所有这些可能值得的东西,但我偶然发现同样的问题,解决方案是解串器没有得到关于你反序列化的类的线索,除非你给他必要的信息。
在顶层,它知道Deserialize&lt;&gt;()的类型参数中的类型。这就是为什么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.Deserialize方法。
如果没有TypeResolver,则会将对象反序列化为Dictionary,因为JavaScriptSerializer没有任何类型信息。
如果你不能在你的json字符串中提供__type属性,我认为你需要首先反序列化为Dictionary,然后添加一个“猜测步骤”来解释字段以找到正确的类型。然后,您可以使用JavaScriptSerializer的ConvertToType方法将字典复制到对象的字段和属性中。
如果您需要使用ASP.NET提供的JavaScriptSerializer并且无法创建自己的JavaScriptSerializer,请从JavaScriptSerializer的.ctor帮助中考虑此部分:
异步通信层用于从客户端脚本调用Web服务的JavaScriptSerializer实例使用特殊类型解析程序。此类型解析程序将可以反序列化的类型限制为Web服务的方法签名中定义的类型,或者应用了GenerateScriptTypeAttribute的类型。您无法以编程方式修改此内置类型解析程序。
也许GenerateScriptType属性可以帮助您。但我不知道这里需要什么类型的__type属性。