Exemple #1
0
        private void AddProperty(Type propertyType, PropertyInfo propertyInfo, Type classType, JsonSerializerOptions options)
        {
            JsonPropertyInfo jsonInfo = CreateProperty(propertyType, propertyType, propertyInfo, classType, options);

            if (propertyInfo != null)
            {
                string propertyName = propertyInfo.Name;

                // At this point propertyName is valid UTF16, so just call the simple UTF16->UTF8 encoder.
                byte[] propertyNameBytes = Encoding.UTF8.GetBytes(propertyName);
                jsonInfo._name = propertyNameBytes;

                // Cache the escaped name.
                int valueIdx = JsonWriterHelper.NeedsEscaping(propertyNameBytes);
                if (valueIdx == -1)
                {
                    jsonInfo._escapedName = propertyNameBytes;
                }
                else
                {
                    int length = JsonWriterHelper.GetMaxEscapedLength(propertyNameBytes.Length, valueIdx);

                    byte[] tempArray = ArrayPool <byte> .Shared.Rent(length);

                    JsonWriterHelper.EscapeString(propertyNameBytes, tempArray, valueIdx, out int written);
                    jsonInfo._escapedName = new byte[written];
                    tempArray.CopyTo(jsonInfo._escapedName, 0);

                    // We clear the array because it is "user data" (although a property name).
                    new Span <byte>(tempArray, 0, written).Clear();
                    ArrayPool <byte> .Shared.Return(tempArray);
                }

                _propertyRefs.Add(new PropertyRef(GetKey(propertyNameBytes), jsonInfo));
            }
            else
            {
                // A single property or an IEnumerable
                _propertyRefs.Add(new PropertyRef(0, jsonInfo));
            }
        }
Exemple #2
0
        private void DeterminePropertyName(JsonSerializerOptions options)
        {
            if (PropertyInfo == null)
            {
                return;
            }

            JsonPropertyNameAttribute nameAttribute = GetAttribute <JsonPropertyNameAttribute>(PropertyInfo);

            if (nameAttribute != null)
            {
                string name = nameAttribute.Name;
                if (name == null)
                {
                    ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameNull(ParentClassType, this);
                }

                NameAsString = name;
            }
            else if (options.PropertyNamingPolicy != null)
            {
                string name = options.PropertyNamingPolicy.ConvertName(PropertyInfo.Name);
                if (name == null)
                {
                    ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameNull(ParentClassType, this);
                }

                NameAsString = name;
            }
            else
            {
                NameAsString = PropertyInfo.Name;
            }

            Debug.Assert(NameAsString != null);

            // At this point propertyName is valid UTF16, so just call the simple UTF16->UTF8 encoder.
            Name = Encoding.UTF8.GetBytes(NameAsString);

            // Set the compare name.
            if (options.PropertyNameCaseInsensitive)
            {
                NameUsedToCompareAsString = NameAsString.ToUpperInvariant();
                NameUsedToCompare         = Encoding.UTF8.GetBytes(NameUsedToCompareAsString);
            }
            else
            {
                NameUsedToCompareAsString = NameAsString;
                NameUsedToCompare         = Name;
            }

            // Cache the escaped name.
#if true
            // temporary behavior until the writer can accept escaped string.
            EscapedName = Name;
#else
            int valueIdx = JsonWriterHelper.NeedsEscaping(_name);
            if (valueIdx == -1)
            {
                _escapedName = _name;
            }
            else
            {
                byte[] pooledName = null;
                int    length     = JsonWriterHelper.GetMaxEscapedLength(_name.Length, valueIdx);

                Span <byte> escapedName = length <= JsonConstants.StackallocThreshold ?
                                          stackalloc byte[length] :
                                          (pooledName = ArrayPool <byte> .Shared.Rent(length));

                JsonWriterHelper.EscapeString(_name, escapedName, 0, out int written);

                _escapedName = escapedName.Slice(0, written).ToArray();

                if (pooledName != null)
                {
                    // We clear the array because it is "user data" (although a property name).
                    new Span <byte>(pooledName, 0, written).Clear();
                    ArrayPool <byte> .Shared.Return(pooledName);
                }
            }
#endif
        }
        internal static void WriteDictionary <TProperty>(
            JsonValueConverter <TProperty> converter,
            JsonSerializerOptions options,
            ref WriteStackFrame current,
            Utf8JsonWriter writer)
        {
            if (converter == null)
            {
                return;
            }

            Debug.Assert(current.Enumerator != null);

            string    key;
            TProperty value;

            if (current.Enumerator is IEnumerator <KeyValuePair <string, TProperty> > enumerator)
            {
                // Avoid boxing for strongly-typed enumerators such as returned from IDictionary<string, TRuntimeProperty>
                value = enumerator.Current.Value;
                key   = enumerator.Current.Key;
            }
            else if (current.Enumerator is IEnumerator <KeyValuePair <string, object> > polymorphicEnumerator)
            {
                value = (TProperty)polymorphicEnumerator.Current.Value;
                key   = polymorphicEnumerator.Current.Key;
            }
            else
            {
                // Todo: support non-generic Dictionary here (IDictionaryEnumerator)
                throw new NotSupportedException();
            }

            if (value == null)
            {
                writer.WriteNull(key);
            }
            else
            {
                byte[] utf8Key = Encoding.UTF8.GetBytes(key);
#if true
                // temporary behavior until the writer can accept escaped string.
                converter.Write(utf8Key, value, writer);
#else
                int valueIdx = JsonWriterHelper.NeedsEscaping(utf8Key);
                if (valueIdx == -1)
                {
                    converter.Write(utf8Key, value, writer);
                }
                else
                {
                    byte[] pooledKey = null;
                    int    length    = JsonWriterHelper.GetMaxEscapedLength(utf8Key.Length, valueIdx);

                    Span <byte> escapedKey = length <= JsonConstants.StackallocThreshold ?
                                             stackalloc byte[length] :
                                             (pooledKey = ArrayPool <byte> .Shared.Rent(length));

                    JsonWriterHelper.EscapeString(utf8Key, escapedKey, valueIdx, out int written);

                    converter.Write(escapedKey.Slice(0, written), value, writer);

                    if (pooledKey != null)
                    {
                        // We clear the array because it is "user data" (although a property name).
                        new Span <byte>(pooledKey, 0, written).Clear();
                        ArrayPool <byte> .Shared.Return(pooledKey);
                    }
                }
#endif
            }
        }
Exemple #4
0
        private void AddProperty(Type propertyType, PropertyInfo propertyInfo, Type classType, JsonSerializerOptions options)
        {
            Type      collectionElementType = null;
            ClassType propertyClassType     = GetClassType(propertyType);

            if (propertyClassType == ClassType.Enumerable)
            {
                collectionElementType = GetElementType(propertyType);
                // todo: if collectionElementType is object, create loosely-typed collection (JsonArray).
            }

            // Create the JsonPropertyInfo<TType, TProperty>
            Type genericPropertyType;

            if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                Type underlyingPropertyType = Nullable.GetUnderlyingType(propertyType);
                genericPropertyType = typeof(JsonPropertyInfoNullable <,>).MakeGenericType(classType, underlyingPropertyType);
            }
            else
            {
                genericPropertyType = typeof(JsonPropertyInfoNotNullable <,>).MakeGenericType(classType, propertyType);
            }

            JsonPropertyInfo jsonInfo = (JsonPropertyInfo)Activator.CreateInstance(
                genericPropertyType,
                BindingFlags.Instance | BindingFlags.NonPublic,
                binder: null,
                new object[] { classType, propertyType, propertyInfo, collectionElementType, options },
                culture: null);

            if (propertyInfo != null)
            {
                string propertyName = propertyInfo.Name;

                // At this point propertyName is valid UTF16, so just call the simple UTF16->UTF8 encoder.
                byte[] propertyNameBytes = Encoding.UTF8.GetBytes(propertyName);
                jsonInfo._name = propertyNameBytes;

                // Cache the escaped name.
                int valueIdx = JsonWriterHelper.NeedsEscaping(propertyNameBytes);
                if (valueIdx == -1)
                {
                    jsonInfo._escapedName = propertyNameBytes;
                }
                else
                {
                    int length = JsonWriterHelper.GetMaxEscapedLength(propertyNameBytes.Length, valueIdx);

                    byte[] tempArray = ArrayPool <byte> .Shared.Rent(length);

                    JsonWriterHelper.EscapeString(propertyNameBytes, tempArray, valueIdx, out int written);
                    jsonInfo._escapedName = new byte[written];
                    tempArray.CopyTo(jsonInfo._escapedName, 0);

                    // We clear the array because it is "user data" (although a property name).
                    ArrayPool <byte> .Shared.Return(tempArray, clearArray : true);
                }

                _property_refs.Add(new PropertyRef(GetKey(propertyNameBytes), jsonInfo));
            }
            else
            {
                // A single property or an IEnumerable
                _property_refs.Add(new PropertyRef(0, jsonInfo));
            }
        }
Exemple #5
0
        private void DeterminePropertyName(JsonSerializerOptions options)
        {
            if (PropertyInfo != null)
            {
                JsonPropertyNameAttribute nameAttribute = GetAttribute <JsonPropertyNameAttribute>();
                if (nameAttribute != null)
                {
                    NameAsString = nameAttribute.Name;

                    // This is detected and thrown by caller.
                    if (NameAsString == null)
                    {
                        return;
                    }
                }
                else if (options.PropertyNamingPolicy != null)
                {
                    NameAsString = options.PropertyNamingPolicy.ConvertName(PropertyInfo.Name);

                    // This is detected and thrown by caller.
                    if (NameAsString == null)
                    {
                        return;
                    }
                }
                else
                {
                    NameAsString = PropertyInfo.Name;
                }

                // At this point propertyName is valid UTF16, so just call the simple UTF16->UTF8 encoder.
                _name = Encoding.UTF8.GetBytes(NameAsString);

                // Set the compare name.
                if (options.PropertyNameCaseInsensitive)
                {
                    CompareNameAsString = NameAsString.ToUpperInvariant();
                    _compareName        = Encoding.UTF8.GetBytes(CompareNameAsString);
                }
                else
                {
                    CompareNameAsString = NameAsString;
                    _compareName        = _name;
                }

                // Cache the escaped name.
                int valueIdx = JsonWriterHelper.NeedsEscaping(_name);
                if (valueIdx == -1)
                {
                    _escapedName = _name;
                }
                else
                {
                    int length = JsonWriterHelper.GetMaxEscapedLength(_name.Length, valueIdx);

                    byte[] tempArray = ArrayPool <byte> .Shared.Rent(length);

                    JsonWriterHelper.EscapeString(_name, tempArray, valueIdx, out int written);
                    _escapedName = new byte[written];
                    tempArray.CopyTo(_escapedName, 0);

                    // We clear the array because it is "user data" (although a property name).
                    new Span <byte>(tempArray, 0, written).Clear();
                    ArrayPool <byte> .Shared.Return(tempArray);
                }
            }
        }