2011-11-24 88 views
3

我使用JSON.Net尝试反序列化来自SurveyGizmo的一些调查响应。 下面是我在读数据的快照:JSON.Net - 反序列化对象格式

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

我设置一个类就datesubmitted,但我不知道如何设置类反序列化的问题,因为量问题会改变吗?如果它存在,我也需要捕捉选项。

我使用此代码使用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 

回答

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(),但是这给你完全的控制。

+0

西蒙, 我很欣赏的努力,你把那个答复! 我有点吓倒最初的回答是,我希望这会很好,很简单!迄今为止,除了具有选项的问题例如“[问题(31),选项(10019)]”:“39.99”外,值得注意的是,问题(31)可能有多个选项响应 所以我认为我需要开始捕获question_id,option_id和value,但我不认为我可以用字典来做到这一点? – Tom

+0

我想我已经排序我很快就会发布我的更改 – Tom

+0

是的,这只是为了让你知道如何覆盖属性名称 - >对象更新过程,我不想猜测什么option()意思:) –