-Added DeserializeAnonymousType overload with JsonSerializerSettings

-Added support for specifying the root type when serialize JSON to use with TypeNameHandling.Auto
-Fixed recursively reading type wrapper objects when deserializing
This commit is contained in:
James Newton-King
2013-02-23 22:09:51 -08:00
parent 159c5ee8cd
commit f9fa0b00e7
10 changed files with 177 additions and 10 deletions
@@ -1266,6 +1266,36 @@ bye", reader.Value);
Assert.IsFalse(jsonReader.Read());
}
[Test]
public void ReadOctalNumberAsInt64()
{
StringReader s = new StringReader(@"[0372, 0xFA, 0XFA]");
JsonTextReader jsonReader = new JsonTextReader(s);
Assert.IsTrue(jsonReader.Read());
Assert.AreEqual(JsonToken.StartArray, jsonReader.TokenType);
jsonReader.Read();
Assert.AreEqual(JsonToken.Integer, jsonReader.TokenType);
Assert.AreEqual(typeof(long), jsonReader.ValueType);
Assert.AreEqual(250, jsonReader.Value);
jsonReader.Read();
Assert.AreEqual(JsonToken.Integer, jsonReader.TokenType);
Assert.AreEqual(typeof(long), jsonReader.ValueType);
Assert.AreEqual(250, jsonReader.Value);
jsonReader.Read();
Assert.AreEqual(JsonToken.Integer, jsonReader.TokenType);
Assert.AreEqual(typeof(long), jsonReader.ValueType);
Assert.AreEqual(250, jsonReader.Value);
Assert.IsTrue(jsonReader.Read());
Assert.AreEqual(JsonToken.EndArray, jsonReader.TokenType);
Assert.IsFalse(jsonReader.Read());
}
[Test]
public void ReadOctalNumberAsInt32()
{
@@ -73,4 +73,4 @@ using System.Security;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
[assembly: AssemblyFileVersion("4.5.11.15814")]
[assembly: AssemblyFileVersion("4.5.11.15823")]
@@ -580,6 +580,30 @@ keyword such as type of business.""
Assert.AreEqual("TestProduct", anonymous.Product.Name);
}
[Test]
public void AnonymousObjectSerializationWithSetting()
{
DateTime d = new DateTime(2000, 1, 1);
var anonymous =
new
{
DateValue = d
};
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new IsoDateTimeConverter
{
DateTimeFormat = "yyyy"
});
string json = JsonConvert.SerializeObject(anonymous, settings);
Assert.AreEqual(@"{""DateValue"":""2000""}", json);
anonymous = JsonConvert.DeserializeAnonymousType(json, anonymous, settings);
Assert.AreEqual(d, anonymous.DateValue);
}
[Test]
public void CustomCollectionSerialization()
{
@@ -27,6 +27,7 @@
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
using System.Dynamic;
#endif
using System.Text;
using Newtonsoft.Json.Tests.Linq;
using global::System;
using global::System.Collections;
@@ -53,6 +54,68 @@ namespace Newtonsoft.Json.Tests.Serialization
[TestFixture]
public class TypeNameHandlingTests : TestFixtureBase
{
[Test]
public void NestedValueObjects()
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
sb.Append(@"{""$value"":");
}
ExceptionAssert.Throws<JsonSerializationException>("Unexpected token when deserializing primitive value: StartObject. Path '$value', line 1, position 11.", () =>
{
var reader = new JsonTextReader(new StringReader(sb.ToString()));
var ser = new JsonSerializer();
ser.Deserialize<bool>(reader);
});
}
[Test]
public void SerializeRootTypeNameIfDerivedWithAuto()
{
var serializer = new JsonSerializer()
{
TypeNameHandling = TypeNameHandling.Auto
};
var sw = new StringWriter();
serializer.Serialize<Person>(new JsonTextWriter(sw) { Formatting = Formatting.Indented }, new WagePerson());
var result = sw.ToString();
Assert.AreEqual(@"{
""$type"": ""Newtonsoft.Json.Tests.TestObjects.WagePerson, Newtonsoft.Json.Tests"",
""HourlyWage"": 0.0,
""Name"": null,
""BirthDate"": ""0001-01-01T00:00:00"",
""LastModified"": ""0001-01-01T00:00:00""
}", result);
Assert.IsTrue(result.Contains("WagePerson"));
using (var rd = new JsonTextReader(new StringReader(result)))
{
var person = serializer.Deserialize<Person>(rd);
CustomAssert.IsInstanceOfType(typeof(WagePerson), person);
}
}
[Test]
public void SerializeRootTypeNameAutoWithJsonConvert()
{
string json = JsonConvert.SerializeObject<object>(new WagePerson(), Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
Assert.AreEqual(@"{
""$type"": ""Newtonsoft.Json.Tests.TestObjects.WagePerson, Newtonsoft.Json.Tests"",
""HourlyWage"": 0.0,
""Name"": null,
""BirthDate"": ""0001-01-01T00:00:00"",
""LastModified"": ""0001-01-01T00:00:00""
}", json);
}
public class Wrapper
{
public IList<EmployeeReference> Array { get; set; }
+21 -1
View File
@@ -792,6 +792,16 @@ namespace Newtonsoft.Json
return SerializeObject(value, Formatting.None, settings);
}
public static string SerializeObject<T>(T value, JsonSerializerSettings settings)
{
return SerializeObject<T>(value, Formatting.None, settings);
}
public static string SerializeObject<T>(T value, Formatting formatting, JsonSerializerSettings settings)
{
return SerializeObjectInternal(value, formatting, settings, typeof (T));
}
/// <summary>
/// Serializes the specified object to a JSON string using a collection of <see cref="JsonConverter"/>.
/// </summary>
@@ -803,6 +813,11 @@ namespace Newtonsoft.Json
/// A JSON string representation of the object.
/// </returns>
public static string SerializeObject(object value, Formatting formatting, JsonSerializerSettings settings)
{
return SerializeObjectInternal(value, formatting, settings, null);
}
public static string SerializeObjectInternal(object value, Formatting formatting, JsonSerializerSettings settings, Type rootType)
{
JsonSerializer jsonSerializer = JsonSerializer.Create(settings);
@@ -812,7 +827,7 @@ namespace Newtonsoft.Json
{
jsonWriter.Formatting = formatting;
jsonSerializer.Serialize(jsonWriter, value);
jsonSerializer.Serialize(jsonWriter, value, rootType);
}
return sw.ToString();
@@ -924,6 +939,11 @@ namespace Newtonsoft.Json
return DeserializeObject<T>(value);
}
public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings)
{
return DeserializeObject<T>(value, settings);
}
/// <summary>
/// Deserializes the JSON to the specified .NET type.
/// </summary>
+18 -3
View File
@@ -632,6 +632,16 @@ namespace Newtonsoft.Json
Serialize(new JsonTextWriter(textWriter), value);
}
public void Serialize(JsonWriter jsonWriter, object value, Type rootType)
{
SerializeInternal(jsonWriter, value, rootType);
}
public void Serialize(TextWriter textWriter, object value, Type rootType)
{
Serialize(new JsonTextWriter(textWriter), value, rootType);
}
/// <summary>
/// Serializes the specified <see cref="Object"/> and writes the Json structure
/// to a <c>Stream</c> using the specified <see cref="JsonWriter"/>.
@@ -640,10 +650,15 @@ namespace Newtonsoft.Json
/// <param name="value">The <see cref="Object"/> to serialize.</param>
public void Serialize(JsonWriter jsonWriter, object value)
{
SerializeInternal(jsonWriter, value);
SerializeInternal(jsonWriter, value, null);
}
internal virtual void SerializeInternal(JsonWriter jsonWriter, object value)
public void Serialize<T>(JsonWriter jsonWriter, object value)
{
SerializeInternal(jsonWriter, value, typeof(T));
}
internal virtual void SerializeInternal(JsonWriter jsonWriter, object value, Type rootType)
{
ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter");
@@ -698,7 +713,7 @@ namespace Newtonsoft.Json
}
JsonSerializerInternalWriter serializerWriter = new JsonSerializerInternalWriter(this);
serializerWriter.Serialize(jsonWriter, value);
serializerWriter.Serialize(jsonWriter, value, rootType);
// reset writer back to previous options
if (previousFormatting != null)
@@ -87,6 +87,6 @@ using System.Security;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
[assembly: AssemblyFileVersion("4.5.11.15814")]
[assembly: AssemblyFileVersion("4.5.11.15823")]
[assembly: CLSCompliant(true)]
@@ -367,11 +367,17 @@ namespace Newtonsoft.Json.Serialization
return PopulateObject(targetObject, reader, objectContract, member, id);
case JsonContractType.Primitive:
JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract) contract;
JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract;
// if the content is inside $value then read past it
if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
{
CheckedRead(reader);
// the token should not be an object because the $type value could have been included in the object
// without needing the $value property
if (reader.TokenType == JsonToken.StartObject)
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing primitive value: " + reader.TokenType);
object value = CreateValueInternal(reader, objectType, primitiveContract, member, null, null, existingValue);
CheckedRead(reader);
@@ -46,6 +46,7 @@ namespace Newtonsoft.Json.Serialization
{
internal class JsonSerializerInternalWriter : JsonSerializerInternalBase
{
private JsonContract _rootContract;
private readonly List<object> _serializeStack = new List<object>();
private JsonSerializerProxy _internalSerializer;
@@ -54,11 +55,14 @@ namespace Newtonsoft.Json.Serialization
{
}
public void Serialize(JsonWriter jsonWriter, object value)
public void Serialize(JsonWriter jsonWriter, object value, Type rootType)
{
if (jsonWriter == null)
throw new ArgumentNullException("jsonWriter");
if (rootType != null)
_rootContract = Serializer.ContractResolver.ResolveContract(rootType);
SerializeValue(jsonWriter, value, GetContractSafe(value), null, null, null);
}
@@ -802,6 +806,11 @@ To fix this error either change the environment to be fully trusted, change the
if (contract.UnderlyingType != containerContract.ItemContract.CreatedType)
return true;
}
else if (_rootContract != null && _serializeStack.Count == 1)
{
if (contract.UnderlyingType != _rootContract.CreatedType)
return true;
}
}
return false;
@@ -232,10 +232,10 @@ namespace Newtonsoft.Json.Serialization
_serializer.Populate(reader, target);
}
internal override void SerializeInternal(JsonWriter jsonWriter, object value)
internal override void SerializeInternal(JsonWriter jsonWriter, object value, Type rootType)
{
if (_serializerWriter != null)
_serializerWriter.Serialize(jsonWriter, value);
_serializerWriter.Serialize(jsonWriter, value, rootType);
else
_serializer.Serialize(jsonWriter, value);
}