Example #1
0
        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}'");
            }
        }