2014-02-28 75 views
1

我通過API從我們的調查提供者處提取調查響應。我沒有用這個類來反序列化,它只是鍵/值對。JSON.NET在解析集合時忽略空值

我正在讀取來自文件的響應數組。每個響應包含許多「答題」我們會打電話給他們,如下:

[ 
    { 
     "response_id":"1234", 
     "hRz5aMmGPf": null, 
     "6UnnAZSEBT": null, 
     "nGS1cyvLwK": "Red" 
    }, 
    { 
     "response_id":"1235", 
     "hRz5aMmGPf": "John Smith", 
     "6UnnAZSEBT": null, 
     "nGS1cyvLwK": "Blue" 
    }, 
    { 
     "response_id":"1236", 
     "hRz5aMmGPf": "Jane Doe", 
     "6UnnAZSEBT": "Yes", 
     "nGS1cyvLwK": null 
    } 
] 

對於這個練習的目的,我從文件中讀取JSON如下:

List<JToken> responseobjs = new List<JToken>(); 
JObject o = JObject.Parse(fcontents); 
responseobjs.AddRange(o["results"].Children()) 

由於根據樣本數據,我希望儘可能以最快的方式消除源數據中的大量空值。我讀過'NullValueHandling',但是這似乎只適用於將序列化成類/對象的情況,這對於由供稿返回的不同字段ID是不可能的。

我有可能帶上面的兒童(),但跳過空位嗎?

現在我正在遍歷響應,然後響應項目來刪除空值,它需要很長時間來轉換。

foreach (JToken obj in responseobjs) 
{ 

    foreach (JProperty rprop in obj.Where(x=> x.HasValues==true).ToList()) 
    { 
     if (rprop.Value.ToString().Trim() == "") 
      continue; 

     ..Continue parsing here... 
    } 
} 
+0

爲什麼要刪除空值。假設我編寫了一個代碼並返回了字典中不爲空的所有屬性。那麼你將不得不檢查一個財產是否在這個詞典中。與檢查null不同的是什麼? –

+0

我必須解析每個響應中返回的每個屬性。源文件包含空值需要很長時間才能完成。我無法改變它包含空值的事實,但如果它由於數據量龐大而不包括它們,它會爲我節省時間。 – Tom

+0

湯姆也許我不清楚(因爲我的英語不好),但再次閱讀評論。什麼會改變如果我發佈了一個解決方案給你一個字典(每個對象的字典)與非空屬性。 –

回答

2

如果您已經解析了JSON,刪除空值的唯一方法是像您已經在做的那樣分別檢查每個屬性。另一種方法是在JSON正在讀取時刪除空值,因此您不必在稍後過濾它們。 Json.Net不開箱提供此功能,但它是可以編寫一個JsonReader直接合作共建JToken層次與空值排除一個輔助方法:

static JToken DeserializeExcludingNulls(string json) 
{ 
    using (JsonTextReader reader = new JsonTextReader(new StringReader(json))) 
    { 
     return DeserializeExcludingNulls(reader); 
    } 
} 

static JToken DeserializeExcludingNulls(JsonReader reader) 
{ 
    if (reader.TokenType == JsonToken.None) 
    { 
     reader.Read(); 
    } 

    if (reader.TokenType == JsonToken.StartArray) 
    { 
     reader.Read(); 
     JArray array = new JArray(); 
     while (reader.TokenType != JsonToken.EndArray) 
     { 
      JToken token = DeserializeExcludingNulls(reader); 
      if (!IsEmpty(token)) 
      { 
       array.Add(token); 
      } 
      reader.Read(); 
     } 
     return array; 
    } 

    if (reader.TokenType == JsonToken.StartObject) 
    { 
     reader.Read(); 
     JObject obj = new JObject(); 
     while (reader.TokenType != JsonToken.EndObject) 
     { 
      string propName = (string)reader.Value; 
      reader.Read(); 
      JToken token = DeserializeExcludingNulls(reader); 
      if (!IsEmpty(token)) 
      { 
       obj.Add(propName, token); 
      } 
      reader.Read(); 
     } 
     return obj; 
    } 

    return new JValue(reader.Value); 
} 

static bool IsEmpty(JToken token) 
{ 
    return (token.Type == JTokenType.Null); 
} 

這裏是一個演示:

string json = @" 
[ 
    { 
     ""response_id"":""1234"", 
     ""hRz5aMmGPf"": null, 
     ""6UnnAZSEBT"": null, 
     ""nGS1cyvLwK"": ""Red"", 
    }, 
    { 
     ""response_id"":""1235"", 
     ""hRz5aMmGPf"": ""John Smith"", 
     ""6UnnAZSEBT"": null, 
     ""nGS1cyvLwK"": ""Blue"" 
    }, 
    { 
     ""response_id"":""1236"", 
     ""hRz5aMmGPf"": ""Jane Doe"", 
     ""6UnnAZSEBT"": ""Yes"", 
     ""nGS1cyvLwK"": null 
    } 
]"; 

JArray array = (JArray)DeserializeExcludingNulls(json); 

foreach (JObject obj in array) 
{ 
    foreach (JProperty prop in obj.Properties()) 
    { 
     Console.WriteLine(prop.Name + ": " + prop.Value); 
    } 
    Console.WriteLine(); 
} 

輸出:

response_id: 1234 
nGS1cyvLwK: Red 

response_id: 1235 
hRz5aMmGPf: John Smith 
nGS1cyvLwK: Blue 

response_id: 1236 
hRz5aMmGPf: Jane Doe 
6UnnAZSEBT: Yes 

如果你也想排除空字符串,你可以改變IsEmpty方法:

static bool IsEmpty(JToken token) 
{ 
    return (token.Type == JTokenType.Null) || 
      (token.Type == JTokenType.String && token.ToString().Trim() == ""); 
} 
+0

真棒,謝謝! – Tom