private JsonSchemaWrapper ResolveSchemaHelper(Uri curr, Uri parent, string data) { var ids = GetIds(data); data = StandardizeReferences(parent, data, ids); var definition = new { csharpType = string.Empty, csharpInterfaces = new string[] { }, properties = new Dictionary <string, JObject>() }; var deserialized = JsonConvert.DeserializeAnonymousType(data, definition); var dependencies = new List <JsonSchemaWrapper>(); MatchCollection matches = Regex.Matches(data, @"\""\$ref\""\s*:\s*\""(.*)\"""); foreach (Match match in matches) { // Get the full path to the file, and change the reference to match string refName = match.Groups[1].Value; var currPath = new Uri(refName, UriKind.RelativeOrAbsolute); if (ids.Contains(refName)) { //internal reference by ID, no need to load a new schema or add a dependency continue; } var currUri = IoUtils.GetAbsoluteUri(parent, currPath, true); JsonSchemaWrapper schema; if (!_schemas.ContainsKey(currUri)) { // if this is a self reference, no need to load anything or add a dependency if (parent.Equals(currUri)) { continue; } schema = ResolveSchemaHelper(parent, currUri); _schemas.Add(currUri, schema); } else { schema = _schemas[currUri]; } // Add schema to dependencies dependencies.Add(schema); } // Go through properties to see if there needs to be more resolving if (deserialized != null && deserialized.properties != null) { foreach (var s in deserialized.properties) { var properties = s.Value.Properties(); // Check that the property also has a top level key called properties or items foreach (var prop in properties) { var isProp = prop.Name.Equals("properties"); var isItem = prop.Name.Equals("items"); // TODO ehhhh let's avoid hardcoding this if (isProp || (isItem && prop.Value.ToString().Contains("\"properties\""))) { var propData = isProp ? s.Value.ToString() : prop.Value.ToString(); // Create dummy internal Uri var dummyUri = new Uri(new Uri(curr + "/"), s.Key); JsonSchemaWrapper schema = ResolveSchemaHelper(dummyUri, curr, propData); if (!_schemas.ContainsKey(dummyUri)) { _schemas.Add(dummyUri, schema); } } } } } // Set up schema and wrapper to return JsonSchema parsed = null; RemoveDuplicateSchemas(); // work around the situation where we don't have a schema in our list of schemas, // but the resolver itself has already loaded that schema because it's a sub-schema // of a schema we've already loaded. In this case, find the already-resolved // schema and add that to our list of schemas foreach (var schema in _resolver.LoadedSchemas) { if (schema.Id != null && schema.Id.Equals(curr.ToString(), StringComparison.InvariantCultureIgnoreCase)) { parsed = schema; } } try { if (parsed == null) { parsed = JsonSchema.Parse(data, _resolver); } } catch (Exception) { _log.Error("Could not parse the schema: " + curr + "\nMake sure your schema is compatible." + "Examine the stack trace below."); throw; } parsed.Id = curr.ToString(); parsed.Title = parsed.Title.SanitizeIdentifier(); var toReturn = new JsonSchemaWrapper(parsed) { Namespace = _ns, Dependencies = dependencies }; // If csharpType is specified if (deserialized != null && !string.IsNullOrEmpty(deserialized.csharpType)) { // Create directories and set namespace int lastIndex = deserialized.csharpType.LastIndexOf('.'); string cType = deserialized.csharpType.Substring(lastIndex == -1 ? 0 : lastIndex + 1); toReturn.Namespace = deserialized.csharpType.Substring(0, lastIndex); toReturn.Schema.Title = cType; if (_createDirs) { IoUtils.CreateDirectoryFromNamespace(_baseDir, toReturn.Namespace); } } // If csharpInterfaces is specified if (deserialized != null && deserialized.csharpInterfaces != null) { foreach (string s in deserialized.csharpInterfaces) { // Try to resolve the type Type t = Type.GetType(s, false); // If type cannot be found, create a new type if (t == null) { var builder = new TypeBuilderHelper(toReturn.Namespace); t = builder.GetCustomType(s, !s.Contains(".")); } toReturn.Interfaces.Add(t); } } return(toReturn); }