-Added support for Serializable attribute and MemberSerialization.Fields

-Added support for ignoring properties with NonSerializable attribute
-Added MaxDepth to JsonReader/JsonSerializer/JsonSerializerSettings
This commit is contained in:
James Newton-King
2012-04-08 19:33:09 +12:00
parent 83618b1ea0
commit e3cec969ef
20 changed files with 620 additions and 118 deletions
@@ -44,6 +44,25 @@ namespace Newtonsoft.Json.Tests
[TestFixture]
public class JsonTextReaderTest : TestFixtureBase
{
[Test]
public void SurrogatePairValid()
{
string json = @"{ ""MATHEMATICAL ITALIC CAPITAL ALPHA"": ""\uD835\uDEE2"" }";
JsonTextReader reader = new JsonTextReader(new StringReader(json));
Assert.IsTrue(reader.Read());
Assert.IsTrue(reader.Read());
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.String, reader.TokenType);
string s = reader.Value.ToString();
StringInfo stringInfo = new StringInfo(s);
Assert.AreEqual(1, stringInfo.LengthInTextElements);
}
[Test]
public void CloseInput()
{
@@ -2195,6 +2214,26 @@ bye", reader.Value);
reader.Read();
}
[Test]
public void MaxDepth()
{
string json = "[[]]";
JsonTextReader reader = new JsonTextReader(new StringReader(json))
{
MaxDepth = 1
};
Assert.IsTrue(reader.Read());
ExceptionAssert.Throws<JsonReaderException>(
"This reader's MaxDepth of 1 has been exceeded.",
() =>
{
Assert.IsTrue(reader.Read());
});
}
[Test]
public void ReadingFromSlowStream()
{
@@ -94,6 +94,7 @@
<Compile Include="Linq\JRawTests.cs" />
<Compile Include="Serialization\ConstructorHandlingTests.cs" />
<Compile Include="Serialization\JsonPropertyCollectionTests.cs" />
<Compile Include="Serialization\WebApiIntegrationTests.cs" />
<Compile Include="TestObjects\Bar.cs" />
<Compile Include="TestObjects\Car.cs" />
<Compile Include="TestObjects\Computer.cs" />
@@ -139,6 +139,7 @@
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
<Compile Include="Serialization\DynamicTests.cs" />
<Compile Include="Serialization\NullValueHandlingTests.cs" />
<Compile Include="Serialization\WebApiIntegrationTests.cs" />
<Compile Include="TestObjects\Bar.cs" />
<Compile Include="TestObjects\Car.cs" />
<Compile Include="TestObjects\Computer.cs" />
@@ -139,6 +139,7 @@
<Compile Include="Serialization\SerializationErrorHandlingTests.cs" />
<Compile Include="Serialization\SerializationEventAttributeTests.cs" />
<Compile Include="Serialization\TypeNameHandlingTests.cs" />
<Compile Include="Serialization\WebApiIntegrationTests.cs" />
<Compile Include="TestObjects\AbstractGenericBase.cs" />
<Compile Include="TestObjects\ArgumentConverterPrecedenceClassConverter.cs" />
<Compile Include="TestObjects\BadJsonPropertyClass.cs" />
@@ -102,6 +102,7 @@
<Compile Include="Serialization\SerializationErrorHandlingTests.cs" />
<Compile Include="Serialization\SerializationEventAttributeTests.cs" />
<Compile Include="Serialization\TypeNameHandlingTests.cs" />
<Compile Include="Serialization\WebApiIntegrationTests.cs" />
<Compile Include="TestObjects\AbstractGenericBase.cs" />
<Compile Include="TestObjects\ArgumentConverterPrecedenceClassConverter.cs" />
<Compile Include="TestObjects\BadJsonPropertyClass.cs" />
@@ -144,6 +144,7 @@
<Compile Include="Serialization\ContractResolverTests.cs" />
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
<Compile Include="Serialization\DynamicTests.cs" />
<Compile Include="Serialization\WebApiIntegrationTests.cs" />
<Compile Include="Serialization\JsonPropertyCollectionTests.cs" />
<Compile Include="Serialization\NullValueHandlingTests.cs" />
<Compile Include="TestObjects\Bar.cs" />
@@ -72,5 +72,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.5.1.14719")]
[assembly: AssemblyFileVersion("4.5.1.14808")]
#endif
@@ -256,27 +256,6 @@ namespace Newtonsoft.Json.Tests.Schema
Assert.AreEqual(typeof(Store).AssemblyQualifiedName, schema.Id);
}
[Test]
public void Generate_NumberFormatInfo()
{
JsonSchemaGenerator generator = new JsonSchemaGenerator();
JsonSchema schema = generator.Generate(typeof(NumberFormatInfo));
string json = schema.ToString();
Console.WriteLine(json);
// Assert.AreEqual(@"{
// ""type"": ""object"",
// ""additionalProperties"": {
// ""type"": ""array"",
// ""items"": {
// ""type"": ""string""
// }
// }
//}", json);
}
[Test]
public void CircularReferenceError()
{
@@ -389,7 +368,12 @@ namespace Newtonsoft.Json.Tests.Schema
{
JsonSchemaGenerator generator = new JsonSchemaGenerator();
generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName;
generator.ContractResolver = new CustomDirectoryInfoMapper();
generator.ContractResolver = new CustomDirectoryInfoMapper
{
#if !(SILVERLIGHT || NETFX_CORE)
IgnoreSerializableAttribute = true
#endif
};
JsonSchema schema = generator.Generate(typeof(DirectoryInfo), true);
@@ -468,7 +452,12 @@ namespace Newtonsoft.Json.Tests.Schema
JTokenWriter jsonWriter = new JTokenWriter();
JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new IsoDateTimeConverter());
serializer.ContractResolver = new CustomDirectoryInfoMapper();
serializer.ContractResolver = new CustomDirectoryInfoMapper
{
#if !(SILVERLIGHT || NETFX_CORE)
IgnoreSerializableInterface = true
#endif
};
serializer.Serialize(jsonWriter, temp);
List<string> errors = new List<string>();
@@ -483,9 +472,14 @@ namespace Newtonsoft.Json.Tests.Schema
{
JsonSchemaGenerator generator = new JsonSchemaGenerator();
generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName;
generator.ContractResolver = new CamelCasePropertyNamesContractResolver();
generator.ContractResolver = new CamelCasePropertyNamesContractResolver()
{
#if !(SILVERLIGHT || NETFX_CORE)
IgnoreSerializableAttribute = true
#endif
};
JsonSchema schema = generator.Generate(typeof (Version), true);
JsonSchema schema = generator.Generate(typeof(Version), true);
string json = schema.ToString();
@@ -525,6 +519,68 @@ namespace Newtonsoft.Json.Tests.Schema
}", json);
}
#if !SILVERLIGHT
[Test]
public void GenerateSchemaSerializable()
{
JsonSchemaGenerator generator = new JsonSchemaGenerator();
generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName;
JsonSchema schema = generator.Generate(typeof (Version), true);
string json = schema.ToString();
Assert.AreEqual(@"{
""id"": ""System.Version"",
""type"": [
""object"",
""null""
],
""additionalProperties"": false,
""properties"": {
""_Major"": {
""required"": true,
""type"": ""integer""
},
""_Minor"": {
""required"": true,
""type"": ""integer""
},
""_Build"": {
""required"": true,
""type"": ""integer""
},
""_Revision"": {
""required"": true,
""type"": ""integer""
}
}
}", json);
JTokenWriter jsonWriter = new JTokenWriter();
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(jsonWriter, new Version(1, 2, 3, 4));
List<string> errors = new List<string>();
jsonWriter.Token.Validate(schema, (sender, args) => errors.Add(args.Message));
Assert.AreEqual(0, errors.Count);
Assert.AreEqual(@"{
""_Major"": 1,
""_Minor"": 2,
""_Build"": 3,
""_Revision"": 4
}", jsonWriter.Token.ToString());
Version version = jsonWriter.Token.ToObject<Version>();
Assert.AreEqual(1, version.Major);
Assert.AreEqual(2, version.Minor);
Assert.AreEqual(3, version.Build);
Assert.AreEqual(4, version.Revision);
}
#endif
public enum SortTypeFlag
{
No = 0,
@@ -77,6 +77,9 @@ using Newtonsoft.Json.Utilities.LinqBridge;
#else
using System.Linq;
#endif
#if !(SILVERLIGHT || NETFX_CORE)
using System.Drawing;
#endif
namespace Newtonsoft.Json.Tests.Serialization
{
@@ -490,8 +493,6 @@ keyword such as type of business.""
new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Unspecified),
new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc),
};
string result;
MemoryStream ms = new MemoryStream();
DataContractJsonSerializer s = new DataContractJsonSerializer(typeof (List<DateTime>));
@@ -501,7 +502,7 @@ keyword such as type of business.""
string expected = sr.ReadToEnd();
result = JsonConvert.SerializeObject(testDates, new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat });
string result = JsonConvert.SerializeObject(testDates, new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat });
Assert.AreEqual(expected, result);
}
@@ -1582,8 +1583,10 @@ keyword such as type of business.""
}
}";
DictionaryInterfaceClass c = JsonConvert.DeserializeObject<DictionaryInterfaceClass>(json,
new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace});
DictionaryInterfaceClass c = JsonConvert.DeserializeObject<DictionaryInterfaceClass>(
json,
new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace});
Assert.AreEqual("Name!", c.Name);
Assert.AreEqual(1, c.Dictionary.Count);
Assert.AreEqual(11, c.Dictionary["Item"]);
@@ -2029,7 +2032,15 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Li
)]
public void SerializePropertyGetError()
{
JsonConvert.SerializeObject(new MemoryStream());
JsonConvert.SerializeObject(new MemoryStream(), new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
#if !(SILVERLIGHT || NETFX_CORE)
IgnoreSerializableAttribute = true
#endif
}
});
}
[Test]
@@ -2040,7 +2051,15 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Li
)]
public void DeserializePropertySetError()
{
JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:0}");
JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:0}", new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
#if !(SILVERLIGHT || NETFX_CORE)
IgnoreSerializableAttribute = true
#endif
}
});
}
[Test]
@@ -2051,7 +2070,15 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Li
)]
public void DeserializeEnsureTypeEmptyStringToIntError()
{
JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:''}");
JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:''}", new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
#if !(SILVERLIGHT || NETFX_CORE)
IgnoreSerializableAttribute = true
#endif
}
});
}
[Test]
@@ -2062,7 +2089,15 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Li
)]
public void DeserializeEnsureTypeNullToIntError()
{
JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:null}");
JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:null}", new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
#if !(SILVERLIGHT || NETFX_CORE)
IgnoreSerializableAttribute = true
#endif
}
});
}
[Test]
@@ -5785,6 +5820,119 @@ Parameter name: value"
Assert.AreEqual(person.Name, roundtrippedPerson.Name);
}
#endif
#if !(SILVERLIGHT || NETFX_CORE)
[Test]
public void MetroBlogPost()
{
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2012, 4, 1);
product.Price = 3.99M;
product.Sizes = new []{"Small", "Medium", "Large"};
string json = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "ExpiryDate": "2012-04-01T00:00:00",
// "Price": 3.99,
// "Sizes": [ "Small", "Medium", "Large" ]
//}
string metroJson = JsonConvert.SerializeObject(product, new JsonSerializerSettings
{
ContractResolver = new MetroPropertyNameResolver(),
Converters = { new MetroStringConverter() },
Formatting = Formatting.Indented
});
Assert.AreEqual(metroJson, @"{
"":::NAME:::"": "":::APPLE:::"",
"":::EXPIRYDATE:::"": ""2012-04-01T00:00:00"",
"":::PRICE:::"": 3.99,
"":::SIZES:::"": [
"":::SMALL:::"",
"":::MEDIUM:::"",
"":::LARGE:::""
]
}");
//{
// ":::NAME:::": ":::APPLE:::",
// ":::EXPIRYDATE:::": "2012-04-01T00:00:00",
// ":::PRICE:::": 3.99,
// ":::SIZES:::": [ ":::SMALL:::", ":::MEDIUM:::", ":::LARGE:::" ]
//}
Color[] colors = new []{ Color.Blue, Color.Red, Color.Yellow, Color.Green, Color.Black, Color.Brown };
string json1 = JsonConvert.SerializeObject(colors);
//[":::GRAY:::", ":::GRAY:::", ":::GRAY:::", ":::GRAY:::", ":::BLACK:::", ":::GRAY:::"]
Assert.AreEqual(json1, @"[""Blue"",""Red"",""Yellow"",""Green"",""Black"",""Brown""]");
string json2 = JsonConvert.SerializeObject(colors, new JsonSerializerSettings
{
ContractResolver = new MetroPropertyNameResolver(),
Converters = { new MetroStringConverter(), new MetroColorConverter() },
Formatting = Formatting.Indented
});
Assert.AreEqual(json2, @"[
"":::GRAY:::"",
"":::GRAY:::"",
"":::GRAY:::"",
"":::GRAY:::"",
"":::BLACK:::"",
"":::GRAY:::""
]");
}
public class MetroStringConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(":::" + value.ToString().ToUpper() + ":::");
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return existingValue;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof (string);
}
}
public class MetroPropertyNameResolver : DefaultContractResolver
{
protected internal override string ResolvePropertyName(string propertyName)
{
return ":::" + propertyName.ToUpper() + ":::";
}
}
public class MetroColorConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Color color = (Color) value;
Color fixedColor = (color == Color.White || color == Color.Black) ? color : Color.Gray;
writer.WriteValue(":::" + fixedColor.ToKnownColor().ToString().ToUpper() + ":::");
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return Enum.Parse(typeof (Color), reader.Value.ToString());
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof (Color);
}
}
#endif
}
public class PersonWithPrivateConstructor
@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using System.IO;
#if !NET20
using System.Linq;
#endif
using System.Text;
using NUnit.Framework;
#if !(SILVERLIGHT || NETFX_CORE || NET20)
using System.Runtime.Serialization.Json;
#endif
namespace Newtonsoft.Json.Tests.Serialization
{
[TestFixture]
public class WebApiIntegrationTests : TestFixtureBase
{
[Test]
public void SerializeSerializableType()
{
SerializableType serializableType = new SerializableType("protected")
{
publicField = "public",
protectedInternalField = "protected internal",
internalField = "internal",
PublicProperty = "private",
nonSerializedField = "Error"
};
#if !(SILVERLIGHT || NETFX_CORE || NET20)
MemoryStream ms = new MemoryStream();
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(SerializableType));
dataContractJsonSerializer.WriteObject(ms, serializableType);
string dtJson = Encoding.UTF8.GetString(ms.ToArray());
string dtExpected = @"{""internalField"":""internal"",""privateField"":""private"",""protectedField"":""protected"",""protectedInternalField"":""protected internal"",""publicField"":""public""}";
Assert.AreEqual(dtExpected, dtJson);
#endif
string expected = "{\"publicField\":\"public\",\"internalField\":\"internal\",\"protectedInternalField\":\"protected internal\",\"protectedField\":\"protected\",\"privateField\":\"private\"}";
string json = JsonConvert.SerializeObject(serializableType);
Assert.AreEqual(expected, json);
}
#if !SILVERLIGHT
[Test]
public void SerializeInheritedType()
{
InheritedType serializableType = new InheritedType("protected")
{
publicField = "public",
protectedInternalField = "protected internal",
internalField = "internal",
PublicProperty = "private",
nonSerializedField = "Error",
inheritedTypeField = "inherited"
};
string json = JsonConvert.SerializeObject(serializableType);
Assert.AreEqual(@"{""inheritedTypeField"":""inherited"",""publicField"":""public"",""PublicProperty"":""private""}", json);
}
#endif
}
public class InheritedType : SerializableType
{
public string inheritedTypeField;
public InheritedType(string protectedFieldValue) : base(protectedFieldValue)
{
}
}
#if !(SILVERLIGHT || NETFX_CORE)
[Serializable]
#else
[JsonObject(MemberSerialization.Fields)]
#endif
public class SerializableType : IEquatable<SerializableType>
{
public SerializableType(string protectedFieldValue)
{
this.protectedField = protectedFieldValue;
}
public string publicField;
internal string internalField;
protected internal string protectedInternalField;
protected string protectedField;
private string privateField;
public string PublicProperty
{
get
{
return privateField;
}
set
{
this.privateField = value;
}
}
#if !(SILVERLIGHT || NETFX_CORE)
[NonSerialized]
#else
[JsonIgnore]
#endif
public string nonSerializedField;
public bool Equals(SerializableType other)
{
return this.publicField == other.publicField &&
this.internalField == other.internalField &&
this.protectedInternalField == other.protectedInternalField &&
this.protectedField == other.protectedField &&
this.privateField == other.privateField;
}
}
}
+22 -20
View File
@@ -109,6 +109,7 @@ namespace Newtonsoft.Json
private JsonPosition _currentPosition;
private CultureInfo _culture;
private DateTimeZoneHandling _dateTimeZoneHandling;
private int? _maxDepth;
/// <summary>
/// Gets the current reader state.
@@ -149,6 +150,18 @@ namespace Newtonsoft.Json
set { _dateTimeZoneHandling = value; }
}
public int? MaxDepth
{
get { return _maxDepth; }
set
{
if (value <= 0)
throw new ArgumentException("Value must be positive.", "value");
_maxDepth = value;
}
}
/// <summary>
/// Gets the type of the current JSON token.
/// </summary>
@@ -235,11 +248,15 @@ namespace Newtonsoft.Json
else
{
_stack.Add(_currentPosition);
var state = new JsonPosition
JsonPosition state = new JsonPosition
{
Type = value
};
_currentPosition = state;
// this is a little hacky because Depth increases when first property/value is written but only testing here is faster/simpler
if (_maxDepth != null && Depth + 1 > _maxDepth)
throw new JsonReaderException("This reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth));
}
}
@@ -667,7 +684,10 @@ namespace Newtonsoft.Json
/// <param name="value">The value.</param>
protected void SetToken(JsonToken newToken, object value)
{
JsonToken previousToken = _tokenType;
_tokenType = newToken;
_value = value;
switch (newToken)
{
@@ -711,8 +731,6 @@ namespace Newtonsoft.Json
UpdateScopeWithFinishedValue();
break;
}
_value = value;
}
private void UpdateScopeWithFinishedValue()
@@ -789,24 +807,8 @@ namespace Newtonsoft.Json
case JsonToken.StartArray:
case JsonToken.StartConstructor:
return true;
case JsonToken.PropertyName:
case JsonToken.None:
case JsonToken.Comment:
case JsonToken.Integer:
case JsonToken.Float:
case JsonToken.String:
case JsonToken.Boolean:
case JsonToken.Null:
case JsonToken.Undefined:
case JsonToken.EndObject:
case JsonToken.EndArray:
case JsonToken.EndConstructor:
case JsonToken.Date:
case JsonToken.Raw:
case JsonToken.Bytes:
return false;
default:
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("token", token, "Unexpected JsonToken value.");
return false;
}
}
+25
View File
@@ -61,6 +61,8 @@ namespace Newtonsoft.Json
private DateFormatHandling? _dateFormatHandling;
private DateTimeZoneHandling? _dateTimeZoneHandling;
private CultureInfo _culture;
private int? _maxDepth;
private bool _maxDepthSet;
/// <summary>
/// Occurs when the <see cref="JsonSerializer"/> errors during serialization and deserialization.
@@ -320,6 +322,19 @@ namespace Newtonsoft.Json
get { return _culture ?? JsonSerializerSettings.DefaultCulture; }
set { _culture = value; }
}
public virtual int? MaxDepth
{
get { return _maxDepth; }
set
{
if (value <= 0)
throw new ArgumentException("Value must be positive.", "value");
_maxDepth = value;
_maxDepthSet = true;
}
}
#endregion
/// <summary>
@@ -371,6 +386,8 @@ namespace Newtonsoft.Json
jsonSerializer._dateFormatHandling = settings._dateFormatHandling;
jsonSerializer._dateTimeZoneHandling = settings._dateTimeZoneHandling;
jsonSerializer._culture = settings._culture;
jsonSerializer._maxDepth = settings._maxDepth;
jsonSerializer._maxDepthSet = settings._maxDepthSet;
if (settings.Error != null)
jsonSerializer.Error += settings.Error;
@@ -478,6 +495,12 @@ namespace Newtonsoft.Json
previousDateTimeZoneHandling = reader.DateTimeZoneHandling;
reader.DateTimeZoneHandling = _dateTimeZoneHandling.Value;
}
int? previousMaxDepth = null;
if (_maxDepthSet && reader.MaxDepth != _maxDepth)
{
previousMaxDepth = reader.MaxDepth;
reader.MaxDepth = _maxDepth;
}
JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this);
object value = serializerReader.Deserialize(reader, objectType);
@@ -487,6 +510,8 @@ namespace Newtonsoft.Json
reader.Culture = previousCulture;
if (previousDateTimeZoneHandling != null)
reader.DateTimeZoneHandling = previousDateTimeZoneHandling.Value;
if (_maxDepthSet)
reader.MaxDepth = previousMaxDepth;
return value;
}
@@ -32,6 +32,8 @@ namespace Newtonsoft.Json
internal DateFormatHandling? _dateFormatHandling;
internal DateTimeZoneHandling? _dateTimeZoneHandling;
internal CultureInfo _culture;
internal int? _maxDepth;
internal bool _maxDepthSet;
/// <summary>
/// Gets or sets how reference loops (e.g. a class referencing itself) is handled.
@@ -124,6 +126,19 @@ namespace Newtonsoft.Json
/// <value>The context.</value>
public StreamingContext Context { get; set; }
public int? MaxDepth
{
get { return _maxDepth; }
set
{
if (value <= 0)
throw new ArgumentException("Value must be positive.", "value");
_maxDepth = value;
_maxDepthSet = true;
}
}
/// <summary>
/// Indicates how JSON text output is formatted.
/// </summary>
+14 -4
View File
@@ -23,6 +23,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Runtime.Serialization;
namespace Newtonsoft.Json
{
/// <summary>
@@ -31,12 +34,19 @@ namespace Newtonsoft.Json
public enum MemberSerialization
{
/// <summary>
/// All members are serialized by default. Members can be excluded using the <see cref="JsonIgnoreAttribute"/>.
/// All public members are serialized by default. Members can be excluded using <see cref="JsonIgnoreAttribute"/> or <see cref="NonSerializedAttribute"/>.
/// This is the default member serialization mode.
/// </summary>
OptOut,
/// <summary>
/// Only members must be marked with the <see cref="JsonPropertyAttribute"/> are serialized.
/// Only members must be marked with <see cref="JsonPropertyAttribute"/> or <see cref="DataMemberAttribute"/> are serialized.
/// This member serialization mode can also be set by marking the class with <see cref="DataContractAttribute"/>.
/// </summary>
OptIn
OptIn,
/// <summary>
/// All public and private fields are serialized. Members can be excluded using <see cref="JsonIgnoreAttribute"/> or <see cref="NonSerializedAttribute"/>.
/// This member serialization mode can also be set by marking the class with <see cref="SerializableAttribute"/>.
/// </summary>
Fields
}
}
}
@@ -88,7 +88,7 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.5.1.14719")]
[assembly: AssemblyFileVersion("4.5.1.14808")]
#endif
[assembly: CLSCompliant(true)]
@@ -151,7 +151,7 @@ namespace Newtonsoft.Json.Serialization
/// </value>
public bool SerializeCompilerGeneratedMembers { get; set; }
#if !SILVERLIGHT && !PocketPC && !NETFX_CORE
#if !(SILVERLIGHT || NETFX_CORE)
/// <summary>
/// Gets or sets a value indicating whether to ignore the ISerializable interface when serializing and deserializing types.
/// </summary>
@@ -159,6 +159,8 @@ namespace Newtonsoft.Json.Serialization
/// <c>true</c> if the ISerializable interface will be ignored when serializing and deserializing types; otherwise, <c>false</c>.
/// </value>
public bool IgnoreSerializableInterface { get; set; }
public bool IgnoreSerializableAttribute { get; set; }
#endif
/// <summary>
@@ -243,45 +245,71 @@ namespace Newtonsoft.Json.Serialization
/// <returns>The serializable members for the type.</returns>
protected virtual List<MemberInfo> GetSerializableMembers(Type objectType)
{
#if !PocketPC && !NET20
DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType);
bool ignoreSerializableAttribute;
#if !(SILVERLIGHT || NETFX_CORE)
ignoreSerializableAttribute = IgnoreSerializableAttribute;
#else
ignoreSerializableAttribute = true;
#endif
List<MemberInfo> defaultMembers = ReflectionUtils.GetFieldsAndProperties(objectType, DefaultMembersSearchFlags)
.Where(m => !ReflectionUtils.IsIndexedProperty(m)).ToList();
MemberSerialization memberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType, ignoreSerializableAttribute);
List<MemberInfo> allMembers = ReflectionUtils.GetFieldsAndProperties(objectType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
.Where(m => !ReflectionUtils.IsIndexedProperty(m)).ToList();
List<MemberInfo> serializableMembers = new List<MemberInfo>();
foreach (MemberInfo member in allMembers)
if (memberSerialization != MemberSerialization.Fields)
{
// exclude members that are compiler generated if set
if (SerializeCompilerGeneratedMembers || !member.IsDefined(typeof(CompilerGeneratedAttribute), true))
{
if (defaultMembers.Contains(member))
{
// add all members that are found by default member search
serializableMembers.Add(member);
}
else
{
// add members that are explicitly marked with JsonProperty/DataMember attribute
if (JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(member.GetCustomAttributeProvider()) != null)
serializableMembers.Add(member);
#if !PocketPC && !NET20
else if (dataContractAttribute != null && JsonTypeReflector.GetAttribute<DataMemberAttribute>(member.GetCustomAttributeProvider()) != null)
serializableMembers.Add(member);
DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType);
#endif
List<MemberInfo> defaultMembers = ReflectionUtils.GetFieldsAndProperties(objectType, DefaultMembersSearchFlags)
.Where(m => !ReflectionUtils.IsIndexedProperty(m)).ToList();
foreach (MemberInfo member in allMembers)
{
// exclude members that are compiler generated if set
if (SerializeCompilerGeneratedMembers || !member.IsDefined(typeof (CompilerGeneratedAttribute), true))
{
if (defaultMembers.Contains(member))
{
// add all members that are found by default member search
serializableMembers.Add(member);
}
else
{
// add members that are explicitly marked with JsonProperty/DataMember attribute
// or are a field if serializing just fields
if (JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(member.GetCustomAttributeProvider()) != null)
serializableMembers.Add(member);
#if !PocketPC && !NET20
else if (dataContractAttribute != null && JsonTypeReflector.GetAttribute<DataMemberAttribute>(member.GetCustomAttributeProvider()) != null)
serializableMembers.Add(member);
#endif
else if (memberSerialization == MemberSerialization.Fields && member.MemberType() == MemberTypes.Field)
serializableMembers.Add(member);
}
}
}
}
#if !PocketPC && !SILVERLIGHT && !NET20
Type match;
// don't include EntityKey on entities objects... this is a bit hacky
if (objectType.AssignableToTypeName("System.Data.Objects.DataClasses.EntityObject", out match))
serializableMembers = serializableMembers.Where(ShouldSerializeEntityMember).ToList();
Type match;
// don't include EntityKey on entities objects... this is a bit hacky
if (objectType.AssignableToTypeName("System.Data.Objects.DataClasses.EntityObject", out match))
serializableMembers = serializableMembers.Where(ShouldSerializeEntityMember).ToList();
#endif
}
else
{
// serialize all fields
foreach (MemberInfo member in allMembers)
{
if (member.MemberType() == MemberTypes.Field)
serializableMembers.Add(member);
}
}
return serializableMembers;
}
@@ -310,7 +338,14 @@ namespace Newtonsoft.Json.Serialization
JsonObjectContract contract = new JsonObjectContract(objectType);
InitializeContract(contract);
contract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(contract.NonNullableUnderlyingType);
bool ignoreSerializableAttribute;
#if !(SILVERLIGHT || NETFX_CORE)
ignoreSerializableAttribute = IgnoreSerializableAttribute;
#else
ignoreSerializableAttribute = true;
#endif
contract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(contract.NonNullableUnderlyingType, ignoreSerializableAttribute);
contract.Properties.AddRange(CreateProperties(contract.NonNullableUnderlyingType, contract.MemberSerialization));
// check if a JsonConstructorAttribute has been defined and use that
@@ -872,7 +907,7 @@ namespace Newtonsoft.Json.Serialization
DataMemberAttribute dataMemberAttribute;
if (dataContractAttribute != null && memberInfo != null)
dataMemberAttribute = JsonTypeReflector.GetDataMemberAttribute((MemberInfo)memberInfo);
dataMemberAttribute = JsonTypeReflector.GetDataMemberAttribute((MemberInfo) memberInfo);
else
dataMemberAttribute = null;
#endif
@@ -881,8 +916,6 @@ namespace Newtonsoft.Json.Serialization
if (propertyAttribute != null)
hasExplicitAttribute = true;
bool hasIgnoreAttribute = (JsonTypeReflector.GetAttribute<JsonIgnoreAttribute>(attributeProvider) != null);
string mappedName;
if (propertyAttribute != null && propertyAttribute.PropertyName != null)
mappedName = propertyAttribute.PropertyName;
@@ -913,13 +946,28 @@ namespace Newtonsoft.Json.Serialization
property.Required = Required.Default;
}
property.Ignored = (hasIgnoreAttribute ||
(memberSerialization == MemberSerialization.OptIn
&& propertyAttribute == null
#if !PocketPC && !NET20
&& dataMemberAttribute == null
bool hasJsonIgnoreAttribute = JsonTypeReflector.GetAttribute<JsonIgnoreAttribute>(attributeProvider) != null
#if !(SILVERLIGHT || NETFX_CORE)
|| JsonTypeReflector.GetAttribute<NonSerializedAttribute>(attributeProvider) != null
#endif
));
;
if (memberSerialization != MemberSerialization.OptIn)
{
// ignored if it has JsonIgnore or NonSerialized attributes
property.Ignored = hasJsonIgnoreAttribute;
}
else
{
// ignored if it has JsonIgnore/NonSerialized or does not have DataMember or JsonProperty attributes
property.Ignored =
hasJsonIgnoreAttribute
|| (propertyAttribute == null
#if !PocketPC && !NET20
&& dataMemberAttribute == null
#endif
);
}
// resolve converter for property
// the class type might have a converter but the property converter takes presidence
@@ -941,6 +989,8 @@ namespace Newtonsoft.Json.Serialization
allowNonPublicAccess = true;
if (propertyAttribute != null)
allowNonPublicAccess = true;
if (memberSerialization == MemberSerialization.Fields)
allowNonPublicAccess = true;
#if !PocketPC && !NET20
if (dataMemberAttribute != null)
@@ -150,6 +150,12 @@ namespace Newtonsoft.Json.Serialization
set { _serializer.Culture = value; }
}
public override int? MaxDepth
{
get { return _serializer.MaxDepth; }
set { _serializer.MaxDepth = value; }
}
internal JsonSerializerInternalBase GetInternalSerializer()
{
if (_serializerReader != null)
@@ -102,19 +102,29 @@ namespace Newtonsoft.Json.Serialization
return GetJsonContainerAttribute(type) as JsonArrayAttribute;
}
#if !(SILVERLIGHT || NETFX_CORE)
public static SerializableAttribute GetSerializableAttribute(Type type)
{
return CachedAttributeGetter<SerializableAttribute>.GetAttribute(type.GetCustomAttributeProvider());
}
#endif
#if !PocketPC && !NET20
public static DataContractAttribute GetDataContractAttribute(Type type)
{
// DataContractAttribute does not have inheritance
DataContractAttribute result = null;
Type currentType = type;
while (result == null && currentType != null)
while (currentType != null)
{
result = CachedAttributeGetter<DataContractAttribute>.GetAttribute(currentType.GetCustomAttributeProvider());
DataContractAttribute result = CachedAttributeGetter<DataContractAttribute>.GetAttribute(currentType.GetCustomAttributeProvider());
if (result != null)
return result;
currentType = currentType.BaseType();
}
return result;
return null;
}
public static DataMemberAttribute GetDataMemberAttribute(MemberInfo memberInfo)
@@ -149,23 +159,29 @@ namespace Newtonsoft.Json.Serialization
}
#endif
public static MemberSerialization GetObjectMemberSerialization(Type objectType)
public static MemberSerialization GetObjectMemberSerialization(Type objectType, bool ignoreSerializableAttribute)
{
JsonObjectAttribute objectAttribute = GetJsonObjectAttribute(objectType);
if (objectAttribute != null)
return objectAttribute.MemberSerialization;
if (objectAttribute == null)
{
#if !PocketPC && !NET20
DataContractAttribute dataContractAttribute = GetDataContractAttribute(objectType);
if (dataContractAttribute != null)
return MemberSerialization.OptIn;
DataContractAttribute dataContractAttribute = GetDataContractAttribute(objectType);
if (dataContractAttribute != null)
return MemberSerialization.OptIn;
#endif
return MemberSerialization.OptOut;
#if !(SILVERLIGHT || NETFX_CORE)
if (!ignoreSerializableAttribute)
{
SerializableAttribute serializableAttribute = GetSerializableAttribute(objectType);
if (serializableAttribute != null)
return MemberSerialization.Fields;
}
#endif
return objectAttribute.MemberSerialization;
// the default
return MemberSerialization.OptOut;
}
private static Type GetJsonConverterType(ICustomAttributeProvider attributeProvider)
@@ -24,15 +24,7 @@ namespace Newtonsoft.Json.Utilities
private bool IsOverridden(string method)
{
return _proxy.GetType().GetMember(method, MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance).Cast<MethodInfo>()
.Any(info =>
// check that the method overrides the original on DynamicObjectProxy
info.DeclaringType != typeof(DynamicProxy<T>)
// todo - find out whether there is a way to do this in winrt
#if !NETFX_CORE
&& info.GetBaseDefinition().DeclaringType == typeof(DynamicProxy<T>)
#endif
);
return ReflectionUtils.IsMethodOverridden(_proxy.GetType(), typeof (DynamicProxy<T>), method);
}
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
@@ -978,5 +978,20 @@ namespace Newtonsoft.Json.Utilities
}
}
}
public static bool IsMethodOverridden(Type currentType, Type methodDeclaringType, string method)
{
bool isMethodOverriden = currentType.GetMember(method, MemberTypes.Method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Cast<MethodInfo>()
.Any(info =>
// check that the method overrides the original on DynamicObjectProxy
info.DeclaringType != methodDeclaringType
// todo - find out whether there is a way to do this in winrt
#if !NETFX_CORE
&& info.GetBaseDefinition().DeclaringType == methodDeclaringType
#endif
);
return isMethodOverriden;
}
}
}