2016-03-06 155 views
0

我想反序列化這個JSON到一個對象,但我不能達到解決方案。自定義反序列化從json對象字符串

JSON格式:

{"option1": 
    {"field1":"true","field2":"false"}, 
"option2": 
    {"field1":"true","field2":"false"}} 

我有以下對象:

[Serializable] 
public class genericFieldOptions 
{ 
    public string option { get; set; } 
    public string field { get; set; } 
    public bool value{ get; set; } 
} 

,然後在 「解串器」:

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

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
    { 
     List<genericFieldOptions> p = new List<genericFieldOptions>(); 

     foreach (var entry in dictionary.Keys) 
     {    
      try 
      { 
       Dictionary<string, Boolean> test = (Dictionary<string, Boolean>)dictionary[entry];//error 
       p.Add(new genericFieldOptions { key = entry, field1=test["field1"],field2=test["field2"] }); 
      } 
      catch { } 
     } 
     return p; 
    } 

召喚:

JavaScriptSerializer serializer = new JavaScriptSerializer(); 
serializer.RegisterConverters(new JavaScriptConverter[] { new genericFieldsConverter() }); 
var example= serializer.Deserialize<List<genericFieldOptions>>(json); 

如何才能以Dictionary<string, Dictionary<string,boolean>>訪問IDictionary<string, object>?還是僅僅是不可能的?

我在做什麼錯?有沒有另一種簡單的方法來做到這一點?

+0

事實上還有另一種簡單的方法 - 使用[Json.NET(http://www.newtonsoft.com/json):-) –

+0

你可以從你的問題複製的JSON字符串,並把光標在需要創建模型的命名空間中。 Goto - Edit-PasteSpecial->作爲JSON CLASS ......然後使用NewtonSoft.Json添加一個包;在頂部和分配標題爲模型/類的每個屬性作爲[JsonProperty(「option1或option2」)] .....提示 –

回答

0

簡單的方法是正確地創建表示序列化值的對象。因此,對於:

{"option1": 
    {"field1":"true","field2":"false"}, 
"option2": 
    {"field1":"true","field2":"false"}} 

我會做:

public class Options 
{ 
    public Option Option1 { get; set; } 
    public Option Option2 { get; set; } 
} 

public class Option 
{ 
    public bool Field1 { get; set; } 
    public bool Field2 { get; set; } 
} 

對於初學者來說,比較容易的方法之一是使用http://json2csharp.com/

+0

感謝您的答案,但這就是爲什麼我試圖做它通用,我不'不想宣佈所有新的選擇。還有另一種方式? – user3157778

0

如上所述,您可以使用Json.NET。如果您不想創建要反序列化的類,則可以按照您的嘗試使用字典,也可以使用dynamic

const string json = "{\"option1\":{\"field1\":true,\"field2\":false}," + 
        "\"option2\":{\"field1\":true,\"field2\":false}}"; 

var result1 = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, bool>>>(json); 
Console.WriteLine(result1["option2"]["field1"]); 

dynamic result2 = JsonConvert.DeserializeObject(json); 
Console.WriteLine(result2.option2.field1); 
+1

對於尋求答案的人來說,既然你提到過不想每次都創建一個模型,可以考慮使用動態模型。如上所述。但是請注意動態在運行時解決事情。如果你的代碼與運行時的值不匹配,那麼它會拋出異常。 –

0

既然你已經選擇使用,首先你需要在List<genericFieldOptions>不是genericFieldOptions的水平做轉換,因爲串行器不能自動JSON對象轉換爲List<T>

其次,而非鑄造的嵌套字典來Dictionary<string, Boolean>,你需要轉換爲IDictionary<string, object>,然後反序列化使用JavaScriptSerializer.ConvertToType<bool>每個值到bool。因此:

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

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
    { 
     var query = from entry in dictionary 
        let subDictionary = entry.Value.AsJsonObject() 
        where subDictionary != null 
        from subEntry in subDictionary 
        select new genericFieldOptions { option = entry.Key, field = subEntry.Key, value = serializer.ConvertToType<bool>(subEntry.Value) }; 
     return query.ToList(); 
    } 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) 
    { 
     var list = (IList<genericFieldOptions>)obj; 
     if (list == null) 
      return null; 
     return list 
      .GroupBy(o => o.option) 
      .ToDictionary(g => g.Key, g => (object)g.ToDictionary(o => o.field, o => serializer.Serialize(o.value))); 
    } 
} 

public static class JavaScriptSerializerObjectExtensions 
{ 
    public static bool IsJsonObject(this object obj) 
    { 
     return obj is IDictionary<string, object>; 
    } 

    public static IDictionary<string, object> AsJsonObject(this object obj) 
    { 
     return obj as IDictionary<string, object>; 
    } 
} 
相關問題