JSON.Net - DeserializeObject Format

久未见 提交于 2019-12-07 17:58:27

问题


I'm using JSON.Net to try and deserialize some survey responses from SurveyGizmo. Here's a snapshot of the data I'm reading in:

{"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",

I've setup a class as far as datesubmitted but I'm not sure how to setup the class to deserialize the questions given that the amount of questions will change? I also need to capture the option if it's present.

I'm using this code to use the JSON.NET Deserialize function:

Dim responses As Responses = JsonConvert.DeserializeObject(Of Responses)(fcontents)

Classes:

Public Class Responses
    Public Property result_OK As Boolean

    Public Property total_count As Integer

    Public Property page As Integer

    Public Property total_pages As Integer

    Public Property results_per_page As Integer

    Public Overridable Property data As List(Of surveyresponse)
End Class

Public Class SurveyResponse
    Public Property id As Integer

    Public Property status As String

    Public Property datesubmitted As Date
End Class

回答1:


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.



来源:https://stackoverflow.com/questions/8252176/json-net-deserializeobject-format

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