JSON.Net - 反序列化对象格式

时间:2011-11-24 04:18:15

标签: vb.net json json.net

我正在使用JSON.Net尝试对来自SurveyGizmo的一些调查回复进行反序列化。 这是我正在阅读的数据的快照:

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

我已经设置了一个类,只要提交了date,但我不确定如何设置类来反序列化问题,因为问题的数量会发生变化?如果它存在,我还需要捕获该选项。

我正在使用此代码来使用JSON.NET反序列化函数:

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

课程:

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 个答案:

答案 0 :(得分:2)

这个支持完全疯狂映射的技巧是使用JsonConverter并完全替换该对象的解析,(我为C#道歉,但我不擅长VB语法):

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

现在很明显你还有很多想要做的事情来让它变得非常强大,但是这为你提供了如何做到这一点的基础知识。如果您只需更改属性名称(JsonPropertyAttribute或覆盖DefaultContractResolver.ResolvePropertyName()),则可以使用更轻量级的替代品,但这可以让您完全控制。