-Added DateTimeKindHandling to BsonWriter to control how a DateTime is converted prior to being serialized
-Added Required.Always attribute validation when writing JSON as well reading -Added TypeNameHandling.Auto to automatically write the type name when a value doesn't match the declared type -Fixed reading multi-byte strings in BSON
This commit is contained in:
@@ -558,5 +558,45 @@ namespace Newtonsoft.Json.Tests.Bson
|
||||
|
||||
Assert.IsFalse(reader.Read());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WriteDateTimes()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BsonWriter writer = new BsonWriter(ms);
|
||||
writer.DateTimeKindHandling = DateTimeKind.Unspecified;
|
||||
|
||||
writer.WriteStartArray();
|
||||
writer.WriteValue(new DateTime(2000, 10, 12, 20, 55, 0, DateTimeKind.Utc));
|
||||
writer.WriteValue(new DateTime(2000, 10, 12, 20, 55, 0, DateTimeKind.Local));
|
||||
writer.WriteValue(new DateTime(2000, 10, 12, 20, 55, 0, DateTimeKind.Unspecified));
|
||||
writer.WriteEndArray();
|
||||
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
BsonReader reader = new BsonReader(ms);
|
||||
reader.ReadRootValueAsArray = true;
|
||||
reader.DateTimeKindHandling = DateTimeKind.Utc;
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.AreEqual(JsonToken.Date, reader.TokenType);
|
||||
Assert.AreEqual(new DateTime(2000, 10, 12, 20, 55, 0, DateTimeKind.Utc), reader.Value);
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.AreEqual(JsonToken.Date, reader.TokenType);
|
||||
Assert.AreEqual(new DateTime(2000, 10, 12, 20, 55, 0, DateTimeKind.Utc), reader.Value);
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.AreEqual(JsonToken.Date, reader.TokenType);
|
||||
Assert.AreEqual(new DateTime(2000, 10, 12, 20, 55, 0, DateTimeKind.Utc), reader.Value);
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
|
||||
|
||||
Assert.IsFalse(reader.Read());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,8 +34,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;
|
||||
|
||||
#region Data
|
||||
private const string BsonHex =
|
||||
@@ -508,7 +508,7 @@ namespace Newtonsoft.Json.Tests
|
||||
|
||||
TimeOperation<object>(() =>
|
||||
{
|
||||
for (int i = 0; i < 5000; i++)
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
test["dummy"] = new JValue(i);
|
||||
Encoding.UTF8.GetBytes(test.ToString(Formatting.None));
|
||||
@@ -526,7 +526,7 @@ namespace Newtonsoft.Json.Tests
|
||||
|
||||
TimeOperation<object>(() =>
|
||||
{
|
||||
for (int i = 0; i < 5000; i++)
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
test["dummy"] = new JValue(i);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
@@ -1012,7 +1012,7 @@ keyword such as type of business.""
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RequiredMembersClassWithNullValues()
|
||||
public void DeserializeRequiredMembersClassWithNullValues()
|
||||
{
|
||||
string json = @"{
|
||||
""FirstName"": ""I can't be null bro!"",
|
||||
@@ -1030,7 +1030,7 @@ keyword such as type of business.""
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Required property 'FirstName' expects a value but got null.")]
|
||||
public void RequiredMembersClassNullRequiredValueProperty()
|
||||
public void DeserializeRequiredMembersClassNullRequiredValueProperty()
|
||||
{
|
||||
string json = @"{
|
||||
""FirstName"": null,
|
||||
@@ -1042,6 +1042,22 @@ keyword such as type of business.""
|
||||
JsonConvert.DeserializeObject<RequiredMembersClass>(json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Cannot write a null value for property 'FirstName'. Property requires a value.")]
|
||||
public void SerializeRequiredMembersClassNullRequiredValueProperty()
|
||||
{
|
||||
RequiredMembersClass requiredMembersClass = new RequiredMembersClass
|
||||
{
|
||||
FirstName = null,
|
||||
BirthDate = new DateTime(2000, 10, 10, 10, 10, 10, DateTimeKind.Utc),
|
||||
LastName = null,
|
||||
MiddleName = null
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject(requiredMembersClass);
|
||||
Console.WriteLine(json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Required property 'LastName' not found in JSON.")]
|
||||
public void RequiredMembersClassMissingRequiredProperty()
|
||||
|
||||
@@ -461,60 +461,82 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
}
|
||||
#endif
|
||||
|
||||
//[Test]
|
||||
//[Ignore("TODO")]
|
||||
//public void CollectionWithAbstractItems()
|
||||
//{
|
||||
// string Text = "";
|
||||
[Test]
|
||||
public void CollectionWithAbstractItems()
|
||||
{
|
||||
HolderClass testObject = new HolderClass();
|
||||
testObject.TestMember = new ContentSubClass("First One");
|
||||
testObject.AnotherTestMember = new Dictionary<int, IList<ContentBaseClass>>();
|
||||
testObject.AnotherTestMember.Add(1, new List<ContentBaseClass>());
|
||||
testObject.AnotherTestMember[1].Add(new ContentSubClass("Second One"));
|
||||
testObject.AThirdTestMember = new ContentSubClass("Third One");
|
||||
|
||||
// HolderClass testObject = new HolderClass();
|
||||
// testObject.TestMember = new ContentSubClass("First One");
|
||||
// testObject.AnotherTestMember = new Dictionary<int, List<ContentBaseClass>>();
|
||||
// testObject.AnotherTestMember.Add(1, new List<ContentBaseClass>());
|
||||
// testObject.AnotherTestMember[1].Add(new ContentSubClass("Second One"));
|
||||
// testObject.AThirdTestMember = new ContentSubClass("Third One");
|
||||
|
||||
// HolderClass anotherTestObject = null;
|
||||
JsonSerializer serializingTester = new JsonSerializer();
|
||||
serializingTester.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
||||
|
||||
// Newtonsoft.Json.JsonSerializer serializingTester = new Newtonsoft.Json.JsonSerializer();
|
||||
// serializingTester.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
|
||||
StringWriter sw = new StringWriter();
|
||||
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
|
||||
{
|
||||
jsonWriter.Formatting = Formatting.Indented;
|
||||
serializingTester.TypeNameHandling = TypeNameHandling.Auto;
|
||||
serializingTester.Serialize(jsonWriter, testObject);
|
||||
}
|
||||
|
||||
// StringWriter sw = new StringWriter();
|
||||
// using (Newtonsoft.Json.JsonTextWriter jsonWriter = new Newtonsoft.Json.JsonTextWriter(sw))
|
||||
// {
|
||||
// jsonWriter.Formatting = Newtonsoft.Json.Formatting.Indented;
|
||||
string json = sw.ToString();
|
||||
|
||||
// if (Text.Equals("Properties All, Serializer All"))
|
||||
// serializingTester.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All;
|
||||
// else if (Text.Equals("Properties All, Serializer Objects"))
|
||||
// serializingTester.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects;
|
||||
// else if (Text.Equals("Properties All, Serializer Arrays"))
|
||||
// serializingTester.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Arrays;
|
||||
// //otherwise leave default, which looks like it's "None"
|
||||
string contentSubClassRef = ReflectionUtils.GetTypeName(typeof(ContentSubClass), FormatterAssemblyStyle.Simple);
|
||||
string dictionaryRef = ReflectionUtils.GetTypeName(typeof(Dictionary<int, IList<ContentBaseClass>>), FormatterAssemblyStyle.Simple);
|
||||
string listRef = ReflectionUtils.GetTypeName(typeof(List<ContentBaseClass>), FormatterAssemblyStyle.Simple);
|
||||
|
||||
// serializingTester.Serialize(jsonWriter, testObject);
|
||||
// }
|
||||
|
||||
// string json = sw.ToString();
|
||||
Assert.AreEqual(@"{
|
||||
""TestMember"": {
|
||||
""$type"": """ + contentSubClassRef + @""",
|
||||
""SomeString"": ""First One""
|
||||
},
|
||||
""AnotherTestMember"": {
|
||||
""$type"": """ + dictionaryRef + @""",
|
||||
""1"": {
|
||||
""$type"": """ + listRef + @""",
|
||||
""$values"": [
|
||||
{
|
||||
""$type"": """ + contentSubClassRef + @""",
|
||||
""SomeString"": ""Second One""
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
""AThirdTestMember"": {
|
||||
""$type"": """ + contentSubClassRef + @""",
|
||||
""SomeString"": ""Third One""
|
||||
}
|
||||
}", json);
|
||||
Console.WriteLine(json);
|
||||
|
||||
// Console.WriteLine(json);
|
||||
StringReader sr = new StringReader(json);
|
||||
|
||||
// StringReader sr = new StringReader(json);
|
||||
JsonSerializer deserializingTester = new JsonSerializer();
|
||||
|
||||
// Newtonsoft.Json.JsonSerializer deserializingTester = new Newtonsoft.Json.JsonSerializer();
|
||||
HolderClass anotherTestObject;
|
||||
|
||||
// using (Newtonsoft.Json.JsonTextReader jsonReader = new Newtonsoft.Json.JsonTextReader(sr))
|
||||
// {
|
||||
// if (Text.Equals("Properties All, Serializer All"))
|
||||
// deserializingTester.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All;
|
||||
// else if (Text.Equals("Properties All, Serializer Objects"))
|
||||
// deserializingTester.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects;
|
||||
// else if (Text.Equals("Properties All, Serializer Arrays"))
|
||||
// deserializingTester.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Arrays;
|
||||
// //otherwise leave default, which looks like it's "None"
|
||||
using (JsonTextReader jsonReader = new JsonTextReader(sr))
|
||||
{
|
||||
deserializingTester.TypeNameHandling = TypeNameHandling.Auto;
|
||||
|
||||
// anotherTestObject = deserializingTester.Deserialize<HolderClass>(jsonReader);
|
||||
// }
|
||||
//}
|
||||
anotherTestObject = deserializingTester.Deserialize<HolderClass>(jsonReader);
|
||||
}
|
||||
|
||||
Assert.IsNotNull(anotherTestObject);
|
||||
Assert.IsInstanceOfType(typeof(ContentSubClass), anotherTestObject.TestMember);
|
||||
Assert.IsInstanceOfType(typeof(Dictionary<int, IList<ContentBaseClass>>), anotherTestObject.AnotherTestMember);
|
||||
Assert.AreEqual(1, anotherTestObject.AnotherTestMember.Count);
|
||||
|
||||
IList<ContentBaseClass> list = anotherTestObject.AnotherTestMember[1];
|
||||
|
||||
Assert.IsInstanceOfType(typeof(List<ContentBaseClass>), list);
|
||||
Assert.AreEqual(1, list.Count);
|
||||
Assert.IsInstanceOfType(typeof(ContentSubClass), list[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Newtonsoft.Json.Tests.TestObjects
|
||||
public ContentBaseClass TestMember { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty(TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All)]
|
||||
public Dictionary<int, List<ContentBaseClass>> AnotherTestMember { get; set; }
|
||||
public Dictionary<int, IList<ContentBaseClass>> AnotherTestMember { get; set; }
|
||||
|
||||
public ContentBaseClass AThirdTestMember { get; set; }
|
||||
|
||||
|
||||
@@ -17,8 +17,11 @@ namespace Newtonsoft.Json.Bson
|
||||
private byte[] _largeByteBuffer;
|
||||
private int _maxChars;
|
||||
|
||||
public DateTimeKind DateTimeKindHandling { get; set; }
|
||||
|
||||
public BsonBinaryWriter(Stream stream)
|
||||
{
|
||||
DateTimeKindHandling = DateTimeKind.Utc;
|
||||
_writer = new BinaryWriter(stream);
|
||||
}
|
||||
|
||||
@@ -107,8 +110,12 @@ namespace Newtonsoft.Json.Bson
|
||||
if (value.Value is DateTime)
|
||||
{
|
||||
DateTime dateTime = (DateTime) value.Value;
|
||||
dateTime = dateTime.ToUniversalTime();
|
||||
ticks = JsonConvert.ConvertDateTimeToJavaScriptTicks(dateTime);
|
||||
if (DateTimeKindHandling == DateTimeKind.Utc)
|
||||
dateTime = dateTime.ToUniversalTime();
|
||||
else if (DateTimeKindHandling == DateTimeKind.Local)
|
||||
dateTime = dateTime.ToLocalTime();
|
||||
|
||||
ticks = JsonConvert.ConvertDateTimeToJavaScriptTicks(dateTime, false);
|
||||
}
|
||||
#if !PocketPC && !NET20
|
||||
else
|
||||
|
||||
@@ -572,23 +572,27 @@ namespace Newtonsoft.Json.Bson
|
||||
StringBuilder builder = null;
|
||||
|
||||
int totalBytesRead = 0;
|
||||
|
||||
// used in case of left over multibyte characters in the buffer
|
||||
int offset = 0;
|
||||
do
|
||||
{
|
||||
// read up to the maximum size of the buffer or what is remaining, minus the offset
|
||||
// of left over multibyte chars
|
||||
int count = ((length - totalBytesRead) > MaxCharBytesSize - offset)
|
||||
? MaxCharBytesSize - offset
|
||||
: length - totalBytesRead - offset;
|
||||
: length - totalBytesRead;
|
||||
|
||||
int byteCount = _reader.BaseStream.Read(_byteBuffer, offset, count);
|
||||
|
||||
if (byteCount == 0)
|
||||
throw new EndOfStreamException("Unable to read beyond the end of the stream.");
|
||||
|
||||
totalBytesRead += byteCount;
|
||||
|
||||
// Above, byteCount is how many bytes we read this time.
|
||||
// Below, byteCount is how many bytes are in the _byteBuffer.
|
||||
byteCount += offset;
|
||||
|
||||
if (totalBytesRead == 0 && byteCount == length)
|
||||
if (byteCount == length)
|
||||
{
|
||||
// pref optimization to avoid reading into a string builder
|
||||
// first iteration and all bytes read then return string directly
|
||||
@@ -615,8 +619,6 @@ namespace Newtonsoft.Json.Bson
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
totalBytesRead += (byteCount - offset);
|
||||
}
|
||||
}
|
||||
while (totalBytesRead < length);
|
||||
|
||||
@@ -45,6 +45,17 @@ namespace Newtonsoft.Json.Bson
|
||||
private BsonToken _parent;
|
||||
private string _propertyName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="DateTimeKind" /> used when writing <see cref="DateTime"/> values to BSON.
|
||||
/// When set to <see cref="DateTimeKind.Unspecified" /> no conversion will occur.
|
||||
/// </summary>
|
||||
/// <value>The <see cref="DateTimeKind" /> used when writing <see cref="DateTime"/> values to BSON.</value>
|
||||
public DateTimeKind DateTimeKindHandling
|
||||
{
|
||||
get { return _writer.DateTimeKindHandling; }
|
||||
set { _writer.DateTimeKindHandling = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BsonWriter"/> class.
|
||||
/// </summary>
|
||||
|
||||
@@ -181,9 +181,14 @@ namespace Newtonsoft.Json
|
||||
|
||||
internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime)
|
||||
{
|
||||
long universialTicks = ToUniversalTicks(dateTime);
|
||||
return ConvertDateTimeToJavaScriptTicks(dateTime, true);
|
||||
}
|
||||
|
||||
return UniversialTicksToJavaScriptTicks(universialTicks);
|
||||
internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, bool convertToUtc)
|
||||
{
|
||||
long ticks = (convertToUtc) ? ToUniversalTicks(dateTime) : dateTime.Ticks;
|
||||
|
||||
return UniversialTicksToJavaScriptTicks(ticks);
|
||||
}
|
||||
|
||||
private static long UniversialTicksToJavaScriptTicks(long universialTicks)
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Newtonsoft.Json
|
||||
get { return _typeNameHandling; }
|
||||
set
|
||||
{
|
||||
if (value < TypeNameHandling.None || value > TypeNameHandling.All)
|
||||
if (value < TypeNameHandling.None || value > TypeNameHandling.Auto)
|
||||
throw new ArgumentOutOfRangeException("value");
|
||||
|
||||
_typeNameHandling = value;
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (jsonWriter == null)
|
||||
throw new ArgumentNullException("jsonWriter");
|
||||
|
||||
SerializeValue(jsonWriter, value, null, GetContractSafe(value));
|
||||
SerializeValue(jsonWriter, value, GetContractSafe(value), null, null);
|
||||
}
|
||||
|
||||
private JsonSerializerProxy GetInternalSerializer()
|
||||
@@ -81,7 +81,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
return Serializer.ContractResolver.ResolveContract(value.GetType());
|
||||
}
|
||||
|
||||
private void SerializeValue(JsonWriter writer, object value, JsonProperty member, JsonContract contract)
|
||||
private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContract collectionValueContract)
|
||||
{
|
||||
JsonConverter converter = (member != null) ? member.Converter : null;
|
||||
|
||||
@@ -92,39 +92,39 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
|
||||
if ((converter != null
|
||||
|| ((converter = contract.Converter) != null)
|
||||
|| ((converter = Serializer.GetMatchingConverter(contract.UnderlyingType)) != null)
|
||||
|| ((converter = contract.InternalConverter) != null))
|
||||
|| ((converter = valueContract.Converter) != null)
|
||||
|| ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
|
||||
|| ((converter = valueContract.InternalConverter) != null))
|
||||
&& converter.CanWrite)
|
||||
{
|
||||
SerializeConvertable(writer, converter, value, contract);
|
||||
SerializeConvertable(writer, converter, value, valueContract);
|
||||
}
|
||||
else if (contract is JsonPrimitiveContract)
|
||||
else if (valueContract is JsonPrimitiveContract)
|
||||
{
|
||||
writer.WriteValue(value);
|
||||
}
|
||||
else if (contract is JsonStringContract)
|
||||
else if (valueContract is JsonStringContract)
|
||||
{
|
||||
SerializeString(writer, value, (JsonStringContract) contract);
|
||||
SerializeString(writer, value, (JsonStringContract) valueContract);
|
||||
}
|
||||
else if (contract is JsonObjectContract)
|
||||
else if (valueContract is JsonObjectContract)
|
||||
{
|
||||
SerializeObject(writer, value, (JsonObjectContract) contract, member);
|
||||
SerializeObject(writer, value, (JsonObjectContract)valueContract, member, collectionValueContract);
|
||||
}
|
||||
else if (contract is JsonDictionaryContract)
|
||||
else if (valueContract is JsonDictionaryContract)
|
||||
{
|
||||
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) contract;
|
||||
SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member);
|
||||
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) valueContract;
|
||||
SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, collectionValueContract);
|
||||
}
|
||||
else if (contract is JsonArrayContract)
|
||||
else if (valueContract is JsonArrayContract)
|
||||
{
|
||||
if (value is IList)
|
||||
{
|
||||
SerializeList(writer, (IList) value, (JsonArrayContract) contract, member);
|
||||
SerializeList(writer, (IList)value, (JsonArrayContract)valueContract, member, collectionValueContract);
|
||||
}
|
||||
else if (value is IEnumerable)
|
||||
{
|
||||
SerializeList(writer, ((IEnumerable)value).Cast<object>().ToList(), (JsonArrayContract)contract, member);
|
||||
SerializeList(writer, ((IEnumerable)value).Cast<object>().ToList(), (JsonArrayContract)valueContract, member, collectionValueContract);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -133,14 +133,14 @@ namespace Newtonsoft.Json.Serialization
|
||||
CultureInfo.InvariantCulture, value.GetType()));
|
||||
}
|
||||
}
|
||||
else if (contract is JsonLinqContract)
|
||||
else if (valueContract is JsonLinqContract)
|
||||
{
|
||||
((JToken)value).WriteTo(writer, (Serializer.Converters != null) ? Serializer.Converters.ToArray() : null);
|
||||
}
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
else if (contract is JsonISerializableContract)
|
||||
else if (valueContract is JsonISerializableContract)
|
||||
{
|
||||
SerializeISerializable(writer, (ISerializable) value, (JsonISerializableContract) contract);
|
||||
SerializeISerializable(writer, (ISerializable) value, (JsonISerializableContract) valueContract);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -198,8 +198,11 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (!CheckForCircularReference(memberValue, property.ReferenceLoopHandling, contract))
|
||||
return;
|
||||
|
||||
if (memberValue == null && property.Required == Required.Always)
|
||||
throw new JsonSerializationException("Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
|
||||
|
||||
writer.WritePropertyName(propertyName);
|
||||
SerializeValue(writer, memberValue, property, contract);
|
||||
SerializeValue(writer, memberValue, contract, property, null);
|
||||
}
|
||||
|
||||
private bool CheckForCircularReference(object value, ReferenceLoopHandling? referenceLoopHandling, JsonContract contract)
|
||||
@@ -286,7 +289,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
contract.InvokeOnSerialized(value, Serializer.Context);
|
||||
}
|
||||
|
||||
private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member)
|
||||
private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContract collectionValueContract)
|
||||
{
|
||||
contract.InvokeOnSerializing(value, Serializer.Context);
|
||||
|
||||
@@ -299,7 +302,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
|
||||
writer.WriteValue(Serializer.ReferenceResolver.GetReference(value));
|
||||
}
|
||||
if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, TypeNameHandling.Objects))
|
||||
if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract))
|
||||
{
|
||||
WriteTypeProperty(writer, contract.UnderlyingType);
|
||||
}
|
||||
@@ -368,14 +371,14 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
}
|
||||
|
||||
private void SerializeList(JsonWriter writer, IList values, JsonArrayContract contract, JsonProperty member)
|
||||
private void SerializeList(JsonWriter writer, IList values, JsonArrayContract contract, JsonProperty member, JsonContract collectionValueContract)
|
||||
{
|
||||
contract.InvokeOnSerializing(values, Serializer.Context);
|
||||
|
||||
SerializeStack.Add(values);
|
||||
|
||||
bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
|
||||
bool includeTypeDetails = HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, TypeNameHandling.Arrays);
|
||||
bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, collectionValueContract);
|
||||
|
||||
if (isReference || includeTypeDetails)
|
||||
{
|
||||
@@ -393,6 +396,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName);
|
||||
}
|
||||
|
||||
JsonContract childValuesContract = Serializer.ContractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object));
|
||||
|
||||
writer.WriteStartArray();
|
||||
|
||||
int initialDepth = writer.Top;
|
||||
@@ -413,7 +418,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (!CheckForCircularReference(value, null, contract))
|
||||
continue;
|
||||
|
||||
SerializeValue(writer, value, null, valueContract);
|
||||
SerializeValue(writer, value, valueContract, null, childValuesContract);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -451,7 +456,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
foreach (SerializationEntry serializationEntry in serializationInfo)
|
||||
{
|
||||
writer.WritePropertyName(serializationEntry.Name);
|
||||
SerializeValue(writer, serializationEntry.Value, null, GetContractSafe(serializationEntry.Value));
|
||||
SerializeValue(writer, serializationEntry.Value, GetContractSafe(serializationEntry.Value), null, null);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
@@ -461,7 +466,39 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
#endif
|
||||
|
||||
private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member)
|
||||
//private bool ShouldWriteTypeProperty(JsonProperty member, JsonContract contract, TypeNameHandling typeFlag)
|
||||
//{
|
||||
// if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, typeFlag))
|
||||
// return true;
|
||||
|
||||
// if ((((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto)
|
||||
|
||||
// || (member != null
|
||||
// && (member.TypeNameHandling ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto
|
||||
// && contract.UnderlyingType != member.PropertyType)
|
||||
// )
|
||||
//}
|
||||
|
||||
private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContract collectionValueContract)
|
||||
{
|
||||
if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, typeNameHandlingFlag))
|
||||
return true;
|
||||
|
||||
if (member != null)
|
||||
{
|
||||
if ((member.TypeNameHandling ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto && contract.UnderlyingType != member.PropertyType)
|
||||
return true;
|
||||
}
|
||||
else if (collectionValueContract != null)
|
||||
{
|
||||
if (Serializer.TypeNameHandling == TypeNameHandling.Auto && contract.UnderlyingType != collectionValueContract.UnderlyingType)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContract collectionValueContract)
|
||||
{
|
||||
contract.InvokeOnSerializing(values.UnderlyingDictionary, Serializer.Context);
|
||||
|
||||
@@ -474,11 +511,13 @@ namespace Newtonsoft.Json.Serialization
|
||||
writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
|
||||
writer.WriteValue(Serializer.ReferenceResolver.GetReference(values.UnderlyingDictionary));
|
||||
}
|
||||
if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, TypeNameHandling.Objects))
|
||||
if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract))
|
||||
{
|
||||
WriteTypeProperty(writer, values.UnderlyingDictionary.GetType());
|
||||
}
|
||||
|
||||
JsonContract childValuesContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));
|
||||
|
||||
int initialDepth = writer.Top;
|
||||
|
||||
// Mono Unity 3.0 fix
|
||||
@@ -505,7 +544,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
writer.WritePropertyName(propertyName);
|
||||
|
||||
SerializeValue(writer, value, null, valueContract);
|
||||
SerializeValue(writer, value, valueContract, null, childValuesContract);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -24,6 +24,10 @@ namespace Newtonsoft.Json
|
||||
/// </summary>
|
||||
Arrays = 2,
|
||||
/// <summary>
|
||||
/// Include the .NET type name when the type of the object being serialized is not the same as its declared type.
|
||||
/// </summary>
|
||||
Auto = 4,
|
||||
/// <summary>
|
||||
/// Always include the .NET type name when serializing.
|
||||
/// </summary>
|
||||
All = Objects | Arrays
|
||||
|
||||
Reference in New Issue
Block a user