/// <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} at '{jtok.Path}'");
}
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 at '{jtok.Path}'");
}
var props = Schema.GetProperties(jtok);
if (jtype.Type == JTokenType.String)
{
string type = (string)jtype;
if (type.Equals("array", StringComparison.Ordinal))
{
return(ArraySchema.NewInstance(jtok, props, names, encspace));
}
if (type.Equals("map", StringComparison.Ordinal))
{
return(MapSchema.NewInstance(jtok, props, names, encspace));
}
if (null != jo["logicalType"]) // logical type based on a primitive
{
return(LogicalSchema.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));
}
else if (jtype.Type == JTokenType.Object && null != jo["logicalType"]) // logical type based on a complex type
{
return(LogicalSchema.NewInstance(jtok, props, names, encspace));
}
}
throw new AvroTypeException($"Invalid JSON for schema: {jtok} at '{jtok.Path}'");
}