Skip to content

Commit e8d6781

Browse files
committed
perf(QueryParser): constants instead of inline strings
1 parent dc46e0e commit e8d6781

File tree

1 file changed

+46
-28
lines changed

1 file changed

+46
-28
lines changed

src/JsonApiDotNetCore/Services/QueryParser.cs

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Linq;
44
using JsonApiDotNetCore.Configuration;
55
using JsonApiDotNetCore.Controllers;
6-
using JsonApiDotNetCore.Extensions;
76
using JsonApiDotNetCore.Internal;
87
using JsonApiDotNetCore.Internal.Query;
98
using JsonApiDotNetCore.Models;
@@ -18,8 +17,17 @@ public class QueryParser : IQueryParser {
1817
private readonly IControllerContext _controllerContext;
1918
private readonly JsonApiOptions _options;
2019

20+
private const string FILTER = "filter";
21+
private const string SORT = "sort";
22+
private const string INCLUDE = "include";
23+
private const string PAGE = "page";
24+
private const string FIELDS = "fields";
2125
private const char OPEN_BRACKET = '[';
2226
private const char CLOSE_BRACKET = ']';
27+
private const char COMMA = ',';
28+
private const char COLON = ':';
29+
private const string COLON_STR = ":";
30+
2331
public QueryParser(
2432
IControllerContext controllerContext,
2533
JsonApiOptions options) {
@@ -32,31 +40,31 @@ public virtual QuerySet Parse(IQueryCollection query) {
3240
var disabledQueries = _controllerContext.GetControllerAttribute<DisableQueryAttribute>() ? .QueryParams ?? QueryParams.None;
3341

3442
foreach (var pair in query) {
35-
if (pair.Key.StartsWith("filter")) {
43+
if (pair.Key.StartsWith(FILTER)) {
3644
if (disabledQueries.HasFlag(QueryParams.Filter) == false)
3745
querySet.Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value));
3846
continue;
3947
}
4048

41-
if (pair.Key.StartsWith("sort")) {
49+
if (pair.Key.StartsWith(SORT)) {
4250
if (disabledQueries.HasFlag(QueryParams.Sort) == false)
4351
querySet.SortParameters = ParseSortParameters(pair.Value);
4452
continue;
4553
}
4654

47-
if (pair.Key.StartsWith("include")) {
55+
if (pair.Key.StartsWith(INCLUDE)) {
4856
if (disabledQueries.HasFlag(QueryParams.Include) == false)
4957
querySet.IncludedRelationships = ParseIncludedRelationships(pair.Value);
5058
continue;
5159
}
5260

53-
if (pair.Key.StartsWith("page")) {
61+
if (pair.Key.StartsWith(PAGE)) {
5462
if (disabledQueries.HasFlag(QueryParams.Page) == false)
5563
querySet.PageQuery = ParsePageQuery(querySet.PageQuery, pair.Key, pair.Value);
5664
continue;
5765
}
5866

59-
if (pair.Key.StartsWith("fields")) {
67+
if (pair.Key.StartsWith(FIELDS)) {
6068
if (disabledQueries.HasFlag(QueryParams.Fields) == false)
6169
querySet.Fields = ParseFieldsQuery(pair.Key, pair.Value);
6270
continue;
@@ -76,10 +84,9 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value) {
7684

7785
var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
7886

79-
var values = value.Split(',');
87+
var values = value.Split(COMMA);
8088
foreach (var val in values) {
81-
(var operation,
82-
var filterValue) = ParseFilterOperation(val);
89+
(var operation, var filterValue) = ParseFilterOperation(val);
8390
queries.Add(new FilterQuery(propertyName, filterValue, operation));
8491
}
8592

@@ -90,7 +97,7 @@ protected virtual(string operation, string value) ParseFilterOperation(string va
9097
if (value.Length < 3)
9198
return (string.Empty, value);
9299

93-
var operation = value.Split(':');
100+
var operation = value.Split(COLON);
94101

95102
if (operation.Length == 1)
96103
return (string.Empty, value);
@@ -100,7 +107,7 @@ protected virtual(string operation, string value) ParseFilterOperation(string va
100107
return (string.Empty, value);
101108

102109
var prefix = operation[0];
103-
value = string.Join(":", operation.Skip(1));
110+
value = string.Join(COLON_STR, operation.Skip(1));
104111

105112
return (prefix, value);
106113
}
@@ -110,11 +117,14 @@ protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, stri
110117
// page[number]=1
111118
pageQuery = pageQuery ?? new PageQuery();
112119

113-
var propertyName = key.Split('[', ']') [1];
120+
var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
121+
122+
const string SIZE = "size";
123+
const string NUMBER = "number";
114124

115-
if (propertyName == "size")
125+
if (propertyName == SIZE)
116126
pageQuery.PageSize = Convert.ToInt32(value);
117-
else if (propertyName == "number")
127+
else if (propertyName == NUMBER)
118128
pageQuery.PageOffset = Convert.ToInt32(value);
119129

120130
return pageQuery;
@@ -123,11 +133,11 @@ protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, stri
123133
// sort=id,name
124134
// sort=-id
125135
protected virtual List<SortQuery> ParseSortParameters(string value) {
126-
const char SORT_DELIMITER = ',';
136+
var sortParameters = new List<SortQuery>();
137+
127138
const char DESCENDING_SORT_OPERATOR = '-';
139+
var sortSegments = value.Split(COMMA);
128140

129-
var sortParameters = new List<SortQuery>();
130-
var sortSegments = value.Split(SORT_DELIMITER);
131141
foreach (var sortSegment in sortSegments) {
132142

133143
var propertyName = sortSegment;
@@ -147,24 +157,26 @@ protected virtual List<SortQuery> ParseSortParameters(string value) {
147157
}
148158

149159
protected virtual List<string> ParseIncludedRelationships(string value) {
150-
if (value.Contains("."))
160+
const string NESTED_DELIMITER = ".";
161+
if (value.Contains(NESTED_DELIMITER))
151162
throw new JsonApiException(400, "Deeply nested relationships are not supported");
152163

153164
return value
154-
.Split(',')
165+
.Split(COMMA)
155166
.ToList();
156167
}
157168

158169
protected virtual List<string> ParseFieldsQuery(string key, string value) {
159170
// expected: fields[TYPE]=prop1,prop2
160-
var typeName = key.Split('[', ']') [1];
171+
var typeName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
161172

162-
var includedFields = new List<string> { "Id" };
173+
const string ID = "Id";
174+
var includedFields = new List<string> { ID };
163175

164176
if (typeName != _controllerContext.RequestEntity.EntityName)
165177
return includedFields;
166178

167-
var fields = value.Split(',');
179+
var fields = value.Split(COMMA);
168180
foreach (var field in fields) {
169181
var internalAttrName = _controllerContext.RequestEntity
170182
.Attributes
@@ -176,11 +188,17 @@ protected virtual List<string> ParseFieldsQuery(string key, string value) {
176188
return includedFields;
177189
}
178190

179-
protected virtual AttrAttribute GetAttribute(string propertyName) => _controllerContext
180-
.RequestEntity
181-
.Attributes
182-
.FirstOrDefault(attr =>
183-
string.Equals(attr.PublicAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
184-
);
191+
protected virtual AttrAttribute GetAttribute(string propertyName) {
192+
try {
193+
return _controllerContext
194+
.RequestEntity
195+
.Attributes
196+
.Single(attr =>
197+
string.Equals(attr.PublicAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
198+
);
199+
} catch (InvalidOperationException e) {
200+
throw new JsonApiException(400, $"Attribute '{propertyName}' does not exist on resource '{_controllerContext.RequestEntity.EntityName}'");
201+
}
202+
}
185203
}
186204
}

0 commit comments

Comments
 (0)