Skip to content

Commit

Permalink
Merge pull request #116 from mattpolzin/fix-optional-meta-omit-decode
Browse files Browse the repository at this point in the history
Allow optional metadata to be omitted as well as nulled out.
  • Loading branch information
mattpolzin authored Apr 30, 2024
2 parents 3856a88 + 6f8e133 commit 58ebdc9
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 12 deletions.
4 changes: 4 additions & 0 deletions Sources/JSONAPI/Document/DocumentDecodingError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public enum DocumentDecodingError: Swift.Error, Equatable {
self = .primaryResourceMissing
case .valueNotFound(let type, let context) where Location(context) == .data && type == UnkeyedDecodingContainer.self:
self = .primaryResourcesMissing
case .valueNotFound(let type, let context) where Location(context) == .data && type is _ArrayType.Type && context.debugDescription.hasSuffix("found null value instead"):
self = .primaryResourcesMissing
case .valueNotFound(_, let context) where Location(context) == .data && context.debugDescription.hasSuffix("found null value instead"):
self = .primaryResourceMissing
case .typeMismatch(let type, let context) where Location(context) == .data && type is _ArrayType.Type && context.debugDescription.hasSuffix("but found null instead."):
self = .primaryResourcesMissing
case .typeMismatch(_, let context) where Location(context) == .data && context.debugDescription.hasSuffix("but found null instead."):
Expand Down
3 changes: 0 additions & 3 deletions Sources/JSONAPI/Resource/Relationship.swift
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,6 @@ extension MetaRelationship: Codable {
}
}

fileprivate protocol _Optional {}
extension Optional: _Optional {}

extension ToOneRelationship: Codable where Identifiable.ID: OptionalId {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ResourceLinkageCodingKeys.self)
Expand Down
12 changes: 11 additions & 1 deletion Sources/JSONAPI/Resource/Resource Object/ResourceObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,17 @@ public extension ResourceObject {
)
}

meta = try (NoMetadata() as? MetaType) ?? container.decode(MetaType.self, forKey: .meta)
do {
meta = try (NoMetadata() as? MetaType) ?? container.decode(MetaType.self, forKey: .meta)
} catch let decodingError as DecodingError {
let anyNil: Any? = nil

guard case .keyNotFound = decodingError,
let omittedMeta = anyNil as? MetaType else {
throw decodingError
}
meta = omittedMeta
}

links = try (NoLinks() as? LinksType) ?? container.decode(LinksType.self, forKey: .links)
}
Expand Down
22 changes: 20 additions & 2 deletions Tests/JSONAPITests/ResourceObject/ResourceObjectTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ extension ResourceObjectTests {
data: entity_no_relationships_no_attributes)
}

func test_EntityNoMetaDecodesAsOptionalMeta() {
let _ = decoded(type: TestEntityOptionalMeta.self,
data: entity_no_relationships_no_attributes)
}

func test_EntityNoRelationshipsSomeAttributes() {
let entity = decoded(type: TestEntity5.self,
data: entity_no_relationships_some_attributes)
Expand Down Expand Up @@ -861,13 +866,13 @@ extension ResourceObjectTests {

public struct Relationships: JSONAPI.Relationships {
public init() {
optionalMeta = nil
optionalMeta = nil
optionalOne = nil
optionalNullableOne = nil
optionalMany = nil
}

let optionalMeta: MetaRelationship<TestEntityMeta, NoLinks>?
let optionalMeta: MetaRelationship<TestEntityMeta, NoLinks>?

let optionalOne: ToOneRelationship<TestEntity1, NoIdMetadata, NoMetadata, NoLinks>?

Expand All @@ -879,6 +884,19 @@ extension ResourceObjectTests {

typealias TestEntity12 = BasicEntity<TestEntityType12>

enum TestEntityOptionalMetaType: JSONAPI.ResourceObjectDescription {
public static var jsonType: String { return "test_entities" }

typealias Attributes = NoAttributes
typealias Relationships = NoRelationships
}

struct UnimportantMeta: JSONAPI.Meta {
let property1: String
}

typealias TestEntityOptionalMeta = JSONAPI.ResourceObject<TestEntityOptionalMetaType, UnimportantMeta?, NoLinks, String>

enum UnidentifiedTestEntityType: ResourceObjectDescription {
public static var jsonType: String { return "unidentified_test_entities" }

Expand Down
8 changes: 2 additions & 6 deletions Tests/JSONAPITests/SparseFields/SparseFieldEncoderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,9 @@ class SparseFieldEncoderTests: XCTestCase {
XCTAssertEqual(allThingsOnDeserialized["bool"] as? Bool, true)
XCTAssertEqual(allThingsOnDeserialized["double"] as? Double, 10.5)
XCTAssertEqual(allThingsOnDeserialized["string"] as? String, "hello")
#if os(Linux)
// There's some bug with Linux where it won't case the value to a float.
// It does exist and it is == 1.2
// For latest versions of MacOS and all versions of Linux, floats
// decode as doubles.
XCTAssertEqual(allThingsOnDeserialized["float"] as? Double, 1.2)
#else
XCTAssertEqual(allThingsOnDeserialized["float"] as? Float, 1.2)
#endif
XCTAssertEqual(allThingsOnDeserialized["int"] as? Int, 3)
XCTAssertEqual(allThingsOnDeserialized["int8"] as? Int8, 4)
XCTAssertEqual(allThingsOnDeserialized["int16"] as? Int16, 5)
Expand Down

0 comments on commit 58ebdc9

Please sign in to comment.