diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs
index 66ee6156a7..54dc30e753 100644
--- a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs
+++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs
@@ -82,5 +82,26 @@ public async Task JsonColumn_GraphQLRead_ReturnsPayloadAsString()
Assert.AreEqual("admin", parsed.GetProperty("role").GetString());
Assert.AreEqual(3, parsed.GetProperty("tier").GetInt32());
}
+
+ ///
+ /// createProfile with malformed JSON in the metadata field must fail with a GraphQL error
+ /// (surfaced from SQL Server's json validation) rather than persisting invalid data.
+ ///
+ [TestMethod]
+ public async Task JsonColumn_GraphQLCreateWithMalformedJson_Fails()
+ {
+ string createMutationName = "createProfile";
+ string createMutation = @"mutation {
+ createProfile(item: { metadata: ""{ not valid json"" }) {
+ id
+ metadata
+ }
+ }";
+
+ JsonElement errors = await ExecuteGraphQLRequestAsync(createMutation, createMutationName, isAuthenticated: false);
+
+ Assert.AreEqual(JsonValueKind.Array, errors.ValueKind, "Expected a GraphQL errors array for malformed JSON payload.");
+ Assert.IsTrue(errors.GetArrayLength() > 0, "Expected at least one GraphQL error.");
+ }
}
}
diff --git a/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs b/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs
index 8e8c20417d..04d2addfab 100644
--- a/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs
+++ b/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs
@@ -114,6 +114,21 @@ public async Task GetJsonTypeWithUnicode()
Assert.AreEqual("éü😀", metadata.GetProperty("unicode").GetString());
}
+ ///
+ /// GET /api/Profile?$filter=metadata ne null - Verify filtering a json column (treated as a
+ /// string) passes through to SQL: the 4 non-null rows match and the null row (id 5) does not.
+ ///
+ [TestMethod]
+ public async Task FilterJsonColumnIsNotNull_Succeeds()
+ {
+ HttpResponseMessage response = await HttpClient.GetAsync($"{JSON_TYPE_REST_PATH}?$filter=metadata%20ne%20null");
+ Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Filtering a json column as a string should pass through and succeed.");
+
+ JsonElement items = JsonDocument.Parse(await response.Content.ReadAsStringAsync())
+ .RootElement.GetProperty("value");
+ Assert.AreEqual(4, items.GetArrayLength(), "Only the 4 rows with non-null metadata should match.");
+ }
+
#endregion
#region Write Tests
@@ -221,6 +236,26 @@ public async Task PatchJsonType_ToNull()
}
}
+ ///
+ /// POST /api/Profile - Verify that supplying invalid JSON for the json column is rejected by
+ /// SQL Server and surfaced as HTTP 400 (a client input error), not a 500. DAB treats the value
+ /// as a normal string, so JSON validation happens at the database boundary.
+ ///
+ [DataTestMethod]
+ [DataRow("{ \"metadata\": \"{ not valid json\" }", DisplayName = "Unclosed / unquoted object")]
+ [DataRow("{ \"metadata\": \"{\\\"key\\\": }\" }", DisplayName = "Missing value")]
+ public async Task InsertMalformedJson_ReturnsBadRequest(string requestBody)
+ {
+ HttpResponseMessage response = await HttpClient.PostAsync(
+ JSON_TYPE_REST_PATH,
+ new StringContent(requestBody, Encoding.UTF8, "application/json"));
+
+ Assert.AreEqual(
+ HttpStatusCode.BadRequest,
+ response.StatusCode,
+ "SQL Server rejects invalid JSON for a native json column; DAB must surface it as HTTP 400.");
+ }
+
#endregion
#region Helpers