From a032f4bbf356844c6f5b28bf32fa89e9622fcceb Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 31 Mar 2012 14:30:14 +1300 Subject: [PATCH] -Fixed deserializing a null string throwing a NullReferenceException -Fixed JsonTextReader reading from a slow stream -Fixed CultureInfo not being overridden on JsonSerializerProxy -Fixed full trust security check in .NET 2.0 & .NET 3.5 -Improved writing JSON with indent performance --- Src/Newtonsoft.Json.Tests/JsonConvertTest.cs | 14 ++ .../JsonTextReaderTest.cs | 146 +++++++++++++++- .../Properties/AssemblyInfo.cs | 76 --------- .../Serialization/ContractResolverTests.cs | 17 ++ Src/Newtonsoft.Json/JsonTextReader.cs | 18 +- Src/Newtonsoft.Json/JsonTextWriter.cs | 9 +- .../Properties/AssemblyInfo.cs | 2 +- .../JsonSerializerInternalReader.cs | 2 +- .../JsonSerializerInternalWriter.cs | 156 +++++++++--------- .../Serialization/JsonSerializerProxy.cs | 6 + .../Serialization/JsonTypeReflector.cs | 22 ++- Src/Newtonsoft.Json/TypeNameHandling.cs | 10 +- 12 files changed, 300 insertions(+), 178 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs index ab2b1545..549e6252 100644 --- a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs @@ -114,6 +114,20 @@ namespace Newtonsoft.Json.Tests } #endif + [Test] + public void DeserializeObject_EmptyString() + { + object result = JsonConvert.DeserializeObject(string.Empty); + Assert.IsNull(result); + } + + [Test] + public void DeserializeObject_Integer() + { + object result = JsonConvert.DeserializeObject("1"); + Assert.AreEqual(1L, result); + } + [Test] public void EscapeJavaScriptString() { diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs index 929b90f9..0afa355d 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs @@ -100,7 +100,7 @@ namespace Newtonsoft.Json.Tests { string json = @"{""DefaultConverter"":new Date(0, ""hi""),""MemberConverter"":""1970-01-01T00:00:00Z""}"; - JsonReader reader = new JsonTextReader(new StringReader(json)); + JsonReader reader = new JsonTextReader(new StreamReader(new SlowStream(json, new UTF8Encoding(false), 1))); Assert.IsTrue(reader.Read()); Assert.IsTrue(reader.Read()); @@ -479,7 +479,7 @@ Parameter name: reader" public void NullCharReading() { string json = "\0{\0'\0h\0i\0'\0:\0[\01\0,\0'\0'\0\0,\0null\0]\0,\0do\0:true\0}\0\0/*\0sd\0f\0*/\0/*\0sd\0f\0*/ \0"; - JsonTextReader reader = new JsonTextReader(new StringReader(json)); + JsonTextReader reader = new JsonTextReader(new StreamReader(new SlowStream(json, new UTF8Encoding(false), 1))); Assert.IsTrue(reader.Read()); Assert.AreEqual(JsonToken.StartObject, reader.TokenType); @@ -710,7 +710,7 @@ Parameter name: reader" count++; } - JsonTextReader reader = new JsonTextReader(new StringReader(json)); + JsonTextReader reader = new JsonTextReader(new StreamReader(new SlowStream(json, new UTF8Encoding(false), 1))); Assert.IsTrue(reader.Read()); Assert.AreEqual(7, reader.LineNumber); @@ -1966,7 +1966,7 @@ bye", reader.Value); public void ParseContentDelimitedByNonStandardWhitespace() { string json = "\x00a0{\x00a0'h\x00a0i\x00a0'\x00a0:\x00a0[\x00a0true\x00a0,\x00a0new\x00a0Date\x00a0(\x00a0)\x00a0]\x00a0/*\x00a0comment\x00a0*/\x00a0}\x00a0"; - JsonTextReader reader = new JsonTextReader(new StringReader(json)); + JsonTextReader reader = new JsonTextReader(new StreamReader(new SlowStream(json, new UTF8Encoding(false), 1))); Assert.IsTrue(reader.Read()); Assert.AreEqual(JsonToken.StartObject, reader.TokenType); @@ -2010,7 +2010,7 @@ bye", reader.Value); ""Sizes"":/*comment*/[/*comment*/ ""Small""/*comment*/]/*comment*/}/*comment*/"; - JsonTextReader reader = new JsonTextReader(new StringReader(json)); + JsonTextReader reader = new JsonTextReader(new StreamReader(new SlowStream(json, new UTF8Encoding(false), 1))); Assert.IsTrue(reader.Read()); Assert.AreEqual(JsonToken.Comment, reader.TokenType); @@ -2194,5 +2194,141 @@ bye", reader.Value); reader.Read(); } + + [Test] + public void ReadingFromSlowStream() + { + string json = "[false, true, true, false, 'test!', 1.11, 0e-10, 0E-10, 0.25e-5, 0.3e10, 6.0221418e23, 'Purple\\r \\n monkey\\'s:\\tdishwasher']"; + + JsonTextReader reader = new JsonTextReader(new StreamReader(new SlowStream(json, new UTF8Encoding(false), 1))); + + Assert.IsTrue(reader.Read()); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(false, reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Boolean, reader.TokenType); + Assert.AreEqual(true, reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Boolean, reader.TokenType); + Assert.AreEqual(true, reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Boolean, reader.TokenType); + Assert.AreEqual(false, reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.String, reader.TokenType); + Assert.AreEqual("test!", reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Float, reader.TokenType); + Assert.AreEqual(1.11d, reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Float, reader.TokenType); + Assert.AreEqual(0d, reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Float, reader.TokenType); + Assert.AreEqual(0d, reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Float, reader.TokenType); + Assert.AreEqual(0.0000025d, reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Float, reader.TokenType); + Assert.AreEqual(3000000000d, reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Float, reader.TokenType); + Assert.AreEqual(602214180000000000000000d, reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.String, reader.TokenType); + Assert.AreEqual(reader.Value, "Purple\r \n monkey's:\tdishwasher"); + + Assert.IsTrue(reader.Read()); + } + } + + public class SlowStream : Stream + { + byte[] bytes; + int totalBytesRead; + int bytesPerRead; + + public SlowStream(byte[] content, int bytesPerRead) + { + this.bytes = content; + this.totalBytesRead = 0; + this.bytesPerRead = bytesPerRead; + } + + public SlowStream(string content, Encoding encoding, int bytesPerRead) + : this(encoding.GetBytes(content), bytesPerRead) + { + } + + public override bool CanRead + { + get { return true; } + } + + public override bool CanSeek + { + get { return false; } + } + + public override bool CanWrite + { + get { return false; } + } + + public override void Flush() + { + } + + public override long Length + { + get { throw new NotSupportedException(); } + } + + public override long Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + + public override int Read(byte[] buffer, int offset, int count) + { + int toReturn = Math.Min(count, this.bytesPerRead); + toReturn = Math.Min(toReturn, this.bytes.Length - this.totalBytesRead); + if (toReturn > 0) + { + Array.Copy(this.bytes, this.totalBytesRead, buffer, offset, toReturn); + } + + this.totalBytesRead += toReturn; + return toReturn; + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } } } diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index e55896be..e69de29b 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -1,76 +0,0 @@ -#region License -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using System.Reflection; -using System.Runtime.InteropServices; -using System.Security; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -#if WINDOWS_PHONE -[assembly: AssemblyTitle("Json.NET Tests Windows Phone")] -#elif SILVERLIGHT -[assembly: AssemblyTitle("Json.NET Tests Silverlight")] -#elif PocketPC -[assembly: AssemblyTitle("Json.NET Tests Compact")] -#elif NET20 -[assembly: AssemblyTitle("Json.NET Tests .NET 2.0")] -#elif NET35 -[assembly: AssemblyTitle("Json.NET Tests .NET 3.5")] -#else -[assembly: AssemblyTitle("Json.NET")] -#endif - -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Newtonsoft")] -[assembly: AssemblyProduct("Json.NET Tests")] -[assembly: AssemblyCopyright("Copyright © James Newton-King 2008")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("0be3d72b-d2ef-409c-985c-d3ede89a25f1")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("4.0.8.0")] -#if !PocketPC -[assembly: AssemblyFileVersion("4.0.8.14718")] -#endif diff --git a/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs index 000c85e4..91825c3a 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using System.Text; #if !NETFX_CORE using NUnit.Framework; @@ -58,9 +59,25 @@ namespace Newtonsoft.Json.Tests.Serialization } } + public class AddressWithDataMember + { + [DataMember(Name = "CustomerAddress1")] + public string AddressLine1 { get; set; } + + } + [TestFixture] public class ContractResolverTests : TestFixtureBase { + [Test] + public void DeserializeDataMemberClassWithNoDataContract() + { + var resolver = new DefaultContractResolver(); + var contract = (JsonObjectContract)resolver.ResolveContract(typeof(AddressWithDataMember)); + + Assert.AreEqual("AddressLine1", contract.Properties[0].PropertyName); + } + [Test] public void ResolveProperties_IgnoreStatic() { diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs index 787d62a5..8272ce25 100644 --- a/Src/Newtonsoft.Json/JsonTextReader.cs +++ b/Src/Newtonsoft.Json/JsonTextReader.cs @@ -343,9 +343,23 @@ namespace Newtonsoft.Json int charsRequired = _charPos + relativePosition - _charsUsed + 1; - int charsRead = ReadData(append, charsRequired); + int totalCharsRead = 0; - if (charsRead < charsRequired) + // it is possible that the TextReader doesn't return all data at once + // repeat read until the required text is returned or the reader is out of content + do + { + int charsRead = ReadData(append, charsRequired - totalCharsRead); + + // no more content + if (charsRead == 0) + break; + + totalCharsRead += charsRead; + } + while (totalCharsRead < charsRequired); + + if (totalCharsRead < charsRequired) return false; return true; } diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs index a7260c68..e14b0d40 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.cs @@ -221,9 +221,14 @@ namespace Newtonsoft.Json // levels of indentation multiplied by the indent count int currentIndentCount = Top*_indentation; - for (int i = 0; i < currentIndentCount; i++) + while (currentIndentCount > 0) { - _writer.Write(_indentChar); + // write up to a max of 10 characters at once to avoid creating too many new strings + int writeCount = Math.Min(currentIndentCount, 10); + + _writer.Write(new string(_indentChar, writeCount)); + + currentIndentCount -= writeCount; } } diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 47b1f423..76834d42 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -85,7 +85,7 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.0.8.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.0.8.14718")] +[assembly: AssemblyFileVersion("4.0.8.14731")] #endif [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index e9f451e8..2e96dd2a 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -117,7 +117,7 @@ namespace Newtonsoft.Json.Serialization if (reader.TokenType == JsonToken.None && !ReadForType(reader, contract, converter != null, false)) { - if (!contract.IsNullable) + if (contract != null && !contract.IsNullable) throw new JsonSerializationException("No JSON content found and type '{0}' is not nullable.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); return null; diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 77e6142a..ee55ade9 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -137,7 +137,7 @@ namespace Newtonsoft.Json.Serialization break; #if !(NET35 || NET20 || WINDOWS_PHONE) case JsonContractType.Dynamic: - SerializeDynamic(writer, (IDynamicMetaObjectProvider) value, (JsonDynamicContract) valueContract); + SerializeDynamic(writer, (IDynamicMetaObjectProvider) value, (JsonDynamicContract) valueContract, member, collectionValueContract); break; #endif #if !SILVERLIGHT && !PocketPC && !NETFX_CORE @@ -184,15 +184,6 @@ namespace Newtonsoft.Json.Serialization private void WriteMemberInfoProperty(JsonWriter writer, object memberValue, JsonProperty property, JsonContract contract) { string propertyName = property.PropertyName; - object defaultValue = property.DefaultValue; - - if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore && - memberValue == null) - return; - - if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore) - && MiscellaneousUtils.ValueEquals(memberValue, defaultValue)) - return; if (ShouldWriteReference(memberValue, property, contract)) { @@ -211,6 +202,19 @@ namespace Newtonsoft.Json.Serialization SerializeValue(writer, memberValue, contract, property, null); } + private bool ShouldWriteProperty(object memberValue, JsonProperty property) + { + if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore && + memberValue == null) + return false; + + if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore) + && MiscellaneousUtils.ValueEquals(memberValue, property.DefaultValue)) + return false; + + return true; + } + private bool CheckForCircularReference(object value, ReferenceLoopHandling? referenceLoopHandling, JsonContract contract) { if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String) @@ -300,18 +304,8 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnSerializing(value, Serializer.Context); _serializeStack.Add(value); - writer.WriteStartObject(); - bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects); - if (isReference) - { - writer.WritePropertyName(JsonTypeReflector.IdPropertyName); - writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, value)); - } - if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract)) - { - WriteTypeProperty(writer, contract.UnderlyingType); - } + WriteObjectStart(writer, value, contract, member, collectionValueContract); int initialDepth = writer.Top; @@ -327,7 +321,10 @@ namespace Newtonsoft.Json.Serialization object memberValue = property.ValueProvider.GetValue(value); JsonContract memberContract = (property.PropertyContract.UnderlyingType.IsSealed()) ? property.PropertyContract : GetContractSafe(memberValue); - WriteMemberInfoProperty(writer, memberValue, property, memberContract); + if (ShouldWriteProperty(memberValue, property)) + { + WriteMemberInfoProperty(writer, memberValue, property, memberContract); + } } } catch (Exception ex) @@ -340,11 +337,28 @@ namespace Newtonsoft.Json.Serialization } writer.WriteEndObject(); + _serializeStack.RemoveAt(_serializeStack.Count - 1); contract.InvokeOnSerialized(value, Serializer.Context); } + private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContract collectionValueContract) + { + writer.WriteStartObject(); + + bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects); + if (isReference) + { + writer.WritePropertyName(JsonTypeReflector.IdPropertyName); + writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, value)); + } + if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract)) + { + WriteTypeProperty(writer, contract.UnderlyingType); + } + } + private void WriteTypeProperty(JsonWriter writer, Type type) { writer.WritePropertyName(JsonTypeReflector.TypePropertyName); @@ -391,32 +405,12 @@ namespace Newtonsoft.Json.Serialization _serializeStack.Add(values.UnderlyingCollection); - bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays); - bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, collectionValueContract); - - if (isReference || includeTypeDetails) - { - writer.WriteStartObject(); - - if (isReference) - { - writer.WritePropertyName(JsonTypeReflector.IdPropertyName); - writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, values.UnderlyingCollection)); - } - if (includeTypeDetails) - { - WriteTypeProperty(writer, values.UnderlyingCollection.GetType()); - } - writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName); - } - - if (contract.CollectionItemContract == null) - contract.CollectionItemContract = Serializer.ContractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object)); - - JsonContract collectionItemValueContract = (contract.CollectionItemContract.UnderlyingType.IsSealed()) ? contract.CollectionItemContract : null; + bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionValueContract); writer.WriteStartArray(); + JsonContract collectionItemValueContract = (contract.CollectionItemContract.UnderlyingType.IsSealed()) ? contract.CollectionItemContract : null; + int initialDepth = writer.Top; int index = 0; @@ -454,16 +448,42 @@ namespace Newtonsoft.Json.Serialization writer.WriteEndArray(); - if (isReference || includeTypeDetails) - { + if (hasWrittenMetadataObject) writer.WriteEndObject(); - } _serializeStack.RemoveAt(_serializeStack.Count - 1); contract.InvokeOnSerialized(values.UnderlyingCollection, Serializer.Context); } + private bool WriteStartArray(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContract collectionValueContract) + { + bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays); + bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, collectionValueContract); + bool writeMetadataObject = isReference || includeTypeDetails; + + if (writeMetadataObject) + { + writer.WriteStartObject(); + + if (isReference) + { + writer.WritePropertyName(JsonTypeReflector.IdPropertyName); + writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, values.UnderlyingCollection)); + } + if (includeTypeDetails) + { + WriteTypeProperty(writer, values.UnderlyingCollection.GetType()); + } + writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName); + } + + if (contract.CollectionItemContract == null) + contract.CollectionItemContract = Serializer.ContractResolver.ResolveContract(contract.CollectionItemType ?? typeof (object)); + + return writeMetadataObject; + } + #if !SILVERLIGHT && !PocketPC && !NETFX_CORE #if !NET20 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Security.SecuritySafeCriticalAttribute")] @@ -480,12 +500,7 @@ To fix this error either change the environment to be fully trusted, change the contract.InvokeOnSerializing(value, Serializer.Context); _serializeStack.Add(value); - writer.WriteStartObject(); - - if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract)) - { - WriteTypeProperty(writer, contract.UnderlyingType); - } + WriteObjectStart(writer, value, contract, member, collectionValueContract); SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter()); value.GetObjectData(serializationInfo, Serializer.Context); @@ -504,18 +519,12 @@ To fix this error either change the environment to be fully trusted, change the #endif #if !(NET35 || NET20 || WINDOWS_PHONE) - /// - /// Serializes the dynamic. - /// - /// The writer. - /// The value. - /// The contract. - private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract) + private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContract collectionValueContract) { contract.InvokeOnSerializing(value, Serializer.Context); _serializeStack.Add(value); - writer.WriteStartObject(); + WriteObjectStart(writer, value, contract, member, collectionValueContract); foreach (string memberName in value.GetDynamicMemberNames()) { @@ -523,9 +532,9 @@ To fix this error either change the environment to be fully trusted, change the if (DynamicUtils.TryGetMember(value, memberName, out memberValue)) { string resolvedPropertyName = (contract.PropertyNameResolver != null) - ? contract.PropertyNameResolver(memberName) - : memberName; - + ? contract.PropertyNameResolver(memberName) + : memberName; + writer.WritePropertyName(resolvedPropertyName); SerializeValue(writer, memberValue, GetContractSafe(memberValue), null, null); } @@ -569,18 +578,8 @@ To fix this error either change the environment to be fully trusted, change the contract.InvokeOnSerializing(values.UnderlyingDictionary, Serializer.Context); _serializeStack.Add(values.UnderlyingDictionary); - writer.WriteStartObject(); - bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects); - if (isReference) - { - writer.WritePropertyName(JsonTypeReflector.IdPropertyName); - writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, values.UnderlyingDictionary)); - } - if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract)) - { - WriteTypeProperty(writer, values.UnderlyingDictionary.GetType()); - } + WriteObjectStart(writer, values.UnderlyingDictionary, contract, member, collectionValueContract); if (contract.DictionaryValueContract == null) contract.DictionaryValueContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object)); @@ -589,12 +588,8 @@ To fix this error either change the environment to be fully trusted, change the int initialDepth = writer.Top; -#if !NETFX_CORE // Mono Unity 3.0 fix - IDictionary d = values; -#else IWrappedDictionary d = values; -#endif foreach (DictionaryEntry entry in d) { @@ -634,6 +629,7 @@ To fix this error either change the environment to be fully trusted, change the } writer.WriteEndObject(); + _serializeStack.RemoveAt(_serializeStack.Count - 1); contract.InvokeOnSerialized(values.UnderlyingDictionary, Serializer.Context); diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs index f35343ca..5eebe32c 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs @@ -144,6 +144,12 @@ namespace Newtonsoft.Json.Serialization set { _serializer.DateTimeZoneHandling = value; } } + public override CultureInfo Culture + { + get { return _serializer.Culture; } + set { _serializer.Culture = value; } + } + internal JsonSerializerInternalBase GetInternalSerializer() { if (_serializerReader != null) diff --git a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs index 180ce080..5709e9b6 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs @@ -28,7 +28,6 @@ using System.ComponentModel; using System.Globalization; using System.Reflection; #if !NETFX_CORE -using System.Runtime.Serialization; using System.Security.Permissions; #endif using Newtonsoft.Json.Utilities; @@ -40,6 +39,7 @@ using Newtonsoft.Json.Utilities.LinqBridge; #else using System.Linq; #endif +using System.Runtime.Serialization; namespace Newtonsoft.Json.Serialization { @@ -102,7 +102,7 @@ namespace Newtonsoft.Json.Serialization return GetJsonContainerAttribute(type) as JsonArrayAttribute; } -#if !PocketPC && !NET20 +#if !PocketPC && !NET20 public static DataContractAttribute GetDataContractAttribute(Type type) { // DataContractAttribute does not have inheritance @@ -126,7 +126,7 @@ namespace Newtonsoft.Json.Serialization return CachedAttributeGetter.GetAttribute(memberInfo.GetCustomAttributeProvider()); // search property and then search base properties if nothing is returned and the property is virtual - PropertyInfo propertyInfo = (PropertyInfo) memberInfo; + PropertyInfo propertyInfo = (PropertyInfo)memberInfo; DataMemberAttribute result = CachedAttributeGetter.GetAttribute(propertyInfo.GetCustomAttributeProvider()); if (result == null) { @@ -259,7 +259,7 @@ namespace Newtonsoft.Json.Serialization else return null; } - + return _cachedMetadataTypeAttributeType; } #endif @@ -403,12 +403,22 @@ namespace Newtonsoft.Json.Serialization { if (_fullyTrusted == null) { -#if !(NET20 || NET35 || SILVERLIGHT) +#if (NETFX_CORE || SILVERLIGHT) + _fullyTrusted = false; +#elif !(NET20 || NET35) AppDomain appDomain = AppDomain.CurrentDomain; _fullyTrusted = appDomain.IsHomogenous && appDomain.IsFullyTrusted; #else - _fullyTrusted = true; + try + { + new SecurityPermission(PermissionState.Unrestricted).Demand(); + _fullyTrusted = true; + } + catch (Exception) + { + _fullyTrusted = false; + } #endif } diff --git a/Src/Newtonsoft.Json/TypeNameHandling.cs b/Src/Newtonsoft.Json/TypeNameHandling.cs index 147af159..33ee5460 100644 --- a/Src/Newtonsoft.Json/TypeNameHandling.cs +++ b/Src/Newtonsoft.Json/TypeNameHandling.cs @@ -21,12 +21,12 @@ namespace Newtonsoft.Json /// Arrays = 2, /// - /// Include the .NET type name when the type of the object being serialized is not the same as its declared type. - /// - Auto = 4, - /// /// Always include the .NET type name when serializing. /// - All = Objects | Arrays + All = Objects | Arrays, + /// + /// Include the .NET type name when the type of the object being serialized is not the same as its declared type. + /// + Auto = 4 } } \ No newline at end of file