Skip to content

JsonObjectConverter throws ArgumentException instead of JsonException on DuplicateKey #123882

@hbeierlein-tekaris

Description

@hbeierlein-tekaris

Describe the bug

When I set JsonSerializerOptions.AllowDuplicateProperties=false and try to Deserialize a Json with duplicate properties to a JsonObject, an ArgumentException is thrown instead of a JsonException.

In System.Text.Json.Serialization.Converters.JsonObjectConverter line 34-41 the correct Code is implemented, but line 101 is called (JsonObject.Add())

To Reproduce

using System;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Nodes;
using Xunit;

namespace JsonObjectBug;

public class JsonObjectTests
{
    [StringSyntax(StringSyntaxAttribute.Json)]
    private const string JSON_DATA = """
                                     {
                                             "keyOne": "normalKey",
                                             "keyOne": "duplicateKey"
                                     }
                                     """;
    private static readonly JsonSerializerOptions JSON_OPTIONS = new(JsonSerializerOptions.Web)
    {
        AllowDuplicateProperties = false
    };

    [Fact]
    public void Test_Expected()
    {
        Assert.Throws<JsonException>(DeserializeFunction);
    }

    [Fact]
    public void Test_Actual()
    {
        Assert.Throws<ArgumentException>(DeserializeFunction);
    }

    private static JsonObject DeserializeFunction()
    {
        return JsonSerializer.Deserialize<JsonObject>(JSON_DATA, JSON_OPTIONS);
    }
}

Exceptions (if any)

System.ArgumentException
An item with the same key has already been added. Key: keyOne (Parameter 'key')
   at System.Collections.ThrowHelper.ThrowDuplicateKey[TKey](TKey key)
   at System.Collections.Generic.OrderedDictionary`2.TryInsert(Int32 index, TKey key, TValue value, InsertionBehavior behavior, Int32& keyIndex)
   at System.Collections.Generic.OrderedDictionary`2.Add(TKey key, TValue value)
   at System.Text.Json.Serialization.Converters.JsonObjectConverter.ReadAsJsonNode(Utf8JsonReader& reader, JsonNodeOptions options)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.Deserialize(Utf8JsonReader& reader, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo`1 jsonTypeInfo, Nullable`1 actualByteCount)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo`1 jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)

Further technical details

details of dotnet --info

.NET SDK: Version: 10.0.102 Commit: 4452502459 Workload version: 10.0.100-manifests.73000c7b MSBuild version: 18.0.7+445250245

Runtime Environment:
OS Name: Windows
OS Version: 10.0.22631
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\10.0.102\

.NET workloads installed:
There are no installed workloads to display.
Configured to use workload sets when installing new manifests.
No workload sets are installed. Run "dotnet workload restore" to install a workload set.

Host:
Version: 10.0.2
Architecture: x64
Commit: 4452502459

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-WorkloadsWorkloads like wasm-toolsuntriagedNew issue has not been triaged by the area owner

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions