2016-03-06 153 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>; 
    } 
} 
相关问题