// issues related to gltf2 schema parsing: // https://github.com/RSuter/NJsonSchema // https://github.com/RSuter/NJsonSchema/issues/378 // https://github.com/RSuter/NJsonSchema/issues/377 #region API public static SchemaType.Context Generate(NJsonSchema.CodeGeneration.CSharp.CSharpTypeResolver types) { var context = new SchemaType.Context(); foreach (var t in types.Types.Keys) { context._UseType(t); } return(context); }
private static SchemaType _UseType(this SchemaType.Context ctx, JSONSCHEMA schema, bool isRequired = true) { if (ctx == null) { throw new ArgumentNullException(nameof(ctx)); } if (schema == null) { throw new ArgumentNullException(nameof(schema)); } if (schema is NJsonSchema.JsonSchemaProperty prop) { // System.Diagnostics.Debug.Assert(prop.Name != "scene"); isRequired &= prop.IsRequired; } if (_IsStringType(schema)) { return(ctx.UseString()); } if (_IsBlittableType(schema)) { bool isNullable = !isRequired; if (schema.Type == NJsonSchema.JsonObjectType.Integer) { return(ctx.UseBlittable(typeof(Int32).GetTypeInfo(), isNullable)); } if (schema.Type == NJsonSchema.JsonObjectType.Number) { return(ctx.UseBlittable(typeof(Double).GetTypeInfo(), isNullable)); } if (schema.Type == NJsonSchema.JsonObjectType.Boolean) { return(ctx.UseBlittable(typeof(Boolean).GetTypeInfo(), isNullable)); } throw new NotImplementedException(); } if (schema.HasReference) { return(ctx._UseType(schema.ActualTypeSchema, isRequired)); // we could have our own ref } if (schema.IsArray) { return(ctx.UseArray(ctx._UseType(schema.Item.ActualSchema))); } if (_IsEnumeration(schema)) { if (schema is NJsonSchema.JsonSchemaProperty property) { bool isNullable = !isRequired; var dict = new Dictionary <string, Int64>(); foreach (var v in property.AnyOf) { var val = v.Enumeration.FirstOrDefault(); var key = v.Description; if (val is String) { key = (string)val; val = (Int64)0; } if (string.IsNullOrWhiteSpace(key)) { continue; } dict[key] = (Int64)val; } // JSon Schema AnyOf enumerations are basically anonymous, so we create // a "shared name" with a concatenation of all the values: var name = string.Join("-", dict.Keys.OrderBy(item => item)); var etype = ctx.UseEnum(name, isNullable); etype.Description = schema.Description; foreach (var kvp in dict) { etype.SetValue(kvp.Key, (int)kvp.Value); } if (dict.Values.Distinct().Count() > 1) { etype.UseIntegers = true; } return(etype); } throw new NotImplementedException(); } if (_IsDictionary(schema)) { var key = ctx.UseString(); var val = ctx._UseType(_GetDictionaryValue(schema)); return(ctx.UseDictionary(key, val)); } if (_IsClass(schema)) { var classDecl = ctx.UseClass(schema.Title); classDecl.Description = schema.Description; // process base class if (schema.InheritedSchema != null) { classDecl.BaseClass = ctx._UseType(schema.InheritedSchema) as ClassType; } // filter declared properties var keys = _GetProperyNames(schema); if (schema.InheritedSchema != null) // filter our parent properties { var baseKeys = _GetInheritedPropertyNames(schema).ToArray(); keys = keys.Except(baseKeys).ToArray(); } // process declared properties var props = keys.Select(key => schema.Properties.Values.FirstOrDefault(item => item.Name == key)); var required = schema.RequiredProperties; // System.Diagnostics.Debug.Assert(schema.Title != "Buffer View"); foreach (var p in props) { var field = classDecl.UseField(p.Name); field.Description = p.Description; field.FieldType = ctx._UseType(p, required.Contains(p.Name)); field.MinimumValue = p.Minimum; field.MaximumValue = p.Maximum; field.DefaultValue = p.Default; field.MinItems = p.MinItems; field.MaxItems = p.MaxItems; } return(classDecl); } if (schema.Type == NJsonSchema.JsonObjectType.Object) { return(ctx.UseAnyType()); } if (schema.Type == NJsonSchema.JsonObjectType.None) { return(ctx.UseAnyType()); } throw new NotImplementedException(); }