diff options
17 files changed, 223 insertions, 38 deletions
diff --git a/Build/build.ps1 b/Build/build.ps1 index d688a1d..ad0fced 100644 --- a/Build/build.ps1 +++ b/Build/build.ps1 @@ -18,7 +18,7 @@ )
}
-task default -depends Build
+task default -depends Test
task Clean {
Set-Location $baseDir
diff --git a/Build/runbuild.cmd b/Build/runbuild.cmd index fa2115e..65c7d0c 100644 --- a/Build/runbuild.cmd +++ b/Build/runbuild.cmd @@ -1 +1,2 @@ -powershell -Command "& {Import-Module ..\Tools\PSake\psake.psm1; Invoke-psake .\build.ps1 %*}"
\ No newline at end of file +powershell -Command "& {Import-Module ..\Tools\PSake\psake.psm1; Invoke-psake .\build.ps1 %*}"
+pause
\ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Converters/CustomCreationConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/CustomCreationConverterTests.cs index 3ed4975..f50f085 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/CustomCreationConverterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/CustomCreationConverterTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq;
using System.Text;
using Newtonsoft.Json.Converters;
+using NUnit.Framework;
namespace Newtonsoft.Json.Tests.Converters
{
@@ -87,5 +88,62 @@ namespace Newtonsoft.Json.Tests.Converters Console.WriteLine(employee.JobTitle);
// Support
}
+
+ public class MyClass
+ {
+ public string Value { get; set; }
+
+ [JsonConverter(typeof(MyThingConverter))]
+ public IThing Thing { get; set; }
+ }
+
+ public interface IThing
+ {
+ int Number { get; }
+ }
+
+ public class MyThing : IThing
+ {
+ public int Number { get; set; }
+ }
+
+ public class MyThingConverter : CustomCreationConverter<IThing>
+ {
+ public override IThing Create(Type objectType)
+ {
+ return new MyThing();
+ }
+ }
+
+ [Test]
+ public void AssertDoesDeserialize()
+ {
+ const string json = @"{
+""Value"": ""A value"",
+""Thing"": {
+""Number"": 123
+}
+}
+";
+ MyClass myClass = JsonConvert.DeserializeObject<MyClass>(json);
+ Assert.IsNotNull(myClass);
+ Assert.AreEqual("A value", myClass.Value);
+ Assert.IsNotNull(myClass.Thing);
+ Assert.AreEqual(123, myClass.Thing.Number);
+ }
+
+ [Test]
+ public void AssertShouldSerializeTest()
+ {
+ MyClass myClass = new MyClass
+ {
+ Value = "Foo",
+ Thing = new MyThing { Number = 456, }
+ };
+ string json = JsonConvert.SerializeObject(myClass); // <-- Exception here
+
+ const string expected = @"{""Value"":""Foo"",""Thing"":{""Number"":456}}";
+ Assert.AreEqual(expected, json);
+ }
}
}
\ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Converters/HtmlColorConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/HtmlColorConverterTests.cs new file mode 100644 index 0000000..8bafa43 --- /dev/null +++ b/Src/Newtonsoft.Json.Tests/Converters/HtmlColorConverterTests.cs @@ -0,0 +1,64 @@ +#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
+
+#if !SILVERLIGHT && !PocketPC
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Converters;
+using NUnit.Framework;
+
+namespace Newtonsoft.Json.Tests.Converters
+{
+ public class HtmlColorConverterTests : TestFixtureBase
+ {
+ [Test]
+ public void WriteJsonTest()
+ {
+ string json;
+
+ json = JsonConvert.SerializeObject(Color.DarkGray, new HtmlColorConverter());
+ Assert.AreEqual(@"""DarkGray""", json);
+
+ json = JsonConvert.SerializeObject(Color.FromArgb(255, 1, 2, 3), new HtmlColorConverter());
+ Assert.AreEqual(@"""#010203""", json);
+ }
+
+ [Test]
+ public void ReadJsonTest()
+ {
+ string json = @"""#010203""";
+
+ Color c = JsonConvert.DeserializeObject<Color>(json, new HtmlColorConverter());
+ Assert.AreEqual(c.A, 255);
+ Assert.AreEqual(c.R, 1);
+ Assert.AreEqual(c.G, 2);
+ Assert.AreEqual(c.B, 3);
+ }
+ }
+}
+#endif
\ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj index a5e7401..7f7e63a 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj @@ -62,8 +62,10 @@ <Compile Include="Bson\BsonReaderTests.cs" />
<Compile Include="Bson\BsonWriterTests.cs" />
<Compile Include="Converters\BinaryConverterTests.cs" />
+ <Compile Include="Converters\CustomCreationConverterTests.cs" />
<Compile Include="Converters\DataSetConverterTests.cs" />
<Compile Include="Converters\DataTableConverterTests.cs" />
+ <Compile Include="Converters\HtmlColorConverterTests.cs" />
<Compile Include="Converters\StringEnumConverterTests.cs" />
<Compile Include="Linq\ComponentModel\BindingTests.cs" />
<Compile Include="Linq\ComponentModel\JPropertyDescriptorTests.cs" />
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj index 2b3f1a5..7eefe6f 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj @@ -57,6 +57,7 @@ </Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
<Reference Include="System.Security" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
@@ -68,6 +69,7 @@ <Compile Include="Converters\CustomCreationConverterTests.cs" />
<Compile Include="Converters\DataSetConverterTests.cs" />
<Compile Include="Converters\DataTableConverterTests.cs" />
+ <Compile Include="Converters\HtmlColorConverterTests.cs" />
<Compile Include="Converters\StringEnumConverterTests.cs" />
<Compile Include="JsonArrayAttributeTests.cs" />
<Compile Include="ExceptionTests.cs" />
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj index 86ff754..853046c 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj @@ -71,8 +71,10 @@ <Compile Include="Bson\BsonReaderTests.cs" />
<Compile Include="Bson\BsonWriterTests.cs" />
<Compile Include="Converters\BinaryConverterTests.cs" />
+ <Compile Include="Converters\CustomCreationConverterTests.cs" />
<Compile Include="Converters\DataSetConverterTests.cs" />
<Compile Include="Converters\DataTableConverterTests.cs" />
+ <Compile Include="Converters\HtmlColorConverterTests.cs" />
<Compile Include="Converters\StringEnumConverterTests.cs" />
<Compile Include="ExceptionTests.cs" />
<Compile Include="JsonArrayAttributeTests.cs" />
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj index 9883da6..c811b98 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj @@ -63,6 +63,7 @@ <Reference Include="System.Data.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
+ <Reference Include="System.Drawing" />
<Reference Include="System.Runtime.Serialization">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
@@ -89,6 +90,7 @@ <Compile Include="Converters\DataTableConverterTests.cs" />
<Compile Include="Converters\DataSetConverterTests.cs" />
<Compile Include="Converters\CustomCreationConverterTests.cs" />
+ <Compile Include="Converters\HtmlColorConverterTests.cs" />
<Compile Include="Converters\StringEnumConverterTests.cs" />
<Compile Include="FileSystemEntityModel.Designer.cs">
<AutoGen>True</AutoGen>
diff --git a/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs b/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs index d5f6441..e20fbfc 100644 --- a/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs +++ b/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs @@ -79,5 +79,16 @@ namespace Newtonsoft.Json.Converters {
return typeof (T).IsAssignableFrom(objectType);
}
+
+ /// <summary>
+ /// Gets a value indicating whether this <see cref="JsonConverter"/> can write JSON.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if this <see cref="JsonConverter"/> can write JSON; otherwise, <c>false</c>.
+ /// </value>
+ public override bool CanWrite
+ {
+ get { return false; }
+ }
}
}
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Converters/HtmlColorConverter.cs b/Src/Newtonsoft.Json/Converters/HtmlColorConverter.cs index fdde9c3..5ae24f8 100644 --- a/Src/Newtonsoft.Json/Converters/HtmlColorConverter.cs +++ b/Src/Newtonsoft.Json/Converters/HtmlColorConverter.cs @@ -68,6 +68,17 @@ namespace Newtonsoft.Json.Converters {
throw new NotImplementedException();
}
+
+ /// <summary>
+ /// Gets a value indicating whether this <see cref="JsonConverter"/> can read JSON.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if this <see cref="JsonConverter"/> can read JSON; otherwise, <c>false</c>.
+ /// </value>
+ public override bool CanRead
+ {
+ get { return false; }
+ }
}
}
#endif
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonConverter.cs b/Src/Newtonsoft.Json/JsonConverter.cs index 27f356c..493e252 100644 --- a/Src/Newtonsoft.Json/JsonConverter.cs +++ b/Src/Newtonsoft.Json/JsonConverter.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Schema;
namespace Newtonsoft.Json
{
@@ -60,5 +61,32 @@ namespace Newtonsoft.Json /// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
/// </returns>
public abstract bool CanConvert(Type objectType);
+
+ /// <summary>
+ /// Gets the <see cref="JsonSchema"/> of the JSON produced by the JsonConverter.
+ /// </summary>
+ /// <returns>The <see cref="JsonSchema"/> of the JSON produced by the JsonConverter.</returns>
+ public virtual JsonSchema GetSchema()
+ {
+ return null;
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this <see cref="JsonConverter"/> can read JSON.
+ /// </summary>
+ /// <value><c>true</c> if this <see cref="JsonConverter"/> can read JSON; otherwise, <c>false</c>.</value>
+ public virtual bool CanRead
+ {
+ get { return true; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this <see cref="JsonConverter"/> can write JSON.
+ /// </summary>
+ /// <value><c>true</c> if this <see cref="JsonConverter"/> can write JSON; otherwise, <c>false</c>.</value>
+ public virtual bool CanWrite
+ {
+ get { return true; }
+ }
}
}
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs index f943579..f759597 100644 --- a/Src/Newtonsoft.Json/JsonSerializer.cs +++ b/Src/Newtonsoft.Json/JsonSerializer.cs @@ -432,18 +432,14 @@ namespace Newtonsoft.Json serializerWriter.Serialize(jsonWriter, value);
}
- internal bool HasMatchingConverter(Type type, out JsonConverter matchingConverter)
+ internal JsonConverter GetMatchingConverter(Type type)
{
- if (HasMatchingConverter(_converters, type, out matchingConverter))
- return true;
-
- return false;
+ return GetMatchingConverter(_converters, type);
}
- internal static bool HasMatchingConverter(IList<JsonConverter> converters, Type objectType, out JsonConverter matchingConverter)
+ internal static JsonConverter GetMatchingConverter(IList<JsonConverter> converters, Type objectType)
{
- if (objectType == null)
- throw new ArgumentNullException("objectType");
+ ValidationUtils.ArgumentNotNull(objectType, "objectType");
if (converters != null)
{
@@ -452,15 +448,11 @@ namespace Newtonsoft.Json JsonConverter converter = converters[i];
if (converter.CanConvert(objectType))
- {
- matchingConverter = converter;
- return true;
- }
+ return converter;
}
}
- matchingConverter = null;
- return false;
+ return null;
}
internal void OnError(ErrorEventArgs e)
diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs index 3d95460..8df6dd9 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.cs @@ -273,7 +273,7 @@ namespace Newtonsoft.Json.Linq {
JsonConverter matchingConverter;
- if (value != null && JsonSerializer.HasMatchingConverter(converters, value.GetType(), out matchingConverter))
+ if (value != null && ((matchingConverter = JsonSerializer.GetMatchingConverter(converters, value.GetType())) != null))
matchingConverter.WriteJson(writer, value, new JsonSerializer());
else
defaultWrite(value);
diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs index a78c81e..805bccf 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs @@ -234,6 +234,15 @@ namespace Newtonsoft.Json.Schema throw new Exception("Unresolved circular reference for type '{0}'. Explicitly define an Id for the type using a JsonObject/JsonArray attribute or automatically generate a type Id using the UndefinedSchemaIdHandling property.".FormatWith(CultureInfo.InvariantCulture, type));
}
+ JsonContract contract = ContractResolver.ResolveContract(type);
+ JsonConverter converter;
+ if ((converter = contract.Converter) != null || (converter = contract.InternalConverter) != null)
+ {
+ JsonSchema converterSchema = converter.GetSchema();
+ if (converterSchema != null)
+ return converterSchema;
+ }
+
Push(new TypeSchema(type, new JsonSchema()));
if (explicitId != null)
@@ -244,8 +253,7 @@ namespace Newtonsoft.Json.Schema CurrentSchema.Title = GetTitle(type);
CurrentSchema.Description = GetDescription(type);
- JsonContract contract = ContractResolver.ResolveContract(type);
- if (contract.Converter != null || contract.InternalConverter != null)
+ if (converter != null)
{
// todo: Add GetSchema to JsonConverter and use here?
CurrentSchema.Type = JsonSchemaType.Any;
diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 73eb3bb..62d10f4 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -204,9 +204,7 @@ namespace Newtonsoft.Json.Serialization contract.Converter = ResolveContractConverter(contract.UnderlyingType);
// then see whether object is compadible with any of the built in converters
- JsonConverter internalConverter;
- if (JsonSerializer.HasMatchingConverter(BuiltInConverters, contract.UnderlyingType, out internalConverter))
- contract.InternalConverter = internalConverter;
+ contract.InternalConverter = JsonSerializer.GetMatchingConverter(BuiltInConverters, contract.UnderlyingType);
if (ReflectionUtils.HasDefaultConstructor(contract.CreatedType, true)
|| contract.CreatedType.IsValueType)
diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index f456fbb..d5e832a 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -179,24 +179,29 @@ namespace Newtonsoft.Json.Serialization private object CreateValue(JsonReader reader, Type objectType, JsonContract contract, object existingValue, JsonConverter memberConverter)
{
- JsonConverter converter;
-
- // member attribute converter
+ JsonConverter converter = null;
if (memberConverter != null)
- return memberConverter.ReadJson(reader, objectType, GetInternalSerializer());
-
- // class attribute converter
- if (contract != null && contract.Converter != null)
- return contract.Converter.ReadJson(reader, objectType, GetInternalSerializer());
+ {
+ // member attribute converter
+ converter = memberConverter;
+ }
+ else if (contract != null)
+ {
+ JsonConverter matchingConverter;
+ if (contract.Converter != null)
+ // class attribute converter
+ converter = contract.Converter;
+ else if ((matchingConverter = Serializer.GetMatchingConverter(contract.UnderlyingType)) != null)
+ // passed in converters
+ converter = matchingConverter;
+ else if (contract.InternalConverter != null)
+ // internally specified converter
+ converter = contract.InternalConverter;
+ }
- // passed in converters
- if (objectType != null && Serializer.HasMatchingConverter(objectType, out converter))
+ if (converter != null && converter.CanRead)
return converter.ReadJson(reader, objectType, GetInternalSerializer());
- // internally specified converter
- if (contract != null && contract.InternalConverter != null)
- return contract.InternalConverter.ReadJson(reader, objectType, GetInternalSerializer());
-
if (contract is JsonLinqContract)
return CreateJToken(reader, contract);
diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 59d0517..c01b72a 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -90,10 +90,11 @@ namespace Newtonsoft.Json.Serialization return;
}
- if (converter != null
+ if ((converter != null
|| ((converter = contract.Converter) != null)
- || Serializer.HasMatchingConverter(contract.UnderlyingType, out converter)
+ || ((converter = Serializer.GetMatchingConverter(contract.UnderlyingType)) != null)
|| ((converter = contract.InternalConverter) != null))
+ && converter.CanWrite)
{
SerializeConvertable(writer, converter, value, contract);
}
|