与简单类型相比,JSON.NET中对象集合的错误处理行为不同

时间:2017-11-10 20:45:51

标签: c# json serialization error-handling json.net

我花了大约一天时间。如果我有一个简单的对象集合,如json中的日期时间,我可以正确地将其反序列化为有效的对象和错误。对一组更复杂的对象使用完全相同的方法会给我带来完全不同的结果:带有问题的一个对象会阻止所有其他对象被正确创建。我已经尝试过各种其他方法,例如使用JsonTextReader来查找json查找对象,但它永远不会超过错误的布尔值' tru'。

基本上我希望能够反序列化所有好的值并跳过坏的值。

我无法在文档中找到有关此行为差异的任何内容。我还查看了各种与解析和处理错误相关的stackoverflow文章,没有运气。非常感谢任何见解。

在此代码中,您可以获得3个良好的日期时间和3个错误。

private void WorkingDeserializer()
{
    List<string> errors = new List<string>();

    List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(
        @"[
        '2009-09-09T00:00:00Z',
        'I am not a date and will error!',
        [
        1
        ],
        '1977-02-20T00:00:00Z',
        null,
        '2000-12-01T00:00:00Z'
        ]",
        new JsonSerializerSettings
        {
            Error = delegate(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
            {
                errors.Add(args.ErrorContext.Error.Message);
                args.ErrorContext.Handled = true;
            } 
        });
}

在此代码中,您不会获得任何有价值的错误

public class FeatureSwitch
{
    public string Name { get; set; }
    public string Description { get; set; }
    public bool Status { get; set; }
}

private void NonWorkingDeserializer()
{
    List<string> errors = new List<string>();

    List<FeatureSwitch> c = JsonConvert.DeserializeObject<List<FeatureSwitch>>(
@"[
    {
        'Name': 'TestSwitch1',
        'Description': 'TestSwitch1_Desc',
        'Status': false
    },
    {
        'Name': 'TestSwitch2',
        'Description': 'bad format',
        'Status': tru
    },
    {
        'Name': 'TestSwitch3',
        'Description': 'should be good',
        'Status': true
    }
]", new JsonSerializerSettings
    {
        Error = delegate(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
        {
            errors.Add(args.ErrorContext.Error.Message);
                       args.ErrorContext.Handled = true;
        }
    });
}

1 个答案:

答案 0 :(得分:3)

这是因为你在第二个例子中使用非法的json语法破坏了json序列化。您没有像第一个示例中那样破坏日期时间或模型的解析。

因此该问题与复杂对象无关。如果您在tru中取NonWorkingDeserializer并将其作为您想要在简单日期时间序列化程序中出错的值之一,则会得到相同的三个错误。错误列表中的三个错误与值tru的位置有关。它们与不工作的反序列化器json字符串中的3个模型对象无关。即使您尝试使用其中10个对象创建一个json字符串,您将获得与值tru相关的3个错误

这是因为您尝试使用损坏的语法反序列化JSON。

JSON中的布尔值语法如下:

它包含真或假值。

var json-object-name = { string : true/false, .......}

您正在使用布尔语法编写json但未提供正确的值

var json-object-name = { string : tru }

字符串的语法如下:

var json-object-name = { string : "string value"}

数组的语法如下:

[ value, .......]

null的语法如下:

null

数字的语法如下:

var obj = {marks: 97}

Json中可用的不同值及其语法:

  • 字符串
  • 数字
  • 对象数组
  • TRUE
  • FALSE
  • NULL

如果你使tru成为一个json字符串'tru',你将得到你想要的解析错误,而不是你得到的破解的json语法错误,例如

List<string> errors = new List<string>();

            List<FeatureSwitch> c = JsonConvert.DeserializeObject<List<FeatureSwitch>>(
        @"[
    {
        'Name': 'TestSwitch1',
        'Description': 'TestSwitch1_Desc',
        'Status': false
    },
    {
        'Name': 'TestSwitch2',
        'Description': 'bad format',
        'Status': 'tru'
    },
    {
        'Name': 'TestSwitch3',
        'Description': 'should be good',
        'Status': true
    }
]", new JsonSerializerSettings
        {
            Error = delegate (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
            {
                errors.Add(args.ErrorContext.Error.Message);
                args.ErrorContext.Handled = true;
            }
        });

这为您提供了一个计数为3的FeatureSwitch列表,它会给您一个错误,因为您没有破坏json本身。

你要做的就是在json字符串中键入一个Lorem Ipsum段落并在那里删除一个有效的json,并期望解串器能够找到你的模型。

e.g。

  List<string> errors = new List<string>();

        List<FeatureSwitch> c = JsonConvert.DeserializeObject<List<FeatureSwitch>>(
    @"[Maecenas nulla mauris, bibendum ac orci ut, consectetur egestas nisl. Morbi purus nibh, consectetur vel aliquet id, dictum vitae ante. 
    Maecenas cursus nunc orci, quis sollicitudin lorem dictum et. In molestie turpis tortor, eget aliquet nunc finibus sed. Proin vel dui nec eros pretium congue.
    Pellentesque vitae tempor dui. Aliquam molestie,
     {
    'Name': 'TestSwitch1',
    'Description': 'TestSwitch1_Desc',
    'Status': false
     }
    dolor nec gravida molestie, felis neque vestibulum lorem, sed tempus arcu ligula at tortor. 
    Duis ac augue tincidunt odio convallis consectetur. Nam blandit mi ac purus convallis vulputate. Proin eget pretium lacus. Lorem ipsum dolor sit amet, 
    consectetur adipiscing elit. Praesent sem ante, gravida et dignissim egestas, commodo tincidunt sapien.]", new JsonSerializerSettings
    {
        Error = delegate (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
        {
            errors.Add(args.ErrorContext.Error.Message);
            args.ErrorContext.Handled = true;
        }
    });