21

I am using JSON.NET to generate JSON Schema from c# object class. But I was unable to add any other json schema attributes e.g. maxLength, pattern(regex to validate email), etc

Below is my working code, I can only generate json schema with required attribute. It would be great if anyone can post some code example about how to add those extra attribute for json schema.

Thanks,

my code example

public class Customer
{
    [JsonProperty(Required = Required.Always)]
    public int CustomerID { get; set; }

    [JsonProperty(Required = Required.Always)]
    public string FirstName { get; set; }

    [JsonProperty(Required = Required.Always)]
    public string LastName { get; set; }

    [JsonProperty(Required = Required.Always)]
    public string Email { get; set; }

    [JsonProperty(Required = Required.AllowNull)]
    public string Phone { get; set; }
}

to

{
    "title" : "Customer",
    "type" : "object",
    "properties" : {
        "CustomerID" : {
            "required" : true,
            "type" : "integer"
        },
        "FirstName" : {
            "required" : true,
            "type" : "string"
        },
        "LastName" : {
            "required" : true,
            "type" : "string"
        },
        "Email" : {
            "required" : true,
            "type" : "string"
        },
        "Phone" : {
            "required" : true,
            "type" : [
                "string",
                "null"
            ]
        }
    }
}
kyrylomyr
  • 12,192
  • 8
  • 52
  • 79
Yoh
  • 211
  • 1
  • 2
  • 3

5 Answers5

16

James Newton-King is right in his answer, I'll just expand it with a code example so people stumbling onto this page don't need to study the whole documentation.

So you can use the attributes provided with .NET to specify those addidional options, like maximum length of the string or allowed regex pattern. Here are some examples:

public class MyDataModel
{
    public enum SampleEnum { EnumPosition1, EnumPosition2, EnumPosition3 }

    [JsonProperty(Required = Required.Always)]
    [RegularExpression(@"^[0-9]+$")]
    public string PatternTest { get; set; }

    [JsonProperty(Required = Required.Always)]
    [MaxLength(3)]
    public string MaxLength3 { get; set; }

    [JsonProperty(Required = Required.AllowNull)]
    [EnumDataType(typeof(SampleEnum))]
    public string EnumProperty { get; set; }
}

The annotations above come from System.ComponentModel.DataAnnotations namespace.

To make those additional attributes affect resulting json schema, you need to use JSchemaGenerator class distributed with Json.NET Schema package. If you use older JsonSchemaGenerator, then some upgrade is needed, as it's now deprecated and does not contain new functions like the aforementioned.

Here's a sample function that generates Json Schema for the class above:

    /// <summary>
    /// Generates JSON schema for a given C# class using Newtonsoft.Json.Schema library.
    /// </summary>
    /// <param name="myType">class type</param>
    /// <returns>a string containing JSON schema for a given class type</returns>
    internal static string GenerateSchemaForClass(Type myType)
    {
        JSchemaGenerator jsonSchemaGenerator = new JSchemaGenerator();
        JSchema schema = jsonSchemaGenerator.Generate(myType);
        schema.Title = myType.Name;

        return schema.ToString();
    }

and you can use it just like this:

 string schema = GenerateSchemaForClass(typeof(MyDataModel));
Community
  • 1
  • 1
Paweł Bulwan
  • 8,467
  • 5
  • 39
  • 50
  • 1
    what about custom attributes? Is there any way to for example get values of customer attribute on a property and add them in the schema of that property? – CageE Mar 29 '21 at 13:41
13

Json.NET Schema now has much improved schema generation support.

You can annotate properties with .NET's Data Annotation attributes to specify information like minimum, maximum, minLength, maxLength and more on a schema.

There is also JSchemaGenerationProvider that lets you take complete control when generating a schema for a type.

More details here: http://www.newtonsoft.com/jsonschema/help/html/GeneratingSchemas.htm

James Newton-King
  • 48,174
  • 24
  • 109
  • 130
  • 1
    Can you help me with what they have mentioned in their licensing for commercial usage? Can we still use this as a free product? http://www.newtonsoft.com/jsonschema#licensing – Rikki Sep 28 '15 at 09:44
  • json-schema is not useful for commercial usage. You have to buy a license from them. I think you better use NJsonSchema, which is MIT: https://github.com/RSuter/NJsonSchema – juFo Nov 29 '17 at 09:48
0

You can create custom JsonConverter something like this. I used reflection to fill out properties.

  public class UserConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var user = (User)value;
        var result = new StringBuilder("{");

        result.Append("title : " + user.GetType().Name + ", ");
        result.Append("properties : {");

        foreach (var prop in user.GetType().GetProperties())
        {
            result.Append(prop.Name + ": {");
            result.Append("value : " + Convert.ToString(prop.GetValue(user, null)) + ", ");

            var attribute = (JsonPropertyAttribute)Attribute.GetCustomAttributes(prop)[0];
            if (attribute.Required == Required.Always)
                result.Append("required : true, ");

            result.Append("type : " + prop.PropertyType.Name.ToLower());
            result.Append(" }");
        }
        writer.WriteValue(result.ToString());
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var user = new User { UserName = (string)reader.Value };

        return user;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(User);
    }

}

[JsonConverter(typeof(UserConverter))]
public class User
{
    [JsonProperty(Required = Required.Always)]
    public string UserName { get; set; }
}

//Run  
string json = JsonConvert.SerializeObject(manager, Formatting.Indented);

Console.WriteLine(json);
sgud
  • 422
  • 2
  • 7
  • This is useful, but I don't think I would add the `JsonConverter` attribute to the class, because then when it comes time to serialize the class with actual data (not the schema), it won't work. Instead, pass an instance of the converter to the `SerializeObject` method when creating the schema. – Brian Rogers Jan 09 '14 at 19:34
-4

You could use the JavaScriptSerializer class.Like:

namespace ExtensionMethods
{
    public static class JSONHelper
    {
        public static string ToJSON(this object obj)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            return serializer.Serialize(obj);
        }

        public static string ToJSON(this object obj, int recursionDepth)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            serializer.RecursionLimit = recursionDepth;
            return serializer.Serialize(obj);
        }
    }
}

Use it like this:

using ExtensionMethods;

...

List<Person> people = new List<Person>{
                   new Person{ID = 1, FirstName = "Scott", LastName = "Gurthie"},
                   new Person{ID = 2, FirstName = "Bill", LastName = "Gates"}
                   };


string jsonString = people.ToJSON();

Read also this articles:

  1. http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
  2. http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick-building-a-tojson-extension-method-using-net-3-5.aspx
  3. http://www.asp.net/AJAX/Documentation/Live/mref/T_System_Web_Script_Serialization_JavaScriptSerializer.aspx

You can also try ServiceStack JsonSerializer

One example to use it:

 var customer = new Customer { Name="Joe Bloggs", Age=31 };
    var json = JsonSerializer.SerializeToString(customer);
    var fromJson = JsonSerializer.DeserializeFromString<Customer>(json); 
Adrian
  • 671
  • 4
  • 17
  • 37
-4
  • first convert you json file in to xml
  • now add xml node that you want to add and convert xml in to json.

This conversion can be easily done by 'newtonsoft.json.jsonconvert' class. To uses this class just import newtonsoft.json dll in your project.

DB5
  • 13,553
  • 7
  • 66
  • 71
  • This is a bad idea. There should not be a need to use XML at all just to create a JSON schema. Plus, structural information can sometimes get lost when converting back and forth from JSON to XML, depending on the situation. – Brian Rogers Jan 09 '14 at 19:30