public static IEnumerable <SerializationType> GetSerializationTypes(AvroSchema avroSchema) { var attributes = avroSchema.GetType().GetCustomAttributes <SerializationType>(); switch (avroSchema) { case LogicalSchema l: attributes = attributes.Union(GetSerializationTypes(l.Type)); break; case UnionSchema u: foreach (var s in u) { attributes = attributes.Union(GetSerializationTypes(s)); } break; } return(attributes); }
public static void ValidateJson(AvroSchema schema, JToken jToken) { if (jToken == null) { return; } switch (schema) { case NullSchema n when jToken.Type == JTokenType.Null: break; case BooleanSchema b when jToken.Type == JTokenType.Boolean: break; case IntSchema i when jToken.Type == JTokenType.Integer && int.TryParse(jToken.ToString(), out _): break; case LongSchema l when jToken.Type == JTokenType.Integer && long.TryParse(jToken.ToString(), out _): break; case FloatSchema f when(jToken.Type == JTokenType.Integer || jToken.Type == JTokenType.Float) && float.TryParse(jToken.ToString(), out _): break; case DoubleSchema d when(jToken.Type == JTokenType.Integer || jToken.Type == JTokenType.Float) && double.TryParse(jToken.ToString(), out _): break; case BytesSchema b when jToken.Type == JTokenType.String && Regex.IsMatch(jToken.ToString(), @"^(\\u00[0-9a-fA-F][0-9a-fA-F])*$"): break; case StringSchema s when jToken.Type == JTokenType.String: break; case ArraySchema s when jToken.Type == JTokenType.Array: foreach (var item in jToken as JArray) { ValidateJson(s.Items, item); } break; case MapSchema s when jToken.Type == JTokenType.Object: foreach (var item in jToken as JObject) { ValidateJson(s.Values, item.Value); } break; case EnumSchema e when jToken.Type == JTokenType.String && Regex.IsMatch(jToken.ToString().Trim('"'), @"^[a-zA-Z][0-9a-zA-Z]*$") && e.Symbols.Contains(jToken.ToString().Trim('"')): break; case FixedSchema f when jToken.Type == JTokenType.String && Regex.Match(jToken.ToString(), @"^(\\u00[0-9a-fA-F][0-9a-fA-F])*$").Length == f.Size * 6: break; case RecordSchema r when jToken.Type == JTokenType.Object && !r.Any(f => f.Default == null && !(jToken as JObject).ContainsKey(f.Name)) && // No fields without defaults omitted in default value. !(jToken as JObject).Properties().Any(k => r.FirstOrDefault(f => f.Name == k.Name) == null): // No invalud default values references foreach (var defaultValue in (jToken as JObject)) { ValidateJson(r.First(f => f.Name == defaultValue.Key).Type, defaultValue.Value); } break; case UnionSchema u: ValidateJson(u[0], jToken); break; case UuidSchema u: if (jToken.Type != JTokenType.String || !Guid.TryParse(jToken.ToString().Trim('"'), out _)) { throw new AvroParseException($"Invalid default value for schema '{schema.GetType().Name}': '{jToken.ToString()}'"); } break; case LogicalSchema l: ValidateJson(l.Type, jToken); break; default: throw new AvroParseException($"Invalid default value for schema '{schema.GetType().Name}': '{jToken.ToString()}'"); } }
public static Type GetTypeFromSchema(AvroSchema schema, Assembly assembly = null) { switch (schema) { case NullSchema r: return(typeof(AvroNull)); case BooleanSchema r: return(typeof(bool)); case IntSchema r: return(typeof(int)); case LongSchema r: return(typeof(long)); case FloatSchema r: return(typeof(float)); case DoubleSchema r: return(typeof(double)); case BytesSchema r: return(typeof(byte[])); case StringSchema r: return(typeof(string)); case ArraySchema r: return(typeof(IList <>).MakeGenericType(GetTypeFromSchema(r.Items, assembly))); case MapSchema r: return(typeof(IDictionary <,>).MakeGenericType(typeof(string), GetTypeFromSchema(r.Values, assembly))); case DecimalSchema r: return(typeof(decimal)); case DateSchema r: return(typeof(DateTime)); case TimestampMillisSchema r: return(typeof(DateTime)); case TimestampMicrosSchema r: return(typeof(DateTime)); case TimestampNanosSchema r: return(typeof(DateTime)); case TimeMillisSchema r: return(typeof(TimeSpan)); case TimeMicrosSchema r: return(typeof(TimeSpan)); case TimeNanosSchema r: return(typeof(TimeSpan)); case DurationSchema r: return(typeof(AvroDuration)); case UuidSchema r: return(typeof(Guid)); case EnumSchema r: if (assembly == null) { return(typeof(GenericEnum)); } else { return(assembly.GetType(r.FullName)); } case FixedSchema r: if (assembly == null) { return(typeof(GenericFixed)); } else { return(assembly.GetType(r.FullName)); } case RecordSchema r: if (assembly == null) { return(typeof(GenericRecord)); } else { return(assembly.GetType(r.FullName)); } case UnionSchema r: if (r.Count == 2 && r.Any(n => n.GetType().Equals(typeof(NullSchema)))) { var nullableSchema = r.First(s => !s.GetType().Equals(typeof(NullSchema))); switch (nullableSchema) { case IntSchema a: case LongSchema b: case FloatSchema c: case DoubleSchema d: case DecimalSchema e: case DateSchema f: case TimestampMillisSchema g: case TimestampMicrosSchema h: case TimestampNanosSchema i: case TimeMillisSchema j: case TimeMicrosSchema k: case TimeNanosSchema l: case UuidSchema m: case EnumSchema n: return(typeof(Nullable <>).MakeGenericType(GetTypeFromSchema(nullableSchema, assembly))); default: return(GetTypeFromSchema(nullableSchema, assembly)); } } return(typeof(object)); case LogicalSchema r: return(GetTypeFromSchema(r.Type, assembly)); default: throw new ArgumentException($"Unsupported schema: '{schema.GetType().Name}'"); } }