问题
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