Skip to content

Commit b384bb3

Browse files
committed
Merge from Newtonsoft.Json master branch
1 parent ddbf56e commit b384bb3

24 files changed

+625
-86
lines changed

src/Newtonsoft.Json.Tests/JsonConvertTest.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,5 +1401,16 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
14011401
writer.WriteValue(Math.Round((double)value, _precision, _rounding));
14021402
}
14031403
}
1404+
1405+
[Test]
1406+
public void GenericBaseClassSerialization()
1407+
{
1408+
string json = JsonConvert.SerializeObject (new NonGenericChildClass ());
1409+
Assert.AreEqual ("{\"Data\":null}", json);
1410+
}
1411+
1412+
public class GenericBaseClass<O, T> { public virtual T Data { get; set; } }
1413+
public class GenericIntermediateClass<O> : GenericBaseClass<O, string> { public override string Data { get; set; } }
1414+
public class NonGenericChildClass : GenericIntermediateClass<int> { }
14041415
}
14051416
}

src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ public void SetValueWithInvalidIndex()
471471
{
472472
JArray a = new JArray();
473473
a["badvalue"] = new JValue(3);
474-
}, @"Set JArray values with invalid key value: ""badvalue"". Array position index expected.");
474+
}, @"Set JArray values with invalid key value: ""badvalue"". Int32 array index expected.");
475475
}
476476

477477
[Test]
@@ -560,5 +560,21 @@ public void Parse_NoComments()
560560
Assert.AreEqual(2, (int)a[1]);
561561
Assert.AreEqual(3, (int)a[2]);
562562
}
563+
564+
[Test]
565+
public void Parse_LineInfo()
566+
{
567+
string json = "[1,2,3]";
568+
569+
JArray a = JArray.Parse(json, new JsonLoadSettings
570+
{
571+
LineInfoHandling = LineInfoHandling.Load
572+
});
573+
574+
Assert.AreEqual(false, ((IJsonLineInfo)a).HasLineInfo());
575+
Assert.AreEqual(false, ((IJsonLineInfo)a[0]).HasLineInfo());
576+
Assert.AreEqual(false, ((IJsonLineInfo)a[1]).HasLineInfo());
577+
Assert.AreEqual(false, ((IJsonLineInfo)a[2]).HasLineInfo());
578+
}
563579
}
564580
}

src/Newtonsoft.Json.Tests/Linq/JValueTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,31 @@ public void UndefinedTests()
6969
Assert.AreEqual("undefined", v.ToString(Formatting.None));
7070
}
7171

72+
[Test]
73+
public void ToObjectEnum()
74+
{
75+
StringComparison? v = new JValue("OrdinalIgnoreCase").ToObject<StringComparison?>();
76+
Assert.AreEqual(StringComparison.OrdinalIgnoreCase, v.Value);
77+
78+
v = JValue.CreateNull().ToObject<StringComparison?>();
79+
Assert.AreEqual(null, v);
80+
81+
v = new JValue(5).ToObject<StringComparison?>();
82+
Assert.AreEqual(StringComparison.OrdinalIgnoreCase, v.Value);
83+
84+
v = new JValue(20).ToObject<StringComparison?>();
85+
Assert.AreEqual((StringComparison)20, v.Value);
86+
87+
v = new JValue(20).ToObject<StringComparison>();
88+
Assert.AreEqual((StringComparison)20, v.Value);
89+
90+
v = JsonConvert.DeserializeObject<StringComparison?>("20");
91+
Assert.AreEqual((StringComparison)20, v.Value);
92+
93+
v = JsonConvert.DeserializeObject<StringComparison>("20");
94+
Assert.AreEqual((StringComparison)20, v.Value);
95+
}
96+
7297
[Test]
7398
public void FloatParseHandling()
7499
{

src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ public void JArrayStringIndex()
926926
{
927927
JArray a = new JArray();
928928
Assert.AreEqual(null, a["purple"]);
929-
}, @"Accessed JArray values with invalid key value: ""purple"". Array position index expected.");
929+
}, @"Accessed JArray values with invalid key value: ""purple"". Int32 array index expected.");
930930
}
931931

932932
[Test]

src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,18 @@ public class Foo64
198198
}
199199
#endif
200200

201+
#if !NET20
202+
[Test]
203+
public void DeserializeMSDateTimeOffset()
204+
{
205+
DateTimeOffset d = JsonConvert.DeserializeObject<DateTimeOffset>(@"""/Date(1418924498000+0800)/""");
206+
long initialTicks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(d.DateTime, d.Offset);
207+
208+
Assert.AreEqual(1418924498000, initialTicks);
209+
Assert.AreEqual(8, d.Offset.Hours);
210+
}
211+
#endif
212+
201213
[Test]
202214
public void CaseInsensitiveRequiredPropertyConstructorCreation()
203215
{
@@ -262,6 +274,23 @@ public void CoercedEmptyStringWithRequiredConstructor()
262274
}, "Required property 'Bars' expects a value but got null. Path '', line 1, position 9.");
263275
}
264276

277+
public class IgnoredProperty
278+
{
279+
[JsonIgnore]
280+
[JsonProperty(Required = Required.Always)]
281+
public string StringProp1 { get; set; }
282+
[JsonIgnore]
283+
public string StringProp2 { get; set; }
284+
}
285+
286+
[Test]
287+
public void NoErrorWhenValueDoesNotMatchIgnoredProperty()
288+
{
289+
IgnoredProperty p = JsonConvert.DeserializeObject<IgnoredProperty>("{'StringProp1':[1,2,3],'StringProp2':{}}");
290+
Assert.IsNull(p.StringProp1);
291+
Assert.IsNull(p.StringProp2);
292+
}
293+
265294
public class Binding
266295
{
267296
[JsonProperty(Required = Required.Always)]

src/Newtonsoft.Json.Tests/Utilities/DateTimeUtilsTests.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,32 @@ private static void RoundtripDateIso(DateTime value)
7070
Assert.AreEqual(value, parsedDt);
7171
}
7272

73+
[Test]
74+
public void Parse24HourDateTime()
75+
{
76+
DateTime dt;
77+
Assert.IsTrue(DateTimeUtils.TryParseDateTimeIso(CreateStringReference("2000-12-15T24:00:00Z"), DateTimeZoneHandling.RoundtripKind, out dt));
78+
Assert.AreEqual(new DateTime(2000, 12, 16, 0, 0, 0, DateTimeKind.Utc), dt);
79+
80+
Assert.IsFalse(DateTimeUtils.TryParseDateTimeIso(CreateStringReference("2000-12-15T24:01:00Z"), DateTimeZoneHandling.RoundtripKind, out dt));
81+
Assert.IsFalse(DateTimeUtils.TryParseDateTimeIso(CreateStringReference("2000-12-15T24:00:01Z"), DateTimeZoneHandling.RoundtripKind, out dt));
82+
Assert.IsFalse(DateTimeUtils.TryParseDateTimeIso(CreateStringReference("2000-12-15T24:00:00.0000001Z"), DateTimeZoneHandling.RoundtripKind, out dt));
83+
}
84+
85+
#if !NET20
86+
[Test]
87+
public void Parse24HourDateTimeOffset()
88+
{
89+
DateTimeOffset dt;
90+
Assert.IsTrue(DateTimeUtils.TryParseDateTimeOffsetIso(CreateStringReference("2000-12-15T24:00:00Z"), out dt));
91+
Assert.AreEqual(new DateTimeOffset(2000, 12, 16, 0, 0, 0, TimeSpan.Zero), dt);
92+
93+
Assert.IsFalse(DateTimeUtils.TryParseDateTimeOffsetIso(CreateStringReference("2000-12-15T24:01:00Z"), out dt));
94+
Assert.IsFalse(DateTimeUtils.TryParseDateTimeOffsetIso(CreateStringReference("2000-12-15T24:00:01Z"), out dt));
95+
Assert.IsFalse(DateTimeUtils.TryParseDateTimeOffsetIso(CreateStringReference("2000-12-15T24:00:00.0000001Z"), out dt));
96+
}
97+
#endif
98+
7399
[Test]
74100
public void NewDateTimeParse()
75101
{
@@ -151,6 +177,21 @@ private void AssertNewDateTimeParseEqual(string text)
151177
}
152178

153179
#if !NET20
180+
[Test]
181+
public void ReadOffsetMSDateTimeOffset()
182+
{
183+
char[] c = @"12345/Date(1418924498000+0800)/12345".ToCharArray();
184+
StringReference reference = new StringReference(c, 5, c.Length - 10);
185+
186+
DateTimeOffset d;
187+
DateTimeUtils.TryParseDateTimeOffset(reference, null, CultureInfo.InvariantCulture, out d);
188+
189+
long initialTicks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(d.DateTime, d.Offset);
190+
191+
Assert.AreEqual(1418924498000, initialTicks);
192+
Assert.AreEqual(8, d.Offset.Hours);
193+
}
194+
154195
[Test]
155196
public void NewDateTimeOffsetParse()
156197
{

src/Newtonsoft.Json/JsonPosition.cs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,20 @@ public JsonPosition(JsonContainerType type)
5656
PropertyName = null;
5757
}
5858

59+
internal int CalculateLength()
60+
{
61+
switch (Type)
62+
{
63+
case JsonContainerType.Object:
64+
return PropertyName.Length + 5;
65+
case JsonContainerType.Array:
66+
case JsonContainerType.Constructor:
67+
return MathUtils.IntLength((ulong)Position) + 2;
68+
default:
69+
throw new ArgumentOutOfRangeException("Type");
70+
}
71+
}
72+
5973
internal void WriteTo(StringBuilder sb)
6074
{
6175
switch (Type)
@@ -71,7 +85,9 @@ internal void WriteTo(StringBuilder sb)
7185
else
7286
{
7387
if (sb.Length > 0)
88+
{
7489
sb.Append('.');
90+
}
7591

7692
sb.Append(propertyName);
7793
}
@@ -90,13 +106,32 @@ internal static bool TypeHasIndex(JsonContainerType type)
90106
return (type == JsonContainerType.Array || type == JsonContainerType.Constructor);
91107
}
92108

93-
internal static string BuildPath(IEnumerable<JsonPosition> positions)
109+
internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition)
94110
{
95-
StringBuilder sb = new StringBuilder();
111+
int capacity = 0;
112+
if (positions != null)
113+
{
114+
for (int i = 0; i < positions.Count; i++)
115+
{
116+
capacity += positions[i].CalculateLength();
117+
}
118+
}
119+
if (currentPosition != null)
120+
{
121+
capacity += currentPosition.Value.CalculateLength();
122+
}
96123

97-
foreach (JsonPosition state in positions)
124+
StringBuilder sb = new StringBuilder(capacity);
125+
if (positions != null)
126+
{
127+
foreach (JsonPosition state in positions)
128+
{
129+
state.WriteTo(sb);
130+
}
131+
}
132+
if (currentPosition != null)
98133
{
99-
state.WriteTo(sb);
134+
currentPosition.Value.WriteTo(sb);
100135
}
101136

102137
return sb.ToString();

src/Newtonsoft.Json/JsonReader.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ protected internal enum State
128128
internal DateParseHandling _dateParseHandling;
129129
internal FloatParseHandling _floatParseHandling;
130130
private string _dateFormatString;
131-
private readonly List<JsonPosition> _stack;
131+
private List<JsonPosition> _stack;
132132

133133
/// <summary>
134134
/// Gets the current reader state.
@@ -280,11 +280,15 @@ public virtual int Depth
280280
{
281281
get
282282
{
283-
int depth = _stack.Count;
283+
int depth = (_stack != null) ? _stack.Count : 0;
284284
if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None)
285+
{
285286
return depth;
287+
}
286288
else
289+
{
287290
return depth + 1;
291+
}
288292
}
289293
}
290294

@@ -302,11 +306,9 @@ public virtual string Path
302306
&& _currentState != State.ConstructorStart
303307
&& _currentState != State.ObjectStart);
304308

305-
IEnumerable<JsonPosition> positions = (!insideContainer)
306-
? _stack
307-
: _stack.Concat(new[] { _currentPosition });
309+
JsonPosition? current = insideContainer ? (JsonPosition?)_currentPosition : null;
308310

309-
return JsonPosition.BuildPath(positions);
311+
return JsonPosition.BuildPath(_stack, current);
310312
}
311313
}
312314

@@ -321,8 +323,10 @@ public CultureInfo Culture
321323

322324
internal JsonPosition GetPosition(int depth)
323325
{
324-
if (depth < _stack.Count)
326+
if (_stack != null && depth < _stack.Count)
327+
{
325328
return _stack[depth];
329+
}
326330

327331
return _currentPosition;
328332
}
@@ -333,7 +337,6 @@ internal JsonPosition GetPosition(int depth)
333337
protected JsonReader()
334338
{
335339
_currentState = State.Start;
336-
_stack = new List<JsonPosition>(4);
337340
_dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
338341
_dateParseHandling = DateParseHandling.DateTime;
339342
_floatParseHandling = FloatParseHandling.Double;
@@ -351,6 +354,11 @@ private void Push(JsonContainerType value)
351354
}
352355
else
353356
{
357+
if (_stack == null)
358+
{
359+
_stack = new List<JsonPosition>();
360+
}
361+
354362
_stack.Add(_currentPosition);
355363
_currentPosition = new JsonPosition(value);
356364

@@ -366,7 +374,7 @@ private void Push(JsonContainerType value)
366374
private JsonContainerType Pop()
367375
{
368376
JsonPosition oldPosition;
369-
if (_stack.Count > 0)
377+
if (_stack != null && _stack.Count > 0)
370378
{
371379
oldPosition = _currentPosition;
372380
_currentPosition = _stack[_stack.Count - 1];
@@ -379,7 +387,9 @@ private JsonContainerType Pop()
379387
}
380388

381389
if (_maxDepth != null && Depth <= _maxDepth)
390+
{
382391
_hasExceededMaxDepth = false;
392+
}
383393

384394
return oldPosition.Type;
385395
}

src/Newtonsoft.Json/JsonSerializerSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public DefaultValueHandling DefaultValueHandling
138138
}
139139

140140
/// <summary>
141-
/// Gets or sets a collection <see cref="JsonConverter"/> that will be used during serialization.
141+
/// Gets or sets a <see cref="JsonConverter"/> collection that will be used during serialization.
142142
/// </summary>
143143
/// <value>The converters.</value>
144144
public IList<JsonConverter> Converters { get; set; }

0 commit comments

Comments
 (0)