public Changes <TResource> BuildChanges <TResource>(DocumentData data, IResourceMapping mapping) { var changes = new Changes <TResource>(); if (data.Id.HasValue) { changes.AddChange(resource => mapping.SetId(resource, data.Id.Value)); } if (data.Attributes != null) { foreach (var attribute in data.Attributes) { var attributeType = mapping.GetAttributeType(attribute.Key); if (attributeType == null) { continue; } var value = attribute.Value.ParseAs(attributeType, _jsonSerializer); changes.AddChange(resource => mapping.SetAttributeValue(resource, attribute.Key, value)); } } if (data.Relationships != null) { foreach (var relation in data.Relationships) { var relationResourceType = mapping.GetResourceTypeOfRelation(relation.Key); if (relationResourceType == null) { throw new JsonApiException(CausedBy.Client, $"Unknown relation {relation.Key}"); } var relationResourceTypeName = GetResourceTypeName(relationResourceType); if (mapping.IsHasManyRelation(relation.Key)) { var relationData = relation.Value.Data.ParseAs <IEnumerable <RelationData> >(_jsonSerializer); if (relationData != null) { if (relationData.Any(x => !x.Type.Equals(relationResourceTypeName))) { throw new JsonApiFormatException(CausedBy.Client, $"Not all relations specified for {relation.Key} are of the type {relationResourceTypeName}"); } var relationIds = relationData.Select(x => x.Id); changes.AddChange(resource => mapping.SetRelationValue(resource, relation.Key, relationIds)); } } else { var relationData = relation.Value.Data.ParseAs <RelationData>(_jsonSerializer); if (relationData != null) { if (!relationData.Type.Equals(relationResourceTypeName)) { throw new JsonApiFormatException(CausedBy.Client, $"Relation type specified for {relation.Key} must be {relationResourceTypeName} instead of {relationData.Type}"); } var relationId = relationData.Id; changes.AddChange(resource => mapping.SetRelationValue(resource, relation.Key, relationId)); } } } } return(changes); }