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?

谢谢你的帮助!

c# JavaScriptConverter -如何反序列化自定义属性

是否考虑过使用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属性