3

I am writing test automation against a RESTful web service (JSON payload) in .NET and would like to validate that the objects sent to me have exactly the fields in a DTO I define, not more or less.

However, it seems that the serialization method I am using (System.Web.Script.Serialization) doesn't mind when object types don't match.

    private class Dog
    {
        public string name;
    }
    private class Cat
    {
        public int legs;
    }
    static void Main(string[] args)
    {
        var dog = new Dog {name = "Fido"};
        var serializer = new JavaScriptSerializer();
        String jsonString = serializer.Serialize(dog);
        var deserializer = new JavaScriptSerializer();
        Cat cat = (Cat)deserializer.Deserialize(jsonString, typeof(Cat)); 
        //No Exception Thrown! Cat has 0 legs.
    }

Is there a .NET serialization library that supports this requirement? Other approaches?

Callagan
  • 35
  • 7

1 Answers1

3

You can solve this problem using JSON Schema validation. The easiest way to do this is by using the schema reflection feature of Json.NET, like so:

using System.Diagnostics;
using Newtonsoft.Json;
using Newtonsoft.Json.Schema;

public class Dog
{
    public string name;
}

public class Cat
{
    public int legs;
}

public class Program
{
    public static void Main()
    {
        var dog = new Dog {name = "Fido"};

        // Serialize the dog
        string serializedDog = JsonConvert.SerializeObject(dog);

        // Infer the schemas from the .NET types
        var schemaGenerator = new JsonSchemaGenerator();
        var dogSchema = schemaGenerator.Generate(typeof (Dog));
        var catSchema = schemaGenerator.Generate(typeof (Cat));

        // Deserialize the dog and run validation
        var dogInPotentia = Newtonsoft.Json.Linq.JObject.Parse(serializedDog);

        Debug.Assert(dogInPotentia.IsValid(dogSchema));
        Debug.Assert(!dogInPotentia.IsValid(catSchema));

        if (dogInPotentia.IsValid(dogSchema))
        {
            Dog reconstitutedDog = dogInPotentia.ToObject<Dog>();
        }
    }
}

You can find more general info on the feature here.

Amy Sutedja
  • 432
  • 2
  • 9