2015-04-22 58 views
2

我正在研究一個與瀏覽器集成的C#應用​​程序。 瀏覽器將以json格式向C#發送一些數據。c#中的自定義JavaScript解串器#

json的一些字段可以使用javascript反序列化器進行反序列化,但是我有一些數據需要自定義反序列化器,我需要註冊一個反序列化器,但是這個東西是自定義反序列化器只能用於這些特殊數據和默認的JavaScript解串器必須被調用其他數據,特殊數據可以從C#中目標字段的數據類型/名稱中識別。我怎樣才能做到這一點。

這樣的事情。

public class example 
{ 
    public string abc; 
    public someOtherDataType xyz; 

    public void example() 
    { 
    serializer = new JavaScriptSerializer(); 

    // receive json string 

     serializer.RegisterConverters(new JavaScriptConverter[] 
     { 
    new System.Web.Script.Serialization.CS.CustomConverter() 
    }); 

    //call deserializer 

} 
} 

JSON字符串會像

{ 
"abc" : "valueabc" 
"xyz" : "valueXYZ" 
} 

現在定製解串器只能反序列化XYZ和默認期間調用必須調用ABC。

謝謝。

+0

是什麼讓這兩個對象有什麼不同?如何在反序列化之前將它們分開?你有沒有反序列化的C#類(如果有的話,你可以發佈它)嗎? – br4d

+0

是的,我確實有一堂課,就像dbc的答案一樣。 – Anurag

回答

2

這裏的難點在於JavaScriptConverter允許你將一個JSON對象映射到一個c#類 - 但在你的JSON中,"xyz"只是一個字符串,而不是一個對象。因此,您無法爲someOtherDataType指定轉換器,而是必須爲包含someOtherDataType實例的每個類指定轉換器。

(請注意,在Json.NET定製轉換器的功能沒有此限制。如果你願意切換到庫,你可以寫一個JsonConverter轉換的someOtherDataType所有用途從和JSON字符串。)

寫這樣的JavaScriptConverter

  1. 覆蓋JavaScriptConverter.Deserialize
  2. 創建第二Dictionary<string, Object>濾除需要定製轉換的字段。
  3. 請致電new JavaScriptSerializer.ConvertToType<T>從過濾的字典中反序列化標準字段。
  4. 手動轉換剩餘的字段。
  5. 重寫SupportedTypes以返回容器類型。

因此,在你的榜樣,你可以這樣做:

public class example 
{ 
    public string abc; 
    public someOtherDataType xyz; 
} 

// Example implementation only. 
public class someOtherDataType 
{ 
    public string SomeProperty { get; set; } 

    public static someOtherDataType CreateFromJsonObject(object xyzValue) 
    { 
     if (xyzValue is string) 
     { 
      return new someOtherDataType { SomeProperty = (string)xyzValue }; 
     } 
     return null; 
    } 
} 

class exampleConverter : JavaScriptConverter 
{ 
    public override IEnumerable<Type> SupportedTypes 
    { 
     get { return new[] { typeof(example) }; } 
    } 

    // Custom conversion code below 

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
    { 
     var defaultDict = dictionary.Where(pair => pair.Key != "xyz").ToDictionary(pair => pair.Key, pair => pair.Value); 
     var overrideDict = dictionary.Where(pair => !(pair.Key != "xyz")).ToDictionary(pair => pair.Key, pair => pair.Value); 

     // Use a "fresh" JavaScriptSerializer here to avoid infinite recursion. 
     var value = (example)new JavaScriptSerializer().ConvertToType<example>(defaultDict); 

     object xyzValue; 
     if (overrideDict.TryGetValue("xyz", out xyzValue)) 
     { 
      value.xyz = someOtherDataType.CreateFromJsonObject(xyzValue); 
     } 
     return value; 
    } 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

,然後進行測試:

public class TestClass 
{ 
    public static void Test() 
    { 
     // receive json string 
     string json = @"{ 
""abc"" : ""valueabc"", 
""xyz"" : ""valueXYZ"" 
}"; 
     var serializer = new JavaScriptSerializer(); 
     serializer.RegisterConverters(new JavaScriptConverter[] 
     { 
      new exampleConverter() 
     }); 

     var example = serializer.Deserialize<example>(json); 
     Debug.Assert(example.abc == "valueabc" && example.xyz.SomeProperty == "valueXYZ"); // No assert 
    } 
} 
+1

感謝dbc,它對我的​​應用程序使用此解決方案工作良好。 – Anurag