Click here to expand the reason why it could lead to mistakes
+
+
+To illustrate the possible problems around an `%optionalValue` operation, picture the following scenario:
+
+```swift
+let request: [String:JSEN] = [
+"middle_name": %optionalString
+]
+
+network.put(request)
+```
+
+Now, if the `%` operator detected a nonnull String, great. But if it detected its underlying value to be `.none` (aka `nil`), it would convert the value to `.null`, which, when encoded, would be converted to `NSNull()` (more on this below in the Codable section). As you imagine, `NSNull()` and `nil` have very different behaviors when it comes to RESTful APIs - the former might delete the key information on the database, while the latter will simply be ignored by Swift Dictionary (as if the field wasn't even there).
+
+Hence, if you want to use an optional value, make the call explicit by using either `.null` if you know the value must be encoded into a `NSNull()` instance, or unwrap its value and wrap it around one of the non-null JSEN cases.
+
+
+
+
+### Conformance to Codable
+
+Of course! We couldn't miss this. JSEN has native support to `Encodable & Decodable` (aka `Codable`), so you can easily parse JSEN to/from JSON-like structures.
+
+One additional utility was added as well, which's the `decode(as:)` function. It receives a Decodable-conformant Type as parameter and will attempt to decode the JSEN value into the given type using a two-pass strategy:
+- First, it encodes the JSEN to `Data`, and attempts to decode that `Data` into the given type.
+- If that fails and the JSEN is a `.string(…)` case, it attempts to encode the JSEN's string using `.utf8`. If it is able to encode it, it attempts to decode the resulting `Data` into the given type.
+
+### Subscript Using KeyPath
+
+Last, but not least, comes the `KeyPath` subscript.
+
+Based on [@olebegemann](https://twitter.com/olebegemann)'s [article](https://oleb.net/blog/2017/01/dictionary-key-paths), `KeyPath` is a simple struct used to represent multiple segments of a string. It is initializable by a string literal such as `"this.is.a.keypath"` and, when initialized, the string gets separated by periods, which compounds the struct's segments.
+
+The subscript to JSEN allows the following syntax:
+
+```swift
+let request: [String:JSEN] = [
+ "1st": [
+ "2nd": [
+ "3rd": "Hello!"
+ ]
+ ]
+]
+print(request[keyPath: "1st.2nd.3rd"]) // "Hello!"
+```
+
+Without this syntax, to access a nested value in a dictionary you'd have to create multiple chains of awkward optionals and unwrap them in weird and verbosy ways. I'm not a fan of doing that :)
+
+# Contributions
+
+If you spot something wrong, missing, or if you'd like to propose improvements to this project, please open an Issue or a Pull Request with your ideas and I promise to get back to you within 24 hours! 😇
+
+# References
+
+JSEN was heavily based on [Statically-typed JSON payload in Swift](https://jobandtalent.engineering/statically-typed-json-payload-in-swift-bd193a9e8cf2) and other various implementations of this same utility spread throughout Stack Overflow and Swift Forums. I brought everything I needed together in this project because I couldn't something similar as a Swift Package, that had everything I needed.
+
+# License
+
+This project is open source and covered by a standard 2-clause BSD license. That means you can use (publicly, commercially and privately), modify and distribute this project's content, as long as you mention *Roger Oba* as the original author of this code and reproduce the LICENSE text inside your app, repository, project or research paper.
+
+# Contact
+
+Twitter: [@rogerluan_](https://twitter.com/rogerluan_)
diff --git a/Sources/JSEN+Codable.swift b/Sources/JSEN+Codable.swift
new file mode 100644
index 0000000..033a12f
--- /dev/null
+++ b/Sources/JSEN+Codable.swift
@@ -0,0 +1,76 @@
+// Copyright © 2021 Roger Oba. All rights reserved.
+
+import Foundation
+
+extension JSEN : Encodable {
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.singleValueContainer()
+ switch self {
+ case .int(let int): try container.encode(int)
+ case .double(let double): try container.encode(double)
+ case .string(let string): try container.encode(string)
+ case .bool(let bool): try container.encode(bool)
+ case .array(let array): try container.encode(array)
+ case .dictionary(let dictionary): try container.encode(dictionary)
+ case .null: try container.encodeNil()
+ }
+ }
+}
+
+extension JSEN : Decodable {
+ public init(from decoder: Decoder) throws {
+ let container = try decoder.singleValueContainer()
+ if let value = try? container.decode(Int.self) {
+ self = .int(value)
+ } else if let value = try? container.decode(Double.self) {
+ self = .double(value)
+ } else if let value = try? container.decode(String.self) {
+ self = .string(value)
+ } else if let value = try? container.decode(Bool.self) {
+ self = .bool(value)
+ } else if let value = try? container.decode([JSEN].self) {
+ self = .array(value)
+ } else if let value = try? container.decode([String:JSEN].self) {
+ self = .dictionary(value)
+ } else if container.decodeNil() {
+ self = .null
+ } else {
+ throw NSError(domain: "domain.codable.jsen", code: 1, userInfo: [ "message" : "Failed to decode JSEN into any known type." ])
+ }
+ }
+
+ /// Decodes **self** into the given type, if possible.
+ ///
+ /// This method will attempt to decode to the given type by first encoding **self** to Data, and then attempting to decode that Data.
+ /// If this step fails, it will attempt to encode **self** using utf8 if **self** is a `.string` case. If it succeeds, it will attempt to
+ /// decode into the given type using the resulting Data.
+ ///
+ /// - Parameters:
+ /// - type: the Decodable type to decode **self** into.
+ /// - dumpingErrorOnFailure: whether the function should dump the error on the console, upon failure. Set true for debugging purposes. Defaults to false.
+ /// - Returns: An instance of the given type, or nil if the decoding wasn't possible.
+ public func decode