JSON.Net - DeserializeObject Format

和自甴很熟 提交于 2019-12-05 18:21:26

This trick to support totally crazy mappings is to use JsonConverter and completely replace the parsing for that object, (I apologize for the C#, but I'm no good at VB syntax):

class Program
{
    static void Main(string[] args)
    {
        var result = JsonConvert.DeserializeObject<Responses>(TestData);
    }

    const string TestData = @"{""result_ok"":true,
""total_count"":""44"",
""page"":1,
""total_pages"":1,
""results_per_page"":50,
""data"":[
    {""id"":""1"",
    ""contact_id"":"""",
    ""status"":""Complete"",
    ""is_test_data"":""0"",
    ""datesubmitted"":""2011-11-13 22:26:53"",
    ""[question(59)]"":""11\/12\/2011"",
    ""[question(60)]"":""06:15 pm"",
    ""[question(62)]"":""72"",
    ""[question(63)]"":""One"",
    ""[question(69), option(10196)]"":""10"",
}]}";
}

[JsonObject]
class Responses
{
    public bool result_ok { get; set; }
    public string total_count { get; set; }
    public int page { get; set; }
    public int total_pages { get; set; }
    public int results_per_page { get; set; }
    public SurveyResponse[] Data { get; set; }
}

[JsonObject]
// Here is the magic: When you see this type, use this class to read it.
// If you want, you can also define the JsonConverter by adding it to
// a JsonSerializer, and parsing with that.
[JsonConverter(typeof(DataItemConverter))]
class SurveyResponse
{
    public string id { get; set; }
    public string contact_id { get; set; }
    public string status { get; set; }
    public string is_test_data { get; set; }
    public DateTime datesubmitted { get; set; }
    public Dictionary<int, string> questions { get; set; }
}

class DataItemConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(SurveyResponse);
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var value = (SurveyResponse)existingValue;
        if (value == null)
        {
            value = new SurveyResponse();
            value.questions = new Dictionary<int, string>()
        }

        // Skip opening {
        reader.Read();

        while (reader.TokenType == JsonToken.PropertyName)
        {
            var name = reader.Value.ToString();
            reader.Read();

                // Here is where you do your magic
            if (name.StartsWith("[question("))
            {
                int index = int.Parse(name.Substring(10, name.IndexOf(')') - 10));
                value.questions[index] = serializer.Deserialize<string>(reader);
            }
            else
            {
                var property = typeof(SurveyResponse).GetProperty(name);
                property.SetValue(value, serializer.Deserialize(reader, property.PropertyType), null);
            }

            // Skip the , or } if we are at the end
            reader.Read();
        }

        return value;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Now obviously there's a lot more you would want to do to get this really robust, but this gives you the basics of how to do it. There are more lightweight alternatives if you simply need to change property names (either JsonPropertyAttribute or overriding DefaultContractResolver.ResolvePropertyName(), but this gives you full control.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!