diff --git a/JSONAPI.Tests/Data/DeserializeRawJsonTest.json b/JSONAPI.Tests/Data/DeserializeRawJsonTest.json
new file mode 100644
index 00000000..684bb5ff
--- /dev/null
+++ b/JSONAPI.Tests/Data/DeserializeRawJsonTest.json
@@ -0,0 +1,14 @@
+{
+ "comments": [
+ {
+ "id": "2",
+ "customData": null
+ },
+ {
+ "id": "4",
+ "customData": {
+ "foo": "bar"
+ }
+ }
+ ]
+}
diff --git a/JSONAPI.Tests/Data/SerializerIntegrationTest.json b/JSONAPI.Tests/Data/SerializerIntegrationTest.json
index 3576bb64..1cc3c50e 100644
--- a/JSONAPI.Tests/Data/SerializerIntegrationTest.json
+++ b/JSONAPI.Tests/Data/SerializerIntegrationTest.json
@@ -1,3 +1,81 @@
-{"posts":[{"id":"1","title":"Linkbait!","links":{"comments":["2","3","4"],"author":"1"}},{"id":"2","title":"Rant #1023","links":{"comments":["5"],"author":"1"}},{"id":"3","title":"Polemic in E-flat minor #824","links":{"comments":null,"author":"1"}},{"id":"4","title":"This post has no author.","links":{"comments":null,"author":null}}],"linked":{"comments":[{"id":"2","body":"Nuh uh!","links":{"post":"1"}},{"id":"3","body":"Yeah huh!","links":{"post":"1"}},{"id":"4","body":"Third Reich.","links":{"post":"1"}},{"id":"5","body":"I laughed, I cried!","links":{"post":"2"}}],"authors":[{"id":"1","name":"Jason Hater","links":{"posts":["1","2","3"]}}]}}
-
-
+{
+ "posts": [
+ {
+ "id": "1",
+ "title": "Linkbait!",
+ "links": {
+ "comments": [ "2", "3", "4" ],
+ "author": "1"
+ }
+ },
+ {
+ "id": "2",
+ "title": "Rant #1023",
+ "links": {
+ "comments": [ "5" ],
+ "author": "1"
+ }
+ },
+ {
+ "id": "3",
+ "title": "Polemic in E-flat minor #824",
+ "links": {
+ "comments": null,
+ "author": "1"
+ }
+ },
+ {
+ "id": "4",
+ "title": "This post has no author.",
+ "links": {
+ "comments": null,
+ "author": null
+ }
+ }
+ ],
+ "linked": {
+ "comments": [
+ {
+ "id": "2",
+ "body": "Nuh uh!",
+ "customData": null,
+ "links": { "post": "1" }
+ },
+ {
+ "id": "3",
+ "body": "Yeah huh!",
+ "customData": null,
+ "links": {
+ "post": "1"
+ }
+ },
+ {
+ "id": "4",
+ "body": "Third Reich.",
+ "customData": {
+ "foo": "bar"
+ },
+ "links": {
+ "post": "1"
+ }
+ },
+ {
+ "id": "5",
+ "body": "I laughed, I cried!",
+ "customData": null,
+ "links": {
+ "post": "2"
+ }
+ }
+ ],
+ "authors": [
+ {
+ "id": "1",
+ "name": "Jason Hater",
+ "links": {
+ "posts": [ "1", "2", "3" ]
+ }
+ }
+ ]
+ }
+}
diff --git a/JSONAPI.Tests/JSONAPI.Tests.csproj b/JSONAPI.Tests/JSONAPI.Tests.csproj
index 3f00810a..90800908 100644
--- a/JSONAPI.Tests/JSONAPI.Tests.csproj
+++ b/JSONAPI.Tests/JSONAPI.Tests.csproj
@@ -80,7 +80,6 @@
-
@@ -104,6 +103,9 @@
Always
+
+ Always
+
Always
diff --git a/JSONAPI.Tests/Json/JsonApiMediaFormaterTests.cs b/JSONAPI.Tests/Json/JsonApiMediaFormaterTests.cs
index 1fd8a6e8..86d80411 100644
--- a/JSONAPI.Tests/Json/JsonApiMediaFormaterTests.cs
+++ b/JSONAPI.Tests/Json/JsonApiMediaFormaterTests.cs
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
using System.Web.Http;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -85,7 +86,8 @@ public void SetupModels()
new Comment() {
Id = 4,
Body = "Third Reich.",
- Post = p
+ Post = p,
+ CustomData = "{ \"foo\": \"bar\" }"
}
};
p2.Comments = new List {
@@ -144,7 +146,8 @@ public void SerializerIntegrationTest()
// Assert
string output = System.Text.Encoding.ASCII.GetString(stream.ToArray());
Trace.WriteLine(output);
- Assert.AreEqual(output.Trim(), File.ReadAllText("SerializerIntegrationTest.json").Trim());
+ var expected = JsonHelpers.MinifyJson(File.ReadAllText("SerializerIntegrationTest.json"));
+ Assert.AreEqual(expected, output.Trim());
//Assert.AreEqual("[2,3,4]", sw.ToString());
}
@@ -168,7 +171,8 @@ public void SerializeArrayIntegrationTest()
// Assert
string output = System.Text.Encoding.ASCII.GetString(stream.ToArray());
Trace.WriteLine(output);
- Assert.AreEqual(output.Trim(), File.ReadAllText("SerializerIntegrationTest.json").Trim());
+ var expected = JsonHelpers.MinifyJson(File.ReadAllText("SerializerIntegrationTest.json"));
+ Assert.AreEqual(expected, output.Trim());
//Assert.AreEqual("[2,3,4]", sw.ToString());
}
@@ -233,8 +237,25 @@ public void DeserializeCollectionIntegrationTest()
// Assert
Assert.AreEqual(2, posts.Count);
Assert.AreEqual(p.Id, posts[0].Id); // Order matters, right?
-
+ }
+ [TestMethod]
+ [DeploymentItem(@"Data\DeserializeRawJsonTest.json")]
+ public async Task DeserializeRawJsonTest()
+ {
+ using (var inputStream = File.OpenRead("DeserializeRawJsonTest.json"))
+ {
+ // Arrange
+ var formatter = new JsonApiFormatter(new PluralizationService());
+
+ // Act
+ var comments = ((IEnumerable)await formatter.ReadFromStreamAsync(typeof (Comment), inputStream, null, null)).ToArray();
+
+ // Assert
+ Assert.AreEqual(2, comments.Count());
+ Assert.AreEqual(null, comments[0].CustomData);
+ Assert.AreEqual("{\"foo\":\"bar\"}", comments[1].CustomData);
+ }
}
// Issue #1
diff --git a/JSONAPI.Tests/Models/Comment.cs b/JSONAPI.Tests/Models/Comment.cs
index df66264f..86b9f13c 100644
--- a/JSONAPI.Tests/Models/Comment.cs
+++ b/JSONAPI.Tests/Models/Comment.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using JSONAPI.Attributes;
using JSONAPI.Core;
namespace JSONAPI.Tests.Models
@@ -11,5 +12,6 @@ class Comment
public int Id { get; set; }
public string Body { get; set; }
public Post Post { get; set; }
+ [SerializeStringAsRawJson]public string CustomData { get; set; }
}
}
diff --git a/JSONAPI/Attributes/SerializeStringAsRawJsonAttribute.cs b/JSONAPI/Attributes/SerializeStringAsRawJsonAttribute.cs
new file mode 100644
index 00000000..941a8823
--- /dev/null
+++ b/JSONAPI/Attributes/SerializeStringAsRawJsonAttribute.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace JSONAPI.Attributes
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public class SerializeStringAsRawJsonAttribute : Attribute
+ {
+ }
+}
diff --git a/JSONAPI/JSONAPI.csproj b/JSONAPI/JSONAPI.csproj
index 5b9fc1e4..8b70800a 100644
--- a/JSONAPI/JSONAPI.csproj
+++ b/JSONAPI/JSONAPI.csproj
@@ -68,6 +68,7 @@
+
@@ -79,6 +80,7 @@
+
diff --git a/JSONAPI/Json/JsonApiFormatter.cs b/JSONAPI/Json/JsonApiFormatter.cs
index c678b402..a28f3c3a 100644
--- a/JSONAPI/Json/JsonApiFormatter.cs
+++ b/JSONAPI/Json/JsonApiFormatter.cs
@@ -203,7 +203,26 @@ protected void Serialize(object value, Stream writeStream, JsonWriter writer, Js
// numbers, strings, dates...
writer.WritePropertyName(_modelManager.GetJsonKeyForProperty(prop));
- serializer.Serialize(writer, prop.GetValue(value, null));
+
+ var propertyValue = prop.GetValue(value, null);
+
+ if (prop.PropertyType == typeof (string) &&
+ prop.GetCustomAttributes().Any(attr => attr is SerializeStringAsRawJsonAttribute))
+ {
+ if (propertyValue == null)
+ {
+ writer.WriteNull();
+ }
+ else
+ {
+ var minifiedValue = JsonHelpers.MinifyJson((string) propertyValue);
+ writer.WriteRawValue(minifiedValue);
+ }
+ }
+ else
+ {
+ serializer.Serialize(writer, propertyValue);
+ }
}
else
{
@@ -603,7 +622,27 @@ public object Deserialize(Type objectType, Stream readStream, JsonReader reader,
//TODO: Embedded would be dropped here!
if (!CanWriteTypeAsPrimitive(prop.PropertyType)) continue; // These aren't supposed to be here, they're supposed to be in "links"!
- prop.SetValue(retval, DeserializePrimitive(prop.PropertyType, reader), null);
+ object propVal;
+ if (prop.PropertyType == typeof (string) &&
+ prop.GetCustomAttributes().Any(attr => attr is SerializeStringAsRawJsonAttribute))
+ {
+ if (reader.TokenType == JsonToken.Null)
+ {
+ propVal = null;
+ }
+ else
+ {
+ var token = JToken.Load(reader);
+ var rawPropVal = token.ToString();
+ propVal = JsonHelpers.MinifyJson(rawPropVal);
+ }
+ }
+ else
+ {
+ propVal = DeserializePrimitive(prop.PropertyType, reader);
+ }
+
+ prop.SetValue(retval, propVal, null);
// Tell the MetadataManager that we deserialized this property
MetadataManager.Instance.SetMetaForProperty(retval, prop, true);
diff --git a/JSONAPI.Tests/Json/JsonHelpers.cs b/JSONAPI/Json/JsonHelpers.cs
similarity index 91%
rename from JSONAPI.Tests/Json/JsonHelpers.cs
rename to JSONAPI/Json/JsonHelpers.cs
index 440e2e1c..a47c48e7 100644
--- a/JSONAPI.Tests/Json/JsonHelpers.cs
+++ b/JSONAPI/Json/JsonHelpers.cs
@@ -1,6 +1,6 @@
using System.Text.RegularExpressions;
-namespace JSONAPI.Tests.Json
+namespace JSONAPI.Json
{
static class JsonHelpers
{