From b40ccee3d6ef55c7cb8daee489509a3ae34d0014 Mon Sep 17 00:00:00 2001 From: Royal Min Date: Fri, 7 Mar 2025 21:19:50 +0800 Subject: [PATCH] Update CleanJSONDecoder.swift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 支持含有未定义枚举的数组。 --- Sources/CleanJSON/CleanJSONDecoder.swift | 36 +++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Sources/CleanJSON/CleanJSONDecoder.swift b/Sources/CleanJSON/CleanJSONDecoder.swift index 82fa3da..2a38dcd 100644 --- a/Sources/CleanJSON/CleanJSONDecoder.swift +++ b/Sources/CleanJSON/CleanJSONDecoder.swift @@ -20,7 +20,7 @@ extension Array: JSONContainerConvertible where Element == Any { public func asJSONContainer() -> Any { self } } -open class CleanJSONDecoder: JSONDecoder { +open class CleanJSONDecoder: JSONDecoder, @unchecked Sendable { /// Options set on the top-level encoder to pass down the decoding hierarchy. struct Options { @@ -123,3 +123,37 @@ private extension CleanJSONDecoder { return value } } + +// Add an internal empty type in the CleanJSON framework to skip elements +private struct _CleanJSONSkip: Decodable { } + +// Extend KeyedDecodingContainer to add special decoding for array types +public extension KeyedDecodingContainer { + func decode(_ type: [Element].Type, forKey key: Key) throws -> [Element] { + // If the key does not exist or its value is null, return an empty array (without throwing an error) + guard contains(key), (try? decodeNil(forKey: key)) == false else { + return [] + } + var container = try nestedUnkeyedContainer(forKey: key) + var result: [Element] = [] + // Iterate through the unkeyed container and decode each element + while !container.isAtEnd { + if let element = try? container.decode(Element.self) { + result.append(element) // Successfully decoded, add to the result + } else { + // Decoding failed, skip the current element: + _ = try? container.decode(_CleanJSONSkip.self) + // ↑ Decode into an empty Decodable type to discard the invalid element + } + } + return result + } + + func decodeIfPresent(_ type: [Element].Type, forKey key: Key) throws -> [Element]? { + // If the key does not exist or its value is null, return nil indicating the absence of this array + guard contains(key), (try? decodeNil(forKey: key)) == false else { + return nil + } + return try decode([Element].self, forKey: key) // Call the decode implementation above + } +}