public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            object retValue = null;

            if (_fc.CustomSerializer == null)
            {
                if (_fc.ValueConverter == null)
                {
                    retValue = serializer.Deserialize(reader, objectType);
                }
                else
                {
                    retValue = _fc.ValueConverter(serializer.Deserialize(reader, typeof(string)));
                }
            }
            else
            {
                retValue = _fc.CustomSerializer(reader);
            }

            if (retValue != null)
            {
                retValue = ChoConvert.ConvertFrom(retValue, objectType, null, _fc.PropConverters, _fc.PropConverterParams, _culture);
            }

            Validate(retValue);

            return(retValue);
        }
        private void HandleCollection(JToken[] jTokens, KeyValuePair <string, ChoJSONRecordFieldConfiguration> kvp)
        {
            if (false) //typeof(ICollection).IsAssignableFrom(kvp.Value.FieldType) && !kvp.Value.FieldType.IsArray)
            {
                Type           itemType = kvp.Value.FieldType.GetItemType();
                IList <object> list     = new List <object>();
                foreach (var jt in jTokens)
                {
                    list.Add(jt.ToObject(itemType));
                }

                MethodInfo method        = GetType().GetMethod("CloneListAs", BindingFlags.NonPublic | BindingFlags.Instance);
                MethodInfo genericMethod = method.MakeGenericMethod(itemType);
                fieldValue = genericMethod.Invoke(this, new[] { list });
            }
            else
            {
                List <object> list = new List <object>();
                foreach (var jt in jTokens)
                {
                    if (fieldConfig.ValueConverter != null)
                    {
                        list.Add(fieldConfig.ValueConverter(jt));
                    }
                    else
                    {
                        list.Add(ToObject(jt, kvp.Value.FieldType));
                    }
                }
                fieldValue = list.ToArray();
            }
        }
Exemple #3
0
        private bool FillRecord(object rec, Tuple <long, JObject> pair)
        {
            long    lineNo;
            JObject node;
            JToken  jToken = null;

            JToken[] jTokens = null;

            lineNo = pair.Item1;
            node   = pair.Item2;

            fieldValue  = null;
            fieldConfig = null;
            pi          = null;
            //IDictionary<string, object> dictValues = ToDictionary(node);

            foreach (KeyValuePair <string, ChoJSONRecordFieldConfiguration> kvp in Configuration.RecordFieldConfigurationsDict)
            {
                fieldValue  = null;
                fieldConfig = kvp.Value;
                if (Configuration.PIDict != null)
                {
                    Configuration.PIDict.TryGetValue(kvp.Key, out pi);
                }

                //fieldValue = dictValues[kvp.Key];
                if (!kvp.Value.JSONPath.IsNullOrWhiteSpace())
                {
                    jTokens = node.SelectTokens(kvp.Value.JSONPath).ToArray();
                    jToken  = jTokens.FirstOrDefault();
                    if (jToken == null)
                    {
                        if (Configuration.ColumnCountStrict)
                        {
                            throw new ChoParserException("No matching '{0}' field found.".FormatString(fieldConfig.FieldName));
                        }
                    }
                }
                else
                {
                    if (!node.TryGetValue(kvp.Key, StringComparison.CurrentCultureIgnoreCase, out jToken))
                    {
                        if (Configuration.ColumnCountStrict)
                        {
                            throw new ChoParserException("No matching '{0}' field found.".FormatString(fieldConfig.FieldName));
                        }
                    }
                }

                fieldValue = jTokens != null ? (object)jTokens : jToken;

                if (!RaiseBeforeRecordFieldLoad(rec, pair.Item1, kvp.Key, ref fieldValue))
                {
                    continue;
                }

                if (fieldConfig.ValueConverter != null)
                {
                    fieldValue = fieldConfig.ValueConverter(fieldValue);
                }

                if (Configuration.IsDynamicObject) //rec is ExpandoObject)
                {
                    if (kvp.Value.FieldType != null)
                    {
                        if (fieldValue is JToken)
                        {
                            fieldValue = ((JToken)fieldValue).ToObject(kvp.Value.FieldType);
                        }
                        else if (fieldValue is JToken[])
                        {
                            jTokens    = (JToken[])fieldValue;
                            fieldValue = null;
                            HandleCollection(jTokens, kvp);
                        }
                    }
                }
                else
                {
                    if (pi != null)
                    {
                        kvp.Value.FieldType = pi.PropertyType;
                    }
                    else
                    {
                        kvp.Value.FieldType = typeof(string);
                    }

                    if (fieldValue is JToken)
                    {
                        fieldValue = ((JToken)fieldValue).ToObject(kvp.Value.FieldType);
                    }
                    else if (fieldValue is JToken[])
                    {
                        jTokens    = (JToken[])fieldValue;
                        fieldValue = null;
                        HandleCollection(jTokens, kvp);
                    }
                }

                if (!(fieldValue is ICollection))
                {
                    if (fieldValue is string)
                    {
                        fieldValue = CleanFieldValue(fieldConfig, kvp.Value.FieldType, fieldValue as string);
                    }
                    else if (fieldValue is JValue)
                    {
                        if (((JValue)fieldValue).Value is string)
                        {
                            fieldValue = CleanFieldValue(fieldConfig, kvp.Value.FieldType, fieldValue.ToString());
                        }
                        else
                        {
                            fieldValue = ((JValue)fieldValue).Value;
                        }
                    }
                }

                try
                {
                    bool ignoreFieldValue = fieldConfig.IgnoreFieldValue(fieldValue);
                    if (ignoreFieldValue)
                    {
                        fieldValue = fieldConfig.IsDefaultValueSpecified ? fieldConfig.DefaultValue : null;
                    }

                    if (Configuration.IsDynamicObject)
                    {
                        var dict = rec as IDictionary <string, Object>;

                        dict.ConvertNSetMemberValue(kvp.Key, kvp.Value, ref fieldValue, Configuration.Culture);

                        if ((Configuration.ObjectValidationMode & ChoObjectValidationMode.MemberLevel) == ChoObjectValidationMode.MemberLevel)
                        {
                            dict.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                        }
                    }
                    else
                    {
                        if (pi != null)
                        {
                            rec.ConvertNSetMemberValue(kvp.Key, kvp.Value, ref fieldValue, Configuration.Culture);
                        }
                        else
                        {
                            throw new ChoMissingRecordFieldException("Missing '{0}' property in {1} type.".FormatString(kvp.Key, ChoType.GetTypeName(rec)));
                        }

                        if ((Configuration.ObjectValidationMode & ChoObjectValidationMode.MemberLevel) == ChoObjectValidationMode.MemberLevel)
                        {
                            rec.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                        }
                    }

                    if (!RaiseAfterRecordFieldLoad(rec, pair.Item1, kvp.Key, fieldValue))
                    {
                        return(false);
                    }
                }
                catch (ChoParserException)
                {
                    Reader.IsValid = false;
                    throw;
                }
                catch (ChoMissingRecordFieldException)
                {
                    Reader.IsValid = false;
                    if (Configuration.ThrowAndStopOnMissingField)
                    {
                        throw;
                    }
                }
                catch (Exception ex)
                {
                    Reader.IsValid = false;
                    ChoETLFramework.HandleException(ex);

                    if (fieldConfig.ErrorMode == ChoErrorMode.ThrowAndStop)
                    {
                        throw;
                    }

                    try
                    {
                        if (Configuration.IsDynamicObject)
                        {
                            var dict = rec as IDictionary <string, Object>;

                            if (dict.SetFallbackValue(kvp.Key, kvp.Value, Configuration.Culture, ref fieldValue))
                            {
                                dict.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                            }
                            else if (dict.SetDefaultValue(kvp.Key, kvp.Value, Configuration.Culture))
                            {
                                dict.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                            }
                            else
                            {
                                throw new ChoReaderException($"Failed to parse '{fieldValue}' value for '{fieldConfig.FieldName}' field.", ex);
                            }
                        }
                        else if (pi != null)
                        {
                            if (rec.SetFallbackValue(kvp.Key, kvp.Value, Configuration.Culture))
                            {
                                rec.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                            }
                            else if (rec.SetDefaultValue(kvp.Key, kvp.Value, Configuration.Culture))
                            {
                                rec.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                            }
                            else
                            {
                                throw new ChoReaderException($"Failed to parse '{fieldValue}' value for '{fieldConfig.FieldName}' field.", ex);
                            }
                        }
                        else
                        {
                            throw new ChoReaderException($"Failed to parse '{fieldValue}' value for '{fieldConfig.FieldName}' field.", ex);
                        }
                    }
                    catch (Exception innerEx)
                    {
                        if (ex == innerEx.InnerException)
                        {
                            if (fieldConfig.ErrorMode == ChoErrorMode.IgnoreAndContinue)
                            {
                                continue;
                            }
                            else
                            {
                                if (!RaiseRecordFieldLoadError(rec, pair.Item1, kvp.Key, fieldValue, ex))
                                {
                                    throw new ChoReaderException($"Failed to parse '{fieldValue}' value for '{fieldConfig.FieldName}' field.", ex);
                                }
                            }
                        }
                        else
                        {
                            throw new ChoReaderException("Failed to assign '{0}' fallback value to '{1}' field.".FormatString(fieldValue, fieldConfig.FieldName), innerEx);
                        }
                    }
                }
            }

            return(true);
        }
Exemple #4
0
        private bool ToText(long index, object rec, out string recText)
        {
            if (typeof(IChoScalarObject).IsAssignableFrom(Configuration.RecordType))
            {
                rec = Activator.CreateInstance(Configuration.RecordType, rec);
            }

            if (!Configuration.IsDynamicObject)
            {
                if (rec.ToTextIfCustomSerialization(out recText))
                {
                    return(true);
                }

                //Check if KVP object
                if (rec.GetType().IsKeyValueType())
                {
                    recText = SerializeObject(rec);
                    return(true);
                }
            }

            recText = null;
            if (rec == null)
            {
                if (Configuration.NullValueHandling == ChoNullValueHandling.Ignore)
                {
                    return(false);
                }
                else if (Configuration.NullValueHandling == ChoNullValueHandling.Default)
                {
                    rec = Activator.CreateInstance(Configuration.RecordType);
                }
                else
                {
                    recText = "{{{0}}}".FormatString(Configuration.Formatting == Formatting.Indented ? Configuration.EOLDelimiter : String.Empty);
                    return(true);
                }
            }

            StringBuilder msg        = new StringBuilder();
            object        fieldValue = null;
            string        fieldText  = null;
            ChoJSONRecordFieldConfiguration fieldConfig = null;

            if (Configuration.ColumnCountStrict)
            {
                CheckColumnsStrict(rec);
            }

            //bool firstColumn = true;
            PropertyInfo pi      = null;
            bool         isFirst = true;
            object       rootRec = rec;

            msg.AppendFormat("{{{0}", Configuration.Formatting == Formatting.Indented ? Configuration.EOLDelimiter : String.Empty);
            foreach (KeyValuePair <string, ChoJSONRecordFieldConfiguration> kvp in Configuration.RecordFieldConfigurationsDict)
            {
                fieldConfig = kvp.Value;
                fieldValue  = null;
                fieldText   = String.Empty;
                if (Configuration.PIDict != null)
                {
                    Configuration.PIDict.TryGetValue(kvp.Key, out pi);
                }
                rec = GetDeclaringRecord(kvp.Value.DeclaringMember, rootRec);

                if (Configuration.ThrowAndStopOnMissingField)
                {
                    if (Configuration.IsDynamicObject)
                    {
                        var dict = rec.ToDynamicObject() as IDictionary <string, Object>;
                        if (!dict.ContainsKey(kvp.Key))
                        {
                            throw new ChoMissingRecordFieldException("No matching property found in the object for '{0}' JSON node.".FormatString(fieldConfig.FieldName));
                        }
                    }
                    else
                    {
                        if (pi == null)
                        {
                            throw new ChoMissingRecordFieldException("No matching property found in the object for '{0}' JSON node.".FormatString(fieldConfig.FieldName));
                        }
                    }
                }

                try
                {
                    if (Configuration.IsDynamicObject)
                    {
                        IDictionary <string, Object> dict = rec.ToDynamicObject() as IDictionary <string, Object>;
                        fieldValue = dict[kvp.Key]; // dict.GetValue(kvp.Key, Configuration.FileHeaderConfiguration.IgnoreCase, Configuration.Culture);
                        if (kvp.Value.FieldType == null)
                        {
                            if (fieldValue == null)
                            {
                                kvp.Value.FieldType = typeof(string);
                            }
                            else
                            {
                                kvp.Value.FieldType = fieldValue.GetType();
                            }
                        }
                    }
                    else
                    {
                        if (pi != null)
                        {
                            fieldValue = ChoType.GetPropertyValue(rec, pi);
                            if (kvp.Value.FieldType == null)
                            {
                                kvp.Value.FieldType = pi.PropertyType;
                            }
                        }
                        else
                        {
                            kvp.Value.FieldType = typeof(string);
                        }
                    }

                    //Discover default value, use it if null
                    if (fieldValue == null)
                    {
                        if (fieldConfig.IsDefaultValueSpecified)
                        {
                            fieldValue = fieldConfig.DefaultValue;
                        }
                    }

                    if (!RaiseBeforeRecordFieldWrite(rec, index, kvp.Key, ref fieldValue))
                    {
                        return(false);
                    }

                    if (fieldConfig.ValueConverter != null)
                    {
                        fieldValue = fieldConfig.ValueConverter(fieldValue);
                    }
                    else
                    {
                        rec.GetNConvertMemberValue(kvp.Key, kvp.Value, Configuration.Culture, ref fieldValue, true);
                    }

                    if ((Configuration.ObjectValidationMode & ChoObjectValidationMode.ObjectLevel) == ChoObjectValidationMode.MemberLevel)
                    {
                        rec.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode, fieldValue);
                    }

                    if (!RaiseAfterRecordFieldWrite(rec, index, kvp.Key, fieldValue))
                    {
                        return(false);
                    }
                }
                catch (ChoParserException)
                {
                    throw;
                }
                catch (ChoMissingRecordFieldException)
                {
                    if (Configuration.ThrowAndStopOnMissingField)
                    {
                        throw;
                    }
                }
                catch (Exception ex)
                {
                    ChoETLFramework.HandleException(ref ex);

                    if (fieldConfig.ErrorMode == ChoErrorMode.ThrowAndStop)
                    {
                        throw;
                    }

                    try
                    {
                        if (Configuration.IsDynamicObject)
                        {
                            var dict = rec.ToDynamicObject() as IDictionary <string, Object>;

                            if (dict.GetFallbackValue(kvp.Key, kvp.Value, Configuration.Culture, ref fieldValue))
                            {
                                dict.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode, fieldValue);
                            }
                            else if (dict.GetDefaultValue(kvp.Key, kvp.Value, Configuration.Culture, ref fieldValue))
                            {
                                dict.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode, fieldValue);
                            }
                            else
                            {
                                var ex1 = new ChoWriterException($"Failed to write '{fieldValue}' value for '{fieldConfig.FieldName}' member.", ex);
                                fieldValue = null;
                                throw ex1;
                            }
                        }
                        else if (pi != null)
                        {
                            if (rec.GetFallbackValue(kvp.Key, kvp.Value, Configuration.Culture, ref fieldValue))
                            {
                                rec.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                            }
                            else if (rec.GetDefaultValue(kvp.Key, kvp.Value, Configuration.Culture, ref fieldValue))
                            {
                                rec.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode, fieldValue);
                            }
                            else
                            {
                                var ex1 = new ChoWriterException($"Failed to write '{fieldValue}' value for '{fieldConfig.FieldName}' member.", ex);
                                fieldValue = null;
                                throw ex1;
                            }
                        }
                        else
                        {
                            var ex1 = new ChoWriterException($"Failed to write '{fieldValue}' value for '{fieldConfig.FieldName}' member.", ex);
                            fieldValue = null;
                            throw ex1;
                        }
                    }
                    catch (Exception innerEx)
                    {
                        if (ex == innerEx.InnerException)
                        {
                            if (fieldConfig.ErrorMode == ChoErrorMode.IgnoreAndContinue)
                            {
                                continue;
                            }
                            else
                            {
                                if (!RaiseRecordFieldWriteError(rec, index, kvp.Key, fieldText, ex))
                                {
                                    throw new ChoWriterException($"Failed to write '{fieldValue}' value of '{kvp.Key}' member.", ex);
                                }
                            }
                        }
                        else
                        {
                            throw new ChoWriterException("Failed to use '{0}' fallback value for '{1}' member.".FormatString(fieldValue, kvp.Key), innerEx);
                        }
                    }
                }

                bool isSimple = true;

                if (RaiseRecordFieldSerialize(rec, index, kvp.Key, ref fieldValue))
                {
                    if (isFirst)
                    {
                        msg.AppendFormat("{1}{0}", fieldValue.ToNString(),
                                         Configuration.Formatting == Formatting.Indented ? " " : String.Empty);
                    }
                    else
                    {
                        msg.AppendFormat(",{1}{2}{0}", fieldValue.ToNString(),
                                         Configuration.Formatting == Formatting.Indented ? Configuration.EOLDelimiter : String.Empty,
                                         Configuration.Formatting == Formatting.Indented ? " " : String.Empty);
                    }
                }
                else
                {
                    Type ft = fieldValue == null ? typeof(object) : fieldValue.GetType();
                    if (fieldValue == null)
                    {
                        fieldText = "null";
                    }
                    else if (ft == typeof(string) || ft == typeof(char))
                    {
                        fieldText = JsonConvert.SerializeObject(NormalizeFieldValue(kvp.Key, fieldValue.ToString(), kvp.Value.Size, kvp.Value.Truncate, false, GetFieldValueJustification(kvp.Value.FieldValueJustification, kvp.Value.FieldType), GetFillChar(kvp.Value.FillChar, kvp.Value.FieldType), false));
                    }
                    else if (ft == typeof(DateTime))
                    {
                        fieldText = JsonConvert.SerializeObject(fieldValue);
                    }
                    else if (ft.IsEnum)
                    {
                        fieldText = JsonConvert.SerializeObject(fieldValue);
                    }
                    else if (ft == typeof(ChoCurrency))
                    {
                        fieldText = "\"{0}\"".FormatString(fieldValue.ToString());
                    }
                    else if (ft == typeof(bool))
                    {
                        fieldText = JsonConvert.SerializeObject(fieldValue);
                    }
                    else if (ft.IsNumeric())
                    {
                        fieldText = fieldValue.ToString();
                    }
                    else
                    {
                        isSimple = false;
                    }

                    if (isFirst)
                    {
                        msg.AppendFormat("{2}\"{0}\":{1}", fieldConfig.FieldName, isSimple ? " {0}".FormatString(fieldText) :
                                         Configuration.Formatting == Formatting.Indented ? SerializeObject(fieldValue, fieldConfig.UseJSONSerialization).Indent(1, " ") : SerializeObject(fieldValue, fieldConfig.UseJSONSerialization),
                                         Configuration.Formatting == Formatting.Indented ? " " : String.Empty);
                    }
                    else
                    {
                        msg.AppendFormat(",{2}{3}\"{0}\":{1}", fieldConfig.FieldName, isSimple ? " {0}".FormatString(fieldText) :
                                         Configuration.Formatting == Formatting.Indented ? SerializeObject(fieldValue, fieldConfig.UseJSONSerialization).Indent(1, " ") : SerializeObject(fieldValue, fieldConfig.UseJSONSerialization),
                                         Configuration.Formatting == Formatting.Indented ? Configuration.EOLDelimiter : String.Empty, Configuration.Formatting == Formatting.Indented ? " " : String.Empty);
                    }
                }
                isFirst = false;
            }
            msg.AppendFormat("{0}}}", Configuration.Formatting == Formatting.Indented ? Configuration.EOLDelimiter : String.Empty);
            recText = msg.ToString();
            return(true);
        }
        private bool FillRecord(object rec, Tuple <long, JObject> pair)
        {
            long    lineNo;
            JObject node;
            JToken  jToken = null;

            JToken[] jTokens = null;

            lineNo = pair.Item1;
            node   = pair.Item2;

            fieldValue  = null;
            fieldConfig = null;
            pi          = null;
            //IDictionary<string, object> dictValues = ToDictionary(node);

            if (!Configuration.IsDynamicObject)
            {
                if (rec.FillIfCustomSerialization(pair.Item2))
                {
                    return(true);
                }

                if (FillIfKeyValueObject(rec, pair))
                {
                    return(true);
                }
            }

            object rootRec = rec;

            foreach (KeyValuePair <string, ChoJSONRecordFieldConfiguration> kvp in Configuration.RecordFieldConfigurationsDict)
            {
                fieldValue  = null;
                fieldConfig = kvp.Value;
                if (Configuration.PIDict != null)
                {
                    Configuration.PIDict.TryGetValue(kvp.Key, out pi);
                }

                rec = GetDeclaringRecord(kvp.Value.DeclaringMember, rootRec);

                //fieldValue = dictValues[kvp.Key];
                if (!kvp.Value.JSONPath.IsNullOrWhiteSpace())
                {
                    jTokens = node.SelectTokens(kvp.Value.JSONPath).ToArray();
                    jToken  = jTokens.FirstOrDefault();
                    if (jToken == null)
                    {
                        if (Configuration.ColumnCountStrict)
                        {
                            throw new ChoParserException("No matching '{0}' field found.".FormatString(fieldConfig.FieldName));
                        }
                    }
                }
                else
                {
                    if (!node.TryGetValue(kvp.Key, StringComparison.CurrentCultureIgnoreCase, out jToken))
                    {
                        if (Configuration.ColumnCountStrict)
                        {
                            throw new ChoParserException("No matching '{0}' field found.".FormatString(fieldConfig.FieldName));
                        }
                    }
                }

                fieldValue = !jTokens.IsNullOrEmpty() ? (object)jTokens : jToken;

                if (!RaiseBeforeRecordFieldLoad(rec, pair.Item1, kvp.Key, ref fieldValue))
                {
                    continue;
                }

                if (Configuration.IsDynamicObject) //rec is ExpandoObject)
                {
                }
                else
                {
                    if (pi != null)
                    {
                        kvp.Value.FieldType = pi.PropertyType;
                    }
                    else
                    {
                        kvp.Value.FieldType = typeof(string);
                    }
                }


                if (fieldConfig.ValueConverter != null)
                {
                    fieldValue = fieldConfig.ValueConverter(fieldValue);
                }
                else
                {
                    if (fieldConfig.FieldType == null)
                    {
                        if (!fieldConfig.IsArray && fieldValue is JToken[])
                        {
                            fieldValue = ((JToken[])fieldValue).FirstOrDefault();
                            if (fieldValue is JArray)
                            {
                                fieldValue = ((JArray)fieldValue).FirstOrDefault();
                            }
                        }
                    }
                    else
                    {
                        if (!fieldConfig.FieldType.IsCollection() && fieldValue is JToken[])
                        {
                            fieldValue = ((JToken[])fieldValue).FirstOrDefault();
                            //if (fieldValue is JArray)
                            //{
                            //    fieldValue = ((JArray)fieldValue).FirstOrDefault();
                            //}
                        }
                    }

                    if (fieldConfig.FieldType == null ||
                        fieldConfig.FieldType == typeof(object) ||
                        fieldConfig.FieldType.GetItemType() == typeof(object))
                    {
                        if (fieldValue is JToken)
                        {
                            if (fieldConfig.ItemConverter != null)
                            {
                                fieldValue = fieldConfig.ItemConverter(fieldValue);
                            }
                            else
                            {
                                fieldValue = ToObject((JToken)fieldValue, null);
                            }
                        }
                        else if (fieldValue is JToken[])
                        {
                            List <object> arr = new List <object>();
                            foreach (var ele in (JToken[])fieldValue)
                            {
                                if (fieldConfig.ItemConverter != null)
                                {
                                    arr.Add(fieldConfig.ItemConverter(ele));
                                }
                                else
                                {
                                    arr.Add(ToObject(ele, null));
                                }
                            }

                            fieldValue = arr.ToArray();
                        }
                    }
                    else if (fieldConfig.FieldType == typeof(string) || fieldConfig.FieldType.IsSimple())
                    {
                        if (fieldValue is JToken[])
                        {
                            fieldValue = ((JToken[])fieldValue).FirstOrDefault();
                        }

                        if (fieldValue is JToken)
                        {
                            if (fieldConfig.ItemConverter != null)
                            {
                                fieldValue = fieldConfig.ItemConverter(fieldValue);
                            }
                            else
                            {
                                fieldValue = ToObject((JToken)fieldValue, fieldConfig.FieldType);
                            }
                        }
                    }
                    //else if (fieldConfig.FieldType.IsCollection())
                    //{
                    //    List<object> list = new List<object>();
                    //    Type itemType = fieldConfig.FieldType.GetItemType().GetUnderlyingType();

                    //    if (fieldValue is JToken)
                    //    {
                    //        if (fieldConfig.ItemConverter != null)
                    //            fieldValue = fieldConfig.ItemConverter(fieldValue);
                    //        else
                    //            fieldValue = ToObject((JToken)fieldValue, itemType);
                    //    }
                    //    else if (fieldValue is JToken[])
                    //    {
                    //        foreach (var ele in (JToken[])fieldValue)
                    //        {
                    //            if (fieldConfig.ItemConverter != null)
                    //                list.Add(fieldConfig.ItemConverter(ele));
                    //            else
                    //            {
                    //                fieldValue = ToObject(ele, itemType);
                    //            }
                    //        }
                    //        fieldValue = list.ToArray();
                    //    }
                    //}
                    else
                    {
                        List <object> list     = new List <object>();
                        Type          itemType = fieldConfig.FieldType.GetUnderlyingType().GetItemType().GetUnderlyingType();

                        if (fieldValue is JToken)
                        {
                            if (fieldConfig.ItemConverter != null)
                            {
                                fieldValue = fieldConfig.ItemConverter(fieldValue);
                            }
                            else
                            {
                                fieldValue = ToObject((JToken)fieldValue, itemType);
                            }
                        }
                        else if (fieldValue is JToken[])
                        {
                            var fi = ((JToken[])fieldValue).FirstOrDefault();

                            if (fi is JArray && !itemType.IsCollection())
                            {
                                if (fieldConfig.ItemConverter != null)
                                {
                                    fieldValue = fieldConfig.ItemConverter(fi);
                                }
                                else
                                {
                                    fieldValue = ToObject(fi, fieldConfig.FieldType);
                                }
                            }
                            else
                            {
                                foreach (var ele in (JToken[])fieldValue)
                                {
                                    if (fieldConfig.ItemConverter != null)
                                    {
                                        list.Add(fieldConfig.ItemConverter(ele));
                                    }
                                    else
                                    {
                                        list.Add(ToObject(ele, itemType));
                                    }
                                }
                                fieldValue = list.ToArray();
                            }
                        }
                    }
                }

                if (!(fieldValue is ICollection))
                {
                    if (fieldValue is string)
                    {
                        fieldValue = CleanFieldValue(fieldConfig, kvp.Value.FieldType, fieldValue as string);
                    }
                    else if (fieldValue is JValue)
                    {
                        if (((JValue)fieldValue).Value is string)
                        {
                            fieldValue = CleanFieldValue(fieldConfig, kvp.Value.FieldType, fieldValue.ToString());
                        }
                        else
                        {
                            fieldValue = ((JValue)fieldValue).Value;
                        }
                    }
                }

                try
                {
                    bool ignoreFieldValue = fieldConfig.IgnoreFieldValue(fieldValue);
                    if (ignoreFieldValue)
                    {
                        fieldValue = fieldConfig.IsDefaultValueSpecified ? fieldConfig.DefaultValue : null;
                    }

                    if (Configuration.IsDynamicObject)
                    {
                        var dict = rec as IDictionary <string, Object>;

                        dict.ConvertNSetMemberValue(kvp.Key, kvp.Value, ref fieldValue, Configuration.Culture);

                        if ((Configuration.ObjectValidationMode & ChoObjectValidationMode.MemberLevel) == ChoObjectValidationMode.MemberLevel)
                        {
                            dict.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                        }
                    }
                    else
                    {
                        if (pi != null)
                        {
                            rec.ConvertNSetMemberValue(kvp.Key, kvp.Value, ref fieldValue, Configuration.Culture);
                        }
                        else
                        {
                            throw new ChoMissingRecordFieldException("Missing '{0}' property in {1} type.".FormatString(kvp.Key, ChoType.GetTypeName(rec)));
                        }

                        if ((Configuration.ObjectValidationMode & ChoObjectValidationMode.MemberLevel) == ChoObjectValidationMode.MemberLevel)
                        {
                            rec.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                        }
                    }

                    if (!RaiseAfterRecordFieldLoad(rec, pair.Item1, kvp.Key, fieldValue))
                    {
                        return(false);
                    }
                }
                catch (ChoParserException)
                {
                    Reader.IsValid = false;
                    throw;
                }
                catch (ChoMissingRecordFieldException)
                {
                    Reader.IsValid = false;
                    if (Configuration.ThrowAndStopOnMissingField)
                    {
                        throw;
                    }
                }
                catch (Exception ex)
                {
                    Reader.IsValid = false;
                    ChoETLFramework.HandleException(ref ex);

                    if (fieldConfig.ErrorMode == ChoErrorMode.ThrowAndStop)
                    {
                        throw;
                    }

                    try
                    {
                        if (Configuration.IsDynamicObject)
                        {
                            var dict = rec as IDictionary <string, Object>;

                            if (dict.SetFallbackValue(kvp.Key, kvp.Value, Configuration.Culture, ref fieldValue))
                            {
                                dict.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                            }
                            else if (dict.SetDefaultValue(kvp.Key, kvp.Value, Configuration.Culture))
                            {
                                dict.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                            }
                            else if (ex is ValidationException)
                            {
                                throw;
                            }
                            else
                            {
                                throw new ChoReaderException($"Failed to parse '{fieldValue}' value for '{fieldConfig.FieldName}' field.", ex);
                            }
                        }
                        else if (pi != null)
                        {
                            if (rec.SetFallbackValue(kvp.Key, kvp.Value, Configuration.Culture))
                            {
                                rec.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                            }
                            else if (rec.SetDefaultValue(kvp.Key, kvp.Value, Configuration.Culture))
                            {
                                rec.DoMemberLevelValidation(kvp.Key, kvp.Value, Configuration.ObjectValidationMode);
                            }
                            else if (ex is ValidationException)
                            {
                                throw;
                            }
                            else
                            {
                                throw new ChoReaderException($"Failed to parse '{fieldValue}' value for '{fieldConfig.FieldName}' field.", ex);
                            }
                        }
                        else
                        {
                            throw new ChoReaderException($"Failed to parse '{fieldValue}' value for '{fieldConfig.FieldName}' field.", ex);
                        }
                    }
                    catch (Exception innerEx)
                    {
                        if (ex == innerEx.InnerException || ex is ValidationException)
                        {
                            if (fieldConfig.ErrorMode == ChoErrorMode.IgnoreAndContinue)
                            {
                                continue;
                            }
                            else
                            {
                                if (!RaiseRecordFieldLoadError(rec, pair.Item1, kvp.Key, fieldValue, ex))
                                {
                                    if (ex is ValidationException)
                                    {
                                        throw;
                                    }

                                    throw new ChoReaderException($"Failed to parse '{fieldValue}' value for '{fieldConfig.FieldName}' field.", ex);
                                }
                            }
                        }
                        else
                        {
                            throw new ChoReaderException("Failed to assign '{0}' fallback value to '{1}' field.".FormatString(fieldValue, fieldConfig.FieldName), innerEx);
                        }
                    }
                }
            }

            return(true);
        }