Skip to content

Commit 0a17020

Browse files
committed
Moved null attribute handling behind IDocumentBuilderBehavior api'
1 parent af9f7d4 commit 0a17020

File tree

7 files changed

+55
-41
lines changed

7 files changed

+55
-41
lines changed

src/JsonApiDotNetCore/Builders/DocumentBuilder.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class DocumentBuilder : IDocumentBuilder
1313
private readonly IJsonApiContext _jsonApiContext;
1414
private readonly IContextGraph _contextGraph;
1515
private readonly IRequestMeta _requestMeta;
16+
private readonly DocumentBuilderOptions _documentBuilderOptions;
1617

1718
public DocumentBuilder(IJsonApiContext jsonApiContext)
1819
{
@@ -27,6 +28,14 @@ public DocumentBuilder(IJsonApiContext jsonApiContext, IRequestMeta requestMeta)
2728
_requestMeta = requestMeta;
2829
}
2930

31+
public DocumentBuilder(IJsonApiContext jsonApiContext, IRequestMeta requestMeta, IDocumentBuilderBehavior documentBuilderBehavior)
32+
{
33+
_jsonApiContext = jsonApiContext;
34+
_contextGraph = jsonApiContext.ContextGraph;
35+
_requestMeta = requestMeta;
36+
_documentBuilderOptions = documentBuilderBehavior?.GetDocumentBuilderOptions() ?? new DocumentBuilderOptions();
37+
}
38+
3039
public Document Build(IIdentifiable entity)
3140
{
3241
var contextEntity = _contextGraph.GetContextEntity(entity.GetType());
@@ -121,7 +130,7 @@ private DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
121130
if (ShouldIncludeAttribute(attr))
122131
{
123132
var value = attr.GetValue(entity);
124-
if (value != null || ShouldIncludeNullValuedAttributes())
133+
if (value != null || _documentBuilderOptions.IncludeNullAttributes)
125134
{
126135
data.Attributes.Add(attr.PublicAttributeName, value);
127136
}
@@ -134,15 +143,6 @@ private DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
134143
return data;
135144
}
136145

137-
private bool ShouldIncludeNullValuedAttributes()
138-
{
139-
object isOmitNullValuedAttributes = false;
140-
return
141-
(_requestMeta?.GetMeta()?.TryGetValue("jsonapidotnet:omit-null-valued-attributes", out isOmitNullValuedAttributes) ?? false ) ?
142-
(bool)isOmitNullValuedAttributes
143-
: _jsonApiContext.Options.OmitNullValuedAttributesFromResponses;
144-
}
145-
146146
private bool ShouldIncludeAttribute(AttrAttribute attr)
147147
{
148148
return (_jsonApiContext.QuerySet == null
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace JsonApiDotNetCore.Builders
6+
{
7+
public struct DocumentBuilderOptions
8+
{
9+
public DocumentBuilderOptions(bool isIncludeNullAttributes = false)
10+
{
11+
this.IncludeNullAttributes = isIncludeNullAttributes;
12+
}
13+
14+
public bool IncludeNullAttributes { get; private set; }
15+
}
16+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace JsonApiDotNetCore.Builders
6+
{
7+
public interface IDocumentBuilderBehavior
8+
{
9+
DocumentBuilderOptions GetDocumentBuilderOptions();
10+
}
11+
}

src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ public class JsonApiOptions
1717
public IContextGraph ContextGraph { get; set; }
1818
public bool RelativeLinks { get; set; }
1919
public bool AllowCustomQueryParameters { get; set; }
20-
public bool OmitNullValuedAttributesFromResponses { get; set; }
2120

2221
[Obsolete("JsonContract resolver can now be set on SerializerSettings.")]
2322
public IContractResolver JsonContractResolver

src/JsonApiDotNetCore/Services/IJsonApiContext.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public interface IJsonApiContext
2626
Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; }
2727
Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; }
2828
Type ControllerType { get; set; }
29+
Dictionary<string, object> DocumentMeta { get; set; }
30+
2931
TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
3032
}
3133
}

src/JsonApiDotNetCore/Services/JsonApiContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public JsonApiContext(
5050
public Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; } = new Dictionary<AttrAttribute, object>();
5151
public Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; } = new Dictionary<RelationshipAttribute, object>();
5252
public Type ControllerType { get; set; }
53+
public Dictionary<string, object> DocumentMeta { get; set; }
5354

5455
public IJsonApiContext ApplyContext<T>(object controller)
5556
{

test/UnitTests/Builders/DocumentBuilder_Tests.cs

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public class DocumentBuilder_Tests
2020

2121
public DocumentBuilder_Tests()
2222
{
23-
_jsonApiContextMock = new Mock<IJsonApiContext>();
24-
_requestMetaMock = new Mock<IRequestMeta>();
23+
_jsonApiContextMock = new Mock<IJsonApiContext>();
24+
_requestMetaMock = new Mock<IRequestMeta>();
2525

2626
_options = new JsonApiOptions();
2727

@@ -144,38 +144,23 @@ public void Build_Can_Build_CustomIEnumerables()
144144
}
145145

146146

147-
[Theory]
148-
[InlineData(null,null,false)]
149-
[InlineData(true,null,true)]
150-
[InlineData(false,null,false)]
151-
[InlineData(true,true,true)]
152-
[InlineData(true,false,false)]
153-
[InlineData(false,false,false)]
154-
[InlineData(null,false,false)]
155-
[InlineData(null,true,true)]
156-
public void CheckNullValueHandling(bool? optionsOmitNullValuedAttributesFromResponses,
157-
bool? requestMetaOmitNullValuedAttributesFromResponses,
158-
bool isNullValuesAreIncludedInResponse)
147+
[Theory]
148+
[InlineData(null,false)]
149+
[InlineData(false,false)]
150+
[InlineData(true,true)]
151+
public void DocumentBuilderOptions(bool? isIcludeNullAttributesOptionValue,
152+
bool isNullValuesAreIncludedInResult)
159153
{
160-
if (optionsOmitNullValuedAttributesFromResponses.HasValue)
154+
var documentBuilderBehaviourMock = new Mock<IDocumentBuilderBehavior>();
155+
if (isIcludeNullAttributesOptionValue.HasValue)
161156
{
162-
_options.OmitNullValuedAttributesFromResponses = optionsOmitNullValuedAttributesFromResponses.Value;
157+
documentBuilderBehaviourMock.Setup(m => m.GetDocumentBuilderOptions())
158+
.Returns(new DocumentBuilderOptions(isIcludeNullAttributesOptionValue.Value));
163159
}
164-
if (requestMetaOmitNullValuedAttributesFromResponses.HasValue)
165-
{
166-
_requestMetaMock.Setup(m => m.GetMeta())
167-
.Returns(new Dictionary<string, object>()
168-
{
169-
{
170-
"jsonapidotnet:omit-null-valued-attributes", requestMetaOmitNullValuedAttributesFromResponses.Value
171-
}
172-
});
173-
}
174-
var documentBuilder = new DocumentBuilder(
175-
_jsonApiContextMock.Object, requestMetaOmitNullValuedAttributesFromResponses.HasValue ? _requestMetaMock.Object : null);
160+
var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, null, isIcludeNullAttributesOptionValue.HasValue ? documentBuilderBehaviourMock.Object : null);
176161
var document = documentBuilder.Build(new Model());
177-
178-
Assert.Equal(isNullValuesAreIncludedInResponse, document.Data.Attributes.ContainsKey("StringProperty"));
162+
163+
Assert.Equal(isNullValuesAreIncludedInResult, document.Data.Attributes.ContainsKey("StringProperty"));
179164
}
180165

181166
private class Model : Identifiable

0 commit comments

Comments
 (0)