From 1d161072caa4ad194b22b75541f804a601e3d812 Mon Sep 17 00:00:00 2001 From: Chris Santero Date: Thu, 15 Sep 2016 19:10:46 -0400 Subject: [PATCH] Treat JToken properties as primitive attributes for serialization --- ..._of_various_types_serialize_correctly.json | 193 ++++++++++-------- .../Controllers/SamplesController.cs | 26 ++- .../Models/Sample.cs | 7 + .../Extensions/TypeExtensionsTests.cs | 4 + JSONAPI/Extensions/TypeExtensions.cs | 3 +- 5 files changed, 144 insertions(+), 89 deletions(-) diff --git a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/AttributeSerialization/Attributes_of_various_types_serialize_correctly.json b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/AttributeSerialization/Attributes_of_various_types_serialize_correctly.json index ba0978cf..ca94936a 100644 --- a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/AttributeSerialization/Attributes_of_various_types_serialize_correctly.json +++ b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/Fixtures/AttributeSerialization/Attributes_of_various_types_serialize_correctly.json @@ -1,89 +1,110 @@ { - "data": [ - { - "type": "samples", - "id": "1", - "attributes": { - "boolean-field": false, - "byte-field": 0, - "complex-attribute-field": null, - "date-time-field": "0001-01-01T00:00:00", - "date-time-offset-field": "0001-01-01T00:00:00.0000000+00:00", - "decimal-field": "0", - "double-field": 0.0, - "enum-field": 0, - "guid-field": "00000000-0000-0000-0000-000000000000", - "int16-field": 0, - "int32-field": 0, - "int64-field": 0, - "nullable-boolean-field": false, - "nullable-byte-field": null, - "nullable-date-time-field": null, - "nullable-date-time-offset-field": null, - "nullable-decimal-field": null, - "nullable-double-field": null, - "nullable-enum-field": null, - "nullable-guid-field": null, - "nullable-int16-field": null, - "nullable-int32-field": null, - "nullable-int64-field": null, - "nullable-sbyte-field": null, - "nullable-single-field": null, - "nullable-uint16-field": null, - "nullable-uint32-field": null, - "nullable-uint64-field": null, - "sbyte-field": 0, - "single-field": 0.0, - "string-field": null, - "uint16-field": 0, - "uint32-field": 0, - "uint64-field": 0 - } + "data": [ + { + "type": "samples", + "id": "1", + "attributes": { + "boolean-field": false, + "byte-field": 0, + "complex-attribute-field": null, + "date-time-field": "0001-01-01T00:00:00", + "date-time-offset-field": "0001-01-01T00:00:00.0000000+00:00", + "decimal-field": "0", + "double-field": 0.0, + "enum-field": 0, + "guid-field": "00000000-0000-0000-0000-000000000000", + "int16-field": 0, + "int32-field": 0, + "int64-field": 0, + "j-token-array-field": null, + "j-token-object-field": null, + "j-token-string-field": null, + "nullable-boolean-field": false, + "nullable-byte-field": null, + "nullable-date-time-field": null, + "nullable-date-time-offset-field": null, + "nullable-decimal-field": null, + "nullable-double-field": null, + "nullable-enum-field": null, + "nullable-guid-field": null, + "nullable-int16-field": null, + "nullable-int32-field": null, + "nullable-int64-field": null, + "nullable-sbyte-field": null, + "nullable-single-field": null, + "nullable-uint16-field": null, + "nullable-uint32-field": null, + "nullable-uint64-field": null, + "sbyte-field": 0, + "single-field": 0.0, + "string-field": null, + "uint16-field": 0, + "uint32-field": 0, + "uint64-field": 0 + } + }, + { + "type": "samples", + "id": "2", + "attributes": { + "boolean-field": true, + "byte-field": 253, + "complex-attribute-field": { + "foo": { + "baz": [ 11 ] + }, + "bar": 5 }, - { - "type": "samples", - "id": "2", - "attributes": { - "boolean-field": true, - "byte-field": 253, - "complex-attribute-field": { - "foo": { - "baz": [ 11 ] - }, - "bar": 5 - }, - "date-time-field": "1776-07-04T00:00:00", - "date-time-offset-field": "1776-07-04T00:00:00.0000000-05:00", - "decimal-field": "1056789.123", - "double-field": 1056789.123, - "enum-field": 1, - "guid-field": "6566f9b4-5245-40de-890d-98b40a4ad656", - "int16-field": 32000, - "int32-field": 2000000000, - "int64-field": 9223372036854775807, - "nullable-boolean-field": true, - "nullable-byte-field": 253, - "nullable-date-time-field": "1776-07-04T00:00:00", - "nullable-date-time-offset-field": "1776-07-04T00:00:00.0000000-05:00", - "nullable-decimal-field": "1056789.123", - "nullable-double-field": 1056789.123, - "nullable-enum-field": 2, - "nullable-guid-field": "3d1fb81e-43ee-4d04-af91-c8a326341293", - "nullable-int16-field": 32000, - "nullable-int32-field": 2000000000, - "nullable-int64-field": 9223372036854775807, - "nullable-sbyte-field": 123, - "nullable-single-field": 1056789.13, - "nullable-uint16-field": 64000, - "nullable-uint32-field": 3000000000, - "nullable-uint64-field": 9223372036854775808, - "sbyte-field": 123, - "single-field": 1056789.13, - "string-field": "Some string 156", - "uint16-field": 64000, - "uint32-field": 3000000000, - "uint64-field": 9223372036854775808 - } - } - ] + "date-time-field": "1776-07-04T00:00:00", + "date-time-offset-field": "1776-07-04T00:00:00.0000000-05:00", + "decimal-field": "1056789.123", + "double-field": 1056789.123, + "enum-field": 1, + "guid-field": "6566f9b4-5245-40de-890d-98b40a4ad656", + "int16-field": 32000, + "int32-field": 2000000000, + "int64-field": 9223372036854775807, + "j-token-array-field": [ + { + "my-field1": "George Washington", + "overridden-field2": null, + "MyField3": 216 + }, + { + "my-field1": "Thomas Jefferson", + "overridden-field2": false, + "MyField3": 631 + } + ], + "j-token-object-field": { + "my-field1": "Abraham Lincoln", + "overridden-field2": true, + "MyField3": 439 + }, + "j-token-string-field": "Andrew Jackson", + "nullable-boolean-field": true, + "nullable-byte-field": 253, + "nullable-date-time-field": "1776-07-04T00:00:00", + "nullable-date-time-offset-field": "1776-07-04T00:00:00.0000000-05:00", + "nullable-decimal-field": "1056789.123", + "nullable-double-field": 1056789.123, + "nullable-enum-field": 2, + "nullable-guid-field": "3d1fb81e-43ee-4d04-af91-c8a326341293", + "nullable-int16-field": 32000, + "nullable-int32-field": 2000000000, + "nullable-int64-field": 9223372036854775807, + "nullable-sbyte-field": 123, + "nullable-single-field": 1056789.13, + "nullable-uint16-field": 64000, + "nullable-uint32-field": 3000000000, + "nullable-uint64-field": 9223372036854775808, + "sbyte-field": 123, + "single-field": 1056789.13, + "string-field": "Some string 156", + "uint16-field": 64000, + "uint32-field": 3000000000, + "uint64-field": 9223372036854775808 + } + } + ] } diff --git a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Controllers/SamplesController.cs b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Controllers/SamplesController.cs index 66588415..4d6d7546 100644 --- a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Controllers/SamplesController.cs +++ b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Controllers/SamplesController.cs @@ -1,6 +1,8 @@ using System; using System.Web.Http; using JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Models; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Controllers { @@ -44,7 +46,10 @@ public IHttpActionResult GetSamples() StringField = null, EnumField = default(SampleEnum), NullableEnumField = null, - ComplexAttributeField = null + ComplexAttributeField = null, + JTokenStringField = null, + JTokenObjectField = null, + JTokenArrayField = null }; var s2 = new Sample { @@ -82,10 +87,27 @@ public IHttpActionResult GetSamples() StringField = "Some string 156", EnumField = SampleEnum.Value1, NullableEnumField = SampleEnum.Value2, - ComplexAttributeField = "{\"foo\": { \"baz\": [11] }, \"bar\": 5}" + ComplexAttributeField = "{\"foo\": { \"baz\": [11] }, \"bar\": 5}", + JTokenStringField = "Andrew Jackson", + JTokenObjectField = JToken.FromObject(new SomeSerializableClass { MyField1 = "Abraham Lincoln", MyField2 = true, MyField3 = 439 }), + JTokenArrayField = new JArray( + JToken.FromObject(new SomeSerializableClass { MyField1 = "George Washington", MyField2 = null, MyField3 = 216 }), + JToken.FromObject(new SomeSerializableClass { MyField1 = "Thomas Jefferson", MyField2 = false, MyField3 = 631 })) }; return Ok(new[] { s1, s2 }); } + + [Serializable] + public class SomeSerializableClass + { + [JsonProperty("my-field1")] + public string MyField1 { get; set; } + + [JsonProperty("overridden-field2")] + public bool? MyField2 { get; set; } + + public int MyField3 { get; set; } + } } } \ No newline at end of file diff --git a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Models/Sample.cs b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Models/Sample.cs index c56ea671..e8096599 100644 --- a/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Models/Sample.cs +++ b/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Models/Sample.cs @@ -1,5 +1,6 @@ using System; using JSONAPI.Attributes; +using Newtonsoft.Json.Linq; namespace JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Models { @@ -48,5 +49,11 @@ public class Sample [SerializeAsComplex] public string ComplexAttributeField { get; set; } + + public JToken JTokenStringField { get; set; } + + public JToken JTokenObjectField { get; set; } + + public JToken JTokenArrayField { get; set; } } } diff --git a/JSONAPI.Tests/Extensions/TypeExtensionsTests.cs b/JSONAPI.Tests/Extensions/TypeExtensionsTests.cs index 19b51b69..9d593abc 100644 --- a/JSONAPI.Tests/Extensions/TypeExtensionsTests.cs +++ b/JSONAPI.Tests/Extensions/TypeExtensionsTests.cs @@ -1,6 +1,7 @@ using System; using JSONAPI.Extensions; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json.Linq; namespace JSONAPI.Tests.Extensions { @@ -46,6 +47,9 @@ public void CanWriteAsJsonApiAttributeTest() Assert.IsTrue(typeof(String).CanWriteAsJsonApiAttribute(), "CanWriteTypeAsAttribute returned wrong answer for String!"); Assert.IsTrue(typeof(TestEnum).CanWriteAsJsonApiAttribute(), "CanWriteTypeAsAttribute returned wrong answer for enum!"); Assert.IsTrue(typeof(TestEnum?).CanWriteAsJsonApiAttribute(), "CanWriteTypeAsAttribute returned wrong answer for nullable enum!"); + Assert.IsTrue(typeof(JToken).CanWriteAsJsonApiAttribute(), "CanWriteTypeAsAttribute returned wrong answer for JToken!"); + Assert.IsTrue(typeof(JObject).CanWriteAsJsonApiAttribute(), "CanWriteTypeAsAttribute returned wrong answer for JObject!"); + Assert.IsTrue(typeof(JArray).CanWriteAsJsonApiAttribute(), "CanWriteTypeAsAttribute returned wrong answer for Jarray!"); Assert.IsFalse(typeof(Object).CanWriteAsJsonApiAttribute(), "CanWriteTypeAsAttribute returned wrong answer for Object!"); } diff --git a/JSONAPI/Extensions/TypeExtensions.cs b/JSONAPI/Extensions/TypeExtensions.cs index 8df43e56..c7d849ca 100644 --- a/JSONAPI/Extensions/TypeExtensions.cs +++ b/JSONAPI/Extensions/TypeExtensions.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace JSONAPI.Extensions { @@ -17,6 +17,7 @@ public static bool CanWriteAsJsonApiAttribute(this Type objectType) || typeof (DateTime).IsAssignableFrom(objectType) || typeof (DateTimeOffset).IsAssignableFrom(objectType) || typeof (String).IsAssignableFrom(objectType) + || typeof (JToken).IsAssignableFrom(objectType) || objectType.IsEnum; }