Skip to content

Commit 1745d7c

Browse files
authored
Fix JTokenWriter when writing comment to an object (#2493)
1 parent 583eb12 commit 1745d7c

File tree

6 files changed

+112
-21
lines changed

6 files changed

+112
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#region License
2+
// Copyright (c) 2007 James Newton-King
3+
//
4+
// Permission is hereby granted, free of charge, to any person
5+
// obtaining a copy of this software and associated documentation
6+
// files (the "Software"), to deal in the Software without
7+
// restriction, including without limitation the rights to use,
8+
// copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the
10+
// Software is furnished to do so, subject to the following
11+
// conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be
14+
// included in all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
// OTHER DEALINGS IN THE SOFTWARE.
24+
#endregion
25+
26+
#if (NET45 || NET50)
27+
#if DNXCORE50
28+
using Xunit;
29+
using Test = Xunit.FactAttribute;
30+
using Assert = Newtonsoft.Json.Tests.XUnitAssert;
31+
#else
32+
using NUnit.Framework;
33+
#endif
34+
using System.Collections.Generic;
35+
using Newtonsoft.Json.Serialization;
36+
using Newtonsoft.Json.Converters;
37+
using System.Collections;
38+
using System;
39+
using System.IO;
40+
using Newtonsoft.Json.Linq;
41+
42+
namespace Newtonsoft.Json.Tests.Issues
43+
{
44+
[TestFixture]
45+
public class Issue2492
46+
{
47+
[Test]
48+
public void Test_Object()
49+
{
50+
string jsontext = @"{ ""ABC"": //DEF
51+
{}}";
52+
53+
using var stringReader = new StringReader(jsontext);
54+
using var jsonReader = new JsonTextReader(stringReader);
55+
56+
JsonSerializer serializer = JsonSerializer.Create();
57+
var x = serializer.Deserialize<JToken>(jsonReader);
58+
59+
Assert.AreEqual(JTokenType.Object, x["ABC"].Type);
60+
}
61+
62+
[Test]
63+
public void Test_Integer()
64+
{
65+
string jsontext = "{ \"ABC\": /*DEF*/ 1}";
66+
67+
using var stringReader = new StringReader(jsontext);
68+
using var jsonReader = new JsonTextReader(stringReader);
69+
70+
JsonSerializer serializer = JsonSerializer.Create();
71+
var x = serializer.Deserialize<JToken>(jsonReader);
72+
73+
Assert.AreEqual(JTokenType.Integer, x["ABC"].Type);
74+
}
75+
}
76+
}
77+
#endif

Src/Newtonsoft.Json/Linq/JContainer.cs

+17-8
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ internal JContainer(JContainer other)
114114
int i = 0;
115115
foreach (JToken child in other)
116116
{
117-
AddInternal(i, child, false);
117+
TryAddInternal(i, child, false);
118118
i++;
119119
}
120120

@@ -349,7 +349,7 @@ internal JToken EnsureParentToken(JToken? item, bool skipParentCheck)
349349

350350
internal abstract int IndexOfItem(JToken? item);
351351

352-
internal virtual void InsertItem(int index, JToken? item, bool skipParentCheck)
352+
internal virtual bool InsertItem(int index, JToken? item, bool skipParentCheck)
353353
{
354354
IList<JToken> children = ChildrenTokens;
355355

@@ -396,6 +396,8 @@ internal virtual void InsertItem(int index, JToken? item, bool skipParentCheck)
396396
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
397397
}
398398
#endif
399+
400+
return true;
399401
}
400402

401403
internal virtual void RemoveItemAt(int index)
@@ -633,12 +635,17 @@ internal virtual void ValidateToken(JToken o, JToken? existing)
633635
/// <param name="content">The content to be added.</param>
634636
public virtual void Add(object? content)
635637
{
636-
AddInternal(ChildrenTokens.Count, content, false);
638+
TryAddInternal(ChildrenTokens.Count, content, false);
639+
}
640+
641+
internal bool TryAdd(object? content)
642+
{
643+
return TryAddInternal(ChildrenTokens.Count, content, false);
637644
}
638645

639646
internal void AddAndSkipParentCheck(JToken token)
640647
{
641-
AddInternal(ChildrenTokens.Count, token, true);
648+
TryAddInternal(ChildrenTokens.Count, token, true);
642649
}
643650

644651
/// <summary>
@@ -647,10 +654,10 @@ internal void AddAndSkipParentCheck(JToken token)
647654
/// <param name="content">The content to be added.</param>
648655
public void AddFirst(object? content)
649656
{
650-
AddInternal(0, content, false);
657+
TryAddInternal(0, content, false);
651658
}
652659

653-
internal void AddInternal(int index, object? content, bool skipParentCheck)
660+
internal bool TryAddInternal(int index, object? content, bool skipParentCheck)
654661
{
655662
if (IsMultiContent(content))
656663
{
@@ -659,15 +666,17 @@ internal void AddInternal(int index, object? content, bool skipParentCheck)
659666
int multiIndex = index;
660667
foreach (object c in enumerable)
661668
{
662-
AddInternal(multiIndex, c, skipParentCheck);
669+
TryAddInternal(multiIndex, c, skipParentCheck);
663670
multiIndex++;
664671
}
672+
673+
return true;
665674
}
666675
else
667676
{
668677
JToken item = CreateFromContent(content);
669678

670-
InsertItem(index, item, skipParentCheck);
679+
return InsertItem(index, item, skipParentCheck);
671680
}
672681
}
673682

Src/Newtonsoft.Json/Linq/JObject.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,15 @@ internal override int IndexOfItem(JToken? item)
135135
return _properties.IndexOfReference(item);
136136
}
137137

138-
internal override void InsertItem(int index, JToken? item, bool skipParentCheck)
138+
internal override bool InsertItem(int index, JToken? item, bool skipParentCheck)
139139
{
140140
// don't add comments to JObject, no name to reference comment by
141141
if (item != null && item.Type == JTokenType.Comment)
142142
{
143-
return;
143+
return false;
144144
}
145145

146-
base.InsertItem(index, item, skipParentCheck);
146+
return base.InsertItem(index, item, skipParentCheck);
147147
}
148148

149149
internal override void ValidateToken(JToken o, JToken? existing)

Src/Newtonsoft.Json/Linq/JProperty.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -241,20 +241,20 @@ internal override int IndexOfItem(JToken? item)
241241
return _content.IndexOf(item);
242242
}
243243

244-
internal override void InsertItem(int index, JToken? item, bool skipParentCheck)
244+
internal override bool InsertItem(int index, JToken? item, bool skipParentCheck)
245245
{
246246
// don't add comments to JProperty
247247
if (item != null && item.Type == JTokenType.Comment)
248248
{
249-
return;
249+
return false;
250250
}
251251

252252
if (Value != null)
253253
{
254254
throw new JsonException("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
255255
}
256256

257-
base.InsertItem(0, item, false);
257+
return base.InsertItem(0, item, false);
258258
}
259259

260260
internal override bool ContainsItem(JToken? item)

Src/Newtonsoft.Json/Linq/JToken.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ public void AddAfterSelf(object? content)
240240
}
241241

242242
int index = _parent.IndexOfItem(this);
243-
_parent.AddInternal(index + 1, content, false);
243+
_parent.TryAddInternal(index + 1, content, false);
244244
}
245245

246246
/// <summary>
@@ -255,7 +255,7 @@ public void AddBeforeSelf(object? content)
255255
}
256256

257257
int index = _parent.IndexOfItem(this);
258-
_parent.AddInternal(index, content, false);
258+
_parent.TryAddInternal(index, content, false);
259259
}
260260

261261
/// <summary>

Src/Newtonsoft.Json/Linq/JTokenWriter.cs

+10-5
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,17 @@ internal void AddValue(JValue? value, JsonToken token)
196196
{
197197
if (_parent != null)
198198
{
199-
_parent.Add(value);
200-
_current = _parent.Last;
201-
202-
if (_parent.Type == JTokenType.Property)
199+
// TryAdd will return false if an invalid JToken type is added.
200+
// For example, a JComment can't be added to a JObject.
201+
// If there is an invalid JToken type then skip it.
202+
if (_parent.TryAdd(value))
203203
{
204-
_parent = _parent.Parent;
204+
_current = _parent.Last;
205+
206+
if (_parent.Type == JTokenType.Property)
207+
{
208+
_parent = _parent.Parent;
209+
}
205210
}
206211
}
207212
else

0 commit comments

Comments
 (0)