private void ReadTokenArray(JsonReader reader, string name, ref List <JToken> values) { EnsureToken(reader, name, JsonToken.StartArray); if (values == null) { values = new List <JToken>(); } while (reader.Read()) { switch (reader.TokenType) { case JsonToken.Comment: // nom nom nom break; case JsonToken.EndArray: return; default: JToken t = JToken.ReadFrom(reader); values.Add(t); break; } } throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading '{0}'.".FormatWith(CultureInfo.InvariantCulture, name)); }
private void PopulateSchemaArray(JsonReader reader, string name, List <JSchema> schemas) { while (reader.Read()) { switch (reader.TokenType) { case JsonToken.StartObject: int itemCount = schemas.Count; LoadAndSetSchema(reader, s => SetAtIndex(schemas, itemCount, s)); break; case JsonToken.Comment: // nom nom nom break; case JsonToken.EndArray: return; default: throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token when reading schemas: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading schemas for '{0}'.".FormatWith(CultureInfo.InvariantCulture, name)); }
private void ReadStringArray(JsonReader reader, string name, out List <string> values) { values = new List <string>(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.String: values.Add((string)reader.Value); break; case JsonToken.Comment: // nom nom nom break; case JsonToken.EndArray: return; default: throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token when reading '{0}': {1}".FormatWith(CultureInfo.InvariantCulture, name, reader.TokenType)); } } throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading '{0}'.".FormatWith(CultureInfo.InvariantCulture, name)); }
internal JSchema ReadRoot(JsonReader reader, bool resolveDeferedSchemas = true) { if (reader.TokenType == JsonToken.None || reader.TokenType == JsonToken.Comment) { if (!reader.Read()) { throw JSchemaReaderException.Create(reader, _baseUri, "Error reading schema from JsonReader."); } } if (reader.TokenType != JsonToken.StartObject) { throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token encountered when reading schema. Expected StartObject, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } RootSchema = new JSchema(); LoadAndSetSchema(reader, s => { RootSchema = s; if (s.BaseUri != null) { Cache[s.BaseUri] = s; } }, true); if (resolveDeferedSchemas) { ResolveDeferedSchemas(); } return(RootSchema); }
private Uri ResolveSchemaReference(JSchema schema) { Uri resolvedReference = null; foreach (JSchema s in _schemaStack.Reverse()) { Uri part = s.Id; if (part != null) { if (resolvedReference == null) { resolvedReference = part; } else { resolvedReference = SchemaDiscovery.ResolveSchemaId(resolvedReference, part); } } } try { resolvedReference = SchemaDiscovery.ResolveSchemaId(resolvedReference, schema.Reference); } catch (Exception ex) { string message = "Error resolving schema reference '{0}' in the scope '{1}'. The resolved reference must be a valid URI.".FormatWith(CultureInfo.InvariantCulture, schema.Reference, resolvedReference); throw JSchemaReaderException.Create(schema, _baseUri, schema.Path, message, ex); } return(resolvedReference); }
private Dictionary <string, JSchema> ReadProperties(JsonReader reader) { EnsureToken(reader, Constants.PropertyNames.Properties, JsonToken.StartObject); Dictionary <string, JSchema> properties = new Dictionary <string, JSchema>(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: string name = (string)reader.Value; EnsureToken(reader, name, JsonToken.StartObject); // use last schema for duplicates // will this cause issues with a previously deferred schemas? LoadAndSetSchema(reader, s => properties[name] = s); break; case JsonToken.Comment: // nom, nom break; case JsonToken.EndObject: return(properties); default: throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token when reading properties: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading schema properties."); }
private void RaiseSchemaValidationError(object sender, SchemaValidationEventArgs e) { throw JSchemaReaderException.Create( (JsonReader)sender, _baseUri, "Validation error raised by version schema '{0}': {1}".FormatWith(CultureInfo.InvariantCulture, _schemaVersionUri, e.ValidationError.Message), JSchemaValidationException.Create(e.ValidationError)); }
private void EnsureToken(JsonReader reader, string name, List <JsonToken> tokenTypes) { EnsureRead(reader, name); if (!tokenTypes.Contains(reader.TokenType)) { throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token encountered when reading value for '{0}'. Expected {1}, got {2}.".FormatWith(CultureInfo.InvariantCulture, name, StringHelpers.Join(", ", tokenTypes), reader.TokenType)); } }
private void EnsureToken(JsonReader reader, string name, JsonToken tokenType) { EnsureRead(reader, name); if (reader.TokenType != tokenType) { throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token encountered when reading value for '{0}'. Expected {1}, got {2}.".FormatWith(CultureInfo.InvariantCulture, name, tokenType, reader.TokenType)); } }
private void ReadDependencies(JsonReader reader, JSchema schema) { EnsureToken(reader, Constants.PropertyNames.Dependencies, JsonToken.StartObject); Dictionary <string, object> dependencies = new Dictionary <string, object>(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: string name = (string)reader.Value; EnsureToken(reader, name, Constants.DependencyTokens); // use last dependency when duplicates are defined if (reader.TokenType == JsonToken.StartObject) { LoadAndSetSchema(reader, s => dependencies[name] = s); } else if (reader.TokenType == JsonToken.StartArray) { List <string> l; ReadStringArray(reader, name, out l); dependencies[name] = l; } else { EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3); dependencies[name] = new List <string> { (string)reader.Value }; } break; case JsonToken.Comment: // nom, nom break; case JsonToken.EndObject: schema._dependencies = dependencies; return; default: throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token when reading dependencies: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading dependencies."); }
private void EnsureRead(JsonReader reader, string name) { // read to the next non-comment while (reader.Read()) { if (reader.TokenType != JsonToken.Comment) { return; } } throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading value for '{0}'.".FormatWith(CultureInfo.InvariantCulture, name)); }
private Uri ReadUri(JsonReader reader, string name) { EnsureToken(reader, name, JsonToken.String); string id = (string)reader.Value; try { return(new Uri(id, UriKind.RelativeOrAbsolute)); } catch (Exception ex) { throw JSchemaReaderException.Create(reader, _baseUri, "Error parsing id '{0}'. Id must be a valid URI.".FormatWith(CultureInfo.InvariantCulture, id), ex); } }
public void ResolveDeferedSchemas() { if (_deferedSchemas.Count > 0) { List <DeferedSchema> resolvedDeferedSchemas = new List <DeferedSchema>(); int initialCount = _deferedSchemas.Count; int i = 0; // note that defered schemas could be added while resolving while (_deferedSchemas.Count > 0) { DeferedSchema deferedSchema = _deferedSchemas[0]; ResolveDeferedSchema(deferedSchema); resolvedDeferedSchemas.Add(deferedSchema); _deferedSchemas.Remove(deferedSchema); if (!deferedSchema.Success && i >= initialCount) { // if schema resolved to another reference and that reference has already not be resolved then fail // probably a circular reference for (int j = initialCount; j < resolvedDeferedSchemas.Count; j++) { DeferedSchema resolvedSchema = resolvedDeferedSchemas[j]; if (deferedSchema != resolvedSchema && deferedSchema.ResolvedReference.ToString() == resolvedSchema.ResolvedReference.ToString()) { throw JSchemaReaderException.Create(resolvedSchema.ReferenceSchema, _baseUri, resolvedSchema.ReferenceSchema.Path, "Could not resolve schema reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, deferedSchema.ResolvedReference)); } } } i++; } foreach (DeferedSchema resolvedDeferedSchema in resolvedDeferedSchemas) { if (!resolvedDeferedSchema.Success) { throw JSchemaReaderException.Create(resolvedDeferedSchema.ReferenceSchema, _baseUri, resolvedDeferedSchema.ReferenceSchema.Path, "Could not resolve schema reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, resolvedDeferedSchema.ResolvedReference)); } } } }
private void ResolveDeferedSchema(DeferedSchema deferedSchema) { Uri reference = deferedSchema.ResolvedReference; bool found = SchemaDiscovery.FindSchema(s => { // additional json copied to referenced schema // kind of hacky if (deferedSchema.ReferenceSchema._extensionData != null) { foreach (KeyValuePair <string, JToken> keyValuePair in deferedSchema.ReferenceSchema._extensionData.ToList()) { s.ExtensionData[keyValuePair.Key] = keyValuePair.Value; } } deferedSchema.SetResolvedSchema(s); }, RootSchema, RootSchema.Id, reference, this, ref _schemaDiscovery); if (found) { return; } JSchema resolvedSchema; try { resolvedSchema = ResolvedSchema(deferedSchema.ReferenceSchema.Reference, deferedSchema.ResolvedReference); } catch (Exception ex) { throw JSchemaReaderException.Create(deferedSchema.ReferenceSchema, _baseUri, deferedSchema.ReferenceSchema.Path, "Error when resolving schema reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, deferedSchema.ReferenceSchema.Reference), ex); } if (resolvedSchema != null) { deferedSchema.SetResolvedSchema(resolvedSchema); return; } throw JSchemaReaderException.Create(deferedSchema.ReferenceSchema, _baseUri, deferedSchema.ReferenceSchema.Path, "Could not resolve schema reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, deferedSchema.ResolvedReference)); }
private void ReadExtends(JsonReader reader, JSchema schema) { EnsureRead(reader, Constants.PropertyNames.Extends); EnsureList(ref schema._allOf); switch (reader.TokenType) { case JsonToken.StartObject: int index = schema._allOf.Count; LoadAndSetSchema(reader, s => SetAtIndex(schema._allOf, index, s)); break; case JsonToken.StartArray: PopulateSchemaArray(reader, Constants.PropertyNames.Extends, schema._allOf); break; default: throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token when reading '{0}': {1}".FormatWith(CultureInfo.InvariantCulture, Constants.PropertyNames.Extends, reader.TokenType)); } }
internal JSchemaType?MapType(JsonReader reader) { string typeName = (string)reader.Value; JSchemaType mappedType; if (!Constants.JSchemaTypeMapping.TryGetValue(typeName, out mappedType)) { if (EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3)) { if (typeName == Constants.Types.Any) { return(null); } } throw JSchemaReaderException.Create(reader, _baseUri, "Invalid JSON schema type: {0}".FormatWith(CultureInfo.InvariantCulture, typeName)); } return(mappedType); }
private void ReadItems(JsonReader reader, JSchema schema) { EnsureRead(reader, Constants.PropertyNames.Items); EnsureList(ref schema._items); switch (reader.TokenType) { case JsonToken.StartObject: LoadAndSetSchema(reader, s => SetAtIndex(schema._items, 0, s)); schema.ItemsPositionValidation = false; break; case JsonToken.StartArray: PopulateSchemaArray(reader, Constants.PropertyNames.Items, schema._items); schema.ItemsPositionValidation = true; break; default: throw JSchemaReaderException.Create(reader, _baseUri, "Expected array or JSON schema object for '{0}', got {1}.".FormatWith(CultureInfo.InvariantCulture, Constants.PropertyNames.Items, reader.TokenType)); } }
private void ReadExtensionData(JsonReader reader, JSchema schema, string name) { if (!reader.Read()) { throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading schema."); } JToken t; if (reader is JTokenReader) { t = ((JTokenReader)reader).CurrentToken; reader.Skip(); } else { string basePath = reader.Path; t = JToken.ReadFrom(reader); t.AddAnnotation(new JTokenPathAnnotation(basePath)); } schema.ExtensionData[name] = t; }
private void ReadRequired(JsonReader reader, JSchema schema) { EnsureRead(reader, Constants.PropertyNames.Required); if (reader.TokenType == JsonToken.Boolean) { if (!EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3)) { throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token encountered when reading value for 'required'. Expected StartArray, got Boolean."); } schema.DeprecatedRequired = (bool)reader.Value; } else { if (!EnsureVersion(SchemaVersion.Draft4)) { throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token encountered when reading value for 'required'. Expected Boolean, got StartArray."); } ReadStringArray(reader, Constants.PropertyNames.Required, out schema._required); } }
private void ReadSchemaProperties(JsonReader reader, bool isRoot, JSchema schema) { while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: ProcessSchemaName(ref reader, isRoot, schema, (string)reader.Value); break; case JsonToken.Comment: // nom, nom break; case JsonToken.EndObject: return; default: throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token when reading schema: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading schema."); }
private void ProcessSchemaName(ref JsonReader reader, bool isRoot, JSchema schema, string name) { switch (name) { case Constants.PropertyNames.Id: schema.Id = ReadUri(reader, name); break; case Constants.PropertyNames.Ref: schema.Reference = ReadUri(reader, name); break; case Constants.PropertyNames.Properties: schema._properties = ReadProperties(reader); // add schemas with deprecated required flag to new required array foreach (KeyValuePair <string, JSchema> schemaProperty in schema.Properties) { if (schemaProperty.Value.DeprecatedRequired) { if (!schema.Required.Contains(schemaProperty.Key)) { schema.Required.Add(schemaProperty.Key); } } } break; case Constants.PropertyNames.Items: ReadItems(reader, schema); break; case Constants.PropertyNames.Type: { object typeResult = ReadType(reader, name); if (typeResult is JSchemaType) { schema.Type = (JSchemaType)typeResult; } else { schema._anyOf = (List <JSchema>)typeResult; } break; } case Constants.PropertyNames.AnyOf: if (EnsureVersion(SchemaVersion.Draft4)) { ReadSchemaArray(reader, name, out schema._anyOf); } else { ReadExtensionData(reader, schema, name); } break; case Constants.PropertyNames.AllOf: if (EnsureVersion(SchemaVersion.Draft4)) { ReadSchemaArray(reader, name, out schema._allOf); } else { ReadExtensionData(reader, schema, name); } break; case Constants.PropertyNames.OneOf: if (EnsureVersion(SchemaVersion.Draft4)) { ReadSchemaArray(reader, name, out schema._oneOf); } else { ReadExtensionData(reader, schema, name); } break; case Constants.PropertyNames.Not: if (EnsureVersion(SchemaVersion.Draft4)) { ReadSchema(reader, name, s => schema.Not = s); } else { ReadExtensionData(reader, schema, name); } break; case Constants.PropertyNames.Title: schema.Title = ReadString(reader, name); break; case Constants.PropertyNames.Description: schema.Description = ReadString(reader, name); break; case Constants.PropertyNames.Format: schema.Format = ReadString(reader, name); break; case Constants.PropertyNames.AdditionalProperties: ReadAdditionalProperties(reader, schema); break; case Constants.PropertyNames.AdditionalItems: ReadAdditionalItems(reader, schema); break; case Constants.PropertyNames.PatternProperties: schema._patternProperties = ReadProperties(reader); break; case Constants.PropertyNames.Required: ReadRequired(reader, schema); break; case Constants.PropertyNames.Dependencies: ReadDependencies(reader, schema); break; case Constants.PropertyNames.Minimum: schema.Minimum = ReadDouble(reader, name); break; case Constants.PropertyNames.Maximum: schema.Maximum = ReadDouble(reader, name); break; case Constants.PropertyNames.ExclusiveMinimum: schema.ExclusiveMinimum = ReadBoolean(reader, name); break; case Constants.PropertyNames.ExclusiveMaximum: schema.ExclusiveMaximum = ReadBoolean(reader, name); break; case Constants.PropertyNames.MaximumLength: schema.MaximumLength = ReadInteger(reader, name); break; case Constants.PropertyNames.MinimumLength: schema.MinimumLength = ReadInteger(reader, name); break; case Constants.PropertyNames.MaximumItems: schema.MaximumItems = ReadInteger(reader, name); break; case Constants.PropertyNames.MinimumItems: schema.MinimumItems = ReadInteger(reader, name); break; case Constants.PropertyNames.MaximumProperties: if (EnsureVersion(SchemaVersion.Draft4)) { schema.MaximumProperties = ReadInteger(reader, name); } else { ReadExtensionData(reader, schema, name); } break; case Constants.PropertyNames.MinimumProperties: if (EnsureVersion(SchemaVersion.Draft4)) { schema.MinimumProperties = ReadInteger(reader, name); } else { ReadExtensionData(reader, schema, name); } break; case Constants.PropertyNames.DivisibleBy: if (EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3)) { schema.MultipleOf = ReadDouble(reader, name); } else { ReadExtensionData(reader, schema, name); } break; case Constants.PropertyNames.MultipleOf: if (EnsureVersion(SchemaVersion.Draft4)) { schema.MultipleOf = ReadDouble(reader, name); } else { ReadExtensionData(reader, schema, name); } break; case Constants.PropertyNames.Disallow: { if (EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3)) { if (schema.Not == null) { schema.Not = new JSchema(); } object disallowResult = ReadType(reader, name); if (disallowResult is JSchemaType) { JSchemaType type = schema.Not.Type ?? JSchemaType.None; schema.Not.Type = type | (JSchemaType)disallowResult; } else { schema.Not._anyOf = (List <JSchema>)disallowResult; } } else { ReadExtensionData(reader, schema, name); } break; } case Constants.PropertyNames.Pattern: schema.Pattern = ReadString(reader, name); if (_validationErrors != null) { Regex patternRegex; string errorMessage; if (!schema.TryGetPatternRegex(out patternRegex, out errorMessage)) { ValidationError error = ValidationError.CreateValidationError("Could not parse regex pattern '{0}'. Regex parser error: {1}".FormatWith(CultureInfo.InvariantCulture, schema.Pattern, errorMessage), ErrorType.Pattern, schema, null, schema.Pattern, null, schema, schema.Path); _validationErrors.Add(error); } } break; case Constants.PropertyNames.Enum: ReadTokenArray(reader, name, ref schema._enum); if (schema._enum.Count == 0) { throw JSchemaReaderException.Create(reader, _baseUri, "Enum array must have at least one value."); } break; case Constants.PropertyNames.Extends: if (EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3)) { ReadExtends(reader, schema); } else { ReadExtensionData(reader, schema, name); } break; case Constants.PropertyNames.UniqueItems: schema.UniqueItems = ReadBoolean(reader, name); break; case Constants.PropertyNames.Default: EnsureRead(reader, Constants.PropertyNames.Default); schema.Default = JToken.ReadFrom(reader); break; default: if (isRoot && name == Constants.PropertyNames.Schema) { if (!reader.Read()) { throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading schema."); } if (reader.TokenType != JsonToken.String) { throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token encountered when reading value for '$schema'. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } _schemaVersionUri = new Uri((string)reader.Value, UriKind.RelativeOrAbsolute); #if !PORTABLE string tempUriText = _schemaVersionUri.OriginalString.ToLower(CultureInfo.InvariantCulture); #else string tempUriText = _schemaVersionUri.OriginalString.ToLower(); #endif Uri tempUri = new Uri(tempUriText, UriKind.RelativeOrAbsolute); if (tempUri == Constants.SchemaVersions.Draft3) { _schemaVersion = SchemaVersion.Draft3; } else if (tempUri == Constants.SchemaVersions.Draft4) { _schemaVersion = SchemaVersion.Draft4; } if (_validateSchema) { if (_schemaVersion == SchemaVersion.Draft3) { _validatingSchema = SpecSchemaCache.Get("schema-draft-v3.json"); } else if (_schemaVersion == SchemaVersion.Draft4) { _validatingSchema = SpecSchemaCache.Get("schema-draft-v4.json"); } else { if (!_schemaVersionUri.IsAbsoluteUri) { throw JSchemaReaderException.Create(reader, _baseUri, "Schema version identifier '{0}' is not an absolute URI.".FormatWith(CultureInfo.InvariantCulture, _schemaVersionUri.OriginalString)); } _validatingSchema = ResolvedSchema(_schemaVersionUri, _schemaVersionUri); if (_validatingSchema == null) { throw JSchemaReaderException.Create(reader, _baseUri, "Could not resolve schema version identifier '{0}'.".FormatWith(CultureInfo.InvariantCulture, _schemaVersionUri.OriginalString)); } } JSchemaValidatingReader validatingReader = new JSchemaValidatingReader(reader); validatingReader.Schema = _validatingSchema; // push state that we're already inside an object validatingReader.Validator.ValidateCurrentToken(JsonToken.StartObject, null, 0); validatingReader.ValidationEventHandler += RaiseSchemaValidationError; reader = validatingReader; } } else { ReadExtensionData(reader, schema, name); } break; } }
private object ReadType(JsonReader reader, string name) { EnsureRead(reader, name); List <JSchemaType> types = new List <JSchemaType>(); List <JSchema> typeSchemas = null; bool isAny = false; switch (reader.TokenType) { case JsonToken.String: return(MapType(reader)); case JsonToken.StartArray: while (reader.Read()) { switch (reader.TokenType) { case JsonToken.String: JSchemaType?t = MapType(reader); if (t == null) { isAny = true; } else { if (typeSchemas != null) { typeSchemas.Add(new JSchema { Type = t }); } else { types.Add(t.Value); } } break; case JsonToken.Comment: // nom nom nom break; case JsonToken.EndArray: // type of "any" removes all other type constraints if (isAny) { return(null); } if (typeSchemas != null) { return(typeSchemas); } JSchemaType finalType = JSchemaType.None; foreach (JSchemaType type in types) { finalType = finalType | type; } return(finalType); default: if (EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3)) { if (typeSchemas == null) { typeSchemas = new List <JSchema>(); foreach (JSchemaType type in types) { typeSchemas.Add(new JSchema { Type = type }); } types = null; } int count = typeSchemas.Count; List <JSchema> l = typeSchemas; LoadAndSetSchema(reader, s => SetAtIndex(l, count, s)); } else { throw JSchemaReaderException.Create(reader, _baseUri, "Expected string token for type, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } break; } } break; default: throw JSchemaReaderException.Create(reader, _baseUri, "Expected array or string for '{0}', got {1}.".FormatWith(CultureInfo.InvariantCulture, Constants.PropertyNames.Type, reader.TokenType)); } throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading schema type."); }