Commits

Anonymous committed dff8c27

Implemented the JsonSerializerOptions object. Updated documentation.

Comments (0)

Files changed (14)

Json.Serialization/Exceptions/TypeDoesNotContainPropertyException.cs

+/***************************************************************************************
+
+	Copyright 2012 Greg Dennis
+
+	   Licensed under the Apache License, Version 2.0 (the "License");
+	   you may not use this file except in compliance with the License.
+	   You may obtain a copy of the License at
+
+		 http://www.apache.org/licenses/LICENSE-2.0
+
+	   Unless required by applicable law or agreed to in writing, software
+	   distributed under the License is distributed on an "AS IS" BASIS,
+	   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	   See the License for the specific language governing permissions and
+	   limitations under the License.
+ 
+	File Name:		TypeDoesNotContainPropertyException.cs
+	Namespace:		Manatee.Json.Serialization.Exceptions
+	Class Name:		TypeDoesNotContainPropertyException
+	Purpose:		Optionally thrown when deserializing and the JSON structure
+					contains property names which are not valid for the type
+					requested.
+
+***************************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Manatee.Json.Serialization.Exceptions
+{
+	/// <summary>
+	/// Optionally thrown when deserializing and the JSON structure contains property names
+	/// which are not valid for the type requested.
+	/// </summary>
+	public class TypeDoesNotContainPropertyException : Exception
+	{
+		/// <summary>
+		/// Gets the type.
+		/// </summary>
+		public Type Type { get; private set; }
+		/// <summary>
+		/// Gets the portion of the JSON structure which contain the invalid properties.
+		/// </summary>
+		public JsonValue Json { get; private set; }
+		/// <summary>
+		/// Initializes a new instance of the TypeDoesNotContainPropertyException class.
+		/// </summary>
+		/// <param name="type">The type.</param>
+		/// <param name="json">The invalid JSON structure.</param>
+		public TypeDoesNotContainPropertyException(Type type, JsonValue json)
+			: base(string.Format("Type {0} does not contain any properties within {1}.", type, json))
+		{
+			Type = type;
+			Json = json;
+		}
+	}
+}

Json.Serialization/JsonSerializer.cs

 using System.Text;
 using Manatee.Json.Serialization.Attributes;
 using Manatee.Json.Serialization.Cache;
+using Manatee.Json.Serialization.Enumerations;
+using Manatee.Json.Serialization.Exceptions;
 using Manatee.Json.Serialization.Helpers;
 
 namespace Manatee.Json.Serialization
 		private const string TypeKey = "#Type";
 		private const string ValueKey = "#Value";
 
-		private JsonSerializerOptions Options { get; set; }
+		public JsonSerializerOptions Options { get; set; }
 
 		#region Public Methods
 		/// <summary>
 		/// <returns>The JSON representation of the object.</returns>
 		public JsonValue Serialize<T>(T obj)
 		{
+			VerifyOptions();
 			if (typeof(IJsonCompatible).IsAssignableFrom(typeof(T)))
 				return ((IJsonCompatible) obj).ToJson();
-			if (EqualsDefaultValue(obj)) return JsonValue.Null;
+			if (EqualsDefaultValue(obj) && !Options.EncodeDefaultValues) return JsonValue.Null;
 			var tryPrimitive = PrimitiveMapper.MapToJson(obj);
 			if (tryPrimitive != JsonValue.Null)
 				return tryPrimitive;
 		/// <returns>The JSON representation of the type.</returns>
 		public JsonValue SerializeType<T>()
 		{
+			VerifyOptions();
 			var json = new JsonObject();
 			var propertyInfoList = typeof(T).GetProperties(BindingFlags.Static | BindingFlags.Public)
 											 .Where(p => p.GetSetMethod() != null)
 		/// <returns>The deserialized object.</returns>
 		public T Deserialize<T>(JsonValue json)
 		{
+			VerifyOptions();
 			if (typeof(IJsonCompatible).IsAssignableFrom(typeof(T)))
 			{
 				var obj = (T)Activator.CreateInstance(typeof (T));
 		/// <param name="json">The JSON representation of the type.</param>
 		public void DeserializeType<T>(JsonValue json)
 		{
+			VerifyOptions();
 			if (json == JsonValue.Null)
 				return;
 			var propertyInfoList = typeof(T).GetProperties(BindingFlags.Static | BindingFlags.Public)
 				{
 					var deserialize = SerializerCache.Instance.GetDeserializer(propertyInfo.PropertyType);
 					propertyInfo.SetValue(null, deserialize.Invoke(this, new[] { json.Object[propertyInfo.Name] }), null);
+					json.Object.Remove(propertyInfo.Name);
 				}
 			}
+			if (json.Object.Count > 0)
+				throw new TypeDoesNotContainPropertyException(typeof(T), json);
 		}
 		#endregion
 
 		{
 			return EqualityComparer<T>.Default.Equals(value, default(T));
 		}
+		private void VerifyOptions()
+		{
+			if (Options == null)
+				Options = JsonSerializerOptions.Default;
+		}
 		private JsonValue AutoSerializeObject<T>(T obj)
 		{
 			var json = new JsonObject();
 					        : propertyInfo.PropertyType;
 				var serialize = SerializerCache.Instance.GetSerializer(type);
 				var jsonProp = (JsonValue) serialize.Invoke(this, new[] {value});
-				if (jsonProp == JsonValue.Null) continue;
+				if ((jsonProp == JsonValue.Null) && !Options.EncodeDefaultValues) continue;
 				json.Add(propertyInfo.Name,
 				         type == propertyInfo.PropertyType
 				         	? jsonProp
 						var deserialize = SerializerCache.Instance.GetDeserializer(propertyInfo.PropertyType);
 						propertyInfo.SetValue(obj, deserialize.Invoke(this, new[] { json.Object[propertyInfo.Name] }), null);
 					}
+					json.Object.Remove(propertyInfo.Name);
 				}
 			}
+			if (json.Object.Count > 0)
+				throw new TypeDoesNotContainPropertyException(typeof (T), json);
 			return obj;
 		}
 		#endregion

Json.Serialization/JsonSerializerOptions.cs

 
 namespace Manatee.Json.Serialization
 {
-	class JsonSerializerOptions
+	/// <summary>
+	/// Represents a set of behavior options for the JsonSerializer object.
+	/// </summary>
+	public class JsonSerializerOptions
 	{
 		/// <summary>
 		/// Default options used by the serializer.
 		/// </summary>
-		public JsonSerializerOptions Default = new JsonSerializerOptions
-		                                       	{
-		                                       		EncodeDefaultValues = false,
-													InvalidPropertyKeyBehavior = InvalidPropertyKeyBehavior.DoNothing
-		                                       	};
+		public static JsonSerializerOptions Default = new JsonSerializerOptions
+		                                              	{
+		                                              		EncodeDefaultValues = false,
+		                                              		InvalidPropertyKeyBehavior = InvalidPropertyKeyBehavior.DoNothing
+		                                              	};
 		/// <summary>
 		/// Gets and sets whether the serializer encodes default values for properties.
 		/// </summary>

Json.Serialization/Manatee.Json.Serialization.csproj

     <Compile Include="Cache\SerializerMethodPair.cs" />
     <Compile Include="Enumerations\InvalidPropertyKeyBehavior.cs" />
     <Compile Include="Exceptions\NotPrimitiveTypeException.cs" />
+    <Compile Include="Exceptions\TypeDoesNotContainPropertyException.cs" />
     <Compile Include="Exceptions\TypeRegistrationException.cs" />
     <Compile Include="Helpers\ObjectCaster.cs" />
     <Compile Include="Helpers\PrimitiveMapper.cs" />

Json.Tests/Json/JsonArrayTest.cs

-using System;
+/***************************************************************************************
+
+	Copyright 2012 Greg Dennis
+
+	   Licensed under the Apache License, Version 2.0 (the "License");
+	   you may not use this file except in compliance with the License.
+	   You may obtain a copy of the License at
+
+		 http://www.apache.org/licenses/LICENSE-2.0
+
+	   Unless required by applicable law or agreed to in writing, software
+	   distributed under the License is distributed on an "AS IS" BASIS,
+	   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	   See the License for the specific language governing permissions and
+	   limitations under the License.
+ 
+	File Name:		JsonArrayTest.cs
+	Namespace:		Manatee.Json.Tests.Json
+	Class Name:		JsonArrayTest
+	Purpose:		Tests for JsonArray.
+
+***************************************************************************************/
+using System;
 using System.Text;
 using System.Collections.Generic;
 using System.Linq;

Json.Tests/Json/JsonObjectTest.cs

-using System;
+/***************************************************************************************
+
+	Copyright 2012 Greg Dennis
+
+	   Licensed under the Apache License, Version 2.0 (the "License");
+	   you may not use this file except in compliance with the License.
+	   You may obtain a copy of the License at
+
+		 http://www.apache.org/licenses/LICENSE-2.0
+
+	   Unless required by applicable law or agreed to in writing, software
+	   distributed under the License is distributed on an "AS IS" BASIS,
+	   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	   See the License for the specific language governing permissions and
+	   limitations under the License.
+ 
+	File Name:		JsonObjectTest.cs
+	Namespace:		Manatee.Json.Tests.Json
+	Class Name:		JsonObjectTest
+	Purpose:		Tests for JsonObject.
+
+***************************************************************************************/
+using System;
 using System.Text;
 using System.Collections.Generic;
 using System.Linq;

Json.Tests/Json/JsonValueTest.cs

-using System;
+/***************************************************************************************
+
+	Copyright 2012 Greg Dennis
+
+	   Licensed under the Apache License, Version 2.0 (the "License");
+	   you may not use this file except in compliance with the License.
+	   You may obtain a copy of the License at
+
+		 http://www.apache.org/licenses/LICENSE-2.0
+
+	   Unless required by applicable law or agreed to in writing, software
+	   distributed under the License is distributed on an "AS IS" BASIS,
+	   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	   See the License for the specific language governing permissions and
+	   limitations under the License.
+ 
+	File Name:		JsonValueTest.cs
+	Namespace:		Manatee.Json.Tests.Json
+	Class Name:		JsonValueTest
+	Purpose:		Tests for JsonValue.
+
+***************************************************************************************/
+using System;
 using System.Text;
 using System.Collections.Generic;
 using System.Linq;

Json.Tests/Json/LinqExtensionsTest.cs

-using System;
+/***************************************************************************************
+
+	Copyright 2012 Greg Dennis
+
+	   Licensed under the Apache License, Version 2.0 (the "License");
+	   you may not use this file except in compliance with the License.
+	   You may obtain a copy of the License at
+
+		 http://www.apache.org/licenses/LICENSE-2.0
+
+	   Unless required by applicable law or agreed to in writing, software
+	   distributed under the License is distributed on an "AS IS" BASIS,
+	   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	   See the License for the specific language governing permissions and
+	   limitations under the License.
+ 
+	File Name:		LinqExtensionsTest.cs
+	Namespace:		Manatee.Json.Tests.Json
+	Class Name:		LinqExtensionsTest
+	Purpose:		Tests for the LINQ extension methods for the Json library.
+
+***************************************************************************************/
+using System;
 using System.Text;
 using System.Collections.Generic;
 using System.Linq;

Json.Tests/Serialization/Helpers/PrimitiveMapperTest.cs

 				PrimitiveMapper.MapFromJson<Uri>(json);
 				Assert.Fail("Expected NotPrimitiveTypeException");
 			}
-			catch (NotPrimitiveTypeException e) { }
+			catch (NotPrimitiveTypeException) { }
 			catch (Exception e)
 			{
 				Assert.Fail(string.Format("Incorrect exception thrown: {0}", e));

Json.Tests/Serialization/JsonSerializerTest.cs

 using System.Collections.Generic;
 using Manatee.Json;
 using Manatee.Json.Serialization;
+using Manatee.Json.Serialization.Enumerations;
+using Manatee.Json.Serialization.Exceptions;
 using Manatee.Json.Tests.Test_References;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
 			           		{"StringProp", "stringValue"},
 			           		{"IntProp", 42},
 			           		{"DoubleProp", 6},
-			           		{"BoolProp", true},
-			           		{"DateTimeProp", DateTime.Today.ToString()}
+			           		{"BoolProp", true}
 			           	};
 			var expected = new ObjectWithBasicProps
 							{
 								StringProp = "stringValue",
 								IntProp = 42,
 								DoubleProp = 6.0,
-								BoolProp = true,
-								DateTimeProp = DateTime.Today
+								BoolProp = true
 							};
 			var actual = _serializer.Deserialize<ObjectWithBasicProps>(json);
 			Assert.AreEqual(expected, actual);
 			var expected = new Dictionary<string, double> { { "four", 4 }, { "three", 3 }, { "five", 5 }, { "six", 6 } };
 			JsonValue json = new JsonArray
 			                     	{
-			                     		new JsonObject {{"Key", "four"},{"Value", 4}},
+			                     		new JsonObject {{"Key", "four"}, {"Value", 4}},
 			                     		new JsonObject {{"Key", "three"}, {"Value", 3}},
 			                     		new JsonObject {{"Key", "five"}, {"Value", 5}},
 			                     		new JsonObject {{"Key", "six"}, {"Value", 6}}
 			Assert.AreEqual(ObjectWithBasicProps.StaticDoubleProp, doubleProp);
 			Assert.AreEqual(ObjectWithBasicProps.StaticBoolProp, boolProp);
 		}
+		[TestMethod]
+		public void Deserialize_DefaultOptions_IgnoresExtraProperties()
+		{
+			var json = new JsonObject
+			           	{
+			           		{"StringProp", "stringValue"},
+			           		{"IntProp", 42},
+							{"UnknownProp", "string"},
+			           		{"DoubleProp", 6},
+			           		{"BoolProp", true},
+							{"OtherProp", Math.PI}
+			           	};
+			var expected = new ObjectWithBasicProps
+			{
+				StringProp = "stringValue",
+				IntProp = 42,
+				DoubleProp = 6.0,
+				BoolProp = true
+			};
+			var actual = _serializer.Deserialize<ObjectWithBasicProps>(json);
+			Assert.AreEqual(expected, actual);
+		}
+		[TestMethod]
+		public void Deserialize_CustomOptions_ThrowsTypeDoesNotContainPropertyException()
+		{
+			try
+			{
+				_serializer.Options = new JsonSerializerOptions
+										{
+											InvalidPropertyKeyBehavior = InvalidPropertyKeyBehavior.ThrowException
+										};
+				var json = new JsonObject
+			           	{
+			           		{"StringProp", "stringValue"},
+			           		{"IntProp", 42},
+							{"UnknownProp", "string"},
+			           		{"DoubleProp", 6},
+			           		{"BoolProp", true},
+							{"OtherProp", Math.PI}
+			           	};
+				var expected = new ObjectWithBasicProps
+				{
+					StringProp = "stringValue",
+					IntProp = 42,
+					DoubleProp = 6.0,
+					BoolProp = true
+				};
+				var actual = _serializer.Deserialize<ObjectWithBasicProps>(json);
+				Assert.Fail("Did not throw exception.");
+			}
+			catch (TypeDoesNotContainPropertyException) { }
+			catch (AssertFailedException)
+			{
+				throw;
+			}
+			catch (Exception e)
+			{
+				Assert.Fail(string.Format("Threw {0}.", e.GetType()));
+			}
+			finally
+			{
+				_serializer.Options = null;
+			}
+		}
 		#endregion
 
 		#region Serialize Tests
 			var actual = _serializer.SerializeType<ObjectWithBasicProps>();
 			Assert.AreEqual(expected, actual);
 		}
+		[TestMethod]
+		public void Serialize_DefaultOptions_IgnoresDefaultValues()
+		{
+			// DoubleProp remains default
+			var obj = new ObjectWithBasicProps
+			{
+				StringProp = "stringValue",
+				IntProp = 42,
+				BoolProp = true
+			};
+			JsonValue expected = new JsonObject
+									{
+										{"StringProp", "stringValue"},
+										{"IntProp", 42},
+										{"BoolProp", true}
+									};
+			var actual = _serializer.Serialize(obj);
+			Assert.AreEqual(expected, actual);
+		}
+		[TestMethod]
+		public void Serialize_CustomOptions_SerializesDefaultValues()
+		{
+			_serializer.Options = new JsonSerializerOptions
+			                      	{
+			                      		EncodeDefaultValues = true
+			                      	};
+			// DoubleProp remains default
+			var obj = new ObjectWithBasicProps
+			{
+				StringProp = "stringValue",
+				IntProp = 42,
+				BoolProp = true
+			};
+			JsonValue expected = new JsonObject
+									{
+										{"StringProp", "stringValue"},
+										{"IntProp", 42},
+										{"DoubleProp", 0},
+										{"BoolProp", true}
+									};
+			var actual = _serializer.Serialize(obj);
+			_serializer.Options = null;
+			Assert.AreEqual(expected, actual);
+		}
 		#endregion
 	}
 }

Json.Tests/Test References/ObjectWithBasicProps.cs

 		public int IntProp { get; set; }
 		public double DoubleProp { get; set; }
 		public bool BoolProp { get; set; }
-		public DateTime DateTimeProp { get; set; }
 		#endregion
 
 		#region Nonserializable Instance Properties
 			       other.IntProp == IntProp &&
 			       other.DoubleProp.Equals(DoubleProp) &&
 			       other.BoolProp.Equals(BoolProp) &&
-				   other.DateTimeProp.Equals(DateTimeProp) &&
 			       Equals(other.ReadOnlyProp, ReadOnlyProp) &&
 			       Equals(other.WriteOnlyProp, WriteOnlyProp) &&
 			       Equals(other.IgnoreProp, IgnoreProp);
 				result = (result * 397) ^ IntProp;
 				result = (result * 397) ^ DoubleProp.GetHashCode();
 				result = (result * 397) ^ BoolProp.GetHashCode();
-				result = (result * 397) ^ DateTimeProp.GetHashCode();
 				result = (result * 397) ^ (ReadOnlyProp != null ? ReadOnlyProp.GetHashCode() : 0);
 				result = (result * 397) ^ (WriteOnlyProp != null ? WriteOnlyProp.GetHashCode() : 0);
 				result = (result * 397) ^ (IgnoreProp != null ? IgnoreProp.GetHashCode() : 0);

Json.sln.docstates.suo

Binary file modified.
Binary file modified.

README.docx

Binary file modified.