Skip to content

Commit 32f3af0

Browse files
author
Bart Koelman
committed
Add test for incompatible ID value.
By default, this produces: ``` The JSON value could not be converted to JsonApiDotNetCore.Serialization.Objects.SingleOrManyData`1[JsonApiDotNetCore.Serialization.Objects.ResourceObject]. Path: $.data | LineNumber: 3 | BytePositionInLine: 11. ``` which is totally unhelpful. Because this is so likely to hit users, we special-case here to produce a better error.
1 parent eaf9a33 commit 32f3af0

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver
6868
{
6969
case "id":
7070
{
71+
if (reader.TokenType != JsonTokenType.String)
72+
{
73+
// Newtonsoft.Json used to auto-convert number to strings, while System.Text.Json does not. This is so likely
74+
// to hit users during upgrade that we special-case for this and produce a helpful error message.
75+
var jsonElement = JsonConverterSupport.ReadSubTree<JsonElement>(ref reader, options);
76+
throw new JsonException($"Failed to convert ID '{jsonElement}' of type '{jsonElement.ValueKind}' to type 'String'.");
77+
}
78+
7179
resourceObject.Id = reader.GetString();
7280
break;
7381
}

test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,46 @@ await _testContext.RunOnDatabaseAsync(async dbContext =>
958958
error.Detail.Should().StartWith("Resource ID is read-only. - Request body: <<");
959959
}
960960

961+
[Fact]
962+
public async Task Cannot_update_resource_with_incompatible_ID_value()
963+
{
964+
// Arrange
965+
WorkItem existingWorkItem = _fakers.WorkItem.Generate();
966+
967+
await _testContext.RunOnDatabaseAsync(async dbContext =>
968+
{
969+
dbContext.WorkItems.Add(existingWorkItem);
970+
await dbContext.SaveChangesAsync();
971+
});
972+
973+
var requestBody = new
974+
{
975+
data = new
976+
{
977+
type = "workItems",
978+
id = existingWorkItem.Id,
979+
attributes = new
980+
{
981+
}
982+
}
983+
};
984+
985+
string route = $"/workItems/{existingWorkItem.StringId}";
986+
987+
// Act
988+
(HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePatchAsync<Document>(route, requestBody);
989+
990+
// Assert
991+
httpResponse.Should().HaveStatusCode(HttpStatusCode.UnprocessableEntity);
992+
993+
responseDocument.Errors.Should().HaveCount(1);
994+
995+
ErrorObject error = responseDocument.Errors[0];
996+
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
997+
error.Title.Should().Be("Failed to deserialize request body.");
998+
error.Detail.Should().StartWith($"Failed to convert ID '{existingWorkItem.Id}' of type 'Number' to type 'String'. - Request body: <<");
999+
}
1000+
9611001
[Fact]
9621002
public async Task Cannot_update_resource_with_incompatible_attribute_value()
9631003
{

0 commit comments

Comments
 (0)