ServiceStack.Text json deserialization создает неправильный объект вместо того, чтобы метать недопустимую строку ввода json
Когда я пытаюсь десериализовать эту недопустимую строку json (}]
отсутствует в конце):
[{"ExtId":"2","Name":"VIP sj�lland","Mobiles":["4533333333","4544444444"]
Сделав это:
var result = JsonSerializer.DeserializeFromString<T>(str);
Deserializer ServiceStack json принимает строку, но создает неправильный объект, потому что в итоге я получаю объект С#, имеющий следующие значения:
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.
В этом случае было бы гораздо лучше создать исключение вместо продолжения с плохими данными. Поэтому я попытался использовать:
JsConfig.ThrowOnDeserializationError = true;
перед вызовом DeserializeFromString, но исключение не было выбрано. В январе я задал этот вопрос Configure ServiceStack.Text, чтобы выбросить недействительный JSON, и ответ заключался в том, что ServiceStack предпочитает resilence и что я могу сделать запрос на перенос в GitHub.
Это все еще так? И кто-нибудь сделал это уже, избавив меня от неприятностей? В противном случае, у меня очень строгий график, поэтому, если у кого-то есть какой-то код или предложения о том, как создать флаг опции для того, чтобы заставить ServiceStack выбрасывать ошибки десериализации, ответьте здесь, чтобы я мог сделать это быстрее.
Ответы
Ответ 1
Это разрешено в ServiceStack.Text v4 +, который по умолчанию не заполняет неполные коллекции, например:
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);
Или, если это предпочтителен, можно выполнить ошибку:
JsConfig.ThrowOnDeserializationError = true;
Assert.Throws<SerializationException>(() =>
json.FromJson<Poco[]>());
Ответ 2
С# немного придирчив, когда дело доходит до JSON. Следующее будет действительным! Обратите внимание: у меня нет анонимного массива объектов в качестве элемента по умолчанию.
{
"ExtItem": [
{
"ExtId": "2",
"Name": "VIPsj�lland",
"Mobiles": [
"4533333333",
"4544444444"
]
}
]
}
Если я создаю POCO из этого, я получаю
public class Rootobject
{
public Extitem[] ExtItem { get; set; }
}
public class Extitem
{
public string ExtId { get; set; }
public string Name { get; set; }
public string[] Mobiles { get; set; }
}
Я лично использую метод расширения для строки
public static class Extensions
{
public static bool DeserializeJson<T>(this String str, out T item)
{
item = default(T);
try
{
item = new JavaScriptSerializer().Deserialize<T>(str);
return true;
}
catch (Exception ex)
{
return false;
}
}
}
Это позволит мне написать:
Rootobject ext;
const string validJson = @"
{
""ExtItem"": [
{
""ExtId"":""2"",
""Name"":""VIPsj�lland"",
""Mobiles"":[
""4533333333"",
""4544444444""
]
}
]
}";
if (validJson.DeserializeJson(out ext))
{ //valid input
// following would print 2 elements : 4533333333, 4544444444
Console.WriteLine(string.Join(", ", ext.ExtItem.First().Mobiles));
} //invalid input
Ответ 3
Я попробовал это, если у меня возникло исключение, когда я пропустил} в конце.
В С# формат для JSON: { "name", "value" } not [{ "name", "value" }].
class M
{
public string ExtId { get; set; }
public string Name { get; set; }
public List<string> Mobiles { get; set; }
}
string str = "{\"ExtId\":\"2\",\"Name\":\"VIP\",\"Mobiles\":[\"4533333333\",\"4544444444\"]";
M m = JsonConvert.DeserializeObject<M>(str);
Когда вы запустите это, вы получите сообщение об ошибке, поскольку отсутствует.
Использование:
string str = "{\"ExtId\":\"2\",\"Name\":\"VIP\",\"Mobiles\":[\"4533333333\",\"4544444444\"]}";
Объект десериализован.
Вы можете увидеть JSON этого объекта:
string s = JsonConvert.SerializeObject(m);
Ответ 4
Я просто использую Newtonsoft.Json
T JsonConvert.DeserializeObject<T>(string value)
и генерирует исключение;
Если я использую object JsonConvert.DeserializeObject(string value)
этот, он создает правильный объект, просто поместив отсутствующий }]
Я обнаружил, что это очень надежная и быстрая библиотека.