Allow omitting relationships if all are optional

When all relationships are optional, the `relationships` key is also
optional and not required in the structure.

I'm not super happy with importing Foundation and creating new objects
any time a key is missing, but ultimately none of my attempts at
conditional generics worked out for me.
This commit is contained in:
Janko Luin
2019-07-02 16:49:47 +02:00
parent f73ca8bc2c
commit fc78958f76
3 changed files with 47 additions and 2 deletions
@@ -5,6 +5,8 @@
// Created by Mathew Polzin on 7/24/18.
//
import Foundation
/// A JSON API structure within an ResourceObject that contains
/// named properties of types `ToOneRelationship` and
/// `ToManyRelationship`.
@@ -582,7 +584,6 @@ public extension ResourceObject {
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ResourceObjectCodingKeys.self)
let type = try container.decode(String.self, forKey: .type)
@@ -597,7 +598,9 @@ public extension ResourceObject {
attributes = try (NoAttributes() as? Description.Attributes) ??
container.decode(Description.Attributes.self, forKey: .attributes)
relationships = try (NoRelationships() as? Description.Relationships) ?? container.decode(Description.Relationships.self, forKey: .relationships)
relationships = try (NoRelationships() as? Description.Relationships)
?? container.decodeIfPresent(Description.Relationships.self, forKey: .relationships)
?? JSONDecoder().decode(Description.Relationships.self, from: "{}".data(using: .utf8)!)
meta = try (NoMetadata() as? MetaType) ?? container.decode(MetaType.self, forKey: .meta)
@@ -403,6 +403,16 @@ extension EntityTests {
data: entity_optional_nullable_nulled_relationship)
}
func test_optionalNullableRelationshipOmitted() {
let entity = decoded(type: TestEntity12.self,
data: entity_all_relationships_optional_and_omitted)
XCTAssertNil(entity ~> \.optionalOne)
XCTAssertNil(entity ~> \.optionalNullableOne)
XCTAssertNil(entity ~> \.optionalMany)
XCTAssertNoThrow(try TestEntity12.check(entity))
}
func test_nullableRelationshipIsNull() {
let entity = decoded(type: TestEntity9.self,
data: entity_nulled_relationship)
@@ -806,6 +816,28 @@ extension EntityTests {
typealias TestEntity11 = BasicEntity<TestEntityType11>
enum TestEntityType12: ResourceObjectDescription {
public static var jsonType: String { return "twelfth_test_entities" }
typealias Attributes = NoAttributes
public struct Relationships: JSONAPI.Relationships {
public init() {
optionalOne = nil
optionalNullableOne = nil
optionalMany = nil
}
let optionalOne: ToOneRelationship<TestEntity1, NoMetadata, NoLinks>?
let optionalNullableOne: ToOneRelationship<TestEntity1?, NoMetadata, NoLinks>?
let optionalMany: ToManyRelationship<TestEntity1, NoMetadata, NoLinks>?
}
}
typealias TestEntity12 = BasicEntity<TestEntityType12>
enum UnidentifiedTestEntityType: ResourceObjectDescription {
public static var jsonType: String { return "unidentified_test_entities" }
@@ -383,6 +383,16 @@ let entity_valid_validated_attribute = """
}
""".data(using: .utf8)!
let entity_all_relationships_optional_and_omitted = """
{
"id": "1",
"type": "twelfth_test_entities",
"attributes": {
"number": 10
}
}
""".data(using: .utf8)!
let entity_unidentified = """
{
"type": "unidentified_test_entities",