我正在使用Newtonsoft JSON库来反序列化来自Web服务的响应。问题是某些字段包含无效的值。例如,一个记录上的一个字段包含一个应该是数字的字段的“T”。我想要做的是使无效字段的值为null或其他一些默认值。我的所有属性都被定义为可为空,因此如果它们默认为null则可以。
有办法做到这一点吗?我尝试过创建自定义JsonConverters,但我不想为每种类型定义JsonConverter。如果可能的话,我想,对于所有字段,如果该属性的值无效(如数字类型的“T”),则将它们设置为null。
我查看了OnError事件处理程序,但这似乎丢弃了整个错误记录。我不想丢弃任何记录。我只想将无效属性的值设为null。
这可能吗?我已经找了很多答案,我没有找到另一个试图做到这一点的问题,但如果我忽略了现有的问题,请告诉我。
感谢您的帮助。
答案 0 :(得分:2)
您可以为所有可空类型创建JsonConverter
,这些类型在非null时尝试将相应的JSON值反序列化为基础类型,并在失败时返回null:
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() } };
如果JSON本身格式错误且无法读取,转换器仍将抛出异常(从调用JToken.Load()
)。如果在加载后无法将JSON值转换为适当的类型,它只会吞下异常。
答案 1 :(得分:1)
尝试在反序列化上设置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;
}
});
}