Clean up DuplicatePropertyNameHandling feature
This commit is contained in:
@@ -1770,11 +1770,11 @@ third line", jsonTextReader.Value);
|
||||
}
|
||||
";
|
||||
|
||||
JsonLoadSettings settings = new JsonLoadSettings { DuplicatePropertyNamesHandling = DuplicatePropertyNamesHandling.Throw };
|
||||
JsonLoadSettings settings = new JsonLoadSettings { DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error };
|
||||
|
||||
JsonTextReader reader = new JsonTextReader(new StringReader(json));
|
||||
await ExceptionAssert.ThrowsAsync<JsonException>( async () => await JToken.ReadFromAsync(reader, settings));
|
||||
await ExceptionAssert.ThrowsAsync<JsonReaderException>(async () => await JToken.ReadFromAsync(reader, settings));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -1761,12 +1761,11 @@ third line", jsonTextReader.Value);
|
||||
}
|
||||
";
|
||||
|
||||
JsonLoadSettings settings = new JsonLoadSettings {DuplicatePropertyNamesHandling = DuplicatePropertyNamesHandling.Throw};
|
||||
JsonLoadSettings settings = new JsonLoadSettings {DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error};
|
||||
|
||||
ExceptionAssert.Throws<JsonException>(() => JObject.Parse(json, settings));
|
||||
JsonTextReader reader = new JsonTextReader(new StringReader(json));
|
||||
ExceptionAssert.Throws<JsonException>(() =>
|
||||
{
|
||||
JsonTextReader reader = new JsonTextReader(new StringReader(json));
|
||||
JToken.ReadFrom(reader, settings);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -162,6 +162,39 @@ namespace Newtonsoft.Json.Tests.Linq
|
||||
await JToken.ReadFromAsync(reader);
|
||||
}, "Unexpected end of content while loading JObject. Path 'short.error.code', line 6, position 14.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ParseMultipleProperties_EmptySettingsAsync()
|
||||
{
|
||||
string json = @"{
|
||||
""Name"": ""Name1"",
|
||||
""Name"": ""Name2""
|
||||
}";
|
||||
|
||||
JsonTextReader reader = new JsonTextReader(new StringReader(json));
|
||||
JObject o = (JObject)await JToken.ReadFromAsync(reader, new JsonLoadSettings());
|
||||
string value = (string)o["Name"];
|
||||
|
||||
Assert.AreEqual("Name2", value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ParseMultipleProperties_IgnoreDuplicateSettingAsync()
|
||||
{
|
||||
string json = @"{
|
||||
""Name"": ""Name1"",
|
||||
""Name"": ""Name2""
|
||||
}";
|
||||
|
||||
JsonTextReader reader = new JsonTextReader(new StringReader(json));
|
||||
JObject o = (JObject)await JToken.ReadFromAsync(reader, new JsonLoadSettings
|
||||
{
|
||||
DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Ignore
|
||||
});
|
||||
string value = (string)o["Name"];
|
||||
|
||||
Assert.AreEqual("Name1", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1604,6 +1604,37 @@ Parameter name: arrayIndex");
|
||||
Assert.AreEqual("Name2", value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseMultipleProperties_EmptySettings()
|
||||
{
|
||||
string json = @"{
|
||||
""Name"": ""Name1"",
|
||||
""Name"": ""Name2""
|
||||
}";
|
||||
|
||||
JObject o = JObject.Parse(json, new JsonLoadSettings());
|
||||
string value = (string)o["Name"];
|
||||
|
||||
Assert.AreEqual("Name2", value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseMultipleProperties_IgnoreDuplicateSetting()
|
||||
{
|
||||
string json = @"{
|
||||
""Name"": ""Name1"",
|
||||
""Name"": ""Name2""
|
||||
}";
|
||||
|
||||
JObject o = JObject.Parse(json, new JsonLoadSettings
|
||||
{
|
||||
DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Ignore
|
||||
});
|
||||
string value = (string)o["Name"];
|
||||
|
||||
Assert.AreEqual("Name1", value);
|
||||
}
|
||||
|
||||
#if !(PORTABLE || DNXCORE50 || PORTABLE40) || NETSTANDARD2_0
|
||||
[Test]
|
||||
public void WriteObjectNullDBNullValue()
|
||||
|
||||
+9
-5
@@ -28,15 +28,19 @@ namespace Newtonsoft.Json.Linq
|
||||
/// <summary>
|
||||
/// Specifies how duplicate property names are handled when loading JSON.
|
||||
/// </summary>
|
||||
public enum DuplicatePropertyNamesHandling
|
||||
public enum DuplicatePropertyNameHandling
|
||||
{
|
||||
/// <summary>
|
||||
/// Ignore duplicate properties, use only last value (default)
|
||||
/// Replace the existing value when there is a duplicate property. The value of the last property in the JSON object will be used.
|
||||
/// </summary>
|
||||
Ignore = 0,
|
||||
Replace = 0,
|
||||
/// <summary>
|
||||
/// Throw exception
|
||||
/// Ignore the new value when there is a duplicate property. The value of the first property in the JSON object will be used.
|
||||
/// </summary>
|
||||
Throw = 1
|
||||
Ignore = 1,
|
||||
/// <summary>
|
||||
/// Throw a <see cref="JsonReaderException"/> when a duplicate property is encountered.
|
||||
/// </summary>
|
||||
Error = 2
|
||||
}
|
||||
}
|
||||
@@ -148,25 +148,15 @@ namespace Newtonsoft.Json.Linq
|
||||
parent.Add(v);
|
||||
break;
|
||||
case JsonToken.PropertyName:
|
||||
string propertyName = reader.Value.ToString();
|
||||
JProperty property = new JProperty(propertyName);
|
||||
property.SetLineInfo(lineInfo, settings);
|
||||
JObject parentObject = (JObject)parent;
|
||||
// handle multiple properties with the same name in JSON
|
||||
JProperty existingPropertyWithName = parentObject.Property(propertyName);
|
||||
if (existingPropertyWithName == null)
|
||||
JProperty property = ReadProperty(reader, settings, lineInfo, parent);
|
||||
if (property != null)
|
||||
{
|
||||
parent.Add(property);
|
||||
parent = property;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings != null && settings.DuplicatePropertyNamesHandling == DuplicatePropertyNamesHandling.Throw)
|
||||
{
|
||||
throw JsonException.Create(lineInfo, property.Path, $"Property with the same name ('{propertyName}') already exists");
|
||||
}
|
||||
existingPropertyWithName.Replace(property);
|
||||
await reader.SkipAsync();
|
||||
}
|
||||
parent = property;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
|
||||
@@ -837,25 +837,15 @@ namespace Newtonsoft.Json.Linq
|
||||
parent.Add(v);
|
||||
break;
|
||||
case JsonToken.PropertyName:
|
||||
string propertyName = r.Value.ToString();
|
||||
JProperty property = new JProperty(propertyName);
|
||||
property.SetLineInfo(lineInfo, settings);
|
||||
JObject parentObject = (JObject)parent;
|
||||
// handle multiple properties with the same name in JSON
|
||||
JProperty existingPropertyWithName = parentObject.Property(propertyName);
|
||||
if (existingPropertyWithName == null)
|
||||
JProperty property = ReadProperty(r, settings, lineInfo, parent);
|
||||
if (property != null)
|
||||
{
|
||||
parent.Add(property);
|
||||
parent = property;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings != null && settings.DuplicatePropertyNamesHandling == DuplicatePropertyNamesHandling.Throw)
|
||||
{
|
||||
throw JsonException.Create(lineInfo, property.Path, $"Property with the same name ('{propertyName}') already exists");
|
||||
}
|
||||
existingPropertyWithName.Replace(property);
|
||||
r.Skip();
|
||||
}
|
||||
parent = property;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, r.TokenType));
|
||||
@@ -863,6 +853,40 @@ namespace Newtonsoft.Json.Linq
|
||||
} while (r.Read());
|
||||
}
|
||||
|
||||
private static JProperty ReadProperty(JsonReader r, JsonLoadSettings settings, IJsonLineInfo lineInfo, JContainer parent)
|
||||
{
|
||||
DuplicatePropertyNameHandling duplicatePropertyNameHandling = settings?.DuplicatePropertyNameHandling ?? DuplicatePropertyNameHandling.Replace;
|
||||
|
||||
JObject parentObject = (JObject)parent;
|
||||
string propertyName = r.Value.ToString();
|
||||
JProperty existingPropertyWithName = parentObject.Property(propertyName);
|
||||
if (existingPropertyWithName != null)
|
||||
{
|
||||
if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Ignore)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Error)
|
||||
{
|
||||
throw JsonReaderException.Create(r, "Property with the name '{0}' already exists in the current JSON object.".FormatWith(CultureInfo.InvariantCulture, propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
JProperty property = new JProperty(propertyName);
|
||||
property.SetLineInfo(lineInfo, settings);
|
||||
// handle multiple properties with the same name in JSON
|
||||
if (existingPropertyWithName == null)
|
||||
{
|
||||
parent.Add(property);
|
||||
}
|
||||
else
|
||||
{
|
||||
existingPropertyWithName.Replace(property);
|
||||
}
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
internal int ContentsHashCode()
|
||||
{
|
||||
int hashCode = 0;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Newtonsoft.Json.Linq
|
||||
{
|
||||
private CommentHandling _commentHandling;
|
||||
private LineInfoHandling _lineInfoHandling;
|
||||
private DuplicatePropertyNamesHandling _duplicatePropertyNamesHandling;
|
||||
private DuplicatePropertyNameHandling _duplicatePropertyNameHandling;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonLoadSettings"/> class.
|
||||
@@ -18,11 +18,12 @@ namespace Newtonsoft.Json.Linq
|
||||
{
|
||||
_lineInfoHandling = LineInfoHandling.Load;
|
||||
_commentHandling = CommentHandling.Ignore;
|
||||
_duplicatePropertyNamesHandling = DuplicatePropertyNamesHandling.Ignore;
|
||||
_duplicatePropertyNameHandling = DuplicatePropertyNameHandling.Replace;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets how JSON comments are handled when loading JSON.
|
||||
/// The default value is <see cref="CommentHandling.Ignore" />.
|
||||
/// </summary>
|
||||
/// <value>The JSON comment handling.</value>
|
||||
public CommentHandling CommentHandling
|
||||
@@ -41,6 +42,7 @@ namespace Newtonsoft.Json.Linq
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets how JSON line info is handled when loading JSON.
|
||||
/// The default value is <see cref="LineInfoHandling.Load" />.
|
||||
/// </summary>
|
||||
/// <value>The JSON line info handling.</value>
|
||||
public LineInfoHandling LineInfoHandling
|
||||
@@ -58,20 +60,21 @@ namespace Newtonsoft.Json.Linq
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets how duplicate property names are handled when loading JSON.
|
||||
/// Gets or sets how duplicate property names in JSON objects are handled when loading JSON.
|
||||
/// The default value is <see cref="DuplicatePropertyNameHandling.Replace" />.
|
||||
/// </summary>
|
||||
/// <value>The JSON duplicate property names handling.</value>
|
||||
public DuplicatePropertyNamesHandling DuplicatePropertyNamesHandling
|
||||
/// <value>The JSON duplicate property name handling.</value>
|
||||
public DuplicatePropertyNameHandling DuplicatePropertyNameHandling
|
||||
{
|
||||
get => this._duplicatePropertyNamesHandling;
|
||||
get => _duplicatePropertyNameHandling;
|
||||
set
|
||||
{
|
||||
if (value< DuplicatePropertyNamesHandling.Ignore|| value> DuplicatePropertyNamesHandling.Throw)
|
||||
if (value < DuplicatePropertyNameHandling.Ignore || value > DuplicatePropertyNameHandling.Error)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(value));
|
||||
}
|
||||
|
||||
this._duplicatePropertyNamesHandling = value;
|
||||
_duplicatePropertyNameHandling = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<None Include="..\..\LICENSE.md" Pack="true" PackagePath="LICENSE.md" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta-62925-02" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta-63127-02" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition="'$(TargetFramework)'=='net45'">
|
||||
<AssemblyTitle>Json.NET</AssemblyTitle>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"projects": [ "src" ],
|
||||
"sdk": {
|
||||
"version": "2.1.500"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user