/// <summary>
        /// grabs the Field/PropertyInfo of <paramref name="obj"/> for <paramref name="key"/> and sets it
        /// with the next element in the JSON string.
        /// </summary>
        /// <param name="obj">Object.</param>
        /// <param name="key">Key.</param>
        private void SetNextValueOnObject(ref object obj, string key)
        {
            FieldInfo field = _cacheResolver.GetField(obj.GetType(), key);

            if (field != null)
            {
                if (_cacheResolver.IsMemberInfoEncodeableOrDecodeable(field, field.IsPublic))
                {
                    object value = DecodeValue(GetNextToken(), field.FieldType);
                    if (obj.GetType().IsValueType)
                    {
                        // obj is a struct.
                        object instanceRef = obj;
                        field.SetValue(instanceRef, value);
                        obj = instanceRef;
                        return;
                    }

                    // obj is a class.
                    field.SetValue(obj, value);
                    return;
                }
            }

            PropertyInfo property = _cacheResolver.GetProperty(obj.GetType(), key);

            if (property != null)
            {
                if (property != null && property.CanWrite && property.IsDefined(JsonConstants.includeAttrType))
                {
                    object value = DecodeValue(GetNextToken(), property.PropertyType);
                    if (obj.GetType().IsValueType)
                    {
                        // obj is a struct.
                        object instanceRef = obj;
                        property.SetValue(instanceRef, value);
                        obj = instanceRef;
                        return;
                    }

                    // obj is a class.
                    property.SetValue(obj, value);
                    return;
                }
            }

            // we still need to eat the value even if we didnt set it so the parser is in the right spot
            object orhpanedValue = DecodeValueUntyped(GetNextToken());

            // check for a JsonConverter and use it if we have one
            JsonTypeConverter converter = _settings?.GetTypeConverterForType(obj.GetType());

            if (converter != null && converter.CanRead)
            {
                converter.OnFoundCustomData(obj, key, orhpanedValue);
            }
        }
Beispiel #2
0
        private void EncodeObject(object value, bool forceTypeHint)
        {
            Type type = value.GetType();

            WriteStartObject();

            // if this returns true, we have a reference so we are done
            if (WriteOptionalReferenceData(value))
            {
                WriteEndObject();
                return;
            }

            WriteOptionalTypeHint(type, forceTypeHint);

            // check for an override converter and use it if present
            JsonTypeConverter converter = _settings.GetTypeConverterForType(type);

            if (converter != null && converter.CanWrite)
            {
                converter.WriteJson(this, value);
                if (converter.WantsExclusiveWrite)
                {
                    WriteEndObject();
                    return;
                }
            }

            foreach (System.Reflection.FieldInfo field in _cacheResolver.GetEncodableFieldsForType(type))
            {
                WriteValueDelimiter();
                EncodeString(field.Name);
                AppendColon();
                EncodeValue(field.GetValue(value));
            }

            foreach (System.Reflection.PropertyInfo property in _cacheResolver.GetEncodablePropertiesForType(type))
            {
                if (property.CanRead)
                {
                    WriteValueDelimiter();
                    EncodeString(property.Name);
                    AppendColon();
                    try {
                        EncodeValue(property.GetValue(value, null));
                    }
                    catch (Exception e) {
                        // encode failed. stick a default value in there
                        EncodeValue(type.IsValueType ? Activator.CreateInstance(type) : null);
                        System.Console.WriteLine($"Failed to write property {property.Name} for type {type.Name}. {e}");
                    }
                }
            }

            WriteEndObject();
        }