-
-
Notifications
You must be signed in to change notification settings - Fork 21
Add support for sorted keys. #9
base: master
Are you sure you want to change the base?
Conversation
Note that I have not changed the default encoder implementation. This must be explicitly enable by overriding the contentConfig:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes LGTM, thanks! Just some gardening comments, plus:
- test to verify key sorting works (also will help ensure API doesn't break)
@@ -11,6 +11,22 @@ | |||
/// See [Mozilla's](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) docs for more information about | |||
/// url-encoded forms. | |||
public final class URLEncodedFormEncoder: DataEncoder { | |||
/// The formatting of the output data. | |||
public struct OutputFormatting : OptionSet { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSON coder calls it "writing options". We should probably follow suit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we're looking at different things? This code is copied from https://github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/JSONEncoder.swift where it is called:
/// The output format to produce. Defaults to `[]`.
open var outputFormatting: OutputFormatting = []
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small change here:
- OutputFormatting : OptionSet
+ OutputFormatting: OptionSet
static let `default` = URLEncodedFormSerializer() | ||
static let `default` = URLEncodedFormSerializer(sortedKeys: false) | ||
|
||
private var sortedKeys: Bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing comment
|
||
for (key, val) in elements { | ||
let key = try key.urlEncodedFormEncoded() | ||
let subdata = try serialize(val, forKey: key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any way we can reduce code dupe here?
@tanner0101 ok should be good to go! |
@tanner0101 any chance this can ship? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the long delay on this. We should try to get it into 1.1.0 tag for this package. Just needs some small code style changes and it will be good to go.
|
||
/// Serializes the data. | ||
func serialize(_ URLEncodedFormEncoded: [String: URLEncodedFormData]) throws -> Data { | ||
var data: [Data] = [] | ||
for (key, val) in URLEncodedFormEncoded { | ||
var elements: [(key: String, value: URLEncodedFormData)]! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to avoid using an IUO here since the compiler can be sure we set elements
w/ the following if / else.
} | ||
|
||
/// The output format to produce. Defaults to `[]`. | ||
public var outputFormatting: OutputFormatting = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vapor style is to set all properties in the init method. We try to avoid default properties on members since they can be easy to miss when refactoring.
@@ -11,6 +11,22 @@ | |||
/// See [Mozilla's](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) docs for more information about | |||
/// url-encoded forms. | |||
public final class URLEncodedFormEncoder: DataEncoder { | |||
/// The formatting of the output data. | |||
public struct OutputFormatting : OptionSet { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small change here:
- OutputFormatting : OptionSet
+ OutputFormatting: OptionSet
@@ -32,10 +48,21 @@ final class URLEncodedFormSerializer { | |||
|
|||
/// Serializes a `[String: URLEncodedFormData]` at a given key. | |||
private func serialize(_ dictionary: [String: URLEncodedFormData], forKey key: Data) throws -> Data { | |||
let values = try dictionary.map { subKey, value -> Data in | |||
var elements: [(key: String, value: URLEncodedFormData)]! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to remove the IUO here as well.
Swift on macOS and Linux have different dictionary enumeration algorithms that lead to non-deterministic encoding output, which breaks testing.
Mimicking JSONSerialization (see https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/JSONSerialization.swift), we must offer support to sort dictionary keys in order to guarantee output consistency.