/// <summary> /// Static function to return instance of the union schema /// </summary> /// <param name="jarr">JSON object for the union schema</param> /// <param name="names">list of named schemas already read</param> /// <param name="encspace">enclosing namespace of the schema</param> /// <returns>new UnionSchema object</returns> internal static UnionSchema NewInstance(JArray jarr, PropertyMap props, SchemaNames names, string encspace) { List <Schema> schemas = new List <Schema>(); IDictionary <string, string> uniqueSchemas = new Dictionary <string, string>(); foreach (JToken jvalue in jarr) { Schema unionType = Schema.ParseJson(jvalue, names, encspace); if (null == unionType) { throw new SchemaParseException("Invalid JSON in union" + jvalue.ToString()); } string name = unionType.Name; if (uniqueSchemas.ContainsKey(name)) { throw new SchemaParseException("Duplicate type in union: " + name); } uniqueSchemas.Add(name, name); schemas.Add(unionType); } return(new UnionSchema(schemas, props)); }
/// <summary> /// Static function to return new instance of the fixed schema class /// </summary> /// <param name="jtok">JSON object for the fixed schema</param> /// <param name="names">list of named schema already parsed in</param> /// <param name="encspace">enclosing namespace of the fixed schema</param> /// <returns></returns> internal static FixedSchema NewInstance(JToken jtok, PropertyMap props, SchemaNames names, string encspace) { SchemaName name = NamedSchema.GetName(jtok, encspace); var aliases = NamedSchema.GetAliases(jtok, name.Space, name.EncSpace); return(new FixedSchema(name, aliases, JsonHelper.GetRequiredInteger(jtok, "size"), props, names)); }
/// <summary> /// Static function to return a new instance of the named schema /// </summary> /// <param name="jo">JSON object of the named schema</param> /// <param name="names">list of named schemas already read</param> /// <param name="encspace">enclosing namespace of the named schema</param> /// <returns></returns> internal static NamedSchema NewInstance(JObject jo, PropertyMap props, SchemaNames names, string encspace) { string type = JsonHelper.GetRequiredString(jo, "type"); switch (type) { case "fixed": return(FixedSchema.NewInstance(jo, props, names, encspace)); case "enum": return(EnumSchema.NewInstance(jo, props, names, encspace)); case "record": return(RecordSchema.NewInstance(Type.Record, jo, props, names, encspace)); case "error": return(RecordSchema.NewInstance(Type.Error, jo, props, names, encspace)); default: NamedSchema result; if (names.TryGetValue(type, null, encspace, out result)) { return(result); } return(null); } }
/// <summary> /// Static function to return new instance of EnumSchema /// </summary> /// <param name="jtok">JSON object for enum schema</param> /// <param name="names">list of named schema already parsed in</param> /// <param name="encspace">enclosing namespace for the enum schema</param> /// <returns>new instance of enum schema</returns> internal static EnumSchema NewInstance(JToken jtok, PropertyMap props, SchemaNames names, string encspace) { SchemaName name = NamedSchema.GetName(jtok, encspace); var aliases = NamedSchema.GetAliases(jtok, name.Space, name.EncSpace); JArray jsymbols = jtok["symbols"] as JArray; if (null == jsymbols) { throw new SchemaParseException("Enum has no symbols: " + name); } List <string> symbols = new List <string>(); IDictionary <string, int> symbolMap = new Dictionary <string, int>(); int i = 0; foreach (JValue jsymbol in jsymbols) { string s = (string)jsymbol.Value; if (symbolMap.ContainsKey(s)) { throw new SchemaParseException("Duplicate symbol: " + s); } symbolMap[s] = i++; symbols.Add(s); } return(new EnumSchema(name, aliases, symbols, symbolMap, props, names)); }
/// <summary> /// Creates a new field for the record /// </summary> /// <param name="jfield">JSON object for the field</param> /// <param name="pos">position number of the field</param> /// <param name="names">list of named schemas already read</param> /// <param name="encspace">enclosing namespace of the records schema</param> /// <returns>new Field object</returns> private static Field createField(JToken jfield, int pos, SchemaNames names, string encspace) { var name = JsonHelper.GetRequiredString(jfield, "name"); var doc = JsonHelper.GetOptionalString(jfield, "doc"); var jorder = JsonHelper.GetOptionalString(jfield, "order"); Field.SortOrder sortorder = Field.SortOrder.ignore; if (null != jorder) { sortorder = (Field.SortOrder)Enum.Parse(typeof(Field.SortOrder), jorder); } var aliases = Field.GetAliases(jfield); var props = Schema.GetProperties(jfield); var defaultValue = jfield["default"]; JToken jtype = jfield["type"]; if (null == jtype) { throw new SchemaParseException("'type' was not found for field: " + name); } var schema = Schema.ParseJson(jtype, names, encspace); return(new Field(schema, name, aliases, pos, doc, defaultValue, sortorder, props)); }
/// <summary> /// Writes the Field class in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schemas already written</param> /// <param name="encspace">enclosing namespace for the field</param> protected internal void writeJson(JsonTextWriter writer, SchemaNames names, string encspace) { writer.WriteStartObject(); JsonHelper.writeIfNotNullOrEmpty(writer, "name", this.Name); JsonHelper.writeIfNotNullOrEmpty(writer, "doc", this.Documentation); if (null != this.DefaultValue) { writer.WritePropertyName("default"); this.DefaultValue.WriteTo(writer, null); } if (null != this.Schema) { writer.WritePropertyName("type"); Schema.WriteJson(writer, names, encspace); } if (null != this.Props) { this.Props.WriteJson(writer); } if (null != aliases) { writer.WritePropertyName("aliases"); writer.WriteStartArray(); foreach (string name in aliases) { writer.WriteValue(name); } writer.WriteEndArray(); } writer.WriteEndObject(); }
/// <summary> /// Writes schema object in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schemas already written</param> /// <param name="encspace">enclosing namespace of the schema</param> protected internal virtual void WriteJson(JsonTextWriter writer, SchemaNames names, string encspace) { writeStartObject(writer); WriteJsonFields(writer, names, encspace); if (null != this.Props) { Props.WriteJson(writer); } writer.WriteEndObject(); }
/// <summary> /// Constructor for enum schema /// </summary> /// <param name="name">name of enum</param> /// <param name="aliases">list of aliases for the name</param> /// <param name="symbols">list of enum symbols</param> /// <param name="symbolMap">map of enum symbols and value</param> /// <param name="names">list of named schema already read</param> private EnumSchema(SchemaName name, IList <SchemaName> aliases, List <string> symbols, IDictionary <String, int> symbolMap, PropertyMap props, SchemaNames names) : base(Type.Enumeration, name, aliases, props, names) { if (null == name.Name) { throw new SchemaParseException("name cannot be null for enum schema."); } this.Symbols = symbols; this.symbolMap = symbolMap; }
/// <summary> /// Static function to return new instance of map schema /// </summary> /// <param name="jtok">JSON object for the map schema</param> /// <param name="names">list of named schemas already read</param> /// <param name="encspace">enclosing namespace of the map schema</param> /// <returns></returns> internal static MapSchema NewInstance(JToken jtok, PropertyMap props, SchemaNames names, string encspace) { JToken jvalue = jtok["values"]; if (null == jvalue) { throw new AvroTypeException("Map does not have 'values'"); } return(new MapSchema(Schema.ParseJson(jvalue, names, encspace), props)); }
/// <summary> /// Static class to return a new instance of ArraySchema /// </summary> /// <param name="jtok">JSON object for the array schema</param> /// <param name="names">list of named schemas already parsed</param> /// <param name="encspace">enclosing namespace for the array schema</param> /// <returns></returns> internal static ArraySchema NewInstance(JToken jtok, PropertyMap props, SchemaNames names, string encspace) { JToken jitem = jtok["items"]; if (null == jitem) { throw new AvroTypeException("Array does not have 'items'"); } return(new ArraySchema(Schema.ParseJson(jitem, names, encspace), props)); }
/// <summary> /// Writes enum schema in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schema already written</param> /// <param name="encspace">enclosing namespace of the enum schema</param> protected internal override void WriteJsonFields(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace) { base.WriteJsonFields(writer, names, encspace); writer.WritePropertyName("symbols"); writer.WriteStartArray(); foreach (string s in this.Symbols) { writer.WriteValue(s); } writer.WriteEndArray(); }
/// <summary> /// Constructor for the record schema /// </summary> /// <param name="type">type of record schema, either record or error</param> /// <param name="name">name of the record schema</param> /// <param name="aliases">list of aliases for the record name</param> /// <param name="fields">list of fields for the record</param> /// <param name="request">true if this is an anonymous record with 'request' instead of 'fields'</param> /// <param name="fieldMap">map of field names and field objects</param> /// <param name="names">list of named schema already read</param> private RecordSchema(Type type, SchemaName name, IList <SchemaName> aliases, PropertyMap props, List <Field> fields, bool request, IDictionary <string, Field> fieldMap, IDictionary <string, Field> fieldAliasMap, SchemaNames names) : base(type, name, aliases, props, names) { if (!request && null == name.Name) { throw new SchemaParseException("name cannot be null for record schema."); } this.Fields = fields; this.request = request; this.fieldLookup = fieldMap; this.fieldAliasLookup = fieldAliasMap; }
/// <summary> /// Writes the schema name in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schemas already written</param> /// <param name="encspace">enclosing namespace of the schema</param> internal void WriteJson(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace) { if (null != this.Name) // write only if not anonymous { JsonHelper.writeIfNotNullOrEmpty(writer, "name", this.Name); if (!String.IsNullOrEmpty(this.Space)) { JsonHelper.writeIfNotNullOrEmpty(writer, "namespace", this.Space); } else if (!String.IsNullOrEmpty(this.EncSpace)) // need to put enclosing name space for code generated classes { JsonHelper.writeIfNotNullOrEmpty(writer, "namespace", this.EncSpace); } } }
/// <summary> /// Parses a JSON string to create a new schema object /// </summary> /// <param name="json">JSON string</param> /// <param name="names">list of named schemas already read</param> /// <param name="encspace">enclosing namespace of the schema</param> /// <returns>new Schema object</returns> internal static Schema Parse(string json, SchemaNames names, string encspace) { Schema sc = PrimitiveSchema.NewInstance(json); if (null != sc) { return(sc); } try { bool IsArray = json.StartsWith("[") && json.EndsWith("]"); JContainer j = IsArray ? (JContainer)JArray.Parse(json) : (JContainer)JObject.Parse(json); return(ParseJson(j, names, encspace)); } catch (Newtonsoft.Json.JsonSerializationException ex) { throw new SchemaParseException("Could not parse. " + ex.Message + Environment.NewLine + json); } }
/// <summary> /// Static function to return new instance of the record schema /// </summary> /// <param name="type">type of record schema, either record or error</param> /// <param name="jtok">JSON object for the record schema</param> /// <param name="names">list of named schema already read</param> /// <param name="encspace">enclosing namespace of the records schema</param> /// <returns>new RecordSchema object</returns> internal static RecordSchema NewInstance(Type type, JToken jtok, PropertyMap props, SchemaNames names, string encspace) { bool request = false; JToken jfields = jtok["fields"]; // normal record if (null == jfields) { jfields = jtok["request"]; // anonymous record from messages if (null != jfields) { request = true; } } if (null == jfields) { throw new SchemaParseException("'fields' cannot be null for record"); } if (jfields.Type != JTokenType.Array) { throw new SchemaParseException("'fields' not an array for record"); } var name = GetName(jtok, encspace); var aliases = NamedSchema.GetAliases(jtok, name.Space, name.EncSpace); var fields = new List <Field>(); var fieldMap = new Dictionary <string, Field>(); var fieldAliasMap = new Dictionary <string, Field>(); var result = new RecordSchema(type, name, aliases, props, fields, request, fieldMap, fieldAliasMap, names); int fieldPos = 0; foreach (JObject jfield in jfields) { string fieldName = JsonHelper.GetRequiredString(jfield, "name"); Field field = createField(jfield, fieldPos++, names, name.Namespace); // add record namespace for field look up fields.Add(field); addToFieldMap(fieldMap, fieldName, field); addToFieldMap(fieldAliasMap, fieldName, field); if (null != field.aliases) // add aliases to field lookup map so reader function will find it when writer field name appears only as an alias on the reader field { foreach (string alias in field.aliases) { addToFieldMap(fieldAliasMap, alias, field); } } } return(result); }
/// <summary> /// Writes the records schema in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schemas already written</param> /// <param name="encspace">enclosing namespace of the record schema</param> protected internal override void WriteJsonFields(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace) { base.WriteJsonFields(writer, names, encspace); // we allow reading for empty fields, so writing of records with empty fields are allowed as well if (request) { writer.WritePropertyName("request"); } else { writer.WritePropertyName("fields"); } writer.WriteStartArray(); if (null != this.Fields && this.Fields.Count > 0) { foreach (Field field in this) { field.writeJson(writer, names, this.Namespace); // use the namespace of the record for the fields } } writer.WriteEndArray(); }
/// <summary> /// Constructor /// </summary> /// <param name="name">name of the fixed schema</param> /// <param name="aliases">list of aliases for the name</param> /// <param name="size">fixed size</param> /// <param name="names">list of named schema already parsed in</param> private FixedSchema(SchemaName name, IList <SchemaName> aliases, int size, PropertyMap props, SchemaNames names) : base(Type.Fixed, name, aliases, props, names) { if (null == name.Name) { throw new SchemaParseException("name cannot be null for fixed schema."); } if (size <= 0) { throw new ArgumentOutOfRangeException("size", "size must be greater than zero."); } this.Size = size; }
/// <summary> /// Writes named schema in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schemas already written</param> /// <param name="encspace">enclosing namespace of the named schema</param> protected internal override void WriteJsonFields(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace) { this.SchemaName.WriteJson(writer, names, encspace); if (null != aliases) { writer.WritePropertyName("aliases"); writer.WriteStartArray(); foreach (SchemaName name in aliases) { string fullname = (null != name.Space) ? name.Space + "." + name.Name : name.Name; writer.WriteValue(fullname); } writer.WriteEndArray(); } }
/// <summary> /// Writes named schema in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schemas already written</param> /// <param name="encspace">enclosing namespace of the named schema</param> protected internal override void WriteJson(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace) { if (!names.Add(this)) { // schema is already in the list, write name only SchemaName schemaName = this.SchemaName; string name; if (schemaName.Namespace != encspace) { name = schemaName.Namespace + "." + schemaName.Name; // we need to add the qualifying namespace of the target schema if it's not the same as current namespace } else { name = schemaName.Name; } writer.WriteValue(name); } else { // schema is not in the list, write full schema definition base.WriteJson(writer, names, encspace); } }
/// <summary> /// Constructor for named schema class /// </summary> /// <param name="type">schema type</param> /// <param name="name">name</param> /// <param name="names">list of named schemas already read</param> protected NamedSchema(Type type, SchemaName name, IList <SchemaName> aliases, PropertyMap props, SchemaNames names) : base(type, props) { this.SchemaName = name; this.aliases = aliases; if (null != name.Name) // Added this check for anonymous records inside Message { if (!names.Add(name, this)) { throw new AvroException("Duplicate schema name " + name.Fullname); } } }
/// <summary> /// Writes the fixed schema class in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schema already written</param> /// <param name="encspace">enclosing namespace for the fixed schema</param> protected internal override void WriteJsonFields(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace) { base.WriteJsonFields(writer, names, encspace); writer.WritePropertyName("size"); writer.WriteValue(this.Size); }
/// <summary> /// Writes primitive schema in JSON format /// </summary> /// <param name="w"></param> /// <param name="names"></param> /// <param name="encspace"></param> protected internal override void WriteJson(JsonTextWriter w, SchemaNames names, string encspace) { w.WriteValue(Name); }
/// <summary> /// Default implementation for writing schema properties in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schemas already written</param> /// <param name="encspace">enclosing namespace of the schema</param> protected internal virtual void WriteJsonFields(JsonTextWriter writer, SchemaNames names, string encspace) { }
/// <summary> /// Writes the array schema in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schemas already written</param> /// <param name="encspace">enclosing namespace</param> protected internal override void WriteJsonFields(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace) { writer.WritePropertyName("items"); ItemSchema.WriteJson(writer, names, encspace); }
/// <summary> /// Static class to return new instance of schema object /// </summary> /// <param name="jtok">JSON object</param> /// <param name="names">list of named schemas already read</param> /// <param name="encspace">enclosing namespace of the schema</param> /// <returns>new Schema object</returns> internal static Schema ParseJson(JToken jtok, SchemaNames names, string encspace) { if (null == jtok) { throw new ArgumentNullException("j", "j cannot be null."); } if (jtok.Type == JTokenType.String) // primitive schema with no 'type' property or primitive or named type of a record field { string value = (string)jtok; PrimitiveSchema ps = PrimitiveSchema.NewInstance(value); if (null != ps) { return(ps); } NamedSchema schema = null; if (names.TryGetValue(value, null, encspace, out schema)) { return(schema); } throw new SchemaParseException("Undefined name: " + value); } if (jtok is JArray) // union schema with no 'type' property or union type for a record field { return(UnionSchema.NewInstance(jtok as JArray, null, names, encspace)); } if (jtok is JObject) // JSON object with open/close parenthesis, it must have a 'type' property { JObject jo = jtok as JObject; JToken jtype = jo["type"]; if (null == jtype) { throw new SchemaParseException("Property type is required"); } var props = Schema.GetProperties(jtok); if (jtype.Type == JTokenType.String) { string type = (string)jtype; if (type.Equals("array")) { return(ArraySchema.NewInstance(jtok, props, names, encspace)); } if (type.Equals("map")) { return(MapSchema.NewInstance(jtok, props, names, encspace)); } Schema schema = PrimitiveSchema.NewInstance((string)type, props); if (null != schema) { return(schema); } return(NamedSchema.NewInstance(jo, props, names, encspace)); } else if (jtype.Type == JTokenType.Array) { return(UnionSchema.NewInstance(jtype as JArray, props, names, encspace)); } } throw new AvroTypeException("Invalid JSON for schema: " + jtok); }
/// <summary> /// Writes union schema in JSON format /// </summary> /// <param name="writer">JSON writer</param> /// <param name="names">list of named schemas already written</param> /// <param name="encspace">enclosing namespace of the schema</param> protected internal override void WriteJson(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace) { writer.WriteStartArray(); foreach (Schema schema in this.Schemas) { schema.WriteJson(writer, names, encspace); } writer.WriteEndArray(); }