Ejemplo n.º 1
0
        private static bool setOneField(Doc doc, Schema.FieldDef def, object fv, bool fromUI, DocReadOptions options)
        {
            var fieldCustomHandler = JsonHandlerAttribute.TryFind(def.MemberInfo);
            var converted          = cast(fv, def.Type, fromUI, options, fieldCustomHandler);

            if (converted != null)
            {
                doc.SetFieldValue(def, converted);
                return(true);
            }

            return(false);
        }//setOneField
Ejemplo n.º 2
0
        }//setOneField

        //Returns non null on success; may return null for collection sub-element in which case null=null and does not indicate failure
        private static object cast(object v, Type toType, bool fromUI, DocReadOptions options, JsonHandlerAttribute fieldCustomHandler = null)
        {
            //See #264 - the collection inability to cast has no amorphous data so it MUST throw
            //used only for collections inner calls
            if (v == null)
            {
                return(null);
            }

            var customHandler = fieldCustomHandler ?? JsonHandlerAttribute.TryFind(toType);

            if (customHandler != null)
            {
                var castResult = customHandler.TypeCastOnRead(v, toType, fromUI, options);

                if (castResult.Outcome >= JsonHandlerAttribute.TypeCastOutcome.ChangedTargetType)
                {
                    toType = castResult.ToType;
                }

                if (castResult.Outcome == JsonHandlerAttribute.TypeCastOutcome.ChangedSourceValue)
                {
                    v = castResult.Value;
                }
                else if (castResult.Outcome == JsonHandlerAttribute.TypeCastOutcome.HandledCast)
                {
                    return(castResult.Value);
                }
            }

            //object goes as is
            if (toType == typeof(object))
            {
                return(v);
            }

            //IJSONDataObject
            if (toType == typeof(IJsonDataObject))
            {
                if (v is IJsonDataObject)
                {
                    return(v);     //goes as is
                }
                if (v is string s) //string containing embedded JSON
                {
                    var jo = s.JsonToDataObject();
                    return(jo);
                }
            }

            //IJSONDataMap
            if (toType == typeof(JsonDataMap))
            {
                if (v is JsonDataMap)
                {
                    return(v);     //goes as is
                }
                if (v is string s) //string containing embedded JSON
                {
                    var jo = s.JsonToDataObject() as JsonDataMap;
                    return(jo);
                }
            }

            //IJSONDataArray
            if (toType == typeof(JsonDataArray))
            {
                if (v is JsonDataArray)
                {
                    return(v);     //goes as is
                }
                if (v is string s) //string containing embedded JSON
                {
                    var jo = s.JsonToDataObject() as JsonDataArray;
                    return(jo);
                }
            }

            var nntp = toType;

            if (nntp.IsGenericType && nntp.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                nntp = toType.GetGenericArguments()[0];
            }

            //20191217 DKh
            if (nntp == typeof(DateTime))
            {
                if (options.LocalDates)
                {
                    var d = v.AsDateTime(System.Globalization.DateTimeStyles.AssumeLocal);
                    return(d);
                }
                else //UTC (the default)
                {
                    var d = v.AsDateTime(System.Globalization.DateTimeStyles.AssumeUniversal | System.Globalization.DateTimeStyles.AdjustToUniversal);
                    return(d);
                }
            }
            //20191217 DKh


            //Custom JSON Readable (including config)
            if (typeof(IJsonReadable).IsAssignableFrom(nntp) || typeof(IConfigSectionNode).IsAssignableFrom(nntp))
            {
                var toAllocate = nntp;

                //Configuration requires special handling because nodes do not exist as independent entities and there
                //is master/detail relationship between them
                if (toAllocate == typeof(Configuration) ||
                    toAllocate == typeof(ConfigSectionNode) ||
                    toAllocate == typeof(IConfigSectionNode))
                {
                    toAllocate = typeof(MemoryConfiguration);
                }

                if (toAllocate.IsAbstract)
                {
                    throw new JSONDeserializationException(StringConsts.JSON_DESERIALIZATION_ABSTRACT_TYPE_ERROR.Args(toAllocate.Name, nameof(JsonHandlerAttribute)));
                }

                var newval = SerializationUtils.MakeNewObjectInstance(toAllocate) as IJsonReadable;
                var got    = newval.ReadAsJson(v, fromUI, options);//this may re-allocate the result based of newval

                if (!got.match)
                {
                    return(null);
                }

                if (typeof(IConfigSectionNode).IsAssignableFrom(nntp))
                {
                    return((got.self as Configuration)?.Root);
                }

                return(got.self);
            }

            //byte[] direct assignment w/o copies
            if (nntp == typeof(byte[]) && v is byte[] passed)
            {
                return(passed);
            }


            //field def = []
            if (toType.IsArray)
            {
                var fvseq = v as IEnumerable;
                if (fvseq == null)
                {
                    return(null);      //can not set non enumerable into array
                }
                var arr    = fvseq.Cast <object>().Select(e => cast(e, toType.GetElementType(), fromUI, options, fieldCustomHandler)).ToArray();
                var newval = Array.CreateInstance(toType.GetElementType(), arr.Length);
                for (var i = 0; i < newval.Length; i++)
                {
                    newval.SetValue(arr[i], i);
                }

                return(newval);
            }

            //field def = List<t>
            if (toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(List <>))
            {
                var fvseq = v as IEnumerable;
                if (fvseq == null)
                {
                    return(false);      //can not set non enumerable into List<t>
                }
                var arr    = fvseq.Cast <object>().Select(e => cast(e, toType.GetGenericArguments()[0], fromUI, options, fieldCustomHandler)).ToArray();
                var newval = SerializationUtils.MakeNewObjectInstance(toType) as IList;
                for (var i = 0; i < arr.Length; i++)
                {
                    newval.Add(arr[i]);
                }

                return(newval);
            }

            //last resort
            try
            {
                return(StringValueConversion.AsType(v.ToString(), toType, false));
            }
            catch
            {
                return(null);//the value could not be converted, and is going to go into amorphous bag if it is enabled
            }
        }
Ejemplo n.º 3
0
        private static void toDoc(Doc doc, DocReadOptions options, JsonDataMap jsonMap, ref string field, bool fromUI)
        {
            var amorph = doc as IAmorphousData;
            var schema = doc.Schema;

            foreach (var mfld in jsonMap)
            {
                field = mfld.Key;
                var fv = mfld.Value;

                //Multi-targeting for deserialization to TypedDoc from JSON
                Schema.FieldDef def;
                if (options.BindBy == DocReadOptions.By.CodeName)
                {
                    def = schema[field];
                }
                else
                {
                    def = schema.TryFindFieldByTargetedBackendName(options.TargetName, field);//what about case sensitive json name?
                }
                //No such field exists in a typed doc, try to put in amorphous data
                if (def == null)
                {
                    if (amorph != null)
                    {
                        if (amorph.AmorphousDataEnabled)
                        {
                            amorph.AmorphousData[mfld.Key] = fv;
                        }
                    }
                    continue;
                }

                if (fromUI && def.NonUI)
                {
                    continue;             //skip NonUI fields
                }
                //weed out NULLS here
                if (fv == null)
                {
                    doc.SetFieldValue(def, null);
                    continue;
                }

                //fv is NEVER NULL here
                var wasset = setOneField(doc, def, fv, fromUI, options); //<------------------- field assignment

                //try to put in amorphous data if could not be set in a field
                if (!wasset && amorph != null)
                {
                    if (amorph.AmorphousDataEnabled)
                    {
                        amorph.AmorphousData[mfld.Key] = fv;
                    }
                }
            }//foreach field in jsonMap

            //process FORM
            var form = doc as Form;

            if (form != null)
            {
                form.FormMode  = jsonMap[Form.JSON_MODE_PROPERTY].AsEnum <FormMode>(FormMode.Unspecified);
                form.CSRFToken = jsonMap[Form.JSON_CSRF_PROPERTY].AsString();
                var roundtrip = jsonMap[Form.JSON_ROUNDTRIP_PROPERTY].AsString();
                if (roundtrip.IsNotNullOrWhiteSpace())
                {
                    form.SetRoundtripBagFromJSONString(roundtrip);
                }
            }

            if (amorph != null && amorph.AmorphousDataEnabled)
            {
                amorph.AfterLoad(options.TargetName ?? "json");
            }
        }