-Added ReadAsInt32 to JsonReader
-Improved performance by using an enum rather than a type check to test contract type
This commit is contained in:
@@ -1075,6 +1075,36 @@ bye", reader.Value);
|
||||
Assert.IsFalse(jsonReader.Read());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReadOctalNumberAsInt32()
|
||||
{
|
||||
StringReader s = new StringReader(@"[0372, 0xFA, 0XFA]");
|
||||
JsonTextReader jsonReader = new JsonTextReader(s);
|
||||
|
||||
Assert.IsTrue(jsonReader.Read());
|
||||
Assert.AreEqual(JsonToken.StartArray, jsonReader.TokenType);
|
||||
|
||||
jsonReader.ReadAsInt32();
|
||||
Assert.AreEqual(JsonToken.Integer, jsonReader.TokenType);
|
||||
Assert.AreEqual(typeof(int), jsonReader.ValueType);
|
||||
Assert.AreEqual(250, jsonReader.Value);
|
||||
|
||||
jsonReader.ReadAsInt32();
|
||||
Assert.AreEqual(JsonToken.Integer, jsonReader.TokenType);
|
||||
Assert.AreEqual(typeof(int), jsonReader.ValueType);
|
||||
Assert.AreEqual(250, jsonReader.Value);
|
||||
|
||||
jsonReader.ReadAsInt32();
|
||||
Assert.AreEqual(JsonToken.Integer, jsonReader.TokenType);
|
||||
Assert.AreEqual(typeof(int), jsonReader.ValueType);
|
||||
Assert.AreEqual(250, jsonReader.Value);
|
||||
|
||||
Assert.IsTrue(jsonReader.Read());
|
||||
Assert.AreEqual(JsonToken.EndArray, jsonReader.TokenType);
|
||||
|
||||
Assert.IsFalse(jsonReader.Read());
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonReaderException), ExpectedMessage = "Unexpected character encountered while parsing value: }. Line 1, position 1.")]
|
||||
public void ReadBadCharInArray()
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace Newtonsoft.Json.Tests
|
||||
|
||||
public class PerformanceTests : TestFixtureBase
|
||||
{
|
||||
private const int Iterations = 100;
|
||||
//private const int Iterations = 5000;
|
||||
//private const int Iterations = 100;
|
||||
private const int Iterations = 5000;
|
||||
|
||||
private static SimpleObject CreateSimpleObject()
|
||||
{
|
||||
@@ -101,12 +101,12 @@ namespace Newtonsoft.Json.Tests
|
||||
|
||||
private void SerializeTests(object value)
|
||||
{
|
||||
//BenchmarkSerializeMethod(SerializeMethod.DataContractSerializer, value);
|
||||
////BenchmarkSerializeMethod(SerializeMethod.BinaryFormatter, value);
|
||||
//BenchmarkSerializeMethod(SerializeMethod.JavaScriptSerializer, value);
|
||||
//BenchmarkSerializeMethod(SerializeMethod.DataContractJsonSerializer, value);
|
||||
BenchmarkSerializeMethod(SerializeMethod.DataContractSerializer, value);
|
||||
BenchmarkSerializeMethod(SerializeMethod.BinaryFormatter, value);
|
||||
BenchmarkSerializeMethod(SerializeMethod.JavaScriptSerializer, value);
|
||||
BenchmarkSerializeMethod(SerializeMethod.DataContractJsonSerializer, value);
|
||||
BenchmarkSerializeMethod(SerializeMethod.JsonNet, value);
|
||||
//BenchmarkSerializeMethod(SerializeMethod.JsonNetBinary, value);
|
||||
BenchmarkSerializeMethod(SerializeMethod.JsonNetBinary, value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -763,6 +763,7 @@ namespace Newtonsoft.Json.Tests
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
[Serializable]
|
||||
public class SimpleObject
|
||||
{
|
||||
[DataMember]
|
||||
|
||||
@@ -1931,7 +1931,7 @@ keyword such as type of business.""
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error converting value """" to type 'System.Int32'. Line 1, position 15.")]
|
||||
[ExpectedException(typeof(JsonReaderException), ExpectedMessage = @"Could not convert string to integer: . Line 1, position 15.")]
|
||||
public void DeserializeEnsureTypeEmptyStringToIntError()
|
||||
{
|
||||
JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:''}");
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace Newtonsoft.Json.Bson
|
||||
if (TokenType == JsonToken.Null)
|
||||
return null;
|
||||
if (TokenType == JsonToken.Bytes)
|
||||
return (byte[]) Value;
|
||||
return (byte[])Value;
|
||||
|
||||
if (ReaderIsSerializerInArray())
|
||||
return null;
|
||||
@@ -238,7 +238,7 @@ namespace Newtonsoft.Json.Bson
|
||||
if (TokenType == JsonToken.Integer || TokenType == JsonToken.Float)
|
||||
{
|
||||
SetToken(JsonToken.Float, Convert.ToDecimal(Value, CultureInfo.InvariantCulture));
|
||||
return (decimal) Value;
|
||||
return (decimal)Value;
|
||||
}
|
||||
|
||||
if (ReaderIsSerializerInArray())
|
||||
@@ -247,6 +247,28 @@ namespace Newtonsoft.Json.Bson
|
||||
throw new JsonReaderException("Error reading decimal. Expected a number but got {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Nullable{Int32}"/>.</returns>
|
||||
public override int? ReadAsInt32()
|
||||
{
|
||||
Read();
|
||||
|
||||
if (TokenType == JsonToken.Integer || TokenType == JsonToken.Float)
|
||||
{
|
||||
SetToken(JsonToken.Float, Convert.ToInt32(Value, CultureInfo.InvariantCulture));
|
||||
return (int)Value;
|
||||
}
|
||||
if (TokenType == JsonToken.Null)
|
||||
return null;
|
||||
|
||||
if (ReaderIsSerializerInArray())
|
||||
return null;
|
||||
|
||||
throw new JsonReaderException("Error reading integer. Expected a number but got {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
|
||||
}
|
||||
|
||||
#if !NET20
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace Newtonsoft.Json.Converters
|
||||
|
||||
while (reader.TokenType == JsonToken.PropertyName)
|
||||
{
|
||||
string columnName = (string) reader.Value;
|
||||
string columnName = (string)reader.Value;
|
||||
|
||||
reader.Read();
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Newtonsoft.Json.Converters
|
||||
|
||||
private object ReadBson(BsonReader reader)
|
||||
{
|
||||
string regexText = (string) reader.Value;
|
||||
string regexText = (string)reader.Value;
|
||||
int patternOptionDelimiterIndex = regexText.LastIndexOf('/');
|
||||
|
||||
string patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1);
|
||||
@@ -126,7 +126,7 @@ namespace Newtonsoft.Json.Converters
|
||||
{
|
||||
reader.Read();
|
||||
reader.Read();
|
||||
string pattern = (string) reader.Value;
|
||||
string pattern = (string)reader.Value;
|
||||
|
||||
reader.Read();
|
||||
reader.Read();
|
||||
|
||||
@@ -529,32 +529,6 @@ namespace Newtonsoft.Json
|
||||
return IsJsonPrimitiveTypeCode(Type.GetTypeCode(type));
|
||||
}
|
||||
|
||||
internal static bool IsJsonPrimitive(object value)
|
||||
{
|
||||
if (value == null)
|
||||
return true;
|
||||
|
||||
IConvertible convertible = value as IConvertible;
|
||||
|
||||
if (convertible != null)
|
||||
return IsJsonPrimitiveTypeCode(convertible.GetTypeCode());
|
||||
|
||||
#if !PocketPC && !NET20
|
||||
if (value is DateTimeOffset)
|
||||
return true;
|
||||
#endif
|
||||
if (value is byte[])
|
||||
return true;
|
||||
if (value is Uri)
|
||||
return true;
|
||||
if (value is TimeSpan)
|
||||
return true;
|
||||
if (value is Guid)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the specified object to a JSON string.
|
||||
/// </summary>
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace Newtonsoft.Json
|
||||
}
|
||||
|
||||
// current Token data
|
||||
private JsonToken _token;
|
||||
private JsonToken _tokenType;
|
||||
private object _value;
|
||||
private char _quoteChar;
|
||||
internal State _currentState;
|
||||
@@ -146,7 +146,7 @@ namespace Newtonsoft.Json
|
||||
/// </summary>
|
||||
public virtual JsonToken TokenType
|
||||
{
|
||||
get { return _token; }
|
||||
get { return _tokenType; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -222,6 +222,12 @@ namespace Newtonsoft.Json
|
||||
/// <returns>true if the next token was read successfully; false if there are no more tokens to read.</returns>
|
||||
public abstract bool Read();
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Nullable{Int32}"/>.</returns>
|
||||
public abstract int? ReadAsInt32();
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
|
||||
/// </summary>
|
||||
@@ -276,7 +282,7 @@ namespace Newtonsoft.Json
|
||||
/// <param name="value">The value.</param>
|
||||
protected void SetToken(JsonToken newToken, object value)
|
||||
{
|
||||
_token = newToken;
|
||||
_tokenType = newToken;
|
||||
|
||||
switch (newToken)
|
||||
{
|
||||
@@ -447,7 +453,7 @@ namespace Newtonsoft.Json
|
||||
public virtual void Close()
|
||||
{
|
||||
_currentState = State.Closed;
|
||||
_token = JsonToken.None;
|
||||
_tokenType = JsonToken.None;
|
||||
_value = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Newtonsoft.Json
|
||||
private enum ReadType
|
||||
{
|
||||
Read,
|
||||
ReadAsInt32,
|
||||
ReadAsBytes,
|
||||
ReadAsDecimal,
|
||||
#if !NET20
|
||||
@@ -459,6 +460,45 @@ namespace Newtonsoft.Json
|
||||
throw CreateReaderException(this, "Unexpected token when reading decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Nullable{Int32}"/>.</returns>
|
||||
public override int? ReadAsInt32()
|
||||
{
|
||||
_readType = ReadType.ReadAsInt32;
|
||||
|
||||
do
|
||||
{
|
||||
if (!ReadInternal())
|
||||
throw CreateReaderException(this, "Unexpected end when reading integer.");
|
||||
} while (TokenType == JsonToken.Comment);
|
||||
|
||||
if (TokenType == JsonToken.Integer)
|
||||
return (int?)Value;
|
||||
if (TokenType == JsonToken.Null)
|
||||
return null;
|
||||
|
||||
int i;
|
||||
if (TokenType == JsonToken.String)
|
||||
{
|
||||
if (int.TryParse((string)Value, NumberStyles.Integer, Culture, out i))
|
||||
{
|
||||
SetToken(JsonToken.Integer, i);
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw CreateReaderException(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
|
||||
}
|
||||
}
|
||||
|
||||
if (ReaderIsSerializerInArray())
|
||||
return null;
|
||||
|
||||
throw CreateReaderException(this, "Unexpected token when reading integer: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
|
||||
}
|
||||
|
||||
#if !NET20
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
|
||||
@@ -1223,7 +1263,34 @@ namespace Newtonsoft.Json
|
||||
bool singleDigit = (char.IsDigit(firstChar) && _stringReference.Length == 1);
|
||||
bool nonBase10 = (firstChar == '0' && _stringReference.Length > 1 && _stringReference.Chars[_stringReference.StartIndex + 1] != '.');
|
||||
|
||||
if (_readType == ReadType.ReadAsDecimal)
|
||||
if (_readType == ReadType.ReadAsInt32)
|
||||
{
|
||||
if (singleDigit)
|
||||
{
|
||||
// digit char values start at 48
|
||||
numberValue = firstChar - 48;
|
||||
}
|
||||
else if (nonBase10)
|
||||
{
|
||||
string number = _stringReference.ToString();
|
||||
|
||||
// decimal.Parse doesn't support parsing hexadecimal values
|
||||
int integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
|
||||
? Convert.ToInt32(number, 16)
|
||||
: Convert.ToInt32(number, 8);
|
||||
|
||||
numberValue = integer;
|
||||
}
|
||||
else
|
||||
{
|
||||
string number = _stringReference.ToString();
|
||||
|
||||
numberValue = Convert.ToInt32(number, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
numberType = JsonToken.Integer;
|
||||
}
|
||||
else if (_readType == ReadType.ReadAsDecimal)
|
||||
{
|
||||
if (singleDigit)
|
||||
{
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Newtonsoft.Json
|
||||
/// </summary>
|
||||
Raw,
|
||||
/// <summary>
|
||||
/// An interger.
|
||||
/// An integer.
|
||||
/// </summary>
|
||||
Integer,
|
||||
/// <summary>
|
||||
|
||||
@@ -344,6 +344,18 @@ namespace Newtonsoft.Json
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Nullable{Int32}"/>.</returns>
|
||||
public override int? ReadAsInt32()
|
||||
{
|
||||
int? i = _reader.ReadAsInt32();
|
||||
|
||||
ValidateCurrentToken();
|
||||
return i;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -111,6 +111,28 @@ namespace Newtonsoft.Json.Linq
|
||||
throw new JsonReaderException("Error reading decimal. Expected a number but got {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Nullable{Int32}"/>.</returns>
|
||||
public override int? ReadAsInt32()
|
||||
{
|
||||
Read();
|
||||
|
||||
if (TokenType == JsonToken.Integer || TokenType == JsonToken.Float)
|
||||
{
|
||||
SetToken(JsonToken.Integer, Convert.ToInt32(Value, CultureInfo.InvariantCulture));
|
||||
return (int)Value;
|
||||
}
|
||||
if (TokenType == JsonToken.Null)
|
||||
return null;
|
||||
|
||||
if (ReaderIsSerializerInArray())
|
||||
return null;
|
||||
|
||||
throw new JsonReaderException("Error reading integer. Expected a number but got {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
|
||||
}
|
||||
|
||||
#if !NET20
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
|
||||
|
||||
@@ -258,87 +258,85 @@ namespace Newtonsoft.Json.Schema
|
||||
// todo: Add GetSchema to JsonConverter and use here?
|
||||
CurrentSchema.Type = JsonSchemaType.Any;
|
||||
}
|
||||
else if (contract is JsonDictionaryContract)
|
||||
{
|
||||
CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
|
||||
|
||||
Type keyType;
|
||||
Type valueType;
|
||||
ReflectionUtils.GetDictionaryKeyValueTypes(type, out keyType, out valueType);
|
||||
|
||||
if (keyType != null)
|
||||
{
|
||||
// can be converted to a string
|
||||
if (typeof (IConvertible).IsAssignableFrom(keyType))
|
||||
{
|
||||
CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (contract is JsonArrayContract)
|
||||
{
|
||||
CurrentSchema.Type = AddNullType(JsonSchemaType.Array, valueRequired);
|
||||
|
||||
CurrentSchema.Id = GetTypeId(type, false);
|
||||
|
||||
JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetJsonContainerAttribute(type) as JsonArrayAttribute;
|
||||
bool allowNullItem = (arrayAttribute == null || arrayAttribute.AllowNullItems);
|
||||
|
||||
Type collectionItemType = ReflectionUtils.GetCollectionItemType(type);
|
||||
if (collectionItemType != null)
|
||||
{
|
||||
CurrentSchema.Items = new List<JsonSchema>();
|
||||
CurrentSchema.Items.Add(GenerateInternal(collectionItemType, (!allowNullItem) ? Required.Always : Required.Default, false));
|
||||
}
|
||||
}
|
||||
else if (contract is JsonStringContract)
|
||||
{
|
||||
JsonSchemaType schemaType = (!ReflectionUtils.IsNullable(contract.UnderlyingType))
|
||||
? JsonSchemaType.String
|
||||
: AddNullType(JsonSchemaType.String, valueRequired);
|
||||
|
||||
CurrentSchema.Type = schemaType;
|
||||
}
|
||||
else if (contract is JsonPrimitiveContract)
|
||||
{
|
||||
CurrentSchema.Type = GetJsonSchemaType(type, valueRequired);
|
||||
|
||||
if (CurrentSchema.Type == JsonSchemaType.Integer && type.IsEnum && !type.IsDefined(typeof(FlagsAttribute), true))
|
||||
{
|
||||
CurrentSchema.Enum = new List<JToken>();
|
||||
CurrentSchema.Options = new Dictionary<JToken, string>();
|
||||
|
||||
EnumValues<long> enumValues = EnumUtils.GetNamesAndValues<long>(type);
|
||||
foreach (EnumValue<long> enumValue in enumValues)
|
||||
{
|
||||
JToken value = JToken.FromObject(enumValue.Value);
|
||||
|
||||
CurrentSchema.Enum.Add(value);
|
||||
CurrentSchema.Options.Add(value, enumValue.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (contract is JsonObjectContract)
|
||||
{
|
||||
CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
|
||||
CurrentSchema.Id = GetTypeId(type, false);
|
||||
GenerateObjectSchema(type, (JsonObjectContract)contract);
|
||||
}
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
else if (contract is JsonISerializableContract)
|
||||
{
|
||||
CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
|
||||
CurrentSchema.Id = GetTypeId(type, false);
|
||||
GenerateISerializableContract(type, (JsonISerializableContract) contract);
|
||||
}
|
||||
#endif
|
||||
else if (contract is JsonLinqContract)
|
||||
{
|
||||
CurrentSchema.Type = JsonSchemaType.Any;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
|
||||
switch (contract.ContractType)
|
||||
{
|
||||
case JsonContractType.Object:
|
||||
CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
|
||||
CurrentSchema.Id = GetTypeId(type, false);
|
||||
GenerateObjectSchema(type, (JsonObjectContract) contract);
|
||||
break;
|
||||
case JsonContractType.Array:
|
||||
CurrentSchema.Type = AddNullType(JsonSchemaType.Array, valueRequired);
|
||||
|
||||
CurrentSchema.Id = GetTypeId(type, false);
|
||||
|
||||
JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetJsonContainerAttribute(type) as JsonArrayAttribute;
|
||||
bool allowNullItem = (arrayAttribute == null || arrayAttribute.AllowNullItems);
|
||||
|
||||
Type collectionItemType = ReflectionUtils.GetCollectionItemType(type);
|
||||
if (collectionItemType != null)
|
||||
{
|
||||
CurrentSchema.Items = new List<JsonSchema>();
|
||||
CurrentSchema.Items.Add(GenerateInternal(collectionItemType, (!allowNullItem) ? Required.Always : Required.Default, false));
|
||||
}
|
||||
break;
|
||||
case JsonContractType.Primitive:
|
||||
CurrentSchema.Type = GetJsonSchemaType(type, valueRequired);
|
||||
|
||||
if (CurrentSchema.Type == JsonSchemaType.Integer && type.IsEnum && !type.IsDefined(typeof (FlagsAttribute), true))
|
||||
{
|
||||
CurrentSchema.Enum = new List<JToken>();
|
||||
CurrentSchema.Options = new Dictionary<JToken, string>();
|
||||
|
||||
EnumValues<long> enumValues = EnumUtils.GetNamesAndValues<long>(type);
|
||||
foreach (EnumValue<long> enumValue in enumValues)
|
||||
{
|
||||
JToken value = JToken.FromObject(enumValue.Value);
|
||||
|
||||
CurrentSchema.Enum.Add(value);
|
||||
CurrentSchema.Options.Add(value, enumValue.Name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JsonContractType.String:
|
||||
JsonSchemaType schemaType = (!ReflectionUtils.IsNullable(contract.UnderlyingType))
|
||||
? JsonSchemaType.String
|
||||
: AddNullType(JsonSchemaType.String, valueRequired);
|
||||
|
||||
CurrentSchema.Type = schemaType;
|
||||
break;
|
||||
case JsonContractType.Dictionary:
|
||||
CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
|
||||
|
||||
Type keyType;
|
||||
Type valueType;
|
||||
ReflectionUtils.GetDictionaryKeyValueTypes(type, out keyType, out valueType);
|
||||
|
||||
if (keyType != null)
|
||||
{
|
||||
// can be converted to a string
|
||||
if (typeof (IConvertible).IsAssignableFrom(keyType))
|
||||
{
|
||||
CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
case JsonContractType.Serializable:
|
||||
CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
|
||||
CurrentSchema.Id = GetTypeId(type, false);
|
||||
GenerateISerializableContract(type, (JsonISerializableContract) contract);
|
||||
break;
|
||||
#endif
|
||||
case JsonContractType.Dynamic:
|
||||
case JsonContractType.Linq:
|
||||
CurrentSchema.Type = JsonSchemaType.Any;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
|
||||
}
|
||||
}
|
||||
|
||||
return Pop().Schema;
|
||||
|
||||
@@ -52,6 +52,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
public JsonArrayContract(Type underlyingType)
|
||||
: base(underlyingType)
|
||||
{
|
||||
ContractType = JsonContractType.Array;
|
||||
|
||||
if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType))
|
||||
{
|
||||
CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0];
|
||||
|
||||
@@ -30,20 +30,44 @@ using Newtonsoft.Json.Utilities;
|
||||
|
||||
namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
internal enum JsonContractType
|
||||
{
|
||||
None,
|
||||
Object,
|
||||
Array,
|
||||
Primitive,
|
||||
String,
|
||||
Dictionary,
|
||||
#if !(NET35 || NET20 || WINDOWS_PHONE)
|
||||
Dynamic,
|
||||
#endif
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
Serializable,
|
||||
#endif
|
||||
Linq
|
||||
}
|
||||
|
||||
internal enum ReadType
|
||||
{
|
||||
Read,
|
||||
ReadAsInt32,
|
||||
ReadAsDecimal,
|
||||
ReadAsBytes,
|
||||
#if !NET20
|
||||
ReadAsDateTimeOffset
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
|
||||
/// </summary>
|
||||
public abstract class JsonContract
|
||||
{
|
||||
internal enum ReadType
|
||||
{
|
||||
Read,
|
||||
ReadAsDecimal,
|
||||
ReadAsBytes,
|
||||
#if !NET20
|
||||
ReadAsDateTimeOffset
|
||||
#endif
|
||||
}
|
||||
internal bool IsNullable;
|
||||
internal bool IsConvertable;
|
||||
internal Type NonNullableUnderlyingType;
|
||||
internal ReadType InternalReadType;
|
||||
internal JsonContractType ContractType;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying type for the contract.
|
||||
@@ -73,11 +97,6 @@ namespace Newtonsoft.Json.Serialization
|
||||
// checked for after passed in converters and attribute specified converters
|
||||
internal JsonConverter InternalConverter { get; set; }
|
||||
|
||||
internal ReadType InternalReadType;
|
||||
internal bool IsNullable;
|
||||
internal bool IsConvertable;
|
||||
internal Type NonNullableUnderlyingType;
|
||||
|
||||
#if !PocketPC
|
||||
/// <summary>
|
||||
/// Gets or sets the method called immediately after deserialization of the object.
|
||||
@@ -177,6 +196,10 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
InternalReadType = ReadType.ReadAsBytes;
|
||||
}
|
||||
else if (NonNullableUnderlyingType == typeof(int))
|
||||
{
|
||||
InternalReadType = ReadType.ReadAsInt32;
|
||||
}
|
||||
else if (NonNullableUnderlyingType == typeof(decimal))
|
||||
{
|
||||
InternalReadType = ReadType.ReadAsDecimal;
|
||||
|
||||
@@ -60,6 +60,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
public JsonDictionaryContract(Type underlyingType)
|
||||
: base(underlyingType)
|
||||
{
|
||||
ContractType = JsonContractType.Dictionary;
|
||||
|
||||
Type keyType;
|
||||
Type valueType;
|
||||
if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IDictionary<,>), out _genericCollectionDefinitionType))
|
||||
|
||||
@@ -56,6 +56,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
public JsonDynamicContract(Type underlyingType)
|
||||
: base(underlyingType)
|
||||
{
|
||||
ContractType = JsonContractType.Dynamic;
|
||||
|
||||
Properties = new JsonPropertyCollection(UnderlyingType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
public JsonISerializableContract(Type underlyingType)
|
||||
: base(underlyingType)
|
||||
{
|
||||
ContractType = JsonContractType.Serializable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
public JsonLinqContract(Type underlyingType)
|
||||
: base(underlyingType)
|
||||
{
|
||||
ContractType = JsonContractType.Linq;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,10 +44,10 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// </summary>
|
||||
/// <value>The object's properties.</value>
|
||||
public JsonPropertyCollection Properties { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the constructor parameters required for any non-default constructor
|
||||
/// </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Gets the constructor parameters required for any non-default constructor
|
||||
/// </summary>
|
||||
public JsonPropertyCollection ConstructorParameters { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -71,8 +71,10 @@ namespace Newtonsoft.Json.Serialization
|
||||
public JsonObjectContract(Type underlyingType)
|
||||
: base(underlyingType)
|
||||
{
|
||||
Properties = new JsonPropertyCollection(UnderlyingType);
|
||||
ConstructorParameters = new JsonPropertyCollection(UnderlyingType);
|
||||
ContractType = JsonContractType.Object;
|
||||
|
||||
Properties = new JsonPropertyCollection(UnderlyingType);
|
||||
ConstructorParameters = new JsonPropertyCollection(UnderlyingType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
public JsonPrimitiveContract(Type underlyingType)
|
||||
: base(underlyingType)
|
||||
{
|
||||
ContractType = JsonContractType.Primitive;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
if (reader.TokenType == JsonToken.StartArray)
|
||||
{
|
||||
if (contract is JsonArrayContract)
|
||||
if (contract.ContractType == JsonContractType.Array)
|
||||
PopulateList(CollectionUtils.CreateCollectionWrapper(target), reader, null, (JsonArrayContract) contract);
|
||||
else
|
||||
throw CreateSerializationException(reader, "Cannot populate JSON array onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
@@ -81,9 +81,9 @@ namespace Newtonsoft.Json.Serialization
|
||||
CheckedRead(reader);
|
||||
}
|
||||
|
||||
if (contract is JsonDictionaryContract)
|
||||
if (contract.ContractType == JsonContractType.Dictionary)
|
||||
PopulateDictionary(CollectionUtils.CreateDictionaryWrapper(target), reader, (JsonDictionaryContract) contract, id);
|
||||
else if (contract is JsonObjectContract)
|
||||
else if (contract.ContractType == JsonContractType.Object)
|
||||
PopulateObject(target, reader, (JsonObjectContract) contract, id);
|
||||
else
|
||||
throw CreateSerializationException(reader, "Cannot populate JSON object onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
@@ -223,7 +223,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
private object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue)
|
||||
{
|
||||
if (contract is JsonLinqContract)
|
||||
if (contract != null && contract.ContractType == JsonContractType.Linq)
|
||||
return CreateJToken(reader, contract);
|
||||
|
||||
do
|
||||
@@ -425,53 +425,43 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (contract == null)
|
||||
throw CreateSerializationException(reader, "Could not resolve type '{0}' to a JsonContract.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
|
||||
JsonDictionaryContract dictionaryContract = contract as JsonDictionaryContract;
|
||||
if (dictionaryContract != null)
|
||||
switch (contract.ContractType)
|
||||
{
|
||||
if (existingValue == null)
|
||||
return CreateAndPopulateDictionary(reader, dictionaryContract, id);
|
||||
case JsonContractType.Object:
|
||||
JsonObjectContract objectContract = (JsonObjectContract) contract;
|
||||
if (existingValue == null)
|
||||
return CreateAndPopulateObject(reader, objectContract, id);
|
||||
|
||||
return PopulateDictionary(dictionaryContract.CreateWrapper(existingValue), reader, dictionaryContract, id);
|
||||
}
|
||||
return PopulateObject(existingValue, reader, objectContract, id);
|
||||
case JsonContractType.Primitive:
|
||||
JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract) contract;
|
||||
// if the content is inside $value then read past it
|
||||
if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
|
||||
{
|
||||
CheckedRead(reader);
|
||||
object value = CreateValueInternal(reader, objectType, primitiveContract, member, existingValue);
|
||||
|
||||
JsonObjectContract objectContract = contract as JsonObjectContract;
|
||||
if (objectContract != null)
|
||||
{
|
||||
if (existingValue == null)
|
||||
return CreateAndPopulateObject(reader, objectContract, id);
|
||||
|
||||
return PopulateObject(existingValue, reader, objectContract, id);
|
||||
}
|
||||
|
||||
JsonPrimitiveContract primitiveContract = contract as JsonPrimitiveContract;
|
||||
if (primitiveContract != null)
|
||||
{
|
||||
// if the content is inside $value then read past it
|
||||
if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
|
||||
{
|
||||
CheckedRead(reader);
|
||||
object value = CreateValueInternal(reader, objectType, primitiveContract, member, existingValue);
|
||||
|
||||
CheckedRead(reader);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
JsonISerializableContract serializableContract = contract as JsonISerializableContract;
|
||||
if (serializableContract != null)
|
||||
{
|
||||
return CreateISerializable(reader, serializableContract, id);
|
||||
}
|
||||
#endif
|
||||
CheckedRead(reader);
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
case JsonContractType.Dictionary:
|
||||
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) contract;
|
||||
if (existingValue == null)
|
||||
return CreateAndPopulateDictionary(reader, dictionaryContract, id);
|
||||
|
||||
return PopulateDictionary(dictionaryContract.CreateWrapper(existingValue), reader, dictionaryContract, id);
|
||||
#if !(NET35 || NET20 || WINDOWS_PHONE)
|
||||
JsonDynamicContract dynamicContract = contract as JsonDynamicContract;
|
||||
if (dynamicContract != null)
|
||||
{
|
||||
return CreateDynamic(reader, dynamicContract, id);
|
||||
}
|
||||
case JsonContractType.Dynamic:
|
||||
JsonDynamicContract dynamicContract = (JsonDynamicContract) contract;
|
||||
return CreateDynamic(reader, dynamicContract, id);
|
||||
#endif
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
case JsonContractType.Serializable:
|
||||
JsonISerializableContract serializableContract = (JsonISerializableContract) contract;
|
||||
return CreateISerializable(reader, serializableContract, id);
|
||||
#endif
|
||||
}
|
||||
|
||||
throw CreateSerializationException(reader, "Cannot deserialize JSON object into type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
@@ -1009,7 +999,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
// handle readonly collection/dictionary properties
|
||||
JsonContract propertyContract = Serializer.ContractResolver.ResolveContract(property.PropertyType);
|
||||
|
||||
if (propertyContract is JsonArrayContract)
|
||||
if (propertyContract.ContractType == JsonContractType.Array)
|
||||
{
|
||||
JsonArrayContract propertyArrayContract = propertyContract as JsonArrayContract;
|
||||
|
||||
@@ -1025,7 +1015,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (propertyContract is JsonDictionaryContract)
|
||||
else if (propertyContract.ContractType == JsonContractType.Dictionary)
|
||||
{
|
||||
JsonDictionaryContract jsonDictionaryContract = propertyContract as JsonDictionaryContract;
|
||||
|
||||
@@ -1116,11 +1106,11 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (hasConverter)
|
||||
return reader.Read();
|
||||
|
||||
JsonContract.ReadType t = (contract != null) ? contract.InternalReadType : JsonContract.ReadType.Read;
|
||||
ReadType t = (contract != null) ? contract.InternalReadType : ReadType.Read;
|
||||
|
||||
switch (t)
|
||||
{
|
||||
case JsonContract.ReadType.Read:
|
||||
case ReadType.Read:
|
||||
do
|
||||
{
|
||||
if (!reader.Read())
|
||||
@@ -1128,20 +1118,26 @@ namespace Newtonsoft.Json.Serialization
|
||||
} while (reader.TokenType == JsonToken.Comment);
|
||||
|
||||
return true;
|
||||
case JsonContract.ReadType.ReadAsDecimal:
|
||||
case ReadType.ReadAsInt32:
|
||||
SetSerializeInArray(reader, inArray, true);
|
||||
reader.ReadAsInt32();
|
||||
SetSerializeInArray(reader, inArray, false);
|
||||
|
||||
return true;
|
||||
case ReadType.ReadAsDecimal:
|
||||
SetSerializeInArray(reader, inArray, true);
|
||||
reader.ReadAsDecimal();
|
||||
SetSerializeInArray(reader, inArray, false);
|
||||
|
||||
return true;
|
||||
case JsonContract.ReadType.ReadAsBytes:
|
||||
case ReadType.ReadAsBytes:
|
||||
SetSerializeInArray(reader, inArray, true);
|
||||
reader.ReadAsBytes();
|
||||
SetSerializeInArray(reader, inArray, false);
|
||||
|
||||
return true;
|
||||
#if !NET20
|
||||
case JsonContract.ReadType.ReadAsDateTimeOffset:
|
||||
case ReadType.ReadAsDateTimeOffset:
|
||||
SetSerializeInArray(reader, inArray, true);
|
||||
reader.ReadAsDateTimeOffset();
|
||||
SetSerializeInArray(reader, inArray, false);
|
||||
|
||||
@@ -105,58 +105,55 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
|
||||
if ((converter != null
|
||||
|| ((converter = valueContract.Converter) != null)
|
||||
|| ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
|
||||
|| ((converter = valueContract.InternalConverter) != null))
|
||||
&& converter.CanWrite)
|
||||
|| ((converter = valueContract.Converter) != null)
|
||||
|| ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
|
||||
|| ((converter = valueContract.InternalConverter) != null))
|
||||
&& converter.CanWrite)
|
||||
{
|
||||
SerializeConvertable(writer, converter, value, valueContract);
|
||||
return;
|
||||
}
|
||||
else if (valueContract is JsonStringContract)
|
||||
|
||||
switch (valueContract.ContractType)
|
||||
{
|
||||
SerializeString(writer, value, (JsonStringContract)valueContract);
|
||||
}
|
||||
else if (valueContract is JsonPrimitiveContract)
|
||||
{
|
||||
SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, collectionValueContract);
|
||||
}
|
||||
else if (valueContract is JsonObjectContract)
|
||||
{
|
||||
SerializeObject(writer, value, (JsonObjectContract)valueContract, member, collectionValueContract);
|
||||
}
|
||||
else if (valueContract is JsonDictionaryContract)
|
||||
{
|
||||
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract)valueContract;
|
||||
SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, collectionValueContract);
|
||||
}
|
||||
else if (valueContract is JsonArrayContract)
|
||||
{
|
||||
JsonArrayContract arrayContract = (JsonArrayContract)valueContract;
|
||||
SerializeList(writer, arrayContract.CreateWrapper(value), arrayContract, member, collectionValueContract);
|
||||
}
|
||||
else if (valueContract is JsonLinqContract)
|
||||
{
|
||||
((JToken)value).WriteTo(writer, (Serializer.Converters != null) ? Serializer.Converters.ToArray() : null);
|
||||
}
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
else if (valueContract is JsonISerializableContract)
|
||||
{
|
||||
SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, collectionValueContract);
|
||||
}
|
||||
#endif
|
||||
case JsonContractType.Object:
|
||||
SerializeObject(writer, value, (JsonObjectContract) valueContract, member, collectionValueContract);
|
||||
break;
|
||||
case JsonContractType.Array:
|
||||
JsonArrayContract arrayContract = (JsonArrayContract) valueContract;
|
||||
SerializeList(writer, arrayContract.CreateWrapper(value), arrayContract, member, collectionValueContract);
|
||||
break;
|
||||
case JsonContractType.Primitive:
|
||||
SerializePrimitive(writer, value, (JsonPrimitiveContract) valueContract, member, collectionValueContract);
|
||||
break;
|
||||
case JsonContractType.String:
|
||||
SerializeString(writer, value, (JsonStringContract) valueContract);
|
||||
break;
|
||||
case JsonContractType.Dictionary:
|
||||
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) valueContract;
|
||||
SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, collectionValueContract);
|
||||
break;
|
||||
#if !(NET35 || NET20 || WINDOWS_PHONE)
|
||||
else if (valueContract is JsonDynamicContract)
|
||||
{
|
||||
SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract);
|
||||
}
|
||||
case JsonContractType.Dynamic:
|
||||
SerializeDynamic(writer, (IDynamicMetaObjectProvider) value, (JsonDynamicContract) valueContract);
|
||||
break;
|
||||
#endif
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
case JsonContractType.Serializable:
|
||||
SerializeISerializable(writer, (ISerializable) value, (JsonISerializableContract) valueContract, member, collectionValueContract);
|
||||
break;
|
||||
#endif
|
||||
case JsonContractType.Linq:
|
||||
((JToken) value).WriteTo(writer, (Serializer.Converters != null) ? Serializer.Converters.ToArray() : null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldWriteReference(object value, JsonProperty property, JsonContract contract)
|
||||
{
|
||||
if (value == null)
|
||||
return false;
|
||||
if (contract is JsonPrimitiveContract)
|
||||
if (contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String)
|
||||
return false;
|
||||
|
||||
bool? isReference = null;
|
||||
@@ -170,7 +167,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
if (isReference == null)
|
||||
{
|
||||
if (contract is JsonArrayContract)
|
||||
if (contract.ContractType == JsonContractType.Array)
|
||||
isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
|
||||
else
|
||||
isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
|
||||
@@ -214,7 +211,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
private bool CheckForCircularReference(object value, ReferenceLoopHandling? referenceLoopHandling, JsonContract contract)
|
||||
{
|
||||
if (value == null || contract is JsonPrimitiveContract)
|
||||
if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String)
|
||||
return true;
|
||||
|
||||
if (_serializeStack.IndexOf(value) != -1)
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
public JsonStringContract(Type underlyingType)
|
||||
: base(underlyingType)
|
||||
{
|
||||
ContractType = JsonContractType.String;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user