diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..ba72e725
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,20 @@
+name: CI
+
+on:
+ push:
+ branches: [ main, master ]
+ pull_request:
+ branches: [ main, master ]
+
+jobs:
+ build-and-test:
+ runs-on: macos-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Build
+ run: xcrun swift build --build-tests
+
+ - name: Run tests
+ run: xcrun swift test
\ No newline at end of file
diff --git a/.swiftlint.yml b/.swiftlint.yml
index 03003d1d..36ee05ac 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -1,7 +1,7 @@
disabled_rules:
- force_cast
- force_try
- - variable_name
+ - identifier_name
- type_name
- file_length
- line_length
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 17140ab1..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-language: objective-c
-osx_image: xcode10.2
-xcode_sdk: iphonesimulator12.0
-script:
-- set -o pipefail
-- travis_retry xcodebuild -workspace SwiftyJSON.xcworkspace -scheme "SwiftyJSON iOS" -destination "platform=iOS Simulator,name=iPhone 6" build-for-testing test | xcpretty
-- travis_retry xcodebuild -workspace SwiftyJSON.xcworkspace -scheme "SwiftyJSON macOS" build-for-testing test | xcpretty
-- travis_retry xcodebuild -workspace SwiftyJSON.xcworkspace -scheme "SwiftyJSON tvOS" -destination "platform=tvOS Simulator,name=Apple TV" build-for-testing test | xcpretty
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6a0935d3..082b0247 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,15 @@
[Full Changelog](https://github.com/SwiftyJSON/SwiftyJSON/compare/2.2.0...HEAD)
+### Added
+- Swift 6 support with full Sendable conformance ([#1163](https://github.com/SwiftyJSON/SwiftyJSON/issues/1163))
+- Comprehensive concurrency tests for actor boundary validation
+
+### Changed
+- `JSON` struct conforms to `@unchecked Sendable`
+- `Type`, `SwiftyJSONError`, `JSONKey` enums conform to `Sendable`
+- Minimum Swift tools version updated to 6.0
+
**Closed issues:**
- 156 compiler errors Mavericks + Xcode 6.2 [\#220](https://github.com/SwiftyJSON/SwiftyJSON/issues/220)
diff --git a/Package.swift b/Package.swift
index 744e95dd..fb026e55 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:5.0
+// swift-tools-version:6.0
import PackageDescription
let package = Package(
@@ -7,8 +7,18 @@ let package = Package(
.library(name: "SwiftyJSON", targets: ["SwiftyJSON"])
],
targets: [
- .target(name: "SwiftyJSON", dependencies: []),
- .testTarget(name: "SwiftJSONTests", dependencies: ["SwiftyJSON"])
- ],
- swiftLanguageVersions: [.v5]
+ .target(name: "SwiftyJSON",
+ dependencies: [],
+ resources: [
+ .copy("PrivacyInfo.xcprivacy")
+ ]
+ ),
+ .testTarget(
+ name: "SwiftJSONTests",
+ dependencies: ["SwiftyJSON"],
+ resources: [
+ .copy("Tests.json")
+ ]
+ )
+ ]
)
diff --git a/README.md b/README.md
index a4cd321f..a6f3037a 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,11 @@
# SwiftyJSON
+[](https://github.com/SwiftyJSON/SwiftyJSON/actions/workflows/ci.yml)
+
[](https://github.com/Carthage/Carthage)   [](https://houndci.com)
SwiftyJSON makes it easy to deal with JSON data in Swift.
-Platform | Build Status
----------| --------------|
-*OS | [](https://travis-ci.org/SwiftyJSON/SwiftyJSON) |
-[Linux](https://github.com/IBM-Swift/SwiftyJSON) | [](https://travis-ci.org/IBM-Swift/SwiftyJSON) |
-
-
1. [Why is the typical JSON handling in Swift NOT good](#why-is-the-typical-json-handling-in-swift-not-good)
2. [Requirements](#requirements)
3. [Integration](#integration)
@@ -24,6 +20,7 @@ Platform | Build Status
- [Raw object](#raw-object)
- [Literal convertibles](#literal-convertibles)
- [Merging](#merging)
+ - [Removing elements](#removing-elements)
5. [Work with Alamofire](#work-with-alamofire)
6. [Work with Moya](#work-with-moya)
7. [SwiftyJSON Model Generator](#swiftyjson-model-generator)
@@ -61,7 +58,7 @@ An unreadable mess--for something that should really be simple!
With SwiftyJSON all you have to do is:
```swift
-let json = JSON(data: dataFromNetworking)
+let json = try? JSON(data: dataFromNetworking)
if let userName = json[0]["user"]["name"].string {
//Now you got your value
}
@@ -70,7 +67,7 @@ if let userName = json[0]["user"]["name"].string {
And don't worry about the Optional Wrapping thing. It's done for you automatically.
```swift
-let json = JSON(data: dataFromNetworking)
+let json = try? JSON(data: dataFromNetworking)
let result = json[999999]["wrong_key"]["wrong_name"]
if let userName = result.string {
//Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety
@@ -83,7 +80,8 @@ if let userName = result.string {
## Requirements
- iOS 8.0+ | macOS 10.10+ | tvOS 9.0+ | watchOS 2.0+
-- Xcode 8
+- Xcode 16+
+- Swift 6.0+
## Integration
@@ -143,7 +141,7 @@ import SwiftyJSON
```
```swift
-let json = JSON(data: dataFromNetworking)
+let json = try? JSON(data: dataFromNetworking)
```
Or
@@ -503,6 +501,69 @@ let updated = original.merge(with: update)
// ]
```
+
+#### Removing elements
+
+If you are storing dictionaries, you can remove elements using `dictionaryObject.removeValue(forKey:)`. This mutates the JSON object in place.
+
+For example:
+
+```swift
+var object = JSON([
+ "one": ["color": "blue"],
+ "two": ["city": "tokyo",
+ "country": "japan",
+ "foods": [
+ "breakfast": "tea",
+ "lunch": "sushi"
+ ]
+ ]
+])
+```
+
+Lets remove the `country` key:
+
+```swift
+object["two"].dictionaryObject?.removeValue(forKey: "country")
+```
+
+If you `print(object)`, you'll see that the `country` key no longer exists.
+
+```json
+{
+ "one" : {
+ "color" : "blue"
+ },
+ "two" : {
+ "city" : "tokyo",
+ "foods" : {
+ "breakfast" : "tea",
+ "lunch" : "sushi"
+ }
+ }
+}
+```
+
+This also works for nested dictionaries:
+
+```swift
+object["two"]["foods"].dictionaryObject?.removeValue(forKey: "breakfast")
+```
+
+```json
+{
+ "one" : {
+ "color" : "blue"
+ },
+ "two" : {
+ "city" : "tokyo",
+ "foods" : {
+ "lunch" : "sushi"
+ }
+ }
+}
+```
+
## String representation
There are two options available:
- use the default Swift one
@@ -556,5 +617,4 @@ provider.request(.showProducts) { result in
## SwiftyJSON Model Generator
Tools to generate SwiftyJSON Models
-* [JSON Cafe](http://www.jsoncafe.com/)
* [JSON Export](https://github.com/Ahmed-Ali/JSONExport)
diff --git a/Source/SwiftyJSON/PrivacyInfo.xcprivacy b/Source/SwiftyJSON/PrivacyInfo.xcprivacy
new file mode 100644
index 00000000..d37d6275
--- /dev/null
+++ b/Source/SwiftyJSON/PrivacyInfo.xcprivacy
@@ -0,0 +1,14 @@
+
+
+
+
+ NSPrivacyCollectedDataTypes
+
+ NSPrivacyAccessedAPITypes
+
+ NSPrivacyTrackingDomains
+
+ NSPrivacyTracking
+
+
+
diff --git a/Source/SwiftyJSON/SwiftyJSON.swift b/Source/SwiftyJSON/SwiftyJSON.swift
index e625810e..d2f39ef2 100644
--- a/Source/SwiftyJSON/SwiftyJSON.swift
+++ b/Source/SwiftyJSON/SwiftyJSON.swift
@@ -24,7 +24,7 @@ import Foundation
// MARK: - Error
// swiftlint:disable line_length
-public enum SwiftyJSONError: Int, Swift.Error {
+public enum SwiftyJSONError: Int, Swift.Error, Sendable {
case unsupportedType = 999
case indexOutOfBounds = 900
case elementTooDeep = 902
@@ -67,7 +67,7 @@ JSON's type definitions.
See http://www.json.org
*/
-public enum Type: Int {
+public enum Type: Int, Sendable {
case number
case string
case bool
@@ -79,7 +79,7 @@ public enum Type: Int {
// MARK: - JSON Base
-public struct JSON {
+public struct JSON: @unchecked Sendable {
/**
Creates a JSON using the data.
@@ -265,11 +265,7 @@ private func unwrap(_ object: Any) -> Any {
case let array as [Any]:
return array.map(unwrap)
case let dictionary as [String: Any]:
- var d = dictionary
- dictionary.forEach { pair in
- d[pair.key] = unwrap(pair.value)
- }
- return d
+ return dictionary.mapValues(unwrap)
default:
return object
}
@@ -343,7 +339,7 @@ extension JSON: Swift.Collection {
/**
* To mark both String and Int can be used in subscript.
*/
-public enum JSONKey {
+public enum JSONKey: Sendable {
case index(Int)
case key(String)
}
@@ -433,7 +429,7 @@ extension JSON {
Example:
- ```
+ ```swift
let json = JSON[data]
let path = [9,"list","person","name"]
let name = json[path]
@@ -467,10 +463,14 @@ extension JSON {
Find a json in the complex data structures by using array of Int and/or String as path.
- parameter path: The target json's path. Example:
-
+ ```swift
let name = json[9,"list","person","name"]
-
- The same as: let name = json[9]["list"]["person"]["name"]
+ ```
+
+ The same as:
+ ```swift
+ let name = json[9]["list"]["person"]["name"]
+ ```
- returns: Return a json found by the path or a null json with error
*/
@@ -524,7 +524,7 @@ extension JSON: Swift.ExpressibleByFloatLiteral {
extension JSON: Swift.ExpressibleByDictionaryLiteral {
public init(dictionaryLiteral elements: (String, Any)...) {
- let dictionary = elements.reduce(into: [String: Any](), { $0[$1.0] = $1.1})
+ let dictionary = Dictionary(elements, uniquingKeysWith: { $1 })
self.init(dictionary)
}
}
@@ -676,7 +676,7 @@ extension JSON {
//Optional [JSON]
public var array: [JSON]? {
- return type == .array ? rawArray.map { JSON($0) } : nil
+ return type == .array ? rawArray.map(JSON.init(_:)) : nil
}
//Non-optional [JSON]
@@ -705,11 +705,7 @@ extension JSON {
//Optional [String : JSON]
public var dictionary: [String: JSON]? {
if type == .dictionary {
- var d = [String: JSON](minimumCapacity: rawDictionary.count)
- rawDictionary.forEach { pair in
- d[pair.key] = JSON(pair.value)
- }
- return d
+ return rawDictionary.mapValues(JSON.init(_:))
} else {
return nil
}
@@ -791,7 +787,7 @@ extension JSON {
switch type {
case .string: return object as? String ?? ""
case .number: return rawNumber.stringValue
- case .bool: return (object as? Bool).map { String($0) } ?? ""
+ case .bool: return (object as? Bool).map(String.init) ?? ""
default: return ""
}
}
diff --git a/SwiftyJSON.podspec b/SwiftyJSON.podspec
index 944a24b7..dd091231 100644
--- a/SwiftyJSON.podspec
+++ b/SwiftyJSON.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "SwiftyJSON"
- s.version = "5.0.1"
+ s.version = "5.0.2"
s.summary = "SwiftyJSON makes it easy to deal with JSON data in Swift"
s.homepage = "https://github.com/SwiftyJSON/SwiftyJSON"
s.license = { :type => "MIT" }
@@ -14,4 +14,5 @@ Pod::Spec.new do |s|
s.tvos.deployment_target = "9.0"
s.source = { :git => "https://github.com/SwiftyJSON/SwiftyJSON.git", :tag => s.version }
s.source_files = "Source/SwiftyJSON/*.swift"
+ s.resource_bundles = {'SwiftyJSON' => ['Source/SwiftyJSON/PrivacyInfo.xcprivacy']}
end
diff --git a/SwiftyJSON.xcodeproj/project.pbxproj b/SwiftyJSON.xcodeproj/project.pbxproj
index 3f48deaa..3c325ac2 100644
--- a/SwiftyJSON.xcodeproj/project.pbxproj
+++ b/SwiftyJSON.xcodeproj/project.pbxproj
@@ -51,6 +51,10 @@
9C459F041A9103C1008C9A41 /* DictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8B66C8B19E51D6500540692 /* DictionaryTests.swift */; };
9C459F051A9103C1008C9A41 /* ArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8B66C8D19E52F4200540692 /* ArrayTests.swift */; };
9C7DFC661A9102BD005AA3F7 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C7DFC5B1A9102BD005AA3F7 /* SwiftyJSON.framework */; };
+ A1DE64C62BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */; };
+ A1DE64C72BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */; };
+ A1DE64C82BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */; };
+ A1DE64C92BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */; };
A819C49719E1A7DD00ADCC3D /* LiteralConvertibleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49619E1A7DD00ADCC3D /* LiteralConvertibleTests.swift */; };
A819C49919E1B10300ADCC3D /* RawRepresentableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49819E1B10300ADCC3D /* RawRepresentableTests.swift */; };
A819C49F19E2EE5B00ADCC3D /* SubscriptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49E19E2EE5B00ADCC3D /* SubscriptTests.swift */; };
@@ -126,6 +130,7 @@
9C459EF61A9103B1008C9A41 /* Info-macOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Info-macOS.plist"; path = "../Info-macOS.plist"; sourceTree = ""; };
9C7DFC5B1A9102BD005AA3F7 /* SwiftyJSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9C7DFC651A9102BD005AA3F7 /* SwiftyJSON macOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SwiftyJSON macOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+ A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = SwiftyJSON/PrivacyInfo.xcprivacy; sourceTree = ""; };
A819C49619E1A7DD00ADCC3D /* LiteralConvertibleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LiteralConvertibleTests.swift; path = ../SwiftJSONTests/LiteralConvertibleTests.swift; sourceTree = ""; };
A819C49819E1B10300ADCC3D /* RawRepresentableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RawRepresentableTests.swift; path = ../SwiftJSONTests/RawRepresentableTests.swift; sourceTree = ""; };
A819C49E19E2EE5B00ADCC3D /* SubscriptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SubscriptTests.swift; path = ../SwiftJSONTests/SubscriptTests.swift; sourceTree = ""; };
@@ -241,6 +246,7 @@
2E4FEFDE19575BE100351305 /* Supporting Files */ = {
isa = PBXGroup;
children = (
+ A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */,
2E4FEFDF19575BE100351305 /* Info-iOS.plist */,
030B6CDC1A6E171D00C2D4F1 /* Info-macOS.plist */,
E4D7CCE91B9465A800EE7221 /* Info-watchOS.plist */,
@@ -272,7 +278,7 @@
2E4FEFEB19575BE100351305 /* Supporting Files */,
);
name = Tests;
- path = Tests/Tes;
+ path = Tests/SwiftJSONTests;
sourceTree = "";
};
2E4FEFEB19575BE100351305 /* Supporting Files */ = {
@@ -527,6 +533,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ A1DE64C62BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -542,6 +549,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ A1DE64C92BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -549,6 +557,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ A1DE64C72BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -572,6 +581,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ A1DE64C82BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Tests/SwiftJSONTests/BaseTests.swift b/Tests/SwiftJSONTests/BaseTests.swift
index 9139c204..8bbebcde 100644
--- a/Tests/SwiftJSONTests/BaseTests.swift
+++ b/Tests/SwiftJSONTests/BaseTests.swift
@@ -31,10 +31,13 @@ class BaseTests: XCTestCase {
super.setUp()
-// let file = "./Tests/Tes/Tests.json"
-// self.testData = try? Data(contentsOf: URL(fileURLWithPath: file))
- if let file = Bundle(for: BaseTests.self).path(forResource: "Tests", ofType: "json") {
- self.testData = try? Data(contentsOf: URL(fileURLWithPath: file))
+ #if SWIFT_PACKAGE
+ let testBundle = Bundle.module
+ #else
+ let testBundle = Bundle(for: BaseTests.self)
+ #endif
+ if let file = testBundle.url(forResource: "Tests", withExtension: "json") {
+ self.testData = try? Data(contentsOf: file)
} else {
XCTFail("Can't find the test JSON file")
}
diff --git a/Tests/SwiftJSONTests/ConcurrencyTests.swift b/Tests/SwiftJSONTests/ConcurrencyTests.swift
new file mode 100644
index 00000000..a6eaa099
--- /dev/null
+++ b/Tests/SwiftJSONTests/ConcurrencyTests.swift
@@ -0,0 +1,89 @@
+// ConcurrencyTests.swift
+//
+// Copyright (c) 2014 - 2017 Ruoyu Fu, Pinglin Tang
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import XCTest
+import SwiftyJSON
+
+/// Tests verifying Sendable conformance for Swift 6 concurrency.
+/// Each test targets a specific type made Sendable in this PR.
+class ConcurrencyTests: XCTestCase {
+
+ actor Processor {
+ func extract(_ json: JSON) -> String {
+ json["name"].stringValue
+ }
+
+ func extractType(_ json: JSON) -> Type {
+ json["value"].type
+ }
+
+ func requireField(_ json: JSON) throws -> String {
+ guard json["required"].exists() else {
+ throw SwiftyJSONError.notExist
+ }
+ return json["required"].stringValue
+ }
+ }
+
+ /// Verifies JSON conforms to Sendable (can cross actor boundary)
+ func testJSONSendable() async {
+ let json = JSON(["name": "test", "count": 42])
+ let processor = Processor()
+
+ let result = await processor.extract(json)
+
+ XCTAssertEqual(result, "test")
+ }
+
+ /// Verifies Type enum conforms to Sendable (can be returned across actor boundary)
+ func testTypeSendable() async {
+ let processor = Processor()
+
+ let stringType = await processor.extractType(JSON(["value": "hello"]))
+ let numberType = await processor.extractType(JSON(["value": 123]))
+ let boolType = await processor.extractType(JSON(["value": true]))
+ let nullType = await processor.extractType(JSON(["value": NSNull()]))
+ let arrayType = await processor.extractType(JSON(["value": [1, 2, 3]]))
+ let dictType = await processor.extractType(JSON(["value": ["nested": "object"]]))
+
+ XCTAssertEqual(stringType, .string)
+ XCTAssertEqual(numberType, .number)
+ XCTAssertEqual(boolType, .bool)
+ XCTAssertEqual(nullType, .null)
+ XCTAssertEqual(arrayType, .array)
+ XCTAssertEqual(dictType, .dictionary)
+ }
+
+ /// Verifies SwiftyJSONError conforms to Sendable (can be thrown across actor boundary)
+ func testSwiftyJSONErrorSendable() async {
+ let processor = Processor()
+
+ do {
+ _ = try await processor.requireField(JSON(["other": "value"]))
+ XCTFail("Should have thrown")
+ } catch SwiftyJSONError.notExist {
+ // Error successfully crossed actor boundary
+ } catch {
+ XCTFail("Unexpected error: \(error)")
+ }
+ }
+}
diff --git a/Tests/SwiftJSONTests/PerformanceTests.swift b/Tests/SwiftJSONTests/PerformanceTests.swift
index 7535f7d8..c0e6cc0b 100644
--- a/Tests/SwiftJSONTests/PerformanceTests.swift
+++ b/Tests/SwiftJSONTests/PerformanceTests.swift
@@ -30,8 +30,13 @@ class PerformanceTests: XCTestCase {
override func setUp() {
super.setUp()
- if let file = Bundle(for: PerformanceTests.self).path(forResource: "Tests", ofType: "json") {
- self.testData = try? Data(contentsOf: URL(fileURLWithPath: file))
+ #if SWIFT_PACKAGE
+ let testBundle = Bundle.module
+ #else
+ let testBundle = Bundle(for: PerformanceTests.self)
+ #endif
+ if let file = testBundle.url(forResource: "Tests", withExtension: "json") {
+ self.testData = try? Data(contentsOf: file)
} else {
XCTFail("Can't find the test JSON file")
}
diff --git a/Tests/SwiftJSONTests/SequenceTypeTests.swift b/Tests/SwiftJSONTests/SequenceTypeTests.swift
index d0d8cadd..a039453f 100644
--- a/Tests/SwiftJSONTests/SequenceTypeTests.swift
+++ b/Tests/SwiftJSONTests/SequenceTypeTests.swift
@@ -25,10 +25,17 @@ import SwiftyJSON
class SequenceTypeTests: XCTestCase {
+ var testData: Data?
+
func testJSONFile() {
- if let file = Bundle(for: BaseTests.self).path(forResource: "Tests", ofType: "json") {
- let testData = try? Data(contentsOf: URL(fileURLWithPath: file))
- guard let json = try? JSON(data: testData!) else {
+ #if SWIFT_PACKAGE
+ let testBundle = Bundle.module
+ #else
+ let testBundle = Bundle(for: SequenceTypeTests.self)
+ #endif
+ if let file = testBundle.url(forResource: "Tests", withExtension: "json") {
+ self.testData = try? Data(contentsOf: file)
+ guard let json = try? JSON(data: self.testData!) else {
XCTFail("Unable to parse the data")
return
}
diff --git a/Tests/Tes/Tests.json b/Tests/SwiftJSONTests/Tests.json
similarity index 100%
rename from Tests/Tes/Tests.json
rename to Tests/SwiftJSONTests/Tests.json