public override TVersionable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) { throw new JsonException(); } var output = Activator.CreateInstance <TVersionable>(); var objectVersionHistory = typeof(TVersionable).GetVersionHistory(); while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return(output); } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException(); } var propertyName = reader.GetString(); var propertyInfo = typeof(TVersionable).GetPropertyBySerialisationName(propertyName); if (propertyInfo != null) { var propertyVersionHistory = propertyInfo.GetVersionHistory(); var applicableVersionHistory = VersionHistory.Merge(propertyVersionHistory, objectVersionHistory); if (applicableVersionHistory.IsApplicableAtVersion(_version)) { var value = JsonSerializer.Deserialize(ref reader, propertyInfo.PropertyType, options); propertyInfo.SetValue(output, value); } } } throw new JsonException(); }
public override void Write(Utf8JsonWriter writer, TVersionable value, JsonSerializerOptions options) { writer.WriteStartObject(); var objectVersionHistory = typeof(TVersionable).GetVersionHistory(); foreach (var propertyInfo in typeof(TVersionable).GetProperties()) { var propertyVersionHistory = propertyInfo.GetVersionHistory(); var applicableVersionHistory = VersionHistory.Merge(propertyVersionHistory, objectVersionHistory); if (applicableVersionHistory.IsApplicableAtVersion(_version)) { writer.WritePropertyName(propertyInfo.GetSerialisationName()); JsonSerializer.Serialize(writer, propertyInfo.GetValue(value), options); } } writer.WriteEndObject(); }
private static IDictionary <string, OpenApiSchema> GetPrunedSchemas(IDictionary <string, OpenApiSchema> schemas, Version version) { var prunedSchemas = new Dictionary <string, OpenApiSchema>(); foreach (var schema in schemas.Where(s => s.Value?.Description != null)) { var objectData = schema.Value.Description; // VersionableSwaggerSchemaAttribute packs data as "@[ClassName]@Description var regEx = new Regex(@"^@\[(?'className'[\s\S]+)\]@(?'description'[\s\S]*)$"); var matches = regEx.Matches(objectData); if (matches.Count == 0) { // Not decorated with VersionableSwaggerSchemaAttribute so pass through untouched prunedSchemas.Add(schema.Key, schema.Value); continue; } var objectName = matches[0].Groups["className"].Value; schema.Value.Description = matches[0].Groups["description"].Value; if (string.IsNullOrWhiteSpace(objectName)) { // Can't determine Versionable object so pass through untouched prunedSchemas.Add(schema.Key, schema.Value); continue; } var objectType = Type.GetType(objectName); if (objectType == null || !objectType.IsClass) { // Not Versionable so pass through untouched prunedSchemas.Add(schema.Key, schema.Value); continue; } var objectVersionHistory = objectType.GetVersionHistory(); if (!objectVersionHistory.IsApplicableAtVersion(version)) { // Entire object not applicable - discard continue; } var excludedProperties = new List <string>(); foreach (var property in schema.Value.Properties) { var propertyInfo = objectType.GetPropertyBySerialisationName(property.Key); if (propertyInfo == null) { continue; } var propertyVersionHistory = propertyInfo.GetVersionHistory(); var applicableVersionHistory = VersionHistory.Merge(propertyVersionHistory, objectVersionHistory); if (!applicableVersionHistory.IsApplicableAtVersion(version)) { excludedProperties.Add(property.Key); } } foreach (var excludedProperty in excludedProperties.Where(excludedProperty => schema.Value.Properties.ContainsKey(excludedProperty))) { schema.Value.Properties.Remove(excludedProperty); } prunedSchemas.Add(schema.Key, schema.Value); } return(prunedSchemas); }