GithubHelp home page GithubHelp logo

ricosuter / njsonschema Goto Github PK

View Code? Open in Web Editor NEW
1.4K 33.0 527.0 10.69 MB

JSON Schema reader, generator and validator for .NET

Home Page: http://NJsonSchema.org

License: MIT License

C# 96.91% Liquid 2.71% Batchfile 0.01% PowerShell 0.21% Shell 0.17%

njsonschema's Introduction

NJsonSchema for .NET

NSwag | NJsonSchema | Apimundo | Namotion.Reflection

Azure DevOps Nuget MyGet Discord StackOverflow Wiki Apimundo

NJsonSchema is a .NET library to read, generate and validate JSON Schema draft v4+ schemas. The library can read a schema from a file or string and validate JSON data against it. A schema can also be generated from an existing .NET class. With the code generation APIs you can generate C# and TypeScript classes or interfaces from a schema.

The library uses Json.NET to read and write JSON data and Namotion.Reflection for additional .NET reflection APIs.

NuGet packages:

Preview NuGet Feed: https://www.myget.org/F/njsonschema/api/v3/index.json

Features:

NJsonSchema is heavily used in NSwag, a Swagger API toolchain for .NET which generates client code for Web API services. NSwag also provides command line tools to use the NJsonSchema's JSON Schema generator (command types2swagger).

The project is developed and maintained by Rico Suter and other contributors.

Some code generators can directly be used via the Apimundo service.

NJsonSchema usage

The JsonSchema class can be used as follows:

var schema = JsonSchema.FromType<Person>();
var schemaData = schema.ToJson();
var errors = schema.Validate("{...}");

foreach (var error in errors)
    Console.WriteLine(error.Path + ": " + error.Kind);

schema = await JsonSchema.FromJsonAsync(schemaData);

The Person class:

public class Person
{
    [Required]
    public string FirstName { get; set; }

    public string MiddleName { get; set; }

    [Required]
    public string LastName { get; set; }

    public Gender Gender { get; set; }

    [Range(2, 5)]
    public int NumberWithRange { get; set; }

    public DateTime Birthday { get; set; }

    public Company Company { get; set; }

    public Collection<Car> Cars { get; set; }
}

public enum Gender
{
    Male,
    Female
}

public class Car
{
    public string Name { get; set; }

    public Company Manufacturer { get; set; }
}

public class Company
{
    public string Name { get; set; }
}

The generated JSON schema data stored in the schemaData variable:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "Person",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "FirstName",
    "LastName"
  ],
  "properties": {
    "FirstName": {
      "type": "string"
    },
    "MiddleName": {
      "type": [
        "null",
        "string"
      ]
    },
    "LastName": {
      "type": "string"
    },
    "Gender": {
      "oneOf": [
        {
          "$ref": "#/definitions/Gender"
        }
      ]
    },
    "NumberWithRange": {
      "type": "integer",
      "format": "int32",
      "maximum": 5.0,
      "minimum": 2.0
    },
    "Birthday": {
      "type": "string",
      "format": "date-time"
    },
    "Company": {
      "oneOf": [
        {
          "$ref": "#/definitions/Company"
        },
        {
          "type": "null"
        }
      ]
    },
    "Cars": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/Car"
      }
    }
  },
  "definitions": {
    "Gender": {
      "type": "integer",
      "description": "",
      "x-enumNames": [
        "Male",
        "Female"
      ],
      "enum": [
        0,
        1
      ]
    },
    "Company": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "Name": {
          "type": [
            "null",
            "string"
          ]
        }
      }
    },
    "Car": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "Name": {
          "type": [
            "null",
            "string"
          ]
        },
        "Manufacturer": {
          "oneOf": [
            {
              "$ref": "#/definitions/Company"
            },
            {
              "type": "null"
            }
          ]
        }
      }
    }
  }
}

NJsonSchema.CodeGeneration usage

The NJsonSchema.CodeGeneration can be used to generate C# or TypeScript code from a JSON schema:

var generator = new CSharpGenerator(schema);
var file = generator.GenerateFile();

The file variable now contains the C# code for all the classes defined in the JSON schema.

TypeScript

The previously generated JSON Schema would generate the following TypeScript interfaces.

Settings:

new TypeScriptGeneratorSettings { TypeStyle = TypeScriptTypeStyle.Interface, TypeScriptVersion = 2.0m }

Output:

export enum Gender {
    Male = 0, 
    Female = 1, 
}

export interface Company {
    Name: string | undefined;
}

export interface Car {
    Name: string | undefined;
    Manufacturer: Company | undefined;
}

export interface Person {
    FirstName: string;
    MiddleName: string | undefined;
    LastName: string;
    Gender: Gender;
    NumberWithRange: number;
    Birthday: Date;
    Company: Company | undefined;
    Cars: Car[] | undefined;
}

... and the following TypeScript classes.

Settings:

new TypeScriptGeneratorSettings { TypeStyle = TypeScriptTypeStyle.Class, TypeScriptVersion = 2.0m }

Output:

export enum Gender {
    Male = 0, 
    Female = 1, 
}

export class Company implements ICompany {
    name: string | undefined;

    constructor(data?: ICompany) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (<any>this)[property] = (<any>data)[property];
            }
        }
    }

    init(data?: any) {
        if (data) {
            this.name = data["Name"];
        }
    }

    static fromJS(data: any): Company {
        let result = new Company();
        result.init(data);
        return result;
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        data["Name"] = this.name;
        return data; 
    }
}

export interface ICompany {
    name: string | undefined;
}

export class Car implements ICar {
    name: string | undefined;
    manufacturer: Company | undefined;

    constructor(data?: ICar) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (<any>this)[property] = (<any>data)[property];
            }
        }
    }

    init(data?: any) {
        if (data) {
            this.name = data["Name"];
            this.manufacturer = data["Manufacturer"] ? Company.fromJS(data["Manufacturer"]) : <any>undefined;
        }
    }

    static fromJS(data: any): Car {
        let result = new Car();
        result.init(data);
        return result;
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        data["Name"] = this.name;
        data["Manufacturer"] = this.manufacturer ? this.manufacturer.toJSON() : <any>undefined;
        return data; 
    }
}

export interface ICar {
    name: string | undefined;
    manufacturer: Company | undefined;
}

export class Person implements IPerson {
    firstName: string;
    middleName: string | undefined;
    lastName: string;
    gender: Gender;
    numberWithRange: number;
    birthday: Date;
    company: Company | undefined;
    cars: Car[] | undefined;

    constructor(data?: IPerson) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (<any>this)[property] = (<any>data)[property];
            }
        }
    }

    init(data?: any) {
        if (data) {
            this.firstName = data["FirstName"];
            this.middleName = data["MiddleName"];
            this.lastName = data["LastName"];
            this.gender = data["Gender"];
            this.numberWithRange = data["NumberWithRange"];
            this.birthday = data["Birthday"] ? new Date(data["Birthday"].toString()) : <any>undefined;
            this.company = data["Company"] ? Company.fromJS(data["Company"]) : <any>undefined;
            if (data["Cars"] && data["Cars"].constructor === Array) {
                this.cars = [];
                for (let item of data["Cars"])
                    this.cars.push(Car.fromJS(item));
            }
        }
    }

    static fromJS(data: any): Person {
        let result = new Person();
        result.init(data);
        return result;
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        data["FirstName"] = this.firstName;
        data["MiddleName"] = this.middleName;
        data["LastName"] = this.lastName;
        data["Gender"] = this.gender;
        data["NumberWithRange"] = this.numberWithRange;
        data["Birthday"] = this.birthday ? this.birthday.toISOString() : <any>undefined;
        data["Company"] = this.company ? this.company.toJSON() : <any>undefined;
        if (this.cars && this.cars.constructor === Array) {
            data["Cars"] = [];
            for (let item of this.cars)
                data["Cars"].push(item.toJSON());
        }
        return data; 
    }
}

export interface IPerson {
    firstName: string;
    middleName: string | undefined;
    lastName: string;
    gender: Gender;
    numberWithRange: number;
    birthday: Date;
    company: Company | undefined;
    cars: Car[] | undefined;
}

Final notes

Applications which use the library:

njsonschema's People

Contributors

alb3ric avatar arogldarthu avatar changethecode avatar cortex93 avatar danzel avatar davidmbillie avatar deceptivesimplicity avatar em1ss1on avatar emilw avatar ili avatar jkonecki avatar kkolstad avatar lahma avatar lheiskan avatar markledwich2 avatar maxdeg avatar paul183425 avatar paulomorgado avatar pekspro avatar ricosuter avatar rogerbramon avatar samuron avatar sumo-mbryant avatar testfirstcoder avatar thebestnom avatar trejjam avatar twodogmbh avatar unchase avatar z16 avatar zehelein avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

njsonschema's Issues

Use default value in code generators

Only applicable for CSharp (TS generates only interfaces):

[DefaultValue(5)]            
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public int Age { get; private set; }

or

public int Age { get; private set; } = 5;

Whats better?

DateParseHandling.DateTimeOffset leads to exceptions during schema validation.

When using DateParseHandling.DateTimeOffset (rather than the lossy default DateParseHandling.DateTime) in Newtonsoft.Json, validating the data against an NJsonSchema.JsonSchema4 results in an InvalidCastException in JsonSchemaValidator.ValidateString.

Attached are two patches: one addition to the UnitTests to demonstrate the problem and one very small one to the JsonSchemaValidator that fixes the problem.

DateTimeOffset-patches.zip

consider reading schema from a external file

Hi Rico Suter,

I have gone through the provided Demo and Tests of NJsonSchema.Codegeneration . I have found only the following two ways -

  1. From JSon data
  2. From C# Type

But are you supporting reading json schema from external file ? If not will you be able to consider this ?

Thanks,
Vijay.

Issue with spinal casing when using NSwag

My urls use spinal casing but when a method is generated in my typescript, ConvertToLowerStartIdentifier and ConvertToUpperStartIdentifier in GeneratorBase only take spaces into consideration. It should replaces dashes with underscores or camel case the value since dashes would break the typescript.

I'm not sure if this belongs here or as an override in ClientGeneratorBase in NSwag.

FlattenInheritanceHierarchy option in generation settings not working

Using version 2.26.5992.40823 from nuget.

JsonSchemaGeneratorSettings settings = new NJsonSchema.Generation.JsonSchemaGeneratorSettings();
settings.DefaultEnumHandling = NJsonSchema.EnumHandling.String;
settings.FlattenInheritanceHierarchy = true;

var generator = new JsonSchemaGenerator(settings);

var schema = JsonSchema4.FromType(typeof(oneofmytypes);
return schema.ToJson();

The generated schema:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "typeName": "OutgoingRemoteInfoserverDto",
    "additionalProperties": false,
    "properties": {
        "RemoteChannelIdentifier": {
            "type": ["null",
            "string"]
        }
    },
    "allOf": [{
        "type": "object",
        "typeName": "OutgoingHttpDto",
        "additionalProperties": false,
        "required": ["Timeout",
        "EndPoint",
        "RetryOnServerError"],
        "properties": {
            "Timeout": {
                "type": "integer",
                "maximum": 1200.0,
                "minimum": 30.0
            },
            "EndPoint": {
                "type": "string"
            },
            "RetryOnServerError": {
                "type": "boolean"
            }
        },
        "allOf": [{
            "type": "object",
            "typeName": "ChannelBaseDto",
            "additionalProperties": false,
            "required": ["Title"],
            "properties": {
                "ChannelTypeName": {
                    "type": ["null",
                    "string"]
                },
                "ChannelTypeInfo": {
                    "type": ["null",
                    "string"]
                },
                "ID": {
                    "type": ["null",
                    "string"]
                },
                "OwnerBoxId": {
                    "type": "integer"
                },
                "Title": {
                    "type": "string"
                },
                "Comment": {
                    "type": ["null",
                    "string"]
                },
                "Status": {
                    "type": ["null",
                    "string"]
                },
                "Interval": {
                    "type": "integer"
                },
                "IntervalUnit": {
                    "type": ["null",
                    "string"]
                },
                "DateTimeStart": {
                    "type": "string",
                    "format": "date-time"
                },
                "DateTimeStop": {
                    "type": "string",
                    "format": "date-time"
                },
                "DateTimeCreated": {
                    "type": "string",
                    "format": "date-time"
                },
                "DateTimeLastChanged": {
                    "type": "string",
                    "format": "date-time"
                },
                "TemporaryFolderName": {
                    "type": ["null",
                    "string"]
                }
            },
            "allOf": [{
                "type": "object",
                "typeName": "DtoBase",
                "additionalProperties": false
            }]
        }]
    }]
}

shouldnt all properties (including properties for base type) be at the "properties" level?

Support allOf with code generator

Sample JSON (single inheritance, properties defined in allOf):

"Pet": {
  "type": "object",
  "allOf": [
    {
      "$ref": "#/definitions/NewPet"
    },
    {
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        }
      }
    }
  ]
},
"NewPet": {
  "type": "object",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "type": "string"
    },
    "tag": {
      "type": "string"
    }
  }
},

Should generate in TypeScript:

export interface Pet implements NewPet {
         id: integer; 
}

export interface NewPet {
    name: string;
    tag?: string;
}

Not able to use JsonSchema4.FromType with System.Type property in target class

Steps to reproduce:

  1. Use code snippet from Readme.md
  2. Add to Person class property with type System.Type. Please find screenshot below
    http://take.ms/rrUaH

Actual result:
System.InvalidOperationException : Could not find item type of array type 'System.Security.Policy.Evidence'.
at NJsonSchema.JsonSchemaGenerator.Generate(TypeΒ type,Β IEnumerable1Β attributes,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 110 at NJsonSchema.JsonSchemaGenerator.LoadProperty(PropertyInfoΒ property,Β TSchemaTypeΒ parentSchema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 276 at NJsonSchema.JsonSchemaGenerator.GeneratePropertiesAndInheritance(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 205 at NJsonSchema.JsonSchemaGenerator.GenerateObject(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 199 at NJsonSchema.JsonSchemaGenerator.Generate(TypeΒ type,Β IEnumerable1Β attributes,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 100
at NJsonSchema.JsonSchemaGenerator.LoadProperty(PropertyInfoΒ property,Β TSchemaTypeΒ parentSchema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 276
at NJsonSchema.JsonSchemaGenerator.GeneratePropertiesAndInheritance(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 205
at NJsonSchema.JsonSchemaGenerator.GenerateObject(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 199
at NJsonSchema.JsonSchemaGenerator.Generate(TypeΒ type,Β IEnumerable1Β attributes,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 100 at NJsonSchema.JsonSchemaGenerator.LoadProperty(PropertyInfoΒ property,Β TSchemaTypeΒ parentSchema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 276 at NJsonSchema.JsonSchemaGenerator.GeneratePropertiesAndInheritance(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 205 at NJsonSchema.JsonSchemaGenerator.GenerateObject(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 199 at NJsonSchema.JsonSchemaGenerator.Generate(TypeΒ type,Β IEnumerable1Β attributes,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 100
at NJsonSchema.JsonSchemaGenerator.Generate(TypeΒ type,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 53
at NJsonSchema.JsonSchemaGenerator.GenerateInheritance(TypeΒ type,Β JsonSchema4Β schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 220
at NJsonSchema.JsonSchemaGenerator.GeneratePropertiesAndInheritance(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 209
at NJsonSchema.JsonSchemaGenerator.GenerateObject(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 199
at NJsonSchema.JsonSchemaGenerator.Generate(TypeΒ type,Β IEnumerable1Β attributes,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 100 at NJsonSchema.JsonSchemaGenerator.LoadProperty(PropertyInfoΒ property,Β TSchemaTypeΒ parentSchema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 276 at NJsonSchema.JsonSchemaGenerator.GeneratePropertiesAndInheritance(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 205 at NJsonSchema.JsonSchemaGenerator.GenerateObject(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 199 at NJsonSchema.JsonSchemaGenerator.Generate(TypeΒ type,Β IEnumerable1Β attributes,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 100
at NJsonSchema.JsonSchemaGenerator.LoadProperty(PropertyInfoΒ property,Β TSchemaTypeΒ parentSchema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 276
at NJsonSchema.JsonSchemaGenerator.GeneratePropertiesAndInheritance(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 205
at NJsonSchema.JsonSchemaGenerator.GenerateObject(TypeΒ type,Β TSchemaTypeΒ schema,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 199
at NJsonSchema.JsonSchemaGenerator.Generate(TypeΒ type,Β IEnumerable`1Β attributes,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 100
at NJsonSchema.JsonSchemaGenerator.Generate(TypeΒ type,Β ISchemaResolverΒ schemaResolver) in C:\projects\njsonschema\src\NJsonSchema\JsonSchemaGenerator.cs: line 53
at NJsonSchema.JsonSchema4.FromType(JsonSchemaGeneratorSettingsΒ settings) in C:\projects\njsonschema\src\NJsonSchema\JsonSchema4.cs: line 71
at NJsonSchema.JsonSchema4.FromType() in C:\projects\njsonschema\src\NJsonSchema\JsonSchema4.cs: line 53

Extensibility issue

Hey, I would like to know if there is any way to add custom extension data to a property (i.e "sortable : true") to JSchema4 object?

Support customizing the generated property and type names

It would be nice if there was a way to (optionally) customize the names for generated properties and types. For instance, we could add few optional generator settings that would allow passing in lambdas for customizing the naming. Lambdas would receive the type|property name from json schema as input, and return the name to use in the generated code. Something like this:

            Func<string, string> namingTransform = (name) => {
                // some_name-b64  ==> SomeName_b64
                var components = name.Split('_');
                var transformedComponents =  components
                        .Select((c) => c.First().ToString().ToUpperInvariant() + c.Substring(1))
                        .Select((c) => c.Replace("-", "_"));
                return string.Join("", transformedComponents);
            };
            var settings = new CSharpGeneratorSettings() {
                    ClassStyle = CSharpClassStyle.Poco,
                    PropertyNameFun = namingTransform, 
                    TypeNameTransformFun = namingTransform 
            };

So given schema

        {
                '$schema': 'http://json-schema.org/draft-04/schema#',
                'id': 'http://domain.name.com/foo.json#',
                'type': 'object',
                'additionalProperties': false,
                'properties': {
                    'foo_bar-b64': {
                        'type': 'string'
                     }
                }
         }

Generated code would end up looking something like this

    public class Foo {
        public string FooBar_b64 {get;set;}
    }

Date format & Pattern is not getting matched.

Hi,
Below data is valid for given schema but we are getting pattern mismatch error.
Sample Schema

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "properties": {
        "SimpleDate": {
             "type": "string",
              "format": "date-time"
          },
        "PatternDate": {
            "type": "string",
            "pattern" : "(^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}Z$|^$)"
        }
    }
}

Sample Data

{
  "SimpleDate":"2012-05-18T00:00:00Z",
  "PatternDate":"2012-11-07T00:00:00Z"
}

Here I found two issues.

  1. If SimpleDate format is "date" then, it should accept only "2015-05-18" & not "2012-05-18T00:00:00Z".
  2. Even if the PatternDate value is matching to the PatternDate schema. it is throw PatternMismatch error.

tried to verify it with
http://www.jsonschemavalidator.net/
it does not return any validation error.

NSwag: ResponseType WebAPI Annotation - List support C#

I have an endpoint which returns a list of objects in the HttpResponseMessage body. It would be nice to be able to set the ResponseType attribute to a List of objects, like in the snippet below.
[ResponseType(List<object>)]

Sorry, if I missed something when reading the docs, but I am not sure how to get around this issue.

Getting Too Many Properties In Tuple error.

When validating the Json schema against an mvc model, it get the error 'Too Many Properties In Tuple" and the path and property get set to null which errors out my code with "Cannot perform runtime binding on a null reference". Amy ideas on what causes this?

.NET 4.0 Support

Hi all,

I want to use the library for a project running on .NET 4.0 and we are using VS 2010.
Is there any possibility to use the library under this circumstances?

GetXmlDocumentationPath

Any chance this can scan the bin folder for XML files?

private static string GetXmlDocumentationPath(dynamic assembly)
 {
        var assemblyName = assembly.GetName();
        var path = DynamicPathCombine(DynamicPathGetDirectoryName(assembly.Location), assemblyName.Name + ".xml");
         if (DynamicFileExists(path))
               return path;

         dynamic currentDomain = Type.GetType("System.AppDomain").GetRuntimeProperty("CurrentDomain").GetValue(null);
         path = DynamicPathCombine(currentDomain.BaseDirectory, assemblyName.Name + ".xml");
         if (DynamicFileExists(path))
                    return path;

         // ADD THIS
         path = DynamicPathCombine(currentDomain.BaseDirectory + "bin", assemblyName.Name + ".xml");
         return path;
}

Schema4.Items not working as expected

NJsonSchemaItemsTest.zip
Attached is a recursive test that compares how NewtonSoft can get hold of all Properties and Items for a given Schema, while NJsonSchema does not get the Items' properties...

Schema:

{
  "typeName": "ClassRoom",
  "additionalProperties": false,
  "type": "object",
  "required": [
    "Id"
  ],
  "properties": {
    "Id": {
      "type": "integer"
    },
    "Name": {
      "type": "string"
    },
    "Size": {
      "type": [ "integer", "null" ]
    },
    "Students": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "Age": {
            "type": [ "integer", "null" ]
          },
          "Name": {
            "type": [ "string", "null" ]
          }
        }
      }
    }
  },
  "$schema": "http://json-schema.org/draft-04/schema#"
}

Output of the test:

NJsonSchema - Properties >> Items:
NJsonSchema Property: Id
NJsonSchema Property: Name
NJsonSchema Property: Size
NJsonSchema Property: Students

Newtonsoft.Json.Schema - Properties >> Items:
Newtonsoft Property: Id
Newtonsoft Property: Name
Newtonsoft Property: Size
Newtonsoft Property: Students
*Newtonsoft Item:  |
Newtonsoft Property: Age
Newtonsoft Property: Name*

Properties in base classes are not flattened - Properties are always included even if that DataMember attributes are not in place

http://stackoverflow.com/questions/36731101/how-to-make-sure-that-njsonschema-only-includes-required-fields

There should be only one schema route, to the outside world is does not matter how a domain class looks like.

                var requiredAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RequiredAttribute");
                var jsonPropertyAttribute = property.GetCustomAttribute<JsonPropertyAttribute>();

                var hasJsonNetAttributeRequired = jsonPropertyAttribute != null && (
                    jsonPropertyAttribute.Required == Required.Always ||
                    jsonPropertyAttribute.Required == Required.AllowNull);

                var hasRequiredAttribute = requiredAttribute != null;
                if (hasRequiredAttribute || hasJsonNetAttributeRequired)
                    parentSchema.RequiredProperties.Add(propertyName);

                var isJsonNetAttributeNullable = jsonPropertyAttribute != null && jsonPropertyAttribute.Required == Required.AllowNull;

                var isNullable = propertyTypeDescription.IsAlwaysRequired == false;
                if (!hasRequiredAttribute && (isNullable || isJsonNetAttributeNullable))
                    jsonProperty.Type = jsonProperty.Type | JsonObjectType.Null;

                dynamic readOnlyAttribute = TryGetAttribute(attributes, "System.ComponentModel.ReadOnlyAttribute");
                if (readOnlyAttribute != null)
                    jsonProperty.IsReadOnly = readOnlyAttribute.IsReadOnly;

                jsonProperty.Description = GetDescription(property, attributes);

                ApplyPropertyAnnotations(jsonProperty, attributes, propertyTypeDescription);`

If a property is not required why is the ApplyPropertyAnnotations still executed?

Not able to use JsonSchema4.FromType on UWP

The static initialization of XpathExtensionsType in FullDotNetMethods throws a TypeInitializationException when used in a UWP app. This can be solved using a static constructor and a try/catch, but I wanted to make sure if this is reproducible and I'm not missing anything.

Thanks.

Incorrect handling of concrete IEnumerable types - they have "type:object", not "type:array"

Firstly, thankyou for building such an awesome tool πŸ‘

I've just found a couple of edge-cases that it would be awesome if you could fix :)

Consider the following code:

public class ArrayModel<T> : IEnumerable<T>
{
    public IEnumerator<T> GetEnumerator() { return null; }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
<SNIP>
Console.WriteLine(JsonSchema4.FromType(typeof(ArrayModel<string>)).ToJson());

This will print the correct JSON schema:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "array",
  "items": {
    "type": "string"
  }
}

However, there are a couple of ways we can change this that won't generate the correct schema:

BROKEN 1

If we make the type of the IEnumerable concrete

public class ArrayModel : IEnumerable<string>
{
    public IEnumerator<string> GetEnumerator() { return null; }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
<SNIP>
Console.WriteLine(JsonSchema4.FromType(typeof(ArrayModel)).ToJson());

we find it doesn't print the type of the array items

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "array",
  "items": {} // Missing type in here.
}

BROKEN 2

Inheriting from a concrete type like List

public class ArrayModel<T> : List<T>
{
}
<SNIP>
Console.WriteLine(JsonSchema4.FromType(typeof(ArrayModel<string>)).ToJson());

produces

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object", // It is treating this as an object, not an array. 
                             // Note that generating from List<string> works correctly.
  "x-typeName": "ArrayModelString",
  "additionalProperties": false,
  "allOf": [
    {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  ]
}

Document supported attributes

public class Model
{
    [JsonProperty("key")]
    [Display(Description = "Some description")]
    public int Key { get; set; }

    [JsonProperty("value")]
    public string Value { get; set; }
}
var schema = JsonSchema4.FromType<Model>();
Console.WriteLine(schema.ToJson());
{
  "typeName": "Model",
  "additionalProperties": false,
  "type": "object",
  "required": [
    "key"
  ],
  "properties": {
    "key": {
      "type": "integer"
    },
    "value": {
      "type": "string"
    }
  },
  "$schema": "http://json-schema.org/draft-04/schema#"
}

Add enumNames property

Add enumNames property, set in schema gen and use in code gen...
Also add StringEnumConverter to string enum properties (C#)...
EnumHandling.Integer should create int enum properties.
(Maybe set default enum handling to integer)

LoadEnumerations throws an exception when an enum inherits from byte

When an enum which inherits from byte is loaded, the code throws and exeption.

Example:

public enum PermissionFlags : byte
    {
        Create  = 0x01,
        Read    = 0x02,
        Update  = 0x04,
        Delete  = 0x08,
    }

The exception occurs in NJsonSchema (line 248 of JsonScheamGenerator.cs)

var value = (int) Enum.Parse(type, enumName);

"Specified cast is not valid" is the exception

Bug: type array with more than 1 primitive type does not validate correctly

A property schema with a Type that encompasses more than 1 primitive type never validates successfully. Reproducible by adding the following unit test to ObjectValidationTests.cs:

[TestMethod]
public void When_property_matches_one_of_the_types_then_it_should_succeed()
{
    //// Arrange
    var schema = new JsonSchema4();
    schema.Type = JsonObjectType.Object;
    schema.Properties["Foo"] = new JsonProperty
    {
        Type = JsonObjectType.Number | JsonObjectType.Null
    };

    var token = new JObject();
    token["Foo"] = new JValue(5);

    //// Act
    var errors = schema.Validate(token);

    //// Assert
    Assert.AreEqual(0, errors.Count());
}

The errors collection will, in fact, contain 2 NullExpected errors

Support for DefaultValue attribute

Your component is a very good contribution to the community. I've testet it out now and things look great. For now all I miss is support for "default" :) Could you add support for this?

It would be nice to have it through the System.ComponentModel.DefaultValueAttribute

public List<string> operators { get; set; } is causing validation errors

I'm generating a json schema from a class and everything works except: public Dictionary<string, object> values { get; set; }.

For some reason it converts it to:

"values": { "type": [ "null", "object" ], "additionalProperties": { "type": "object" } },.

What the json should look like is this:

"values": { "employee Only": "Employee Only", "employee and Spouse": "Employee and Spouse", "employee and Children": "Employee and Children", "employee and Family": "Employee and Family" }

This is causing an error to be thrown when it shouldn't.

If you want me to post the fully convert Json Schema, I can but it is quite long. Hopefully this makes sense. I'm thinking the "additionalProperties" is what is causing the error. Am I doing something wrong maybe?

Modify format based on custom DataType attribute

Hi,
First of all thanks for a great product.
I'm using this with jdorn/json-editor. This editor uses format elements to describe non-standard format requests, such as, for an object, "format": "grid" displaying that object in a grid rather than tabular format.
Currently you output formatting based on data types, ignoring (I think) the DataTypeAttibute.
It would be good to be able to inject specific formatting requirements through the DataType attribute and specifically the datatype.custom type. Perhaps there's another simpler way to do this, but I would like to be able to influence the format elements in a schema by changing the attributes on the class member declarations.

Support for handling different Property Name conventions

When using Json.NET CamelCasePropertyNamesContractResolver the serialized data has camel case property names. However NJsonSchema generates upper-case property names (based on reflection).

It would be beneficial to allow users to control the naming convention of the generated property names.

Suggested solution:

  1. Define enum PropertyNameHandling { Default, CamelCase }
  2. Add a new option DefaultPropertyNameHandling to JsonSchemaGeneratorSettings
  3. Pass the naming convention to Property.GetName()

Add extension to describe generics

In JSON Schema/Swagger/OpenAPI you cannot define generics or templates, see: OAI/OpenAPI-Specification#957

This is a proposal how to implement generics with custom extensions.

Define a schema with generic parameters:

{
    "type": "object",
    "title": "KeyValuePair",  
    "properties": {
        "key": {
            "x-generic": "TKey"
        }, 
        "value": {
            "x-generic": "TValue"
        }
    }
}

Usage of the generic schema in a property:

{
    "properties": {
        "myPairProperty": {
            "x-generics": {
                "TKey": {
                    "type": "string"
                },
                "TValue": {
                    "type": "number"
                }
            }, 
            "oneOf": [
                {
                     "$ref": "#/definitions/KeyValuePair"
                }
            ]
        }
    }
}
  • x-generic defined on JsonProperty: Defines a generic property (if one property has x-generic set, then the property and schema is generic). If the processor understands x-generic, it will ignore all other properties and instead replace the schema with the specified one. Otherwise you can define a default schema for processors which do not support this.
  • x-generics defined on JsonSchema4: Defines the type of the generic parameters (i.e. an instance of the generic schema). If the property schema is generic, then all generic parameters from the generic schema must be defined in x-generics.
    • Update ActualPropertySchema (just for generator): Create copy of generic schema, replace the type parameters, and return it...
  • Update JsonSchemaValidator

It’s important to note that this will only work with the complete NJsonSchema/NSwag toolchain and will probably break or yield wrong results when used with other tools. Ideally we’d also generate a reasonable fallback with eg any typing etc...

Support for nullable Primitives

The schema generated by NJsonSchema doesn't looks like supporting nullable primitive types. Instead the schema looks similar to that of non-nullable types, for example int, datetime & string. This is a feature request.

Option to flatten inheritance hierarchy

Add an option to flatten the inheritance hierarchy when generating JSON Schema from a type:

public class AA
{
    public string FirstName { get; set; }
}

public class BB : AA
{
    public string LastName { get; set; }
}

public class CC : BB
{
    public string Address { get; set; }
}

Currently converts to:

{
  "typeName": "CC",
  "additionalProperties": false,
  "type": "object",
  "properties": {
    "Address": {
      "type": "string"
    }
  },
  "allOf": [
    {
      "typeName": "BB",
      "additionalProperties": false,
      "type": "object",
      "properties": {
        "LastName": {
          "type": "string"
        }
      },
      "allOf": [
        {
          "typeName": "AA",
          "additionalProperties": false,
          "type": "object",
          "properties": {
            "FirstName": {
              "type": "string"
            }
          }
        }
      ]
    }
  ],
  "$schema": "http://json-schema.org/draft-04/schema#"
}

And with this new option to:

{
  "typeName": "CC",
  "additionalProperties": false,
  "type": "object",
  "properties": {
    "Address": {
      "type": "string"
    },
    "LastName": {
      "type": "string"
    },
    "FirstName": {
      "type": "string"
    }
  }
}

Do not generate optional properties in TypeScript

Is it ok if I remove all ? on the generated interface properties? We just had a bug, where the interface was:

interface Person {
     parents: Person[];
}

And someone forgot the "s" postfix:

var x = <Person>{
    parent: { ... }
}

Which didn't yield a compiler error because the parents property is optional...
This is why I want to completely avoid ? (all TS properties are nullable anyways).

What do you think?

Filed not letting me have null and expects an object.

Whenever I use something like:

public QueryRule ReportRules { get; set; } or public Validation validation { get; set; }

it won't let it be null, it errors out expecting an object even though I've not set it to required and I need to be able to let the value be null and not have to put an empty object in it's place. have you encountered this before as well?

Date handling: Add support for moment.js and string

Changes:

  • Add generator option/setting
  • ConvertToClassTemplate: Replace "new Date()" with correct code (depending on setting)
  • ConvertToJavaScriptTemplate: Replace "toISOString()" with correct code (depending on setting)

Need schema validation for an object

In my c# I have a public object value { get; set; } and in my json I have a key value pair where the key will always be a string but the value might be an integer, boolean or string so i cannot implicity set this as one of those three in the model. I need it to be flexible. For some reason the schema errors out with object expected. How can i get around this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.