C# 从json对象字符串自定义反序列化

C# 从json对象字符串自定义反序列化,c#,json,serialization,javascriptserializer,C#,Json,Serialization,Javascriptserializer,我试图将这个JSON反序列化为一个对象,但我无法找到解决方案 Json格式: {"option1": {"field1":"true","field2":"false"}, "option2": {"field1":"true","field2":"false"}} 我的目标如下: [Serializable] public class genericFieldOptions { public string option { get; set; } public st

我试图将这个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; }
}
然后是“反序列化程序”:

公共类genericFieldsConverter:JavaScriptConverter
{
公共覆盖IEnumerable SupportedTypes
{
得到
{
返回新的[]{typeof(genericfieldpoptions)};
}
}
公共重写对象反序列化(IDictionary dictionary、类型、JavaScriptSerializer序列化程序)
{
列表p=新列表();
foreach(dictionary.Keys中的var条目)
{             
尝试
{
字典测试=(字典)字典[条目];//错误
p、 添加(新的genericFieldOptions{key=entry,field1=test[“field1”],field2=test[“field2”]});
}
捕获{}
}
返回p;
}
电话:

JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] { new genericFieldsConverter() });
var example= serializer.Deserialize<List<genericFieldOptions>>(json);
JavaScriptSerializer serializer=新的JavaScriptSerializer();
serializer.RegisterConverters(新JavaScriptConverter[]{new genericFieldsConverter()});
var-example=serializer.Deserialize(json);
我怎样才能以
字典的身份访问
IDictionary
?还是根本不可能


我做错了什么?还有其他简单的方法吗?

简单的方法是正确创建表示序列化值的对象。因此:

{"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; }
}
对于初学者来说,其中一种更简单的方法是使用。

如前所述,您可以使用。如果您不想创建要反序列化的类,您可以使用您尝试过的词典,或者您可以使用
动态

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);
const string json=“{\'option1\':{\'field1\':true,\'field2\':false},”+
“\'option2\':{\'field1\':true,\'field2\':false}”;
var result1=JsonConvert.DeserializeObject(json);
Console.WriteLine(结果1[“选项2”][“字段1”]);
DynamicResult2=JsonConvert.DeserializeObject(json);
Console.WriteLine(结果2.选项2.字段1);

鉴于您已选择使用,首先您需要在
列表
而不是
通用字段选项
的级别进行转换,因为序列化程序无法自动将JSON对象转换为
列表

其次,与将嵌套字典强制转换为
Dictionary
不同,您需要强制转换为
IDictionary
,然后使用将每个值反序列化为
bool
。因此:

公共类genericFieldsListConverter:JavaScriptConverter
{
公共覆盖IEnumerable SupportedTypes
{
得到
{
返回新的[]{typeof(List)};
}
}
公共重写对象反序列化(IDictionary dictionary、类型、JavaScriptSerializer序列化程序)
{
var query=来自字典中的条目
让subDictionary=entry.Value.AsJsonObject()
其中子字典!=null
从子词典中的子条目
选择new genericFieldOptions{option=entry.Key,field=subEntry.Key,value=serializer.ConvertToType(subEntry.value)};
返回query.ToList();
}
公共重写IDictionary序列化(对象obj、JavaScriptSerializer序列化程序)
{
var list=(IList)obj;
if(list==null)
返回null;
返回列表
.GroupBy(o=>o.option)
.ToDictionary(g=>g.Key,g=>(object)g.ToDictionary(o=>o.field,o=>serializer.Serialize(o.value));
}
}
公共静态类JavaScriptSerializerObjectExtensions
{
公共静态bool IsJsonObject(此对象obj)
{
返回obj是索引的;
}
公共静态IDictionary AsJsonObject(此对象obj)
{
将obj返回为IDictionary;
}
}

实际上还有另一种简单的方法-使用:-)您可以从问题中复制JSON字符串,并将光标放在需要创建模型的命名空间中。转到-编辑PasteSpecial->As JSON CLASS……然后在顶部使用NewtonSoft.JSON;添加一个包,并将头作为[JsonProperty]分配给模型/类的每个属性(“选项1或选项2”)]谢谢你的回答,但这就是为什么我要做的是泛型,我不想宣布所有的新的时间。还有另外一种方法吗?对于一个寻求答案的人,因为你提到不想每次创建一个模型,考虑使用动态。如上所述。但是注意动态在运行时解决问题。如果你的代码不't与运行时的值不匹配,则它将引发异常。
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);
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>;
    }
}