-Fixed not parsing some ISO date timezones

-Fixed float schema validation of integer values
-Changed writing of IConvertible values to convert objects to strings
-Fixed serializing proxy objects with no default constructor
This commit is contained in:
James Newton-King
2013-10-04 22:29:32 +13:00
parent e77fdf285b
commit 107d15a38d
10 changed files with 163 additions and 18 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ http://james.newtonking.com/projects/json/help/
Versions:
Json.NET has different libaries for the various .NET Framework versions.
Json.NET has different libraries for the various .NET Framework versions.
-Net45:
.NET latest (4.5)
@@ -664,5 +664,23 @@ namespace Newtonsoft.Json.Tests.Linq
]", a.ToString());
}
#endif
#if !NET20
[Test]
public void ParseIsoTimeZones()
{
DateTimeOffset expectedDate = new DateTimeOffset(2013, 08, 14, 4, 38, 31, TimeSpan.FromHours(12).Add(TimeSpan.FromMinutes(30)));
JsonTextReader reader = new JsonTextReader(new StringReader("'2013-08-14T04:38:31.000+1230'"));
reader.DateParseHandling = DateParseHandling.DateTimeOffset;
JValue date = (JValue)JToken.ReadFrom(reader);
Assert.AreEqual(expectedDate, date.Value);
DateTimeOffset expectedDate2 = new DateTimeOffset(2013, 08, 14, 4, 38, 31, TimeSpan.FromHours(12));
JsonTextReader reader2 = new JsonTextReader(new StringReader("'2013-08-14T04:38:31.000+12'"));
reader2.DateParseHandling = DateParseHandling.DateTimeOffset;
JValue date2 = (JValue)JToken.ReadFrom(reader2);
Assert.AreEqual(expectedDate2, date2.Value);
}
#endif
}
}
@@ -75,4 +75,4 @@ using System.Security;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
[assembly: AssemblyFileVersion("5.0.6.16530")]
[assembly: AssemblyFileVersion("5.0.6.16604")]
@@ -555,5 +555,30 @@ namespace Newtonsoft.Json.Tests.Schema
}
}", json);
}
[Test]
public void IntegerValidatesAgainstFloatFlags()
{
JsonSchema schema = JsonSchema.Parse(@"{
""type"": ""object"",
""$schema"": ""http://json-schema.org/draft-03/schema"",
""required"": false,
""properties"": {
""NumberProperty"": {
""required"": false,
""type"": [
""number"",
""null""
]
}
}
}");
JObject json = JObject.Parse(@"{
""NumberProperty"": 23
}");
Assert.IsTrue(json.IsValid(schema));
}
}
}
@@ -8559,6 +8559,25 @@ Parameter name: value",
]", json);
}
#if !(NET20 || NET35)
[Test]
public void SerializeDeserializeTuple()
{
Tuple<int, int> tuple = Tuple.Create(500, 20);
string json = JsonConvert.SerializeObject(tuple);
Assert.AreEqual(@"{""Item1"":500,""Item2"":20}", json);
Tuple<int, int> tuple2 = JsonConvert.DeserializeObject<Tuple<int, int>>(json);
Assert.AreEqual(500, tuple2.Item1);
Assert.AreEqual(20, tuple2.Item2);
}
#endif
public class MessageWithIsoDate
{
public String IsoDate { get; set; }
}
[Test]
public void JsonSerializerStringEscapeHandling()
{
@@ -9393,6 +9412,57 @@ Parameter name: value",
set { _properties = value; }
}
}
#if !(PORTABLE || NETFX_CORE)
public class ConvertibleId : IConvertible
{
public int Value;
TypeCode IConvertible.GetTypeCode() { return TypeCode.Object; }
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
{
if (conversionType == typeof(object)) { return this; }
if (conversionType == typeof(int)) { return (int)Value; }
if (conversionType == typeof(long)) { return (long)Value; }
if (conversionType == typeof(string)) { return Value.ToString(CultureInfo.InvariantCulture); }
throw new InvalidCastException();
}
bool IConvertible.ToBoolean(IFormatProvider provider) { throw new InvalidCastException(); }
byte IConvertible.ToByte(IFormatProvider provider) { throw new InvalidCastException(); }
char IConvertible.ToChar(IFormatProvider provider) { throw new InvalidCastException(); }
DateTime IConvertible.ToDateTime(IFormatProvider provider) { throw new InvalidCastException(); }
decimal IConvertible.ToDecimal(IFormatProvider provider) { throw new InvalidCastException(); }
double IConvertible.ToDouble(IFormatProvider provider) { throw new InvalidCastException(); }
short IConvertible.ToInt16(IFormatProvider provider) { return (short)Value; }
int IConvertible.ToInt32(IFormatProvider provider) { return Value; }
long IConvertible.ToInt64(IFormatProvider provider) { return (long)Value; }
sbyte IConvertible.ToSByte(IFormatProvider provider) { throw new InvalidCastException(); }
float IConvertible.ToSingle(IFormatProvider provider) { throw new InvalidCastException(); }
string IConvertible.ToString(IFormatProvider provider) { throw new InvalidCastException(); }
ushort IConvertible.ToUInt16(IFormatProvider provider) { throw new InvalidCastException(); }
uint IConvertible.ToUInt32(IFormatProvider provider) { throw new InvalidCastException(); }
ulong IConvertible.ToUInt64(IFormatProvider provider) { throw new InvalidCastException(); }
}
public class TestClassConvertable
{
public ConvertibleId Id;
public int X;
}
[Test]
public void ConvertibleIdTest()
{
var c = new TestClassConvertable { Id = new ConvertibleId { Value = 1 }, X = 2 };
var s = JsonConvert.SerializeObject(c, Formatting.Indented);
Assert.AreEqual(@"{
""Id"": ""1"",
""X"": 2
}", s);
}
#endif
}
public class PersonReference
+9 -3
View File
@@ -1398,10 +1398,16 @@ namespace Newtonsoft.Json
// the value is a non-standard IConvertible
// convert to the underlying value and retry
IConvertible convertable = (IConvertible)value;
TypeInformation typeInformation = ConvertUtils.GetTypeInformation(convertable);
object convertedValue = convertable.ToType(typeInformation.Type, CultureInfo.InvariantCulture);
WriteValue(writer, typeInformation.TypeCode, convertedValue);
TypeInformation typeInformation = ConvertUtils.GetTypeInformation(convertable);
// if convertable has an underlying typecode of Object then attempt to convert it to a string
PrimitiveTypeCode resolvedTypeCode = (typeInformation.TypeCode == PrimitiveTypeCode.Object) ? PrimitiveTypeCode.String : typeInformation.TypeCode;
Type resolvedType = (typeInformation.TypeCode == PrimitiveTypeCode.Object) ? typeof(string) : typeInformation.Type;
object convertedValue = convertable.ToType(resolvedType, CultureInfo.InvariantCulture);
WriteValue(writer, resolvedTypeCode, convertedValue);
}
else
#endif
@@ -92,6 +92,6 @@ using System.Security;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
[assembly: AssemblyFileVersion("5.0.6.16530")]
[assembly: AssemblyFileVersion("5.0.6.16604")]
[assembly: CLSCompliant(true)]
@@ -404,7 +404,7 @@ namespace Newtonsoft.Json.Schema
return true;
// integer is a subset of float
if (value == JsonSchemaType.Float && flag == JsonSchemaType.Integer)
if (flag == JsonSchemaType.Integer && (value & JsonSchemaType.Float) == JsonSchemaType.Float)
return true;
return false;
@@ -507,11 +507,16 @@ namespace Newtonsoft.Json.Serialization
if (matchingMemberProperty != null && matchingMemberProperty.PropertyType != parameterInfo.ParameterType)
matchingMemberProperty = null;
JsonProperty property = CreatePropertyFromConstructorParameter(matchingMemberProperty, parameterInfo);
if (property != null)
// ensure that property will have a name from matching property or from parameterinfo
// parameterinfo could have no name if generated by a proxy (I'm looking at you Castle)
if (matchingMemberProperty != null || parameterInfo.Name != null)
{
parameterCollection.AddProperty(property);
JsonProperty property = CreatePropertyFromConstructorParameter(matchingMemberProperty, parameterInfo);
if (property != null)
{
parameterCollection.AddProperty(property);
}
}
}
@@ -176,26 +176,47 @@ namespace Newtonsoft.Json.Utilities
}
else
{
if (start + 5 < _length
if (start + 2 < _length
&& Parse2Digit(start + Lz_, out ZoneHour)
&& ZoneHour <= 99
&& ParseChar(start + Lz_zz, ':')
&& Parse2Digit(start + Lz_zz_, out ZoneMinute)
&& ZoneMinute <= 99)
&& ZoneHour <= 99)
{
switch (ch)
{
case '-':
Zone = ParserTimeZone.LocalWestOfUtc;
start += Lz_zz_zz;
start += Lz_zz;
break;
case '+':
Zone = ParserTimeZone.LocalEastOfUtc;
start += Lz_zz_zz;
start += Lz_zz;
break;
}
}
if (start < _length)
{
if (ParseChar(start, ':'))
{
start += 1;
if (start + 1 < _length
&& Parse2Digit(start, out ZoneMinute)
&& ZoneMinute <= 99)
{
start += 2;
}
}
else
{
if (start + 1 < _length
&& Parse2Digit(start, out ZoneMinute)
&& ZoneMinute <= 99)
{
start += 2;
}
}
}
}
}