diff --git a/.swiftlint.yml b/.swiftlint.yml index 52b3d75..00669a8 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -8,6 +8,7 @@ disabled_rules: - inclusive_language # disabled until we complete work for the "remove offensive terminology" project. - cyclomatic_complexity - opening_brace # conflicts with SwiftFormat wrapMultilineStatementBraces + - nesting opt_in_rules: - array_init diff --git a/Guides/JSON-Interop.md b/Guides/JSON-Interop.md index 6cb927a..bca9740 100644 --- a/Guides/JSON-Interop.md +++ b/Guides/JSON-Interop.md @@ -57,7 +57,7 @@ The `ExtendedJSONEncoder` produces relaxed Extended JSON by default, but can be ```swift let bob = Person(name: "Bob", age: 25) let encoder = ExtendedJSONEncoder() -encoder.mode = .canonical +encoder.format = .canonical let canonicalEncoded = try encoder.encode(bob) // "{\"name\":\"Bob\",\"age\":{\"$numberInt\":\"25\"}}" ``` The `ExtendedJSONDecoder` accepts either format, or a mix of both: diff --git a/Sources/SwiftBSON/BSONDocument.swift b/Sources/SwiftBSON/BSONDocument.swift index ea302e8..f18348c 100644 --- a/Sources/SwiftBSON/BSONDocument.swift +++ b/Sources/SwiftBSON/BSONDocument.swift @@ -135,7 +135,7 @@ public struct BSONDocument { /// On error, an empty string will be returned. public func toCanonicalExtendedJSONString() -> String { let encoder = ExtendedJSONEncoder() - encoder.mode = .canonical + encoder.format = .canonical guard let encoded = try? encoder.encode(self) else { return "" } diff --git a/Sources/SwiftBSON/ExtendedJSONEncoder.swift b/Sources/SwiftBSON/ExtendedJSONEncoder.swift index 0bed5ab..cd970b0 100644 --- a/Sources/SwiftBSON/ExtendedJSONEncoder.swift +++ b/Sources/SwiftBSON/ExtendedJSONEncoder.swift @@ -4,20 +4,31 @@ import NIO /// Facilitates the encoding of `Encodable` values into ExtendedJSON. public class ExtendedJSONEncoder { - /// An enum representing one of the two supported string formats based on the JSON standard - /// that describe how to represent BSON documents in JSON using standard JSON types and/or type wrapper objects. - public enum Mode { + /// A struct representing the supported string formats based on the JSON standard that describe how to represent + /// BSON documents in JSON using standard JSON types and/or type wrapper objects. + public struct Format { /// Canonical Extended JSON Format: Emphasizes type preservation /// at the expense of readability and interoperability. - case canonical + public static let canonical = Format(.canonical) /// Relaxed Extended JSON Format: Emphasizes readability and interoperability /// at the expense of type preservation. - case relaxed + public static let relaxed = Format(.relaxed) + + /// Internal representation of extJSON format. + fileprivate enum _Format { + case canonical, relaxed + } + + fileprivate var _format: _Format + + private init(_ _format: _Format) { + self._format = _format + } } /// Determines whether to encode to canonical or relaxed extended JSON. Default is relaxed. - public var mode: Mode = .relaxed + public var format: Format = .relaxed /// Contextual user-provided information for use during encoding. public var userInfo: [CodingUserInfoKey: Any] = [:] @@ -29,14 +40,14 @@ public class ExtendedJSONEncoder { // T --> BSON --> JSONValue --> Data // Takes in any encodable type `T`, converts it to an instance of the `BSON` enum via the `BSONDecoder`. // The `BSON` is converted to an instance of the `JSON` enum via the `toRelaxedExtendedJSON` - // or `toCanonicalExtendedJSON` methods on `BSONValue`s (depending on the `mode`). + // or `toCanonicalExtendedJSON` methods on `BSONValue`s (depending on the `format`). // The `JSON` is then passed through a `JSONEncoder` and outputted as `Data`. let encoder = BSONEncoder() encoder.userInfo = self.userInfo let bson: BSON = try encoder.encodeFragment(value) let json: JSON - switch self.mode { + switch self.format._format { case .canonical: json = bson.bsonValue.toCanonicalExtendedJSON() case .relaxed: @@ -49,7 +60,8 @@ public class ExtendedJSONEncoder { } /// Encodes an instance of the Encodable Type `T` into Data representing canonical or relaxed extended JSON. - /// The value of `self.mode` will determine which format is used. If it is not set explicitly, relaxed will be used. + /// The value of `self.format` will determine which format is used. If it is not set explicitly, relaxed will + /// be used. /// /// - SeeAlso: https://docs.mongodb.com/manual/reference/mongodb-extended-json/ /// @@ -62,7 +74,7 @@ public class ExtendedJSONEncoder { } /// Encodes an instance of the Encodable Type `T` into a `ByteBuffer` representing canonical or relaxed extended - /// JSON. The value of `self.mode` will determine which format is used. If it is not set explicitly, relaxed will + /// JSON. The value of `self.format` will determine which format is used. If it is not set explicitly, relaxed will /// be used. /// /// - SeeAlso: https://docs.mongodb.com/manual/reference/mongodb-extended-json/ diff --git a/Tests/.swiftlint.yml b/Tests/.swiftlint.yml index ba32760..db61a05 100644 --- a/Tests/.swiftlint.yml +++ b/Tests/.swiftlint.yml @@ -2,7 +2,6 @@ disabled_rules: - force_cast - force_try - force_unwrapping - - nesting - explicit_acl - missing_docs - cyclomatic_complexity diff --git a/Tests/SwiftBSONTests/BSONCorpusTests.swift b/Tests/SwiftBSONTests/BSONCorpusTests.swift index 2b5da46..1167e49 100644 --- a/Tests/SwiftBSONTests/BSONCorpusTests.swift +++ b/Tests/SwiftBSONTests/BSONCorpusTests.swift @@ -166,12 +166,12 @@ final class BSONCorpusTests: BSONTestCase { // native_to_canonical_extended_json( bson_to_native(cB) ) = cEJ let canonicalEncoder = ExtendedJSONEncoder() - canonicalEncoder.mode = .canonical + canonicalEncoder.format = .canonical expect(try canonicalEncoder.encode(docFromCB)) .to(cleanEqual(test.canonicalExtJSON), description: test.description) // native_to_relaxed_extended_json( bson_to_native(cB) ) = rEJ (if rEJ exists) - let relaxedEncoder = ExtendedJSONEncoder() // default mode is .relaxed + let relaxedEncoder = ExtendedJSONEncoder() // default format is .relaxed if let rEJ = test.relaxedExtJSON { expect(try relaxedEncoder.encode(docFromCB)) .to(cleanEqual(rEJ), description: test.description) diff --git a/Tests/SwiftBSONTests/ExtendedJSONConversionTests.swift b/Tests/SwiftBSONTests/ExtendedJSONConversionTests.swift index 0ac7b00..cb1e854 100644 --- a/Tests/SwiftBSONTests/ExtendedJSONConversionTests.swift +++ b/Tests/SwiftBSONTests/ExtendedJSONConversionTests.swift @@ -26,14 +26,14 @@ open class ExtendedJSONConversionTestCase: BSONTestCase { // Test canonical encoder let encoder = ExtendedJSONEncoder() - encoder.mode = .canonical + encoder.format = .canonical let encoded: Data = try encoder.encode(test) expect(encoded).to(cleanEqual(canonicalExtJSON)) let encodedBuffer = try encoder.encodeBuffer(test) expect(Data(encodedBuffer.readableBytesView)).to(cleanEqual(canonicalExtJSON)) // Test relaxed encoder - encoder.mode = .relaxed + encoder.format = .relaxed let relaxedEncoded: Data = try encoder.encode(test) let relaxedExtJSON = "{\"x\":true,\"y\":5,\"z\":\(regexStr)}" expect(relaxedEncoded).to(cleanEqual(relaxedExtJSON))