Esempio n. 1
0
        // ===================[ Interface Methods ]===========================

        public JsonValue AppendNew(JsonBuilder valueBuilder)
        {
            int currTabbing = JsonHelper.EvaluteBegginningTabOffset(this, valueBuilder.BuilderSettings);

            int startIndex = this.OffsetInSource + this.StringValue.Length - 1;

            JsonHelper.FindInsertStart(this.Source.Text, ref startIndex);

            var trackerBuilder = new IndexTrackingStringBuilder(startIndex);

            if (this.Count > 0)
            {
                trackerBuilder.Write(",");
            }
            JsonBuilder.MakeNewline(trackerBuilder, currTabbing, valueBuilder.BuilderSettings);

            this.Source.BeginPlaceholderMode(trackerBuilder);
            JsonValue value = valueBuilder.BuildJsonValue(this.Source, trackerBuilder, currTabbing);

            this.Add(value);
            this.Source.PlaceholderSetupComplete();
            return(value);
        }
Esempio n. 2
0
        public JsonValue AppendNew(string key, JsonBuilder valueBuilder)
        {
            int currTabbing = JsonHelper.EvaluteBegginningTabOffset(this, valueBuilder.BuilderSettings);

            int startIndex = this.OffsetInSource + this.StringValue.Length - 1;

            JsonHelper.FindInsertStart(this.Source.Text, ref startIndex);

            var trackerBuilder = new IndexTrackingStringBuilder(startIndex);

            if (this.Count > 0)
            {
                trackerBuilder.Write(",");
            }

            JsonBuilder.MakeNewline(trackerBuilder, currTabbing, valueBuilder.BuilderSettings);

            // Add the key part. This will actually be invalid until the PlaceholderSetupComplete happens
            JsonBuilder.WritePropertyHeading(trackerBuilder, key, out int keyStart, valueBuilder.BuilderSettings);

            if (!valueBuilder.IsValue)
            {
                JsonBuilder.MakeNewline(trackerBuilder, currTabbing, valueBuilder.BuilderSettings);
            }


            this.Source.BeginPlaceholderMode(trackerBuilder);
            TrackedString trackedKey = new TrackedString(this.Source, keyStart, key);

            JsonValue value = valueBuilder.BuildJsonValue(this.Source, trackerBuilder, currTabbing);

            this.Add(trackedKey, value);
            this.Source.PlaceholderSetupComplete();

            return(value);
        }
Esempio n. 3
0
        /// <summary>
        /// The recursive utility that fills out a <see cref="JsonBuilder"/> based off of the passed in source
        /// </summary>
        /// <param name="source">The object to pull data from</param>
        /// <param name="target">The builder to fill out</param>
        public static void FillOutJsonBuilderForObject(object source, JsonBuilder target)
        {
            Type sourceType = source.GetType();
            bool isUsuallyQuoted;

            // If we're elevating one of the properties of this thing, as itself, then we need to
            //  alter the type we're operating on
            string elevatedPropertyName = sourceType.GetAttributes <JsonPropertyAsSelfAttribute>()?.FirstOrDefault()?.PropertyName;

            if (elevatedPropertyName != null)
            {
                PropertyInfo targetProp = sourceType.GetProperty(elevatedPropertyName, BindingFlags.Public | BindingFlags.Instance);
                if (targetProp != null)
                {
                    source     = targetProp.GetValue(source);
                    sourceType = source.GetType();
                }
            }

            // ----------- Handle Simple Values ------------
            if (_CheckForSettingsRegisteredSimpleValue(sourceType, source, out isUsuallyQuoted, out string value))
            {
                target.IsValueUsualQuoteTarget = isUsuallyQuoted;
                _SetValue(value);
                return;
            }

            // ----------- Handle Array ------------
            if (typeof(IEnumerable).IsAssignableFrom(sourceType))
            {
                JsonBuilder array           = target.StartArray();
                IEnumerable enumerableValue = (IEnumerable)source;
                if (enumerableValue != null)
                {
                    foreach (object arrayItemObj in enumerableValue)
                    {
                        // =================[ Null Array Item ]===================
                        if (arrayItemObj == null)
                        {
                            // We've got a null element, but bad news it's an array that means we
                            //  *MUST* preserver element order and add an empty element. If it's
                            //  not an array, order doesn't matter, so we'll just skip it.
                            if (sourceType.IsArray)
                            {
                                Type elementType = sourceType.GetElementType();
                                if (typeof(IEnumerable).IsAssignableFrom(elementType))
                                {
                                    var emptyChildArr = array.StartArray();
                                    emptyChildArr.End();
                                }
                                else if (elementType.IsSimpleType() || target.BuilderSettings.TryGetJsonValueStringMakerFor(elementType) != null)
                                {
                                    var item = array.AddArrayItem(String.Empty);
                                    item.IsValueUsualQuoteTarget = true;
                                }
                                else
                                {
                                    var document = array.StartDocument();
                                    document.End();
                                }
                            }

                            continue;
                        }

                        // =================[ Normal Array Item ]===================
                        // Simple array item
                        if (_CheckForSettingsRegisteredSimpleValue(arrayItemObj.GetType(), arrayItemObj, out isUsuallyQuoted, out string stringValue))
                        {
                            var item = array.AddArrayItem(stringValue);
                            item.IsValueUsualQuoteTarget = isUsuallyQuoted;
                        }
                        // Array of array item
                        else if (arrayItemObj is IEnumerable)
                        {
                            FillOutJsonBuilderForObject(arrayItemObj, array);
                        }
                        // Document array item
                        else
                        {
                            JsonBuilder arrayItem = array.StartDocument();
                            FillOutJsonBuilderForObject(arrayItemObj, arrayItem);
                        }
                    }
                }

                target.End();
                return;
            }

            // ----------- Handle KeyValuePair special case -----------
            if (target.BuilderSettings.HasAnyKVPTypeIdWriteInstructions &&
                sourceType.IsGenericType &&
                typeof(KeyValuePair <,>) == sourceType.GetGenericTypeDefinition())
            {
                // [Special Case] Array item documents get started when they're added
                if (!target.IsArrayItem)
                {
                    target = target.StartDocument();
                }

                PropertyInfo keyProp = sourceType.GetProperty("Key");
                object       keyObj  = keyProp.GetValue(source);
                if (TryGetTypeIdForType(target.BuilderSettings.KeyValuePairKeyTypeIdToWrite, keyObj?.GetType() ?? sourceType.GenericTypeArguments[0], out string keyTypeId))
                {
                    target.AddProperty(JsonDocument.kKVPKeyTypeIndicator, keyTypeId);
                }

                PropertyInfo valueProp = sourceType.GetProperty("Value");
                object       valueObj  = valueProp.GetValue(source);
                if (TryGetTypeIdForType(target.BuilderSettings.KeyValuePairValueTypeIdToWrite, valueObj?.GetType() ?? sourceType.GenericTypeArguments[1], out string valueTypeId))
                {
                    target.AddProperty(JsonDocument.kKVPValueTypeIndicator, valueTypeId);
                }

                _HandleApplyProperty(source, keyProp);
                _HandleApplyProperty(source, valueProp);
                return;
            }

            // ----------- Handle Document ------------
            PropertyInfo[] allProperties = GetPropertiesFrom(source.GetType(), true, false
#if WINDOWS_UWP
                                                             , target.BuilderSettings.UWP_RequireOptInViaDataMemberAttribute
#endif
                                                             );

            if (allProperties.Length == 0 && target.Parent != null)
            {
                target.Parent.Children.Remove(target);
                return;
            }

            // [Special Case] Array item documents get started when they're added
            if (!target.IsArrayItem)
            {
                target = target.StartDocument();
            }

            // Make sure to write out the type for the instance if requested
            if (TryGetTypeIdForType(target.BuilderSettings.TypeIdToWrite, sourceType, out string typeId))
            {
                target.AddProperty(JsonDocument.kTypeIndicator, typeId);
            }

            foreach (PropertyInfo prop in allProperties)
            {
                _HandleApplyProperty(source, prop);
            }

            // ----------- Handle Value (Simple Type) ------------
            void _HandleApplyProperty(object _propSource, PropertyInfo _propInfo)
            {
                object _sourceValue = _propInfo.GetValue(_propSource);

                if (_sourceValue != null)
                {
                    var runtimeTypeEval = _propInfo.GetAttributes <JsonRuntimeTypeEvalAttribute>()?.FirstOrDefault();
                    if (runtimeTypeEval != null && JsonHelper.TryGetTypeIdForType(runtimeTypeEval.TypeWriteTarget, _sourceValue?.GetType(), out string _foundTypeId))
                    {
                        JsonBuilder propertyObjectBuilder = target.StartProperty(_propInfo.Name).StartDocument();
                        propertyObjectBuilder.AddProperty(JsonDocument.kTypeIndicator, _foundTypeId);
                        JsonBuilder typedValueObjectBuilder = propertyObjectBuilder.StartProperty(JsonDocument.kRuntimeTypeEvalValue);
                        FillOutJsonBuilderForObject(_sourceValue, typedValueObjectBuilder);
                    }
                    else if (_CheckForSettingsRegisteredSimpleValue(_propInfo.PropertyType, _sourceValue, out isUsuallyQuoted, out string simpleStringValue))
                    {
                        var created = target.AddProperty(_propInfo.Name, simpleStringValue);
                        created.IsValueUsualQuoteTarget = isUsuallyQuoted;
                    }
                    else
                    {
                        JsonBuilder propertyBuilder = target.StartProperty(_propInfo.Name);
                        FillOutJsonBuilderForObject(_sourceValue, propertyBuilder);
                    }
                }
            }

            bool _CheckForSettingsRegisteredSimpleValue(Type _type, object _instance, out bool _isUsuallyQuoted, out string simplifiedStringValue)
            {
                _isUsuallyQuoted = false;
                var valueBuilder = target.BuilderSettings.TryGetJsonValueStringMakerFor(_type);

                if (valueBuilder != null)
                {
                    simplifiedStringValue = valueBuilder(_instance);
                    if (_type == typeof(string) || _type == typeof(char)
#if WINDOWS_UWP
                        || _type.IsEnum())
#else
                        || _type.IsEnum)
#endif
                    {
                        _isUsuallyQuoted = true;
                    }

                    return(true);
                }

                simplifiedStringValue = null;
                return(false);
            }

            void _SetValue(string _value)
            {
                if (target.IsValue)
                {
                    target.Value = _value;
                }
                else
                {
                    target.DocumentKVPValue       = new JsonBuilder(target);
                    target.DocumentKVPValue.Value = _value;
                }
            }
        }
Esempio n. 4
0
 internal JsonBuilder(JsonBuilder parent) : this(parent.BuilderSettings)
 {
     this.Parent = parent;
 }