-Added ReadAsInt32 to JsonReader

-Improved performance by using an enum rather than a type check to test contract type
This commit is contained in:
JamesNK
2012-01-22 01:51:01 +00:00
parent cd424a7bc5
commit 58d51cda5c
24 changed files with 398 additions and 238 deletions
@@ -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:''}");
+24 -2
View File
@@ -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();
-26
View File
@@ -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>
+10 -4
View File
@@ -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;
}
+68 -1
View File
@@ -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)
{
+1 -1
View File
@@ -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>
+22
View File
@@ -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;
}
}
}