2016-02-11 28 views
4

我正在使用Newtonsoft JSON庫反序列化來自Web服務的響應。問題是一些字段包含無效的值。例如,一個記錄上的一個字段包含一個「T」,表示應該是數字的字段。我想要做的是讓無效字段的值爲空或其他默認值。我所有的屬性都被定義爲可空,所以如果它們默認爲null,那就沒問題。如何使用JSON.net的默認值來處理無效值的屬性

有沒有辦法做到這一點?我曾嘗試創建自定義JsonConverters,但我寧願不必爲每種類型定義JsonConverter。如果可能的話,我希望對於所有字段,如果該屬性的值無效(如數字類型的「T」),則將它們設置爲null。

我看過OnError事件處理程序,但似乎放棄了錯誤的整個記錄​​。我不想丟棄任何記錄。我只想將無效屬性的值設爲null。

這可能嗎?我已經看了很多答案,我沒有找到另一個試圖做到這一點的問題,但請讓我知道,如果我忽略了現有的問題。

謝謝你的幫助。

+0

可能的替代方法是將您的類中的定義更改爲「object」,然後執行檢查文章解析。或者可能類似[this](http://stackoverflow.com/questions/19747914/change-default-null-value-in-json-net)讓我知道如果我誤你的意圖。 – Gabe

+0

@Gabe將C#屬性的類型更改爲對象可能會起作用,但如果可能,我寧願不這樣做,因爲我希望C#類中的所有屬性都是正確的類型。我想要做的是採取如下這樣的JSON響應:{「count」:「T」}(其中計數應該被定義爲一個整數),並在C#中使用Count屬性的值爲null類。在實際的迴應中,有更多的領域比一個更多,所以我不想丟棄整個記錄。我只想爲每個屬性設置一個默認值,比如null。謝謝你的幫助。 – ashipma

+0

dbc的自定義轉換器是最好的選擇 - 你仍然需要空檢查。您可以執行默認值和註釋,但這些都不會阻止反序列化時產生的問題。有幾個模型和轉換器是迄今爲止最可用的選項。然而,我很好奇 - 爲什麼將空值/空值存儲爲字符串?你使用它的泛型(可能沒有給你想要它爲空)?你有權訪問數據傳遞/存儲的方式嗎?數據庫限制?在'發件人'一方解決這個問題可以解決你所有的問題。 – Gabe

回答

2

你可以做的是試圖反序列化相應JSON價值爲基礎類型時,非空,並且在失敗時,返回null所有可空類型一JsonConverter

public class NullableTypeConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return Nullable.GetUnderlyingType(objectType) != null; 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     var underlyingType = Nullable.GetUnderlyingType(objectType); 
     if (underlyingType == null) 
      throw new JsonSerializationException("Invalid type " + objectType.ToString()); 
     var token = JToken.Load(reader); 
     try 
     { 
      return token.ToObject(underlyingType, serializer); 
     } 
     catch (Exception ex) 
     { 
      // Log the exception somehow 
      Debug.WriteLine(ex); 
      return null; 
     } 
    } 

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

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

然後use it反序列化你的類。

var settings = new JsonSerializerSettings { Converters = new[] { new NullableTypeConverter() } }; 

轉換器仍然會拋出異常(從調用JToken.Load())如果JSON本身是不正確,無法讀取。如果在加載後無法將JSON值轉換爲適當的類型,它只會吞下異常。

+0

到目前爲止測試後的最佳選擇。 – Gabe

+0

謝謝你的幫助。這解決了我所問的問題。我最終不得不申請'[JsonConverter(typeof(NullableTypeConverter)'作爲每個屬性的屬性,而不是在設置對象中設置它,因爲有兩個屬性實際上是不可空的,我之前沒有提到。再次感謝你的幫助。 – ashipma

1

嘗試在Deserialize上設置Error委託並通過設置args.ErrorContext.Handled = true來處理您正在查找的錯誤。看看下面的示例代碼:

public class TestClass1 
{ 
    public string Id { get; set; } 
    public int Height { get; set; } 
} 

public class TestClass2 
{ 
    public string Id { get; set; } 
    public string Height { get; set; } 
} 

[TestMethod] 
public void Test() 
{ 
    TestClass2 x = new TestClass2() { Id = "1", Height = "something" }; 
    string str = JsonConvert.SerializeObject(x); 

    JsonConvert.DeserializeObject<TestClass1>(str, new JsonSerializerSettings() 
     { 
      Error = delegate(object sender, ErrorEventArgs args) 
      { 
       if (args.ErrorContext.Error.GetType().FullName == typeof(JsonReaderException).FullName) 
        args.ErrorContext.Handled = true; 
      } 
    }); 
} 
+0

謝謝你對此的幫助。 – ashipma