Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ServiceStack.Text json deserialization creates wrong object instead of throwing on invalid json input string

When I try to deserialise this invalid json string ( }] missing in the end) :

[{"ExtId":"2","Name":"VIP sj�lland","Mobiles":["4533333333","4544444444"]

By doing this:

var result = JsonSerializer.DeserializeFromString<T>(str);    

The ServiceStack json deserializer accepts the string, but it creates a wrong object, because I end up with a C# object having these values:

ExtId : "2"                                      // ok fine.
Name: "VIP sj�lland"                            // ok fine
Mobiles: ["4533333333","4544444444", "544444444"]// Aarg! An array with 3 objects ?!? 
                                                 // There were only two in the JSON string.

In this case it would be much better to have an exception thrown instead of continuing with bad data. Therefore I tried using:

JsConfig.ThrowOnDeserializationError = true; 

just before calling DeserializeFromString but no exception was thrown. In January I asked this question Configure ServiceStack.Text to throw on invalid JSON and the answer was that ServiceStack is favoring resilence and that I could make a pull request in GitHub.

Is this still the case? And have anyone done it already, saving me the trouble? Otherwise, I am on a very tight schedule, so if anyone has some code or suggestions for how to create an option-flag for making ServiceStack throw on deserialization errors, please reply here, so that I can get this done faster.

like image 485
ssn Avatar asked Apr 14 '12 12:04

ssn


1 Answers

This is resolved in ServiceStack.Text v4+ which by default doesn't populate incomplete collections, e.g:

public class Poco
{
    public string ExtId { get; set; }
    public string Name { get; set; }
    public string[] Mobiles { get; set; }
}

var json = "[{\"ExtId\":\"2\",\"Name\":\"VIP sj�lland\",\"Mobiles\":[\"4533333333\",\"4544444444\"]";

var dto = json.FromJson<Poco[]>();

Assert.That(dto[0].ExtId, Is.EqualTo("2"));
Assert.That(dto[0].Name, Is.EqualTo("VIP sj�lland"));
Assert.That(dto[0].Mobiles, Is.Null);

Or if preferred can throw on Error:

JsConfig.ThrowOnDeserializationError = true;

Assert.Throws<SerializationException>(() => 
    json.FromJson<Poco[]>());
like image 84
mythz Avatar answered Nov 09 '22 12:11

mythz