예제 #1
0
파일: JContainer.cs 프로젝트: zha0/Cerberus
        private static JProperty ReadProperty([Nullable(1)] JsonReader r, JsonLoadSettings settings, IJsonLineInfo lineInfo, [Nullable(1)] JContainer parent)
        {
            DuplicatePropertyNameHandling duplicatePropertyNameHandling = (settings != null) ? settings.DuplicatePropertyNameHandling : DuplicatePropertyNameHandling.Replace;
            JObject   jobject   = (JObject)parent;
            string    text      = r.Value.ToString();
            JProperty jproperty = jobject.Property(text, StringComparison.Ordinal);

            if (jproperty != null)
            {
                if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Ignore)
                {
                    return(null);
                }
                if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Error)
                {
                    throw JsonReaderException.Create(r, "Property with the name '{0}' already exists in the current JSON object.".FormatWith(CultureInfo.InvariantCulture, text));
                }
            }
            JProperty jproperty2 = new JProperty(text);

            jproperty2.SetLineInfo(lineInfo, settings);
            if (jproperty == null)
            {
                parent.Add(jproperty2);
            }
            else
            {
                jproperty.Replace(jproperty2);
            }
            return(jproperty2);
        }
예제 #2
0
        /// <summary>
        ///   Initializes a new instance of the <see cref="JsonObject"/> class representing the empty object.
        /// </summary>
        /// <param name="duplicatePropertyNameHandling">Specifies the way of handling duplicate property names.</param>
        /// <exception cref="ArgumentException">
        ///   Provided manner of handling duplicates does not exist.
        /// </exception>
        public JsonObject(DuplicatePropertyNameHandling duplicatePropertyNameHandling = DuplicatePropertyNameHandling.Replace)
        {
            if ((uint)duplicatePropertyNameHandling > (uint)DuplicatePropertyNameHandling.Error)
            {
                throw new ArgumentOutOfRangeException(SR.InvalidDuplicatePropertyNameHandling);
            }

            _dictionary = new Dictionary <string, JsonNode>();
            _duplicatePropertyNameHandling = duplicatePropertyNameHandling;
        }
예제 #3
0
        private JsonObject ReadObject(ref Utf8JsonReader reader, JsonSerializerOptions options)
        {
            DuplicatePropertyNameHandling duplicatePropertyNameHandling = options.GetDuplicatePropertyNameHandling();

            JsonObject obj = new JsonObject();

            while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
            {
                if (reader.TokenType != JsonTokenType.PropertyName)
                {
                    throw new JsonException();
                }

                string?propertyName = reader.GetString();

                if (propertyName == null)
                {
                    throw new JsonException("Property name cannot be null");
                }

                reader.Read();
                JsonNode propertyValue = Read(ref reader, typeof(JsonNode), options);

                switch (duplicatePropertyNameHandling)
                {
                case DuplicatePropertyNameHandling.Replace:
                    obj[propertyName] = propertyValue;
                    break;

                case DuplicatePropertyNameHandling.Ignore:
                    if (!obj.ContainsProperty(propertyName))
                    {
                        obj.Add(propertyName, propertyValue);
                    }
                    break;

                case DuplicatePropertyNameHandling.Error:
                    if (!obj.ContainsProperty(propertyName))
                    {
                        obj.Add(propertyName, propertyValue);
                    }
                    else
                    {
                        throw new JsonException($"Duplicate property '{propertyName}'");
                    }
                    break;
                }
            }

            return(obj);
        }
예제 #4
0
        public void ReadDuplicateKey(DuplicatePropertyNameHandling duplicatePropertyNameHandling, string expectedValue, Type expectedExceptionType)
        {
            JsonSerializerOptions options = new JsonSerializerOptions().SetupExtensions();

            options.SetDuplicatePropertyNameHandling(duplicatePropertyNameHandling);

            const string json = @"{""key"":""foo"",""key"":""bar""}";

            Dictionary <string, string> expected = new Dictionary <string, string>
            {
                ["key"] = expectedValue,
            };

            Helper.TestRead <Dictionary <string, string> >(json, expected, options, expectedExceptionType);
        }
예제 #5
0
        private static void AddToParent(
            KeyValuePair <string, JsonNode> nodePair,
            ref Stack <KeyValuePair <string, JsonNode> > currentNodes,
            ref JsonNode toReturn,
            DuplicatePropertyNameHandling duplicatePropertyNameHandling = DuplicatePropertyNameHandling.Replace)
        {
            if (currentNodes.Any())
            {
                KeyValuePair <string, JsonNode> parentPair = currentNodes.Peek();

                // Parent needs to be JsonObject or JsonArray
                Debug.Assert(parentPair.Value is JsonObject || parentPair.Value is JsonArray);

                if (parentPair.Value is JsonObject jsonObject)
                {
                    Debug.Assert(nodePair.Key != null);

                    // Handle duplicate properties accordingly to duplicatePropertyNameHandling:

                    if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Replace)
                    {
                        jsonObject[nodePair.Key] = nodePair.Value;
                    }
                    else if (jsonObject._dictionary.ContainsKey(nodePair.Key))
                    {
                        if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Error)
                        {
                            throw new ArgumentException(SR.JsonObjectDuplicateKey);
                        }

                        Debug.Assert(duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Ignore);
                    }
                    else
                    {
                        jsonObject.Add(nodePair);
                    }
                }
                else if (parentPair.Value is JsonArray jsonArray)
                {
                    Debug.Assert(nodePair.Key == null);
                    jsonArray.Add(nodePair.Value);
                }
            }
            else
            {
                toReturn = nodePair.Value;
            }
        }
예제 #6
0
        private static void TestDuplicates(DuplicatePropertyNameHandling duplicatePropertyNameHandling, string previousValue, string newValue, string expectedValue, bool useDefaultCtor = false)
        {
            JsonObject jsonObject = useDefaultCtor ? new JsonObject() : new JsonObject(duplicatePropertyNameHandling);

            jsonObject.Add("property", new JsonString(previousValue));

            Assert.Equal(previousValue, ((JsonString)jsonObject["property"]).Value);

            jsonObject.Add("property", new JsonString(newValue));

            Assert.Equal(expectedValue, ((JsonString)jsonObject["property"]).Value);

            // with indexer, property should change no matter which duplicates handling option is chosen:
            jsonObject["property"] = (JsonString)"indexer value";
            Assert.Equal("indexer value", (JsonString)jsonObject["property"]);
        }
        private static void PrintJson(string header, DuplicatePropertyNameHandling duplicateFlag)
        {
            try
            {
                Console.WriteLine();
                Console.WriteLine("---" + header + "---");

                JsonLoadSettings jsonLoadSettings = (duplicateFlag == DuplicatePropertyNameHandling.Replace)
                                        ? null
                                        : new JsonLoadSettings {
                    DuplicatePropertyNameHandling = duplicateFlag
                };

                JToken jToken = JToken.Parse(data, jsonLoadSettings);

                Console.WriteLine(jToken.ToString(Formatting.Indented));
                Console.WriteLine();
            }
            catch (JsonReaderException jsonReaderException)
            {
                Console.WriteLine("Exception thrown: " + jsonReaderException.Message);
            }
        }
예제 #8
0
 /// <summary>
 ///   Initializes a new instance of the <see cref="JsonObject"/> class representing provided set of JSON properties.
 /// </summary>
 /// <param name="jsonProperties">>Properties to represent as a JSON object.</param>
 /// <param name="duplicatePropertyNameHandling">Specifies the way of handling duplicate property names.</param>
 /// <exception cref="ArgumentException">
 ///   Provided collection contains duplicates if handling duplicates is set to <see cref="DuplicatePropertyNameHandling.Error"/>.
 /// </exception>
 public JsonObject(
     IEnumerable <KeyValuePair <string, JsonNode> > jsonProperties,
     DuplicatePropertyNameHandling duplicatePropertyNameHandling = DuplicatePropertyNameHandling.Replace)
     : this(duplicatePropertyNameHandling)
     => AddRange(jsonProperties);
예제 #9
0
 public static void SetDuplicatePropertyNameHandling(this JsonSerializerOptions options, DuplicatePropertyNameHandling duplicatePropertyNameHandling)
 {
     options.GetState().DuplicatePropertyNameHandling = duplicatePropertyNameHandling;
 }
예제 #10
0
 public static void TestDuplicatesReplaceAndIgnore(DuplicatePropertyNameHandling duplicatePropertyNameHandling, string previousValue, string newValue, string expectedValue, bool useDefaultCtor = false)
 {
     TestDuplicates(duplicatePropertyNameHandling, previousValue, newValue, expectedValue, useDefaultCtor);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="JsonLoadSettings"/> class.
 /// </summary>
 public JsonLoadSettings()
 {
     _lineInfoHandling = LineInfoHandling.Load;
     _commentHandling  = CommentHandling.Ignore;
     _duplicatePropertyNameHandling = DuplicatePropertyNameHandling.Replace;
 }
예제 #12
0
        /// <summary>
        ///   Parses a string representing JSON document into <see cref="JsonNode"/>.
        /// </summary>
        /// <param name="json">JSON to parse.</param>
        /// <param name="options">Options to control the reader behavior during parsing.</param>
        /// <param name="duplicatePropertyNameHandling">Specifies the way of handling duplicate property names.</param>
        /// <returns><see cref="JsonNode"/> representation of <paramref name="json"/>.</returns>
        public static JsonNode Parse(string json, JsonDocumentOptions options = default, DuplicatePropertyNameHandling duplicatePropertyNameHandling = DuplicatePropertyNameHandling.Replace)
        {
            Utf8JsonReader reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json), options.GetReaderOptions());

            var      currentNodes = new Stack <KeyValuePair <string, JsonNode> >(); // nodes currently being created
            JsonNode toReturn     = null;

            while (reader.Read())
            {
                JsonTokenType tokenType = reader.TokenType;
                KeyValuePair <string, JsonNode> currentPair = new KeyValuePair <string, JsonNode>();
                if (currentNodes.Any())
                {
                    currentPair = currentNodes.Peek();
                }

                void AddNewPair(JsonNode jsonNode, bool keepInCurrentNodes = false)
                {
                    KeyValuePair <string, JsonNode> newProperty;

                    if (currentPair.Value == null)
                    {
                        // If previous token was property name,
                        // it was added to stack with not null name and null value,
                        // otherwise, this is first JsonNode added
                        if (currentPair.Key != null)
                        {
                            // Create as property, keep name, replace null with new JsonNode:
                            currentNodes.Pop();
                            newProperty = new KeyValuePair <string, JsonNode>(currentPair.Key, jsonNode);
                        }
                        else
                        {
                            // Add first JsonNode:
                            newProperty = new KeyValuePair <string, JsonNode>(null, jsonNode);
                        }
                    }
                    else
                    {
                        // Create as value:
                        newProperty = new KeyValuePair <string, JsonNode>(null, jsonNode);
                    }

                    if (keepInCurrentNodes)
                    {
                        // If after adding property, it should be kept in currentNodes, it must be JsonObject or JsonArray
                        Debug.Assert(jsonNode.ValueKind == JsonValueKind.Object || jsonNode.ValueKind == JsonValueKind.Array);

                        currentNodes.Push(newProperty);
                    }
                    else
                    {
                        AddToParent(newProperty, ref currentNodes, ref toReturn, duplicatePropertyNameHandling);
                    }
                }

                switch (tokenType)
                {
                case JsonTokenType.StartObject:
                    AddNewPair(new JsonObject(), true);
                    break;

                case JsonTokenType.EndObject:
                    Debug.Assert(currentPair.Value is JsonObject);

                    currentNodes.Pop();
                    AddToParent(currentPair, ref currentNodes, ref toReturn, duplicatePropertyNameHandling);
                    break;

                case JsonTokenType.StartArray:
                    AddNewPair(new JsonArray(), true);
                    break;

                case JsonTokenType.EndArray:
                    Debug.Assert(currentPair.Value is JsonArray);

                    currentNodes.Pop();
                    AddToParent(currentPair, ref currentNodes, ref toReturn, duplicatePropertyNameHandling);
                    break;

                case JsonTokenType.PropertyName:
                    currentNodes.Push(new KeyValuePair <string, JsonNode>(reader.GetString(), null));
                    break;

                case JsonTokenType.Number:
                    AddNewPair(new JsonNumber(JsonHelpers.Utf8GetString(reader.ValueSpan)));
                    break;

                case JsonTokenType.String:
                    AddNewPair(new JsonString(reader.GetString()));
                    break;

                case JsonTokenType.True:
                    AddNewPair(new JsonBoolean(true));
                    break;

                case JsonTokenType.False:
                    AddNewPair(new JsonBoolean(false));
                    break;

                case JsonTokenType.Null:
                    AddNewPair(new JsonNull());
                    break;
                }
            }

            Debug.Assert(toReturn != null);
            return(toReturn);
        }