URL query encoder with OpenAPI serialization options support

Overview

URLQueryEncoder

A customizable Swift Encoder that encodes instances of data types as URL query items. Supports all OpenAPI serialization options.

Examples

Encoding Primitives

let encoder = URLQueryEncoder()
encoder.encode(id, forKey: "id")

print(encoder.queryItems)
// [URLQueryItem(name: "id", value: "5")]

By default, optional values are not encoded.

var id: Int?
let encoder = URLQueryEncoder()
encoder.encode(id, forKey: "id")

print(encoder.queryItems)
// []

Encoding Arrays

let ids = [3, 4, 5]
let encoder = URLQueryEncoder()
encoder.encode(ids, forKey: "id")

// Query: "id=3&id=4&id=5"

With an explode option disabled:

let ids = [3, 4, 5]
let encoder = URLQueryEncoder()
encoder.encode(ids, forKey: "id", explode: false)

// Query: "id=3,4,5"

With an explode option disabled and a custom delimiter:

let ids = [3, 4, 5]
let encoder = URLQueryEncoder()
encoder.encode(ids, forKey: "id", explode: false, delimeter: "|")

// Query: "id=3|4|5"

Encoding Objects

let user = User(role: "admin", name: "kean")

let encoder = URLQueryEncoder()
encoder.encode(user, forKey: "id")

// Query: "role=admin&name=kean"

With an explode option disabled:

let user = User(role: "admin", name: "kean")

let encoder = URLQueryEncoder()
encoder.encode(user, forKey: "id", explode: false)

// Query: "id=role,admin,name,kean"

As a "deep" object:

let user = User(role: "admin", name: "kean")

let encoder = URLQueryEncoder()
encoder.encode(user, forKey: "id", isDeepObject: true)

// Query: "id[role]=admin&id[name]=kean")"

If you are encoding a request body using URL-form encoding, you can use a convenience URLQueryEncoder.encode(_:) method.

Encoding Options

There are two ways to change the encoding options. You can set them directly on URLQueryEncoder instance.

let encoder = URLQueryEncoder()
encoder.explode = false
encoder.isDeepObject = true
encoder.delimiter = "|"
encoder.dateEncodingStrategy = .millisecondsSince1970

Or pass options in each individual encode call.

let user = User(role: "admin", name: "kean")
let ids = [3, 4, 5]

let encoder = URLQueryEncoder()
encoder.encode(ids, forKey: "ids", explode: false)
encoder.encode(ids, forKey: "ids2", explode: true)
encoder.encode(user, forKey: "user", isDeepObject: true)
encoder.encode(2, forKey: "id")

// Query: "ids=3,4,5&ids2=3&ids2=4&ids2=5&user[role]=admin&user[name]=kean&id=2"

The reason it's designed this way is that in OpenAPI each parameter can come with different serialization options.

Accessing Results

You can access the encoding results at any time, and they come in different forms:

public final class URLQueryEncoder {
    // Encoded query items.
    public var queryItems: [URLQueryItem]
    // Encoded query items as name-value pairs.
    public var items: [(String, String?)]
    // The encoded query items as a URL query subcomponent.
    public var query: String?
    // The encoded query items as a URL query subcomponent with percent-encoded values.
    public var percentEncodedQuery: String?
}

License

URLQueryEncoder is available under the MIT license. See the LICENSE file for more info.

You might also like...
Delightful code generation for OpenAPI specs for Swift written in Swift
Delightful code generation for OpenAPI specs for Swift written in Swift

Create API Delightful code generation for OpenAPI specs for Swift written in Swi

OpenAPI specification generator for Vapor based Swift projects.

VaporToOpenAPI VaporToOpenAPI is a Swift library which can generate output compatible with OpenAPI version 3.0.1 from Vapor code. You can use generate

A Collection of PropertyWrappers to make custom Serialization of Swift Codable Types easy

CodableWrappers Simplified Serialization with Property Wrappers Move your Codable and (En/De)coder customization to annotations! struct YourType: Coda

This project brings FlatBuffers (an efficient cross platform serialization library) to Swift.

FlatBuffersSwift Motivation This project brings FlatBuffers (an efficient cross platform serialization library) to Swift. One minute introduction Ther

Cereal is a serialization framework built for Swift

Cereal is a serialization framework built for Swift. Its intended as a substitution for NSCoding to allow advanced Swift features. With NSCoding, you cannot encode or decode a Swift struct, enum, or generic class. Cereal solves this issue through deferred decoding with generics, and a protocol that doesn't depend on NSObjectProtocol.

JSONNeverDie - Auto reflection tool from JSON to Model, user friendly JSON encoder / decoder, aims to never die
JSONNeverDie - Auto reflection tool from JSON to Model, user friendly JSON encoder / decoder, aims to never die

JSONNeverDie is an auto reflection tool from JSON to Model, a user friendly JSON encoder / decoder, aims to never die. Also JSONNeverDie is a very important part of Pitaya.

PMJSON provides a pure-Swift strongly-typed JSON encoder/decoder

Now Archived and Forked PMJSON will not be maintained in this repository going forward. Please use, create issues on, and make PRs to the fork of PMJS

A Swift Encoder for encoding any Encodable value into an array of URLQueryItem.

URLQueryItemEncoder A Swift Encoder for encoding any Encodable value into an array of URLQueryItem. As part of the SE-0166, Swift has a foundation for

Rudimentary implementation of a uncompressed PNG encoder in Swift without any dependencies

MicroPNG This package currently offers a very minimal PNG encoder for uncompressed RGB and RGBA PNG files. It does not rely on any frameworks and shou

Auto reflection tool from JSON to Model, user friendly JSON encoder / decoder, aims to never die
Auto reflection tool from JSON to Model, user friendly JSON encoder / decoder, aims to never die

JSONNeverDie is an auto reflection tool from JSON to Model, a user friendly JSON encoder / decoder, aims to never die. Also JSONNeverDie is a very imp

iCalSwift - iCalendar(RFC 5545) encoder and decoder for Swift

iCalSwift - iCalendar(RFC 5545) encoder and decoder for Swift

QueryKit, a simple type-safe Core Data query language.
QueryKit, a simple type-safe Core Data query language.

QueryKit QueryKit, a simple type-safe Core Data query language. Usage QuerySetPerson(context, "Person")

Reel Search is a Swift UI controller that allows you to choose options from a list
Reel Search is a Swift UI controller that allows you to choose options from a list

REEL SEARCH Reel Search is a Swift UI controller that allows you to choose options from a list We specialize in the designing and coding of custom UI

A Swift library to design custom prompts with a great scope of options to choose from.
A Swift library to design custom prompts with a great scope of options to choose from.

Installation CocoaPods Install with CocoaPods by adding the following to your Podfile: source 'https://github.com/CocoaPods/Specs.git' platform :ios,

๐Ÿ—ƒ Powerful and easy to use Swift Query Builder for Vapor 3.
๐Ÿ—ƒ Powerful and easy to use Swift Query Builder for Vapor 3.

โš ๏ธ This lib is DEPRECATED โš ๏ธ please use SwifQL with Bridges Quick Intro struct PublicUser: Codable { var name: String var petName: String

A SARS-CoV-2 Mutation Pattern Query Tool

vdb A SARS-CoV-2 Mutation Pattern Query Tool 1. Purpose The vdb program is designed to query the SARS-CoV-2 mutational landscape. It runs as a command

Swift implementation of JMESPath, a query language for JSON.

Swift implementation of JMESPath, the JSON query language

Query and print phone information from SimpleMDM

PhoneCat Query and print phone information from SimpleMDM. Currently only supports printing in CSV format. Usage Compile PhoneCat and print usage: swi

Provides a custom presentation modifier that provides more options including full screen presentations. (iOS)

Presentation Also available as a part of my SwiftUI+ Collection โ€“ just add it to Xcode 13+ Provides a custom presentation modifier that provides more

Comments
  • LICENSE file not included in Swift package

    LICENSE file not included in Swift package

    Looks like when installing as swift package the LICENSE file is not included in the package of 0.2.0. So automated license collecting tools like https://github.com/nicklockwood/Tribute can't read the license. Seems like the LICENSE file was added after 0.2.0, maybe just the version number needs to be increased?

    opened by deni2s 2
  • This library has a problem using xcframeworks

    This library has a problem using xcframeworks

    background https://github.com/unsignedapps/swift-create-xcframework/issues/80

    https://github.com/apple/swift/issues/56573

    warning: public struct 'AnyCodable.AnyCodable' shadows module 'AnyCodable', which may cause failures when importing 'AnyCodable' or its clients in some configurations; please rename either the struct 'AnyCodable.AnyCodable' or the module 'AnyCodable', or see https://bugs.swift.org/browse/SR-14195 for workarounds @Frozen public struct AnyCodable: Codable {

    to verify

    brew install mint mint install unsignedapps/swift-create-xcframework swift create-xcframework URLQueryEncoder should see above error.

    Seems like either the class or module has to be renamed.

    
    // swift-tools-version:5.5
    // The swift-tools-version declares the minimum version of Swift required to build this package.
    
    import PackageDescription
    
    let package = Package(
        name: "URLQueryEncoderKit",
        platforms: [
            .macOS(.v10_13),
            .iOS(.v11),
            .tvOS(.v11),
            .watchOS(.v4)
        ],
        products: [
            .library(
                name: "URLQueryEncoderKit",
                targets: ["URLQueryEncoderKit"]),
        ],
        targets: [
            .target(
                name: "URLQueryEncoderKit",
                dependencies: []),
            .testTarget(
                name: "URLQueryEncoderTests",
                dependencies: ["URLQueryEncoderKit"]),
        ]
    )
    
    
    

    rename sources/URLQueryEncoder -> sources/URLQueryEncoderKit

    working branch

    
    // swift-tools-version:5.5
    // The swift-tools-version declares the minimum version of Swift required to build this package.
    
    import PackageDescription
    
    let package = Package(
      name: "GoTrue",
      platforms: [
        .iOS(.v13),
        .macCatalyst(.v13),
        .macOS(.v10_15),
        .watchOS(.v6),
        .tvOS(.v13),
      ],
      products: [
        .library(name: "GoTrue", targets: ["GoTrue"])
      ],
      dependencies: [
        .package(url: "https://github.com/WeTransfer/Mocker", from: "2.7.0"),
        .package(url: "https://github.com/binaryscraping/swift-composable-keychain", from: "0.0.2"),
        .package(url: "https://github.com/kean/Get", from: "2.0.0"),
        .package(url: "https://github.com/wweevv-johndpope/URLQueryEncoderKit", from: "0.2.2"),
      ],
      targets: [
        .target(
          name: "GoTrue",
          dependencies: [
            .product(name: "Get", package: "Get"),
            .product(name: "ComposableKeychain", package: "swift-composable-keychain"),
            .product(name: "URLQueryEncoderKit", package: "URLQueryEncoderKit"),
          ]
        ),
        .testTarget(
          name: "GoTrueTests",
          dependencies: [
            "GoTrue",
            "Mocker",
          ],
          resources: [
            .process("Resources")
          ]
        ),
      ]
    )
    
    
    
    opened by wweevv-johndpope 1
  • Dictionary of [String: Object] not encoded correctly?

    Dictionary of [String: Object] not encoded correctly?

    When encoding a dictionary that contains objects with form style and true explode value, the key for each parameter should be the key for each entry in the dictionary, not the key that is passed in.

    This is the behaviour experienced when using https://editor.swagger.io with the following yaml file:

    openapi: 3.0.3
    info:
      title: Test API
      version: v1
    paths:
      /products:
        get:
          summary: Get list of products
          parameters:
            - name: filters
              in: query
              schema:
                $ref: '#/components/schemas/ProductFilterRequestQueryParameter'
          responses:
            '204':
              description: OK
    components:
      schemas:
        ProductFilterRequestQueryParameter:
          type: object
          description: |
            A set of constraints placed on filters, keyed by the filter name, and containg an operator and an array of values.
          additionalProperties:
            $ref: '#/components/schemas/ProductFilterRequestConstraint'
          example:
            color:
              operator: eq
              value:
                - blue_code
            material:
              operator: in
              value:
                - gold_code
                - blue_code
        ProductFilterRequestConstraint:
          type: object
          description: |
            A constraint placed on a filter. Constraints can either be "in" (an array) or "equals" (to a value).
          properties:
            operator:
              type: string
            value:
              type: array
              items:
                type: string
          required:
            - operator
            - value
    

    You can see the results of the query produced by "trying out" the request in editor.swagger.io.

    However, this package produces a query string that ignores the keys in the dictionary and flattens the values.

    A failing test representing the expected output:

        func testEncodeDictionaryWithObject() {
    
            struct Filter: Codable {
                let `operator`: String
                let value: [String]
            }
    
            // GIVEN
            let parameter = [
                "color": Filter(operator: "eq", value: ["blue"]),
                "material": Filter(operator: "in", value: ["leather", "metal"])
            ]
            // THEN
            let query = URLQueryEncoder().encode(parameter, forKey: "filters").percentEncodedQuery
            // produces query == "filters=in&filters=leather&filters=metal&filters=eq&filters=blue"
            XCTAssertEqual(query, "color[operator]=eq&color[value]=blue&material[operator]=in&material[value]=leather&material[value]=metal")
        }
    

    I am aware that the output produced by editor.swagger.io seems to be encoding the object as deepObject style while expecting a form style, so perhaps this is not a bug in this package but nonetheless I thought it important to raise an issue to discuss.

    As far as I can tell, there is no official OpenAPI Spec support for deeply-nested objects. There is some discussion here with links to other discussions too. Perhaps it would be useful to define what this package will do with deep objects, and officially add support for it?

    opened by kerrmarin 1
Releases(0.2.1)
  • 0.2.1(Nov 29, 2022)

    What's Changed

    • Properly include LICENSE file for improved compatibility with tools like Tribute (https://github.com/CreateAPI/URLQueryEncoder/issues/5)
    • Add GitHub Actions Workflow for CI checks on macOS by @liamnichols in https://github.com/CreateAPI/URLQueryEncoder/pull/2
    • Add CI workflows for testing Linux by @liamnichols in https://github.com/CreateAPI/URLQueryEncoder/pull/3

    New Contributors

    • @liamnichols made their first contribution in https://github.com/CreateAPI/URLQueryEncoder/pull/2

    Full Changelog: https://github.com/CreateAPI/URLQueryEncoder/compare/0.2.0...0.2.1

    Source code(tar.gz)
    Source code(zip)
  • 0.1.0(Dec 28, 2021)

Owner
Alexander Grebenyuk
I write kean.blog and like porridge
Alexander Grebenyuk
A GUI for dynamically creating NSPredicates at runtime to query data in your iOS app.

PredicateEditor PredicateEditor is a visual editor for creating and using NSPredicates for querying data in your app. PredicateEditor was inspired by

Arvindh Sukumar 362 Jul 1, 2022
Hotels By Location - Click on the table view cell will navigate to hotel url

HotelsByLocation About This is the final project of IOS Nano Degree. Longpress or search locations. It'll drop a pin on the map. Click on the annotaio

HWYS 0 Jan 15, 2022
Modern interface to UserDefaults + Codable support

Default Modern interface to UserDefaults + Codable support What is Default? Default is a library that extends what UserDefaults can do by providing ex

Nicholas Maccharoli 475 Dec 20, 2022
A Swift wrapper for system shell over posix_spawn with search path and env support.

AuxiliaryExecute A Swift wrapper for system shell over posix_spawn with search path and env support. Usage import AuxiliaryExecute AuxiliaryExecute.l

Lakr Aream 11 Sep 13, 2022
Enables developers to write code that interacts with CloudKit in targets that don't support the CloudKit Framework directly

CloudKit Web Services This package enables developers to write code that interac

Eric Dorphy 3 May 11, 2022
Enables developers to write code that interacts with CloudKit in targets that don't support the CloudKit Framework directly

CloudKit Web Services This package enables developers to write code that interac

Eric Dorphy 2 Dec 27, 2021
AppCodableStorage - Extends `@AppStorage` in SwiftUI to support any Codable object

AppCodableStorage Extends @AppStorage in SwiftUI to support any Codable object.

Andrew Pouliot 19 Nov 25, 2022
๐Ÿ”ฅ ๐Ÿ”ฅ ๐Ÿ”ฅSupport for ORM operation,Customize the PQL syntax for quick queries,Support dynamic query,Secure thread protection mechanism,Support native operation,Support for XML configuration operations,Support compression, backup, porting MySQL, SQL Server operation,Support transaction operations.

?? ?? ??Support for ORM operation,Customize the PQL syntax for quick queries,Support dynamic query,Secure thread protection mechanism,Support native operation,Support for XML configuration operations,Support compression, backup, porting MySQL, SQL Server operation,Support transaction operations.

null 60 Dec 12, 2022
Crossroad is an URL router focused on handling Custom URL Scheme

Crossroad is an URL router focused on handling Custom URL Scheme. Using this, you can route multiple URL schemes and fetch arguments and parameters easily.

Kohki Miki 331 May 23, 2021
OpenAPI/Swagger 3.0 Parser and Swift code generator

SwagGen SwagGen is a library and command line tool for parsing and generating code for OpenAPI/Swagger 3.0 specs, completely written in Swift. Swagger

Yonas Kolb 568 Jan 5, 2023