From 22dc13f301775cfbb4f46c4018b22dccc7bf2ecc Mon Sep 17 00:00:00 2001 From: Chris Santero Date: Mon, 2 Feb 2015 17:25:04 -0500 Subject: [PATCH] safeguards against invalid raw json strings Conflicts: JSONAPI.Tests/Json/JsonApiMediaFormaterTests.cs --- .../Data/MalformedRawJsonString.json | 12 ++++++ ...eformatsRawJsonStringWithUnquotedKeys.json | 14 +++++++ JSONAPI.Tests/JSONAPI.Tests.csproj | 6 +++ .../Json/JsonApiMediaFormaterTests.cs | 38 +++++++++++++++++++ JSONAPI/Json/JsonApiFormatter.cs | 20 +++++++++- 5 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 JSONAPI.Tests/Data/MalformedRawJsonString.json create mode 100644 JSONAPI.Tests/Data/ReformatsRawJsonStringWithUnquotedKeys.json diff --git a/JSONAPI.Tests/Data/MalformedRawJsonString.json b/JSONAPI.Tests/Data/MalformedRawJsonString.json new file mode 100644 index 00000000..54c335f8 --- /dev/null +++ b/JSONAPI.Tests/Data/MalformedRawJsonString.json @@ -0,0 +1,12 @@ +{ + "comments": [ + { + "id": "5", + "body": null, + "customData": { }, + "links": { + "post": null + } + } + ] +} diff --git a/JSONAPI.Tests/Data/ReformatsRawJsonStringWithUnquotedKeys.json b/JSONAPI.Tests/Data/ReformatsRawJsonStringWithUnquotedKeys.json new file mode 100644 index 00000000..49894bcf --- /dev/null +++ b/JSONAPI.Tests/Data/ReformatsRawJsonStringWithUnquotedKeys.json @@ -0,0 +1,14 @@ +{ + "comments": [ + { + "id": "5", + "body": null, + "customData": { + "unquotedKey": 5 + }, + "links": { + "post": null + } + } + ] +} diff --git a/JSONAPI.Tests/JSONAPI.Tests.csproj b/JSONAPI.Tests/JSONAPI.Tests.csproj index 3a2d8917..ea3f694b 100644 --- a/JSONAPI.Tests/JSONAPI.Tests.csproj +++ b/JSONAPI.Tests/JSONAPI.Tests.csproj @@ -96,6 +96,12 @@ + + Always + + + Always + Always diff --git a/JSONAPI.Tests/Json/JsonApiMediaFormaterTests.cs b/JSONAPI.Tests/Json/JsonApiMediaFormaterTests.cs index 84c01cdc..3639061b 100644 --- a/JSONAPI.Tests/Json/JsonApiMediaFormaterTests.cs +++ b/JSONAPI.Tests/Json/JsonApiMediaFormaterTests.cs @@ -250,6 +250,44 @@ public void Serializes_attributes_properly() Assert.AreEqual(expected, output.Trim()); } + [TestMethod] + [DeploymentItem(@"Data\ReformatsRawJsonStringWithUnquotedKeys.json")] + public void Reformats_raw_json_string_with_unquoted_keys() + { + // Arrange + JsonApiFormatter formatter = new JsonApiFormatter(new PluralizationService()); + MemoryStream stream = new MemoryStream(); + + // Act + var payload = new [] { new Comment { Id = 5, CustomData = "{ unquotedKey: 5 }"}}; + formatter.WriteToStreamAsync(typeof(Comment), payload, stream, null, null); + + // Assert + var minifiedExpectedJson = JsonHelpers.MinifyJson(File.ReadAllText("ReformatsRawJsonStringWithUnquotedKeys.json")); + string output = System.Text.Encoding.ASCII.GetString(stream.ToArray()); + Trace.WriteLine(output); + output.Should().Be(minifiedExpectedJson); + } + + [TestMethod] + [DeploymentItem(@"Data\MalformedRawJsonString.json")] + public void Does_not_serialize_malformed_raw_json_string() + { + // Arrange + JsonApiFormatter formatter = new JsonApiFormatter(new PluralizationService()); + MemoryStream stream = new MemoryStream(); + + // Act + var payload = new[] { new Comment { Id = 5, CustomData = "{ x }" } }; + formatter.WriteToStreamAsync(typeof(Comment), payload, stream, null, null); + + // Assert + var minifiedExpectedJson = JsonHelpers.MinifyJson(File.ReadAllText("MalformedRawJsonString.json")); + string output = System.Text.Encoding.ASCII.GetString(stream.ToArray()); + Trace.WriteLine(output); + output.Should().Be(minifiedExpectedJson); + } + [TestMethod] [DeploymentItem(@"Data\FormatterErrorSerializationTest.json")] public void Should_serialize_error() diff --git a/JSONAPI/Json/JsonApiFormatter.cs b/JSONAPI/Json/JsonApiFormatter.cs index 81b3bac2..6a01782e 100644 --- a/JSONAPI/Json/JsonApiFormatter.cs +++ b/JSONAPI/Json/JsonApiFormatter.cs @@ -42,8 +42,11 @@ internal JsonApiFormatter(IModelManager modelManager, IErrorSerializer errorSeri _modelManager = modelManager; _errorSerializer = errorSerializer; SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/vnd.api+json")); + ValidateRawJsonStrings = true; } + public bool ValidateRawJsonStrings { get; set; } + [Obsolete("Use ModelManager.PluralizationService instead")] public IPluralizationService PluralizationService //FIXME: Deprecated, will be removed shortly { @@ -212,8 +215,21 @@ protected void Serialize(object value, Stream writeStream, JsonWriter writer, Js } else { - var minifiedValue = JsonHelpers.MinifyJson((string) propertyValue); - writer.WriteRawValue(minifiedValue); + var json = (string) propertyValue; + if (ValidateRawJsonStrings) + { + try + { + var token = JToken.Parse(json); + json = token.ToString(); + } + catch (Exception) + { + json = "{}"; + } + } + var valueToSerialize = JsonHelpers.MinifyJson(json); + writer.WriteRawValue(valueToSerialize); } } else