Reputation: 2901
I'm deserializing a third party string like this:
{"status":4,"errors":[{"Duplicate Application":"Duplicate Application"}]}
I use my standard extension method:
public static T DeserializeJson<T>(string response)
where T : class
{
var s = new DataContractJsonSerializer(typeof(T));
try {
using (var ms = new MemoryStream()) {
byte[] data = System.Text.Encoding.UTF8.GetBytes(response);
ms.Write(data, 0, data.Length);
ms.Position = 0;
return (T)s.ReadObject(ms);
}
}
catch {
return default(T);
}
}
The class I'm trying to deserialize to looks like this:
[DataContract]
public class ResponseProps
{
[DataMember(Name = "status", Order = 0)]
public string ResponseCode { get; set; }
[DataMember(Name = "lead_id", Order=1)]
public string LeadId { get; set; }
[DataMember(Name = "price", Order=2)]
public decimal Price { get; set; }
[DataMember(Name = "redirect_url", Order = 3)]
public string RedirectUrl { get; set; }
[DataMember(Name = "errors", Order = 4)]
public List<Dictionary<string, string>> Errors { get; set; }
}
I'm using a List of type Dictionary (string, string) for the Errors property because other types I've tried have broken the deserializer - this works in that the serializer no longer throws an exception.
However, I'm now trying to retrieve the data from Errors - I'm using this code:
var cr = XmlHelper.DeserializeJson<ResponseProps>(response);
var errorStore = new HashSet<string>();
foreach (var dict in cr.Errors)
{
foreach (var kvp in dict)
{
errorStore.Add(kvp.Key + ": " + kvp.Value);
}
}
I've done various tests - the dict counts 1, but there are no kvp, so when the loop runs I get no messages.
I'm guessing this is again down to deserialization rather than incorrect looping, but I've not been able to fix it.
Anyone got any advice?
Upvotes: 1
Views: 1216
Reputation: 31312
To be able to deserialize such dictionary, you should customize settings of DataContractJsonSerializer
with UseSimpleDictionaryFormat
set to true
:
DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings
{
UseSimpleDictionaryFormat = true
};
var s = new DataContractJsonSerializer(typeof(T), settings);
By the way, do you have any reason to use DataContractJsonSerializer
with your custom DeserializeJson<T>()
method? You could do the same in one line of code with JSON.Net:
var obj = JsonConvert.DeserializeObject<ResponseProps>(str);
JSON.Net is also much more flexible and have a better performance than DataContractJsonSerializer
.
Upvotes: 1