Skip to content

Commit f5d0e8f

Browse files
committed
feat: throw error on deeply nested selections
1 parent b02445c commit f5d0e8f

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

src/JsonApiDotNetCore/QueryParameterServices/SparseFieldsService.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ public virtual void Parse(KeyValuePair<string, StringValues> queryParameter)
5151

5252
var keySplitted = queryParameter.Key.Split(QueryConstants.OPEN_BRACKET, QueryConstants.CLOSE_BRACKET);
5353

54-
if (keySplitted.Count() == 1) // input format: fields=prop1,prop2
54+
if (keySplitted.Count() == 1)
55+
{ // input format: fields=prop1,prop2
5556
foreach (var field in fields)
5657
RegisterRequestResourceField(field);
58+
}
5759
else
5860
{ // input format: fields[articles]=prop1,prop2
5961
string navigation = keySplitted[1];
@@ -65,6 +67,9 @@ public virtual void Parse(KeyValuePair<string, StringValues> queryParameter)
6567
$" the square bracket navigations is now reserved " +
6668
$"for relationships only. See https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/555#issuecomment-543100865");
6769

70+
if (navigation.Contains(QueryConstants.DOT))
71+
throw new JsonApiException(400, $"fields[{navigation}] is not valid: deeply nested sparse field selection is not yet supported.");
72+
6873
var relationship = _requestResource.Relationships.SingleOrDefault(a => a.Is(navigation));
6974
if (relationship == null)
7075
throw new JsonApiException(400, $"\"{navigation}\" in \"fields[{navigation}]\" is not a valid relationship of {_requestResource.EntityName}");

test/UnitTests/QueryParameters/SparseFieldsServiceTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,32 @@ public void Parse_TypeNameAsNavigation_ThrowsJsonApiException()
8383
Assert.Contains("relationships only", ex.Message);
8484
}
8585

86+
[Fact]
87+
public void Parse_DeeplyNestedSelection_ThrowsJsonApiException()
88+
{
89+
// arrange
90+
const string type = "articles";
91+
const string relationship = "author.employer";
92+
const string attrName = "some-field";
93+
const string internalAttrName = "SomeField";
94+
var attribute = new AttrAttribute(attrName) { InternalAttributeName = internalAttrName };
95+
var idAttribute = new AttrAttribute("id") { InternalAttributeName = "Id" };
96+
97+
var query = new KeyValuePair<string, StringValues>($"fields[{relationship}]", new StringValues(attrName));
98+
99+
var contextEntity = new ContextEntity
100+
{
101+
EntityName = type,
102+
Attributes = new List<AttrAttribute> { attribute, idAttribute },
103+
Relationships = new List<RelationshipAttribute>()
104+
};
105+
var service = GetService(contextEntity);
106+
107+
// act, assert
108+
var ex = Assert.Throws<JsonApiException>(() => service.Parse(query));
109+
Assert.Contains("deeply nested", ex.Message);
110+
}
111+
86112
[Fact]
87113
public void Parse_InvalidField_ThrowsJsonApiException()
88114
{

0 commit comments

Comments
 (0)