I have a simple JSON generated with WCF Rest client, but when I try to deserialize a response I get an error NullReferenceException
in JSON.Net. I have following JSON:
{"Code":-2146232800,"ExceptionType":"IOException","Message":"Msg","Stacktrace":"Some"}
And following class:
[DataContract]
public class FileUploadError
{
public FileUploadError(Exception exception)
{
Code = exception.HResult;
ExceptionType = exception.GetType().Name;
Message = GetMessage(exception);
Stacktrace = exception.StackTrace;
if (exception.Data.Count > 0)
{
Data = string.Join(Environment.NewLine, exception.Data.Cast<DictionaryEntry>().Select(x => x.Key + "=" + x.Value));
}
}
private string GetMessage(Exception exception)
{
if (exception.InnerException == null)
{
return exception.Message;
}
const string delimiter = "->";
var sb = new StringBuilder(1024);
for (var ex = exception; ex != null; ex = ex.InnerException)
{
sb.Append(ex.Message).Append(delimiter);
}
sb.Length -= delimiter.Length;
return sb.ToString();
}
[DataMember(IsRequired = true)]
[JsonProperty("Code", NullValueHandling = NullValueHandling.Ignore)]
public int Code { get; set; }
[DataMember(IsRequired = true)]
[JsonProperty("ExceptionType", NullValueHandling = NullValueHandling.Ignore)]
public string ExceptionType { get; set; }
[DataMember(EmitDefaultValue = false)]
[JsonProperty("Message", NullValueHandling = NullValueHandling.Ignore)]
public string Message { get; set; }
[DataMember(EmitDefaultValue = false)]
[JsonProperty("Stacktrace", NullValueHandling = NullValueHandling.Ignore)]
public string Stacktrace { get; set; }
[DataMember(EmitDefaultValue = false)]
[JsonProperty("Data", NullValueHandling = NullValueHandling.Ignore)]
public string Data { get; set; }
}
Then I deserialize it:
const string text = "{\"Code\":-2146232800,\"ExceptionType\":\"IOException\",\"Message\":\"Msg\",\"Stacktrace\":\"Some\"}";
var obj = JsonConvert.DeserializeObject<FileUploadError>(text);
And get subj error. Reproduced in new console application, which I can provide if required. JSON is very simple, why I am getting this error?
Sample: https://dotnetfiddle.net/76FJd0
Stacktrace:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at FileUploadError..ctor(Exception exception) in d:\Windows\Temp\nclgvim3.0.cs:line 28
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ConstructorInfo constructorInfo, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at Program.Main(String[] args)
The result of deserializing the JSON is three successfully deserialized dates and three error messages: one for the badly formatted string ("I am not a date and will error!"), one for the nested JSON array, and one for the null value since the list doesn't allow nullable DateTimes.
Serializing and Deserializing JSON. The quickest method of converting between JSON text and a .NET object is using the JsonSerializer . The JsonSerializer converts .NET objects into their JSON equivalent and back again by mapping the .NET object property names to the JSON property names and copies the values for you.
The result of deserializing the JSON is three successfully deserialized dates and three error messages: one for the badly formatted string ("I am not a date and will error!"), one for the nested JSON array, and one for the null value since the list doesn't allow nullable DateTimes.
JsonConvert.DeserializeObject can throw several unexpected exceptions (JsonReaderException is the one that is usually expected). These are: ArgumentException JsonSerializationException JsonWriterException NullReferenceException Documenta...
You need to add a public parameterless constructor to your FileUploadError
class:
public class FileUploadError
{
public FileUploadError()
{
}
Or, you could make it private and use [JsonConstructor]
:
public class FileUploadError
{
[JsonConstructor]
private FileUploadError()
{
}
Or, leave it private and deserialize with ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
:
var settings = new JsonSerializerSettings
{
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
var obj = JsonConvert.DeserializeObject<FileUploadError>(text, settings);
with:
public class FileUploadError
{
private FileUploadError()
{
}
For those tumbling upon this later and since OP's specific case has been solved.
Here is what to do to get a clearer error message when it happens.
Source: https://www.newtonsoft.com/json/help/html/SerializationErrorHandling.htm
var errors = new List<string>();
List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(
yourJsonHere,
new JsonSerializerSettings
{
Error = delegate(object sender, ErrorEventArgs args)
{
errors.Add(args.ErrorContext.Error.Message);
args.ErrorContext.Handled = true;
}
});
And errors
will contain a list of the errors that occured! Works both for serialization and deserialization!
Doing so you do lose the context though! So alternatively you can set it to Handled = false
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With