Validating JSON before deserializing into C# object

我的梦境 提交于 2020-01-03 03:59:06

问题


If a JavaScript object in JSON is not going to deserialize into the C# object I want, how can I interrogate it to provide an error message explaining what is wrong with the input? (Assuming the JSON format is correct, just the data is not valid.)

My C# class: (simplified)

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

Test code to deserialize:

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

This all works. EXCEPT if a non-date is passed in as the birthday, it will fail to deserialize.

I want to provide an error message like "Dependent 2 date of birth is not a valid date." or "Dependent 2 must be under age 18."

How can I validate the details of the JSON if it won't deserialize into my object?

Possible solution:

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

And then I should not get any errors having everything as a string, and I can loop through the objects and do my validation. This seems wrong though.


回答1:


JavaScriptSerializer does not support extensive error handling. I suggest you use the Json.NET library. You can use the JsonSerializerSettings object's Error event handler to capture more details on what went wrong. Information on using this member is present in the documentation.

For your above code snippet, a handler which populates an array of error messages can be written as follows:

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
}



回答2:


You can validate JSON in C# using JSON Schema (framework provided by Newtonsoft). It allows to validate JSON data. Below is the code illustrating how it looks like. For more details you could read the article 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


来源:https://stackoverflow.com/questions/26186892/validating-json-before-deserializing-into-c-sharp-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!