<PackageReference Include="NJsonSchema" Version="11.3.2" />

SampleJsonSchemaGenerator

Generates a JSON Schema from sample JSON data.
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; namespace NJsonSchema { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public class SampleJsonSchemaGenerator { private readonly SampleJsonSchemaGeneratorSettings _settings; public SampleJsonSchemaGenerator() { _settings = new SampleJsonSchemaGeneratorSettings(); } public SampleJsonSchemaGenerator(SampleJsonSchemaGeneratorSettings settings) { _settings = settings; } public JsonSchema Generate(string json) { JToken token = JsonConvert.DeserializeObject<JToken>(json, new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.IsoDateFormat }); JsonSchema jsonSchema = new JsonSchema(); Generate(token, jsonSchema, jsonSchema, "Anonymous"); return jsonSchema; } public JsonSchema Generate(Stream stream) { using (StreamReader reader = new StreamReader(stream)) using (JsonTextReader reader2 = new JsonTextReader(reader)) { JsonSerializer jsonSerializer = JsonSerializer.Create(new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.IsoDateFormat }); JToken token = jsonSerializer.Deserialize<JToken>(reader2); JsonSchema jsonSchema = new JsonSchema(); Generate(token, jsonSchema, jsonSchema, "Anonymous"); return jsonSchema; } } private void Generate(JToken token, JsonSchema schema, JsonSchema rootSchema, string typeNameHint) { if (schema != rootSchema && token.Type == JTokenType.Object) { JsonSchema jsonSchema = null; JObject jObject = token as JObject; if (jObject != null) { IEnumerable<JProperty> properties = jObject.Properties(); jsonSchema = (from t in rootSchema.Definitions select t.Value).FirstOrDefault(delegate(JsonSchema s) { if ((int)s.Type == 32 && properties.Any()) return properties.All((JProperty p) => s.Properties.ContainsKey(p.Name)); return false; }); } if (jsonSchema == null) { jsonSchema = new JsonSchema(); AddSchemaDefinition(rootSchema, jsonSchema, typeNameHint); } schema.Reference = jsonSchema; GenerateWithoutReference(token, jsonSchema, rootSchema, typeNameHint); } else GenerateWithoutReference(token, schema, rootSchema, typeNameHint); } private void GenerateWithoutReference(JToken token, JsonSchema schema, JsonSchema rootSchema, string typeNameHint) { if (token == null) return; switch (token.Type) { case JTokenType.Object: GenerateObject(token, schema, rootSchema); break; case JTokenType.Array: GenerateArray(token, schema, rootSchema, typeNameHint); break; case JTokenType.Date: schema.Type = 64; schema.Format = ((token.Value<DateTime>() == token.Value<DateTime>().Date) ? "date" : "date-time"); break; case JTokenType.String: schema.Type = 64; break; case JTokenType.Boolean: schema.Type = 2; break; case JTokenType.Integer: schema.Type = 4; break; case JTokenType.Float: schema.Type = 16; break; case JTokenType.Bytes: schema.Type = 64; schema.Format = "byte"; break; case JTokenType.TimeSpan: schema.Type = 64; schema.Format = "duration"; break; case JTokenType.Guid: schema.Type = 64; schema.Format = "guid"; break; case JTokenType.Uri: schema.Type = 64; schema.Format = "uri"; break; } if ((int)schema.Type == 64 && Regex.IsMatch(token.Value<string>(), "^[0-2][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$")) schema.Format = "date"; if ((int)schema.Type == 64 && Regex.IsMatch(token.Value<string>(), "^[0-2][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9](:[0-9][0-9])?$")) schema.Format = "date-time"; if ((int)schema.Type == 64 && Regex.IsMatch(token.Value<string>(), "^[0-9][0-9]:[0-9][0-9](:[0-9][0-9])?$")) schema.Format = "duration"; if (_settings.SchemaType != SchemaType.OpenApi3) return; bool flag; if ((int)schema.Type == 4) { long? nullable = token.Value<long?>(); if (nullable.HasValue) { long valueOrDefault = nullable.GetValueOrDefault(); if (valueOrDefault < -2147483648 || valueOrDefault > 2147483647) { flag = true; goto IL_01ea; } } flag = false; goto IL_01ea; } goto IL_0206; IL_01ea: if (flag) schema.Format = "int64"; else schema.Format = "int32"; goto IL_0206; IL_024c: if (flag) schema.Format = "double"; else schema.Format = "float"; return; IL_0206: if ((int)schema.Type != 16) return; double? nullable2 = token.Value<double?>(); if (nullable2.HasValue) { double valueOrDefault2 = nullable2.GetValueOrDefault(); if (valueOrDefault2 < -3.4028234663852886E+38 || valueOrDefault2 > 3.4028234663852886E+38) { flag = true; goto IL_024c; } } flag = false; goto IL_024c; } private void GenerateObject(JToken token, JsonSchema schema, JsonSchema rootSchema) { schema.Type = 32; foreach (JProperty item in ((JObject)token).Properties()) { JsonSchemaProperty jsonSchemaProperty = new JsonSchemaProperty(); string input = (item.Value.Type == JTokenType.Array) ? ConversionUtilities.Singularize(item.Name) : item.Name; string typeNameHint = ConversionUtilities.ConvertToUpperCamelCase(input, true); Generate(item.Value, jsonSchemaProperty, rootSchema, typeNameHint); schema.Properties[item.Name] = jsonSchemaProperty; } } private void GenerateArray(JToken token, JsonSchema schema, JsonSchema rootSchema, string typeNameHint) { schema.Type = 1; List<JsonSchema> list = ((JArray)token).Select(delegate(JToken item) { JsonSchema jsonSchema = new JsonSchema(); GenerateWithoutReference(item, jsonSchema, rootSchema, typeNameHint); return jsonSchema; }).ToList(); if (list.Count == 0) schema.Item = new JsonSchema(); else if ((from s in (IEnumerable<JsonSchema>)list group s by s.Type).Count() == 1) { MergeAndAssignItemSchemas(rootSchema, schema, list, typeNameHint); } else { schema.Item = list.First(); } } private static void MergeAndAssignItemSchemas(JsonSchema rootSchema, JsonSchema schema, List<JsonSchema> itemSchemas, string typeNameHint) { JsonSchema jsonSchema = itemSchemas.First(); JsonSchema jsonSchema2 = new JsonSchema { Type = jsonSchema.Type }; if ((int)jsonSchema.Type == 32) { foreach (IGrouping<string, KeyValuePair<string, JsonSchemaProperty>> item in from p in itemSchemas.SelectMany((JsonSchema s) => s.Properties) group p by p.Key) { jsonSchema2.Properties[item.Key] = item.First().Value; } } AddSchemaDefinition(rootSchema, jsonSchema2, typeNameHint); schema.Item = new JsonSchema { Reference = jsonSchema2 }; } private static void AddSchemaDefinition(JsonSchema rootSchema, JsonSchema schema, string typeNameHint) { if (string.IsNullOrEmpty(typeNameHint) || rootSchema.Definitions.ContainsKey(typeNameHint)) rootSchema.Definitions["Anonymous" + (rootSchema.Definitions.Count + 1).ToString()] = schema; else rootSchema.Definitions[typeNameHint] = schema; } } }