在反序列化为C#对象之前验证JSON

时间:2014-10-03 21:15:06

标签: c# json serialization javascriptserializer

如果JSON中的JavaScript对象不会反序列化为我想要的C#对象,我如何查询它以提供错误消息来解释输入有什么问题? (假设JSON格式正确,则只是数据无效。)

我的C#课程:(简化)

public class Dependent
{
    public Dependent()
    {
    }
    public string FirstName { get; set; }
    public DateTime DateOfBirth { get; set; }
}

测试反序列化代码:

string dependents = @"[
                            {
                                ""FirstName"": ""Kenneth"",
                                ""DateOfBirth"": ""02-08-2013""
                            },
                            {
                                ""FirstName"": ""Ronald"",
                                ""DateOfBirth"": ""08-07-2011""
                            }
                      ]";

JavaScriptSerializer jss = new JavaScriptSerializer();

List<Dependent> deps = new List<Dependent>();
deps = jss.Deserialize<List<Dependent>>(dependents);

这一切都有效。除非作为生日传递非日期,否则将无法反序列化。

我想提供一条错误消息,例如“Dependent 2出生日期不是有效日期”。或“受抚养人2必须未满18岁”。

如果JSON不会反序列化到我的对象中,如何验证JSON的详细信息?

可能的解决方案:

public class SerializableDependent
{
    public SerializableDependent()
    {
    }
    public string FirstName { get; set; }
    public string DateOfBirth { get; set; }
}

然后我不应该将所有内容都作为字符串得到任何错误,并且我可以遍历对象并进行验证。这似乎不对。

2 个答案:

答案 0 :(得分:2)

JavaScriptSerializer不支持广泛的错误处理。我建议你使用Json.NET library。您可以使用JsonSerializerSettings对象的Error事件处理程序来捕获有关错误的更多详细信息。有关使用此成员的信息存在于documentation中。

对于上面的代码片段,填充错误消息数组的处理程序可以写成如下:

public class Dependent
{
    public Dependent()
    {
    }
    public string FirstName { get; set; }
    public DateTime? DateOfBirth { get; set; } // Use a nullable object to hold the error value
}

void DeserializeTest()
{
   string dependents = @"[
                            {
                                ""FirstName"": ""Kenneth"",
                                ""DateOfBirth"": ""02-08-2013""
                            },
                            {
                                ""FirstName"": ""Ronald"",
                                ""DateOfBirth"": ""asdf""
                            }
                      ]";

    var messages = new List<string>();

    var settings = new JsonSerializerSettings(){
        Error = (s,e)=>{
            var depObj = e.CurrentObject as Dependent;
            if(depObj != null)
            {
                messages.Add(string.Format("Obj:{0} Message:{1}",depObj.FirstName, e.ErrorContext.Error.Message));
            }
            else 
            {
                messages.Add(e.ErrorContext.Error.Message);
            }
            e.ErrorContext.Handled = true; // Set the datetime to a default value if not Nullable
        }
    };
    var ndeps = JsonConvert.DeserializeObject<Dependent[]>(dependents, settings);
    //ndeps contains the serialized objects, messages contains the errors
}

答案 1 :(得分:1)

您可以使用JSON Schema(Newtonsoft提供的框架)在JSON中验证C#。它允许验证JSON数据。下面的代码说明了它的外观。有关更多详细信息,请阅读文章Validating JSON with JSON Schema in C#

     string myschemaJson = @"{
        'description': 'An employee', 'type': 'object',
        'properties':
        {
           'name': {'type':'string'},
           'id': {'type':'string'},
           'company': {'type':'string'},
           'role': {'type':'string'},
           'skill': {'type': 'array',
           'items': {'type':'string'}
        }
     }";

     JsonSchema schema = JsonSchema.Parse(myschemaJson);

     JObject employee = JObject.Parse(@"{
        'name': 'Tapas', 'id': '12345', 'company': 'TCS',
        'role': 'developer',
        'skill': ['.NET', 'JavaScript', 'C#', 'Angular',
        'HTML']
     }");
     bool valid = employee.IsValid(schema);
     // True

     JsonSchema schema1 = JsonSchema.Parse(myschemaJson);

     JObject employee1 = JObject.Parse(@"{
        'name': null, 'id': '12345', 'company': 'TCS',
        'role': 'developer',
        'skill': ['.NET', 'JavaScript', 'C#', 'Angular',
        'HTML']
     }");

     IList<string> messages;
     bool valid1 = employee1.IsValid(schema1, out messages);
     // False
     // "Invalid type. Expected String but got Null. Line 2,
     // position 24."


     JsonSchema schema2 = new JsonSchema();
     schema2.Type = JsonSchemaType.Object;
     schema2.Properties = new Dictionary<string, JsonSchema>
     {
        { "name", new JsonSchema
           { Type = JsonSchemaType.String } },
        { "id", new JsonSchema
           { Type = JsonSchemaType.String } },
        { "company", new JsonSchema
           { Type = JsonSchemaType.String } },
        { "role", new JsonSchema
           { Type = JsonSchemaType.String } },
        {
           "skill", new JsonSchema
           {
              Type = JsonSchemaType.Array,
              Items = new List<JsonSchema>
                 { new JsonSchema
                    { Type = JsonSchemaType.String } }
           }
        },
     };

     JObject employee2 = JObject.Parse(@"{
        'name': 'Tapas', 'id': '12345',
        'company': 'TCS', 'role': 'developer',
        'skill': ['.NET', 'JavaScript', 'C#', 'Angular',
        'HTML']
     }");
     bool valid2 = employee2.IsValid(schema2);
     // True