JSON data validation in C#

Validate JSON data with C# in .NET framework 4

  • Share

JSON is slowly but certainly taking over the throne of XML. It is much lighter, a lot easier to deserialize, but still there are some features that XML is better in.

One of these is validation. XML has XSD schema validation support so it is very easy to validate the XML data against XSD schema.

I've been recently working on an application which heavily relies on JSON. What I needed is something like XSD but for JSON. After some time Googling around I found that there is something called JSON schema and that there are actually libraries for handling this schema and validation of JSON at against it in C#.

How ever, to be honest, I do not like it at all. Imagine, you have to define your rules fr validation in plain text. It is really hard to define a complex schema for something like this.

Instead of doing this, it got to my mind to use built in validation attributes which I used for MVC websites and WebAPI services. Of course, this approach is only to validate well formad JSON data structure. In case of invalid JSON string you parser, whether you use Json.Net or native .NET classes will either throw an exception or in best case will not create instance or leave the property empty or with default value.

Using model validaton in MVC is easy, but it is not any more difficult than using it in any other type of application. All you need to do is to add the reference to System.ComponentModel.DataAnnotations and you can start using Model or POCO class validation in you application.

The approach is pretty much the same as with MVC application. Firts you need to add attributes to your model or POCO classs

using System;
using System.ComponentModel.DataAnnotations;

namespace ModelValidation
{
    public class SampleModel
    {
        [Required(ErrorMessage = "Id is required")]
        [Range(1, int.MaxValue)]
        public int Id { get; set; }

        [Required]
        [EmailAddress(ErrorMessage = "Invalid email address")]
        public string Email { get; set; }

        [MaxLength(255, ErrorMessage = "Comment too long")]
        public string Comment { get; set; }
    }
}

    

The actual validation is done by ValidationContext class instance. This instance will create the context for our model and prepare it for validation. After instatiating, simple validation method call can be done.

        private static bool IsModelValid(object model)
        {
            var validationContext = new ValidationContext(model, null, null);
            return Validator.TryValidateObject(model, validationContext, null, true);
        }
    

For the sake of simplicity, I created a small Console Application sample to demonstrate validation. For the purposes of demo, I created several instances of model and set different property values to them, so I get the different validation results for different property values

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace ModelValidation
{
    class Program
    {
        static void Main(string[] args)
        {
            var InvalidObject = new SampleModel() { Email = "test" };
            Console.WriteLine(IsModelValid(InvalidObject));

            InvalidObject = new SampleModel() { Id = -7, Email = "someone@somewhere.com" };
            Console.WriteLine(IsModelValid(InvalidObject));

            InvalidObject = new SampleModel() { Id = 117, Email = "someone@somewhere.com", Comment = string.Concat(Enumerable.Repeat("*", 500)) };
            Console.WriteLine(IsModelValid(InvalidObject));

            InvalidObject = new SampleModel();
            Console.WriteLine(IsModelValid(InvalidObject));

            var validObject = new SampleModel() { Id = 117, Email = "someone@somewhere.com", Comment = "This is test" };
            Console.WriteLine(IsModelValid(validObject));

            Console.ReadLine();
        }

        private static bool IsModelValid(object model)
        {
            var validationContext = new ValidationContext(model, null, null);
            return Validator.TryValidateObject(model, validationContext, null, true);
        }
    }
}

    

When you run this console application code you will see that only validObject instance returns true when validated as it is the only one that has proper values. Now this code has nothing much to do with JSON as by assumption JSON string was previously parsed to a model instance. This code is not much suitable for usage in code where you deal with JSON string data.

Model Validation

This is the reason why I wrote the following extension which validates JSON string against type which is passed as an instance generic type T. The code is written as an extension method and it extends String with method ValidateModel.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Script.Serialization;

namespace ModelValidation
{
    public static class ValidationExtensions
    {
        public static bool ValidateModel<T>(this string json) where T : new()
        {
            T model = new JavaScriptSerializer().Deserialize<T>(json);
            return ValidateModel<T>(model);
        }

        public static bool ValidateModel<T>(this T model) where T : new()
        {
            var validationContext = new ValidationContext(model, null, null);
            return Validator.TryValidateObject(model, validationContext, null, true);
        }
    }
}

    

This way our validation code is reusable and does not have to be repeated in application anywhere.

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace ModelValidation
{
    class Program
    {
        static void Main(string[] args)
        {
            var InvalidObject = new SampleModel() { Email = "test" };
            Console.WriteLine(InvalidObject.ValidateModel<SampleModel>());

            InvalidObject = new SampleModel() { Id = -7, Email = "someone@somewhere.com" };
            Console.WriteLine(InvalidObject.ValidateModel<SampleModel>());

            InvalidObject = new SampleModel() { Id = 117, Email = "someone@somewhere.com", Comment = string.Concat(Enumerable.Repeat("*", 500)) };
            Console.WriteLine(InvalidObject.ValidateModel<SampleModel>());

            InvalidObject = new SampleModel();
            Console.WriteLine(InvalidObject.ValidateModel<SampleModel>());

            var validObject = new SampleModel() { Id = 117, Email = "someone@somewhere.com", Comment = "This is test" };
            Console.WriteLine(validObject.ValidateModel<SampleModel>());

            Console.ReadLine();
        }

    }
}

    

References

  • Share

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.

Comments for this article

comments powered by Disqus