in Services/DataX.Flow/DataX.Flow.SchemaInference/Engine.cs [196:284]
private void GetSchemaStruct(JObject jObject, StructObject structObject, string keyPath)
{
if (structObject == null && string.IsNullOrEmpty(_errors.Where(e => e.Contains(keyPath)).FirstOrDefault()))
{
_errors.Add($"Error in generating schema for '{keyPath}'. Result holder is null");
return;
}
foreach (KeyValuePair<string, JToken> child in jObject)
{
string childkeyPath = $"{keyPath}.{child.Key}";
// This means the child is of type Struct object
if (child.Value.GetType() == typeof(JObject))
{
// Check if the field already exists. If not, create it. If it exists, ensure the type is as expected.
Field fKey = structObject.fields.Where(field => field.name == child.Key).FirstOrDefault();
StructObject childStructObject = null;
if (fKey == null)
{
childStructObject = new StructObject();
structObject.fields.Add(new Field(child.Key, childStructObject));
}
else if (fKey.type.GetType() == typeof(StructObject))
{
childStructObject = fKey.type as StructObject;
}
else
{
if (string.IsNullOrEmpty(_errors.Where(e => e.Contains($"'{childkeyPath}'")).FirstOrDefault()))
{
_errors.Add($"Conflict in schema. Key with path '{childkeyPath}' has different types");
}
continue;
}
GetSchemaStruct(child.Value as JObject, childStructObject, childkeyPath);
}
// This means the child is of type Array
if (child.Value.GetType() == typeof(JArray))
{
// Check if the field already exists. If not, create it. If it exists, ensure the type is as expected.
Field fKey = structObject.fields.Where(f => f.name == child.Key).FirstOrDefault();
Type childType = null;
if (fKey == null)
{
childType = new Type();
structObject.fields.Add(new Field(child.Key, childType));
}
else if (fKey.type.GetType() == typeof(Type))
{
childType = fKey.type as Type;
}
else
{
if (string.IsNullOrEmpty(_errors.Where(e => e.Contains($"'{childkeyPath}'")).FirstOrDefault()))
{
_errors.Add($"Conflict in schema. Key with path '{childkeyPath}' has different types");
}
continue;
}
GetSchemaArray(child.Value as JArray, childType, childkeyPath);
}
// This means the child is of simple type
if (child.Value.GetType() == typeof(JValue))
{
// Check if the field already exists. If not, create it. If it exists, ensure the type is as expected.
Field fKey = structObject.fields.Where(field => field.name == child.Key).FirstOrDefault();
string type = GetObjectType(child.Value);
if (fKey == null)
{
structObject.fields.Add(new Field(child.Key, type));
}
// If the key already exists, but is not of the same type then there is conflict in schema
else if (fKey.type.GetType() != type.GetType() || fKey.type.ToString() != type.ToString())
{
if (string.IsNullOrEmpty(_errors.Where(error => error.Contains($"'{childkeyPath}'")).FirstOrDefault()))
{
_errors.Add($"Conflict in schema. Key with path '{childkeyPath}' has different types");
}
}
}
}
}