简体   繁体   中英

Custom deserialize from json object string

I'm trying to deserialize this JSON into an object but I can't reach the solution.

Json format:

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

I Have the following object:

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

And then the "deserializer":

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;
    }

The call:

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

How can I access the IDictionary<string, object> as Dictionary<string, Dictionary<string,boolean>> ? Or is it just impossible?

What am I doing wrong? Is there another easy way to do this?

The easy way is to correctly make objects that represent the serialized values. So for:

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

I would make:

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; }
}

For beginners, one of the easier ways is to use http://json2csharp.com/ .

As mentioned, you can use Json.NET . If you don't want to create classes to deserialise to, you can use dictionaries as you have tried, or you could use a 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);

Given that you have chosen to use , firstly you need to do your conversion at the level of the List<genericFieldOptions> not the genericFieldOptions , because the serializer cannot convert a JSON object to a List<T> automatically.

Secondly, rather than casting the nested dictionaries to Dictionary<string, Boolean> , you need to cast to IDictionary<string, object> and then deserialize each value to a bool using JavaScriptSerializer.ConvertToType<bool> . Thus:

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>;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM