Skip to content

Commit 734bd3e

Browse files
committed
fix(de-serialization): improve error handling
1 parent 773073e commit 734bd3e

File tree

2 files changed

+59
-29
lines changed

2 files changed

+59
-29
lines changed

src/JsonApiDotNetCore/Formatters/JsonApiReader.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.IO;
3+
using System.Text;
34
using System.Threading.Tasks;
5+
using JsonApiDotNetCore.Internal;
46
using JsonApiDotNetCore.Serialization;
57
using JsonApiDotNetCore.Services;
68
using Microsoft.AspNetCore.Mvc.Formatters;
@@ -50,6 +52,13 @@ public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
5052
context.HttpContext.Response.StatusCode = 422;
5153
return InputFormatterResult.FailureAsync();
5254
}
55+
catch(JsonApiException jex)
56+
{
57+
_logger?.LogError(new EventId(), jex, "An error occurred while de-serializing the payload");
58+
context.HttpContext.Response.StatusCode = jex.GetStatusCode();
59+
context.HttpContext.Response.Body = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jex.GetError())));
60+
return InputFormatterResult.FailureAsync();
61+
}
5362
}
5463

5564
private string GetRequestBody(Stream body)

src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class JsonApiDeSerializer : IJsonApiDeSerializer
1616
private readonly IJsonApiContext _jsonApiContext;
1717
private readonly IGenericProcessorFactory _genericProcessorFactor;
1818

19-
public JsonApiDeSerializer(
19+
public JsonApiDeSerializer(
2020
IJsonApiContext jsonApiContext,
2121
IGenericProcessorFactory genericProcessorFactory)
2222
{
@@ -26,9 +26,16 @@ public JsonApiDeSerializer(
2626

2727
public object Deserialize(string requestBody)
2828
{
29-
var document = JsonConvert.DeserializeObject<Document>(requestBody);
30-
var entity = DocumentToObject(document.Data);
31-
return entity;
29+
try
30+
{
31+
var document = JsonConvert.DeserializeObject<Document>(requestBody);
32+
var entity = DocumentToObject(document.Data);
33+
return entity;
34+
}
35+
catch (Exception e)
36+
{
37+
throw new JsonApiException("400", "Failed to deserialize request body", e.Message);
38+
}
3239
}
3340

3441
public object Deserialize<TEntity>(string requestBody)
@@ -38,26 +45,40 @@ public object Deserialize<TEntity>(string requestBody)
3845

3946
public object DeserializeRelationship(string requestBody)
4047
{
41-
var data = JToken.Parse(requestBody)["data"];
48+
try
49+
{
50+
var data = JToken.Parse(requestBody)["data"];
4251

43-
if(data is JArray)
44-
return data.ToObject<List<DocumentData>>();
52+
if (data is JArray)
53+
return data.ToObject<List<DocumentData>>();
4554

46-
return new List<DocumentData> { data.ToObject<DocumentData>() };
55+
return new List<DocumentData> { data.ToObject<DocumentData>() };
56+
}
57+
catch (Exception e)
58+
{
59+
throw new JsonApiException("400", "Failed to deserialize request body", e.Message);
60+
}
4761
}
4862

4963
public List<TEntity> DeserializeList<TEntity>(string requestBody)
5064
{
51-
var documents = JsonConvert.DeserializeObject<Documents>(requestBody);
65+
try
66+
{
67+
var documents = JsonConvert.DeserializeObject<Documents>(requestBody);
68+
69+
var deserializedList = new List<TEntity>();
70+
foreach (var data in documents.Data)
71+
{
72+
var entity = DocumentToObject(data);
73+
deserializedList.Add((TEntity)entity);
74+
}
5275

53-
var deserializedList = new List<TEntity>();
54-
foreach (var data in documents.Data)
76+
return deserializedList;
77+
}
78+
catch (Exception e)
5579
{
56-
var entity = DocumentToObject(data);
57-
deserializedList.Add((TEntity)entity);
80+
throw new JsonApiException("400", "Failed to deserialize request body", e.Message);
5881
}
59-
60-
return deserializedList;
6182
}
6283

6384
private object DocumentToObject(DocumentData data)
@@ -66,7 +87,7 @@ private object DocumentToObject(DocumentData data)
6687
_jsonApiContext.RequestEntity = contextEntity;
6788

6889
var entity = Activator.CreateInstance(contextEntity.EntityType);
69-
90+
7091
entity = SetEntityAttributes(entity, contextEntity, data.Attributes);
7192
entity = SetRelationships(entity, contextEntity, data.Relationships);
7293

@@ -106,8 +127,8 @@ private object SetEntityAttributes(
106127
}
107128

108129
private object SetRelationships(
109-
object entity,
110-
ContextEntity contextEntity,
130+
object entity,
131+
ContextEntity contextEntity,
111132
Dictionary<string, RelationshipData> relationships)
112133
{
113134
if (relationships == null || relationships.Count == 0)
@@ -117,18 +138,18 @@ private object SetRelationships(
117138

118139
foreach (var attr in contextEntity.Relationships)
119140
{
120-
entity = attr.IsHasOne
121-
? SetHasOneRelationship(entity, entityProperties, attr, contextEntity, relationships)
141+
entity = attr.IsHasOne
142+
? SetHasOneRelationship(entity, entityProperties, attr, contextEntity, relationships)
122143
: SetHasManyRelationship(entity, entityProperties, attr, contextEntity, relationships);
123144
}
124145

125146
return entity;
126147
}
127148

128-
private object SetHasOneRelationship(object entity,
129-
PropertyInfo[] entityProperties,
130-
RelationshipAttribute attr,
131-
ContextEntity contextEntity,
149+
private object SetHasOneRelationship(object entity,
150+
PropertyInfo[] entityProperties,
151+
RelationshipAttribute attr,
152+
ContextEntity contextEntity,
132153
Dictionary<string, RelationshipData> relationships)
133154
{
134155
var entityProperty = entityProperties.FirstOrDefault(p => p.Name == $"{attr.InternalRelationshipName}Id");
@@ -142,7 +163,7 @@ private object SetHasOneRelationship(object entity,
142163
{
143164
var relationshipAttr = _jsonApiContext.RequestEntity.Relationships
144165
.SingleOrDefault(r => r.PublicRelationshipName == relationshipName);
145-
166+
146167
var data = (Dictionary<string, string>)relationshipData.ExposedData;
147168

148169
if (data == null) return entity;
@@ -159,9 +180,9 @@ private object SetHasOneRelationship(object entity,
159180
}
160181

161182
private object SetHasManyRelationship(object entity,
162-
PropertyInfo[] entityProperties,
163-
RelationshipAttribute attr,
164-
ContextEntity contextEntity,
183+
PropertyInfo[] entityProperties,
184+
RelationshipAttribute attr,
185+
ContextEntity contextEntity,
165186
Dictionary<string, RelationshipData> relationships)
166187
{
167188
var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalRelationshipName);
@@ -179,7 +200,7 @@ private object SetHasManyRelationship(object entity,
179200

180201
var genericProcessor = _genericProcessorFactor.GetProcessor(attr.Type);
181202
var ids = relationshipData.ManyData.Select(r => r["id"]);
182-
genericProcessor.SetRelationships(entity, attr, ids);
203+
genericProcessor.SetRelationships(entity, attr, ids);
183204
}
184205

185206
return entity;

0 commit comments

Comments
 (0)