简体   繁体   English

ServiceStack.Text json反序列化创建错误的对象,而不是抛出无效的json输入字符串

[英]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) : 当我尝试反序列化此无效的json字符串( }]结尾时):

[{"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: ServiceStack json反序列化器接受该字符串,但会创建一个错误的对象,因为我最终得到一个具有以下值的C#对象:

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. 就在调用DeserializeFromString之前,但未引发任何异常。 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. 1月,我问了一个问题,将ServiceStack.Text配置为抛出无效的JSON ,答案是ServiceStack支持回弹,我可以在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. 否则,我的时间表很紧,因此,如果有人对如何创建使ServiceStack引发反序列化错误的选项标志有一些代码或建议,请在此处答复,以便我更快地完成此工作。

This is resolved in ServiceStack.Text v4+ which by default doesn't populate incomplete collections, eg: 这在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);

Or if preferred can throw on Error: 或者如果首选可以抛出错误:

JsConfig.ThrowOnDeserializationError = true;

Assert.Throws<SerializationException>(() => 
    json.FromJson<Poco[]>());

C# is a little bit picky when it comes to JSON. 对于JSON,C#有点挑剔。 Following would be valid ! 以下将是有效的 Note i do not have anonymous object array as the default element. 注意我没有匿名对象数组作为默认元素。

{
    "ExtItem": [
        {
            "ExtId": "2",
            "Name": "VIPsj�lland",
            "Mobiles": [
                "4533333333",
                "4544444444"
            ]
        }
    ]
}

If i generate a POCO from this I get 如果我从中生成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; }
}

I personally use extension method to string 我个人使用扩展方法来字符串

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;
        }
    }
}

This would enable me to write: 这将使我能够编写:

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

I tried this an have the exception thrown when I missed the } at the end. 我尝试过此操作,但最后错过}时引发了异常。

In C#, the format for JSON is {"name", "value"} not [{"name", "value"}]. 在C#中,JSON的格式为{“ name”,“ value”},而不是[{“ 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);

When run this, you will get error as a } is missing. 运行此命令时,您会得到错误,因为缺少}。

Using: 使用方法:

string str = "{\"ExtId\":\"2\",\"Name\":\"VIP\",\"Mobiles\":[\"4533333333\",\"4544444444\"]}";

The object is deserialized fine. 该对象反序列化很好。

You can see the JSON of this object from: 您可以从以下位置查看此对象的JSON:

string s = JsonConvert.SerializeObject(m);

I just use the Newtonsoft.Json T JsonConvert.DeserializeObject<T>(string value) and it throws an exception; 我只是使用Newtonsoft.Json T JsonConvert.DeserializeObject<T>(string value) ,它会引发异常。

If I use the object JsonConvert.DeserializeObject(string value) this one it creates the correct object by simply placing the missing }] 如果我使用object JsonConvert.DeserializeObject(string value) ,则只需放置缺少的}]即可创建正确的对象

I found that this is a very reliable and fast library. 我发现这是一个非常可靠且快速的库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM