private static TypeSchemaGreen GetFieldType(string typeName, IDictionary <string, TypeSchemaGreen> known) { if (known.TryGetValue(typeName, out var res)) { return(res); } if (WellKnownTypeSchemaGreen.ByCode.TryGetValue(typeName, out var wkt)) { known.Add(wkt.SchemaName, wkt); return(wkt); } if (typeName.EndsWith("[]")) { var at = new ArrayTypeSchemaGreen(Option.None, -1); known.Add(typeName, at); var et = GetFieldType(typeName.Substring(0, typeName.Length - 2), known); at = new ArrayTypeSchemaGreen(at, Option.None, et.Id); known[typeName] = at; return(at); } if (typeName.EndsWith("?")) { var ot = new NullableTypeSchemaGreen(Option.None, -1); known.Add(typeName, ot); var et = GetFieldType(typeName.Substring(0, typeName.Length - 1), known); ot = new NullableTypeSchemaGreen(ot, Option.None, et.Id); known[typeName] = ot; return(ot); } var rt = new RefTypeSchemaGreen(); known.Add(typeName, rt); return(rt); }
private static TypeSchemaGreen JsonToType(JProperty typeProp, IDictionary <string, TypeSchemaGreen> known) { if (!(typeProp.Value is JObject jobj)) { throw new SchemaFormatException($"Invalid type description as {typeProp.Path}"); } if (!known.TryGetValue(typeProp.Name, out var type)) { type = new RefTypeSchemaGreen(); known.Add(typeProp.Name, type); } var codeName = (string)null; if (jobj.TryGetValue("title", StringComparison.InvariantCultureIgnoreCase, out var tkn)) { try { codeName = tkn.ToObject <string>(); } catch (Exception ex) { throw new SchemaFormatException( $"Invalid token in codeName description at path {tkn.Path}", ex); } } var contract = (string)null; if (jobj.TryGetValue("contract", StringComparison.InvariantCultureIgnoreCase, out tkn)) { try { contract = tkn.ToObject <string>(); } catch (Exception ex) { throw new SchemaFormatException( $"Invalid token in contract description at path {tkn.Path}", ex); } } if (jobj.TryGetValue("fields", StringComparison.InvariantCultureIgnoreCase, out var fieldToken)) { if (!(fieldToken is JObject fields)) { throw new SchemaFormatException($"Invalid fields description as path {fieldToken.Path}"); } TypeSchemaGreen @base = null; if (jobj.TryGetValue("base", StringComparison.InvariantCultureIgnoreCase, out tkn)) { try { var baseName = tkn.ToObject <string>(); if (!known.TryGetValue(baseName, out @base)) { @base = new ComplexTypeSchemaGreen(Option.None, baseName, null, null, null, false, ImmutableDictionary <string, int> .Empty); known.Add(baseName, @base); } } catch (Exception ex) { throw new SchemaFormatException( $"Invalid token in base type description at path {tkn.Path}", ex); } } bool isStruct = false; if (jobj.TryGetValue("struct", StringComparison.InvariantCultureIgnoreCase, out tkn)) { try { isStruct = tkn.ToObject <bool>(); } catch (Exception ex) { throw new SchemaFormatException( $"Invalid token in struct type description at path {tkn.Path}", ex); } } var flds = new Dictionary <string, int>(); foreach (var property in fields.Properties()) { var fieldName = property.Name; try { var fieldTypeName = property.Value.ToObject <string>(); var fieldType = GetFieldType(fieldTypeName, known); flds.Add(fieldName, fieldType.Id); } catch (Exception ex) { throw new SchemaFormatException( $"Invalid token in type field description at path {property.Path}", ex); } } type = new ComplexTypeSchemaGreen(type, Option.None, typeProp.Name, codeName, contract, @base?.Id, isStruct, ImmutableDictionary.CreateRange(flds)); known[typeProp.Name] = type; return(type); } if (jobj.TryGetValue("values", StringComparison.InvariantCultureIgnoreCase, out var valuesToken)) { if (!(valuesToken is JObject values)) { throw new SchemaFormatException($"Invalid values description as path {fieldToken.Path}"); } TypeSchemaGreen @base = WellKnownTypeSchemaGreen.ByType[typeof(int)]; if (jobj.TryGetValue("base", StringComparison.InvariantCultureIgnoreCase, out tkn)) { try { var baseName = tkn.ToObject <string>(); if (!known.TryGetValue(baseName, out @base)) { @base = WellKnownTypeSchemaGreen.ByCode[baseName]; known.Add(baseName, @base); } } catch (Exception ex) { throw new SchemaFormatException( $"Invalid token in based on description at path {tkn.Path}", ex); } } bool isFlags = false; if (jobj.TryGetValue("flags", StringComparison.InvariantCultureIgnoreCase, out tkn)) { try { isFlags = tkn.ToObject <bool>(); } catch (Exception ex) { throw new SchemaFormatException( $"Invalid token in flags type description at path {tkn.Path}", ex); } } var vls = new Dictionary <string, long>(); foreach (var property in values.Properties()) { var fieldName = property.Name; try { var fieldValue = property.Value.ToObject <long>(); vls.Add(fieldName, fieldValue); } catch (Exception ex) { throw new SchemaFormatException( $"Invalid token in type field description at path {property.Path}", ex); } } type = new EnumTypeSchemaGreen(type, Option.None, typeProp.Name, codeName, contract, @base.Id, isFlags, ImmutableDictionary.CreateRange(vls)); known[typeProp.Name] = type; return(type); } throw new SchemaFormatException($"Unknown type schema at {typeProp.Path}"); }