Skip to content

Commit 0bfe81b

Browse files
author
Piotr Brzezianski
committed
fix: #528
Allowing string foreign keys on optional HasOne relationship
1 parent 19d7586 commit 0bfe81b

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ private void SetHasOneForeignKeyValue(object entity, HasOneAttribute hasOneAttr,
252252

253253
// e.g. PATCH /articles
254254
// {... { "relationships":{ "Owner": { "data": null } } } }
255-
if (rio == null && Nullable.GetUnderlyingType(foreignKeyProperty.PropertyType) == null)
255+
bool foreignKeyPropertyIsNullableType = Nullable.GetUnderlyingType(foreignKeyProperty.PropertyType) != null
256+
|| foreignKeyProperty.PropertyType == typeof(string);
257+
if (rio == null && !foreignKeyPropertyIsNullableType)
256258
throw new JsonApiException(400, $"Cannot set required relationship identifier '{hasOneAttr.IdentifiablePropertyName}' to null because it is a non-nullable type.");
257259

258260
var convertedValue = TypeHelper.ConvertType(foreignKeyPropertyValue, foreignKeyProperty.PropertyType);

test/UnitTests/Serialization/JsonApiDeSerializerTests.cs

+59-1
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,51 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship()
222222
Assert.Equal(property, result.Property);
223223
}
224224

225+
[Fact]
226+
public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_String_Keys()
227+
{
228+
// arrange
229+
var resourceGraphBuilder = new ResourceGraphBuilder();
230+
resourceGraphBuilder.AddResource<IndependentWithStringKey, string>("independents");
231+
resourceGraphBuilder.AddResource<DependentWithStringKey, string>("dependents");
232+
var resourceGraph = resourceGraphBuilder.Build();
233+
234+
var jsonApiContextMock = new Mock<IJsonApiContext>();
235+
jsonApiContextMock.SetupAllProperties();
236+
jsonApiContextMock.Setup(m => m.ResourceGraph).Returns(resourceGraph);
237+
jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
238+
jsonApiContextMock.Setup(m => m.HasOneRelationshipPointers).Returns(new HasOneRelationshipPointers());
239+
240+
var jsonApiOptions = new JsonApiOptions();
241+
jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
242+
243+
var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
244+
245+
var property = Guid.NewGuid().ToString();
246+
var content = new Document
247+
{
248+
Data = new ResourceObject
249+
{
250+
Type = "independents",
251+
Id = "natural-key",
252+
Attributes = new Dictionary<string, object> { { "property", property } },
253+
Relationships = new Dictionary<string, RelationshipData>
254+
{
255+
{ "dependent" , new RelationshipData { } }
256+
}
257+
}
258+
};
259+
260+
var contentString = JsonConvert.SerializeObject(content);
261+
262+
// act
263+
var result = deserializer.Deserialize<IndependentWithStringKey>(contentString);
264+
265+
// assert
266+
Assert.NotNull(result);
267+
Assert.Equal(property, result.Property);
268+
}
269+
225270
[Fact]
226271
public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Relationship_Body()
227272
{
@@ -348,6 +393,19 @@ private class Dependent : Identifiable
348393
public int IndependentId { get; set; }
349394
}
350395

396+
private class IndependentWithStringKey : Identifiable<string>
397+
{
398+
[Attr("property")] public string Property { get; set; }
399+
[HasOne("dependent")] public Dependent Dependent { get; set; }
400+
public string DependentId { get; set; }
401+
}
402+
403+
private class DependentWithStringKey : Identifiable<string>
404+
{
405+
[HasOne("independent")] public Independent Independent { get; set; }
406+
public string IndependentId { get; set; }
407+
}
408+
351409
[Fact]
352410
public void Can_Deserialize_Object_With_HasManyRelationship()
353411
{
@@ -538,7 +596,7 @@ public void Can_Deserialize_Nested_Included_HasMany_Relationships()
538596
resourceGraphBuilder.AddResource<ManyToManyNested>("many-to-manys");
539597

540598
var deserializer = GetDeserializer(resourceGraphBuilder);
541-
599+
542600
var contentString =
543601
@"{
544602
""data"": {

0 commit comments

Comments
 (0)