Skip to content

Commit 3db8048

Browse files
author
Chris Santero
committed
fix crash with null to-one relationships
1 parent 3955509 commit 3db8048

File tree

3 files changed

+42
-26
lines changed

3 files changed

+42
-26
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
{"posts":[{"id":"1","title":"Linkbait!","links":{"comments":["2","3","4"],"author":"1"}},{"id":"2","title":"Rant #1023","links":{"comments":["5"],"author":"1"}},{"id":"3","title":"Polemic in E-flat minor #824","links":{"comments":null,"author":"1"}}],"linked":{"comments":[{"id":"2","body":"Nuh uh!","links":{"post":"1"}},{"id":"3","body":"Yeah huh!","links":{"post":"1"}},{"id":"4","body":"Third Reich.","links":{"post":"1"}},{"id":"5","body":"I laughed, I cried!","links":{"post":"2"}}],"authors":[{"id":"1","name":"Jason Hater","links":{"posts":["1","2","3"]}}]}}
1+
{"posts":[{"id":"1","title":"Linkbait!","links":{"comments":["2","3","4"],"author":"1"}},{"id":"2","title":"Rant #1023","links":{"comments":["5"],"author":"1"}},{"id":"3","title":"Polemic in E-flat minor #824","links":{"comments":null,"author":"1"}},{"id":"4","title":"This post has no author.","links":{"comments":null,"author":null}}],"linked":{"comments":[{"id":"2","body":"Nuh uh!","links":{"post":"1"}},{"id":"3","body":"Yeah huh!","links":{"post":"1"}},{"id":"4","body":"Third Reich.","links":{"post":"1"}},{"id":"5","body":"I laughed, I cried!","links":{"post":"2"}}],"authors":[{"id":"1","name":"Jason Hater","links":{"posts":["1","2","3"]}}]}}
22

33

JSONAPI.Tests/Json/JsonApiMediaFormaterTests.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Linq;
23
using Microsoft.VisualStudio.TestTools.UnitTesting;
34
using JSONAPI.Tests.Models;
45
using Newtonsoft.Json;
@@ -14,7 +15,7 @@ namespace JSONAPI.Tests.Json
1415
public class JsonApiMediaFormaterTests
1516
{
1617
Author a;
17-
Post p, p2, p3;
18+
Post p, p2, p3, p4;
1819

1920
[TestInitialize]
2021
public void SetupModels()
@@ -43,6 +44,11 @@ public void SetupModels()
4344
Title = "Polemic in E-flat minor #824",
4445
Author = a
4546
};
47+
p4 = new Post
48+
{
49+
Id = 4,
50+
Title = "This post has no author."
51+
};
4652

4753
a.Posts = new List<Post> { p, p2, p3 };
4854

@@ -108,7 +114,7 @@ public void SerializerIntegrationTest()
108114
// Act
109115
//Payload payload = new Payload(a.Posts);
110116
//js.Serialize(jw, payload);
111-
formatter.WriteToStreamAsync(typeof(Post), a.Posts, stream, (System.Net.Http.HttpContent)null, (System.Net.TransportContext)null);
117+
formatter.WriteToStreamAsync(typeof(Post), new[] { p, p2, p3, p4 }.ToList(), stream, (System.Net.Http.HttpContent)null, (System.Net.TransportContext)null);
112118

113119
// Assert
114120
string output = System.Text.Encoding.ASCII.GetString(stream.ToArray());

JSONAPI/Json/JsonApiFormatter.cs

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -249,30 +249,40 @@ protected void Serialize(object value, Stream writeStream, JsonWriter writer, Js
249249
}
250250
else
251251
{
252-
string objId;
253-
254-
objId = GetIdFor(prop.GetValue(value, null));
255-
256-
switch (sa)
252+
var propertyValue = prop.GetValue(value, null);
253+
if (propertyValue == null)
257254
{
258-
case SerializeAsOptions.Ids:
259-
//writer.WritePropertyName(ContractResolver.FormatPropertyName(prop.Name));
260-
serializer.Serialize(writer, objId);
261-
if (iip)
262-
if (aggregator != null) aggregator.Add(prop.PropertyType, prop.GetValue(value, null));
263-
break;
264-
case SerializeAsOptions.Link:
265-
if (lt == null) throw new JsonSerializationException("A property was decorated with SerializeAs(SerializeAsOptions.Link) but no LinkTemplate attribute was provided.");
266-
string link = String.Format(lt, objId, value.GetType().GetProperty("Id").GetValue(value, null));
267-
//writer.WritePropertyName(ContractResolver.FormatPropertyName(prop.Name));
268-
writer.WriteValue(link);
269-
break;
270-
case SerializeAsOptions.Embedded:
271-
// Not really supported by Ember Data yet, incidentally...but easy to implement here.
272-
//writer.WritePropertyName(ContractResolver.FormatPropertyName(prop.Name));
273-
//serializer.Serialize(writer, prop.GetValue(value, null));
274-
this.Serialize(prop.GetValue(value, null), writeStream, writer, serializer, aggregator);
275-
break;
255+
writer.WriteNull();
256+
}
257+
else
258+
{
259+
string objId = GetIdFor(propertyValue);
260+
261+
switch (sa)
262+
{
263+
case SerializeAsOptions.Ids:
264+
//writer.WritePropertyName(ContractResolver.FormatPropertyName(prop.Name));
265+
serializer.Serialize(writer, objId);
266+
if (iip)
267+
if (aggregator != null)
268+
aggregator.Add(prop.PropertyType, prop.GetValue(value, null));
269+
break;
270+
case SerializeAsOptions.Link:
271+
if (lt == null)
272+
throw new JsonSerializationException(
273+
"A property was decorated with SerializeAs(SerializeAsOptions.Link) but no LinkTemplate attribute was provided.");
274+
string link = String.Format(lt, objId,
275+
value.GetType().GetProperty("Id").GetValue(value, null));
276+
//writer.WritePropertyName(ContractResolver.FormatPropertyName(prop.Name));
277+
writer.WriteValue(link);
278+
break;
279+
case SerializeAsOptions.Embedded:
280+
// Not really supported by Ember Data yet, incidentally...but easy to implement here.
281+
//writer.WritePropertyName(ContractResolver.FormatPropertyName(prop.Name));
282+
//serializer.Serialize(writer, prop.GetValue(value, null));
283+
this.Serialize(prop.GetValue(value, null), writeStream, writer, serializer, aggregator);
284+
break;
285+
}
276286
}
277287
}
278288

0 commit comments

Comments
 (0)