-Added support for DateFormatString when reading JSON

This commit is contained in:
James Newton-King
2014-04-26 13:03:04 +12:00
parent 6cc34d026c
commit 35fc7ed0f4
8 changed files with 155 additions and 22 deletions
@@ -75,4 +75,4 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("6.0.0.0")]
[assembly: AssemblyFileVersion("6.0.2.17225")]
[assembly: AssemblyFileVersion("6.0.2.17226")]
@@ -7818,5 +7818,76 @@ Parameter name: value",
Assert.AreEqual(originalUri, uriWithPlus2.OriginalString);
}
[Test]
public void DateFormatStringWithDateTime()
{
DateTime dt = new DateTime(2000, 12, 22);
string dateFormatString = "yyyy'-pie-'MMM'-'dddd'-'dd";
JsonSerializerSettings settings = new JsonSerializerSettings
{
DateFormatString = dateFormatString
};
string json = JsonConvert.SerializeObject(dt, settings);
Assert.AreEqual(@"""2000-pie-Dec-Friday-22""", json);
DateTime dt1 = JsonConvert.DeserializeObject<DateTime>(json, settings);
Assert.AreEqual(dt, dt1);
JsonTextReader reader = new JsonTextReader(new StringReader(json))
{
DateFormatString = dateFormatString
};
JValue v = (JValue)JToken.ReadFrom(reader);
Assert.AreEqual(JTokenType.Date, v.Type);
Assert.AreEqual(typeof(DateTime), v.Value.GetType());
Assert.AreEqual(dt, (DateTime)v.Value);
reader = new JsonTextReader(new StringReader(@"""abc"""))
{
DateFormatString = dateFormatString
};
v = (JValue)JToken.ReadFrom(reader);
Assert.AreEqual(JTokenType.String, v.Type);
Assert.AreEqual(typeof(string), v.Value.GetType());
Assert.AreEqual("abc", v.Value);
}
#if !NET20
[Test]
public void DateFormatStringWithDateTimeOffset()
{
DateTimeOffset dt = new DateTimeOffset(new DateTime(2000, 12, 22));
string dateFormatString = "yyyy'-pie-'MMM'-'dddd'-'dd";
JsonSerializerSettings settings = new JsonSerializerSettings
{
DateFormatString = dateFormatString
};
string json = JsonConvert.SerializeObject(dt, settings);
Assert.AreEqual(@"""2000-pie-Dec-Friday-22""", json);
DateTimeOffset dt1 = JsonConvert.DeserializeObject<DateTimeOffset>(json, settings);
Assert.AreEqual(dt, dt1);
JsonTextReader reader = new JsonTextReader(new StringReader(json))
{
DateFormatString = dateFormatString,
DateParseHandling = DateParseHandling.DateTimeOffset
};
JValue v = (JValue)JToken.ReadFrom(reader);
Assert.AreEqual(JTokenType.Date, v.Type);
Assert.AreEqual(typeof(DateTimeOffset), v.Value.GetType());
Assert.AreEqual(dt, (DateTimeOffset)v.Value);
}
#endif
}
}
+12 -2
View File
@@ -127,6 +127,7 @@ namespace Newtonsoft.Json
private bool _hasExceededMaxDepth;
internal DateParseHandling _dateParseHandling;
internal FloatParseHandling _floatParseHandling;
private string _dateFormatString;
private readonly List<JsonPosition> _stack;
/// <summary>
@@ -193,6 +194,15 @@ namespace Newtonsoft.Json
set { _floatParseHandling = value; }
}
/// <summary>
/// Get or set how custom date formatted strings are parsed when reading JSON.
/// </summary>
public string DateFormatString
{
get { return _dateFormatString; }
set { _dateFormatString = value; }
}
/// <summary>
/// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
/// </summary>
@@ -440,7 +450,7 @@ namespace Newtonsoft.Json
}
object temp;
if (DateTimeUtils.TryParseDateTime(s, DateParseHandling.DateTimeOffset, DateTimeZoneHandling, out temp))
if (DateTimeUtils.TryParseDateTime(s, DateParseHandling.DateTimeOffset, DateTimeZoneHandling, _dateFormatString, Culture, out temp))
{
dt = (DateTimeOffset)temp;
SetToken(JsonToken.Date, dt, false);
@@ -728,7 +738,7 @@ namespace Newtonsoft.Json
}
object temp;
if (DateTimeUtils.TryParseDateTime(s, DateParseHandling.DateTime, DateTimeZoneHandling, out temp))
if (DateTimeUtils.TryParseDateTime(s, DateParseHandling.DateTime, DateTimeZoneHandling, _dateFormatString, Culture, out temp))
{
dt = (DateTime)temp;
dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
+9
View File
@@ -713,6 +713,13 @@ namespace Newtonsoft.Json
reader.MaxDepth = _maxDepth;
}
string previousDateFormatString = null;
if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString)
{
previousDateFormatString = reader.DateFormatString;
reader.DateFormatString = _dateFormatString;
}
TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
? new TraceJsonReader(reader)
: null;
@@ -734,6 +741,8 @@ namespace Newtonsoft.Json
reader.FloatParseHandling = previousFloatParseHandling.Value;
if (_maxDepthSet)
reader.MaxDepth = previousMaxDepth;
if (_dateFormatStringSet)
reader.DateFormatString = previousDateFormatString;
return value;
}
+1 -1
View File
@@ -153,7 +153,7 @@ namespace Newtonsoft.Json
dateParseHandling = _dateParseHandling;
object dt;
if (DateTimeUtils.TryParseDateTime(text, dateParseHandling, DateTimeZoneHandling, out dt))
if (DateTimeUtils.TryParseDateTime(text, dateParseHandling, DateTimeZoneHandling, DateFormatString, Culture, out dt))
{
SetToken(JsonToken.Date, dt);
return;
@@ -91,5 +91,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("6.0.0.0")]
[assembly: AssemblyFileVersion("6.0.2.17225")]
[assembly: AssemblyFileVersion("6.0.2.17226")]
[assembly: CLSCompliant(true)]
@@ -1121,28 +1121,35 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
object keyValue = reader.Value;
if (CheckPropertyName(reader, keyValue.ToString()))
continue;
try
{
try
{
object dt;
// this is for correctly reading ISO and MS formatted dictionary keys
if ((keyTypeCode == PrimitiveTypeCode.DateTime || keyTypeCode == PrimitiveTypeCode.DateTimeNullable)
&& DateTimeUtils.TryParseDateTime(keyValue.ToString(), DateParseHandling.DateTime, reader.DateTimeZoneHandling, out dt))
DateParseHandling dateParseHandling;
switch (keyTypeCode)
{
keyValue = dt;
}
case PrimitiveTypeCode.DateTime:
case PrimitiveTypeCode.DateTimeNullable:
dateParseHandling = DateParseHandling.DateTime;
break;
#if !NET20
else if ((keyTypeCode == PrimitiveTypeCode.DateTimeOffset || keyTypeCode == PrimitiveTypeCode.DateTimeOffsetNullable)
&& DateTimeUtils.TryParseDateTime(keyValue.ToString(), DateParseHandling.DateTimeOffset, reader.DateTimeZoneHandling, out dt))
{
keyValue = dt;
}
case PrimitiveTypeCode.DateTimeOffset:
case PrimitiveTypeCode.DateTimeOffsetNullable:
dateParseHandling = DateParseHandling.DateTimeOffset;
break;
#endif
else
{
keyValue = EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType);
default:
dateParseHandling = DateParseHandling.None;
break;
}
// this is for correctly reading ISO and MS formatted dictionary keys
object dt;
if (dateParseHandling != DateParseHandling.None && DateTimeUtils.TryParseDateTime(keyValue.ToString(), dateParseHandling, reader.DateTimeZoneHandling, reader.DateFormatString, reader.Culture, out dt))
keyValue = dt;
else
keyValue = EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType);
}
catch (Exception ex)
{
+39 -3
View File
@@ -284,7 +284,7 @@ namespace Newtonsoft.Json.Utilities
}
}
internal static bool TryParseDateTime(string s, DateParseHandling dateParseHandling, DateTimeZoneHandling dateTimeZoneHandling, out object dt)
internal static bool TryParseDateTime(string s, DateParseHandling dateParseHandling, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out object dt)
{
if (s.Length > 0)
{
@@ -292,12 +292,20 @@ namespace Newtonsoft.Json.Utilities
{
if (s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal))
{
return TryParseDateMicrosoft(s, dateParseHandling, dateTimeZoneHandling, out dt);
if (TryParseDateMicrosoft(s, dateParseHandling, dateTimeZoneHandling, out dt))
return true;
}
}
else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[0]) && s[10] == 'T')
{
return TryParseDateIso(s, dateParseHandling, dateTimeZoneHandling, out dt);
if (TryParseDateIso(s, dateParseHandling, dateTimeZoneHandling, out dt))
return true;
}
if (!string.IsNullOrEmpty(dateFormatString))
{
if (TryParseDateExact(s, dateParseHandling, dateTimeZoneHandling, dateFormatString, culture, out dt))
return true;
}
}
@@ -357,6 +365,34 @@ namespace Newtonsoft.Json.Utilities
}
}
private static bool TryParseDateExact(string text, DateParseHandling dateParseHandling, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out object dt)
{
#if !NET20
if (dateParseHandling == DateParseHandling.DateTimeOffset)
{
DateTimeOffset temp;
if (DateTimeOffset.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out temp))
{
dt = temp;
return true;
}
}
else
#endif
{
DateTime temp;
if (DateTime.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out temp))
{
temp = EnsureDateTime(temp, dateTimeZoneHandling);
dt = temp;
return true;
}
}
dt = null;
return false;
}
private static TimeSpan ReadOffset(string offsetText)
{
bool negative = (offsetText[0] == '-');