【问题标题】:ServiceStack.Text json deserialization creates wrong object instead of throwing on invalid json input stringServiceStack.Text json 反序列化创建错误的对象,而不是抛出无效的 json 输入字符串
【发布时间】:2012-04-26 13:34:33
【问题描述】:

当我尝试反序列化这个无效的 json 字符串时(}] 最后缺少):

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

通过这样做:

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

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.

在这种情况下,抛出异常比继续处理错误数据要好得多。因此我尝试使用:

JsConfig.ThrowOnDeserializationError = true; 

就在调用 DeserializeFromString 之前,但没有抛出异常。一月份我问了这个问题Configure ServiceStack.Text to throw on invalid JSON,答案是 ServiceStack 偏爱弹性,我可以在 GitHub 中提出拉取请求。

现在还是这样吗?有没有人已经这样做了,省去了我的麻烦?否则,我的日程安排很紧,所以如果有人对如何创建选项标志以使 ServiceStack 引发反序列化错误有一些代码或建议,请在此处回复,以便我可以更快地完成这项工作。

【问题讨论】:

  • 我看到了您的原始帖子,我同意您至少应该可以选择打开严格的 json 验证。通过切换回 Newtonsoft 序列化程序,我得到了相同的结果。正如我的一所大学指出的那样,如果我们使用弹性序列化,我们将回到允许无错误地解析垃圾 html 的同一条道路上,因为它允许马虎的开发人员。
  • 这看起来像一个错误。你提交an issue for it了吗?

标签: c# json 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】:

    C# 对 JSON 有点挑剔。以下将是有效!注意我没有匿名对象数组作为默认元素。

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

    如果我从中生成 POCO,我会得到 ​​p>

    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】:

      我试过这个,当我最后错过了 } 时抛出了异常。

      在 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);
      

      运行此程序时,您将收到错误,因为缺少 }。

      使用:

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

      对象反序列化很好。

      您可以从以下位置查看此对象的 JSON:

      string s = JsonConvert.SerializeObject(m);
      

      【讨论】:

        【解决方案4】:

        我只是使用Newtonsoft.JsonT JsonConvert.DeserializeObject&lt;T&gt;(string value),它会引发异常;

        如果我使用 object JsonConvert.DeserializeObject(string value) 这个,它会通过简单地放置缺少的 }] 来创建正确的对象

        我发现这是一个非常可靠和快速的库。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-12-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-22
          • 1970-01-01
          相关资源
          最近更新 更多