Functional JSON parsing library for Swift

Overview

Argo Carthage compatible Reviewed by Hound

Argo is a library that lets you extract models from JSON or similar structures in a way that's concise, type-safe, and easy to extend. Using Argo, you won't need to write validation code to ensure that incoming data is of the right type, or to make sure required data fields aren't turning up empty. Argo uses Swift's expressive type system to do that for you, and reports back explicit failure states in case it doesn't find what you've told it to expect.

Argo is the Greek word for swift and the name of the ship used by Jason, son of Aeson, of the Argonauts. Aeson is the JSON parsing library in Haskell that inspired Argo, much like Aeson inspired his son Jason.

Version Compatibility

Note that we're aggressive about pushing master forward along with new versions of Swift. Therefore, we highly recommend against pointing at master, and instead using one of the releases we've provided.

Here is the current Swift compatibility breakdown:

Swift Version Argo Version
4.X master
3.X 4.X
2.2, 2.3 3.X
2.0, 2.1 2.X
1.2 - 2.0 1.X
1.1 0.3.X

Installation

Carthage

Add the following to your Cartfile:

github "thoughtbot/Argo"

Then run carthage update.

Follow the current instructions in Carthage's README for up to date installation instructions.

Note that if you are using newer versions of Argo, you will need to link both Argo.framework and Runes.framework into your app.

CocoaPods

Add the following to your Podfile:

pod 'Argo'

You will also need to make sure you're opting into using frameworks:

use_frameworks!

Then run pod install with CocoaPods 0.36 or newer.

Git Submodules

I guess you could do it this way if that's your thing.

Add this repo as a submodule, and add the project file to your workspace. You can then link against Argo.framework for your application target.

You will need to do the same for Runes if you are using newer versions of Argo.

Usage tl;dr:

Please note: the example below requires an additional, external module named Curry which lets us use the curry function to curry User.init.

It also imports Runes, which is a dependency of Argo in newer versions. If you are using an older version of Argo, you might not need that import.

import Argo
import Curry
import Runes

struct User {
  let id: Int
  let name: String
  let email: String?
  let role: Role
  let companyName: String
  let friends: [User]
}

extension User: Decodable {
  static func decode(_ json: JSON) -> Decoded<User> {
    return curry(User.init)
      <^> json <| "id"
      <*> json <| "name"
      <*> json <|? "email" // Use ? for parsing optional values
      <*> json <| "role" // Custom types that also conform to Decodable just work
      <*> json <| ["company", "name"] // Parse nested objects
      <*> json <|| "friends" // parse arrays of objects
  }
}

// Wherever you receive JSON data:

let json: Any? = try? NSJSONSerialization.JSONObjectWithData(data, options: [])

if let j: Any = json {
  let user: User? = decode(j)
}

For more information, see the Documentation

Contributing

See the CONTRIBUTING document. Thank you, contributors!

License

Argo is Copyright (c) 2015 thoughtbot, inc. It is free software, and may be redistributed under the terms specified in the LICENSE file.

About

thoughtbot

Argo is maintained and funded by thoughtbot, inc. The names and logos for thoughtbot are trademarks of thoughtbot, inc.

We love open source software! See our other projects or look at our product case studies and hire us to help build your iOS app.

Comments
  • Argo 2, large objects, and ambiguous references.

    Argo 2, large objects, and ambiguous references.

    An old problem seems to have resurfaced with a new head. We are breaking up large (more than 11 elements) objects into intermediate parts in order to appease the compiler. However, with the migration to Argo 2.0 and Swift 2, the compiler has a new complaint. Take this case (names made neutral):

    public static func decode(j: JSON) -> Decoded<DataObject> {
        let firstPart =  DataObject.create
            <^> j <| "data1"
            <*> j <| "data2"
            <*> j <| "data3"
            <*> j <|? "data4"
            <*> j <|? "data5"
    
        let secondPart = firstPart
            <*> j <|? "data6"
            <*> j <|? "data7"
            <*> j <|? "data8"
            <*> j <|? "data9"
            <*> j <|? "data10"
    
        let thirdPart = secondPart
            <*> j <|? "data11"
            <*> j <|? "data12"
            <*> j <|? "data13"
            <*> j <|? "data14"
            <*> j <|? "data15"
    
        let fourthPart = thirdPart
            <*> j <|? "data16"
            <*> j <|? "data17"
            <*> j <|? "data18"
            <*> j <|? "data19"
            <*> j <|? "data20"
    
        return fourthPart
            <*> j <|? "data21"
            <*> j <|? "data22"
            <*> j <|? "data23"
            <*> j <|| "data24"
            <*> j <|| "data25"
            <*> j <|| "data26"
            <*> j <|? "data27"
    }
    

    The compiler complains in two spots (the second line of the secondPart assignment and the second line of the thirdPart assignment) about an "Ambiguous reference to member <|?". Does anyone know a way to get around this that doesn't involve breaking up the DataObject itself into multiple smaller objects that then get merged?

    opened by nomothetis 42
  • Error: Expression was too complex to be solved in reasonable time

    Error: Expression was too complex to be solved in reasonable time

    I’m getting an error Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions when using Argo to parse GitHub’s pull request JSON into my struct. I have the following decoder:

    static var decoder: JSONValue -> PullRequest? {
            return PullRequest.create
                <^> <|"number"
                <*> <|"state"
                <*> <|"title"
                <*> <||"labels"
                <*> <|*"created_at"
                <*> <|*"updated_at"
                <*> <|*"merged_at"
                <*> <|*"closed_at"
                <*> <|["user", "login"]
                <*> <|*"assignee"
                <*> <|["repository", "owner", "login"]
                <*> <|"comments"
                <*> <|"html_url"
                <*> <|*"statuses_url"
    }
    

    That is 14 properties for the pull request entity from GitHub’s API (which returns a ton more). I’m currently using the code in #2 as master would lead to the compiler and indexer more or less hanging (they did not but they never finished in reasonable time ^^).

    This seems to be caused by a bug in swiftc where only 11 statements per expression works.

    Do you have a suggestion for workaround of this? As it would be great to be able to have more than 11 properties :smile:

    opened by rastersize 32
  • Performance issues

    Performance issues

    I found that on a 4S device, my data model was taking almost 12 seconds, to be parsed. So I did a small experiment with the following:

    import Foundation
    import Argo
    import Curry
    import Runes
    
    struct Person {
    
        let firstName: String
        let secondName: String?
        let age: Int
        let hoobies: [String]
        let description: String
    }
    
    extension Person: Decodable {
    
        static func decode(j: JSON) -> Decoded<Person> {
            return curry(Person.init)
                <^> j <| "firstName"
                <*> j <|? "secondName"
                <*> j <| "age"
                <*> j <|| "hobbies"
                <*> j <| "description"
        }
    }
    

    This is not my original model, but a far simpler one. So I used a testing file with 100k lines of JSON with a total of 9130 objects. The original one has more than 330k lines and far deeper hierarchy and complexity (number of members).

    I wasn't sure which would the best approach so I used the ones I saw in the wild (the measurements are in release mode on a MacbookPro 2015):

    screen shot 2015-11-15 at 21 26 40

    Then I did the parsing "by hand":

    screen shot 2015-11-15 at 21 28 09

    Obviously, the second version has a lot more boilerplate, it's not as easy to maintain or extend, but in this case all those niceties are not worth with such timings. A demo project can be found here.

    opened by RuiAAPeres 31
  • Encode to JSON?

    Encode to JSON?

    Is there any planned support for reversing the decode process and encoding back to JSON? I'm thinking this could be a good way to also automatically support serialization to disk.

    opened by jshier 31
  • Argo in Swift 2.0

    Argo in Swift 2.0

    I integrated Argo with my project ( Swift 1.2, Xcode 6.4 ). I wanna move to the Xcode 7 beta 6, with Swift 2.0. I want to integrate argo with Swift 2.0. When i imported project to Xcode 7 beta 6, it suggested lot of code changes from Swift 1.2 to Swift 2.0. Which was really bad, i really could not understand what Xcode did to my project.

    Could you please tell me that, which is the best way, updating via cocoapods ? Do i have to wait till the release of Xcode 7, Cause i decided that i will be taking Argo with my app to the production. So i don't want to waste time by integrating again and solving the bugs.

    May i wait till the release of Xcode 7 ? or this Argo gonna behave the same without any problem in Xcode 7.

    Suggest me your thoughts.

    opened by speaktoalvin 27
  • no such module 'Runes'

    no such module 'Runes'

    I have Argo embedded within my existing project (and have had for ages). I'm finally getting around to updating to Swift 3.

    I updated my project's Cartfileto point to Argo master (instead of 3.1.0):

    github "thoughtbot/Argo" "master"
    

    and run carthage update --use-submodules. This successfully fetches Argo and Runes. As you can see from the log below, Runes compiles OK and I can see the artifacts in the Carthage/Build/XXX folders. However, when it tried to build Argo, I get an error saying that it can't find the Runes module.

    There is a mention of a similar problem in #407 (which I don't think is related to the PR... just a similar problem).

    I've tried a bunch of carthage combos (bootstrap, build, update, et al), but just can't get a working build.

    I'm still digging through the logs, but any thoughts would be great.

    Error Messages

    *** xcodebuild output can be found in /var/folders/p6/xcv59nqd4wv0y6hwpm3q16m40000gn/T/carthage-xcodebuild.7gtojh.log
    *** Building scheme "Runes-tvOS" in Runes.xcodeproj
    *** Building scheme "Runes-Mac" in Runes.xcodeproj
    *** Building scheme "Runes-iOS" in Runes.xcodeproj
    *** Building scheme "Runes-watchOS" in Runes.xcodeproj
    *** Building scheme "Argo-watchOS" in Argo.xcworkspace
    ** BUILD FAILED **
    
    
    The following build commands failed:
        CompileSwift normal armv7k
        CompileSwiftSources normal armv7k com.apple.xcode.tools.swift.compiler
        Ld /Users/edwardsc/Library/Developer/Xcode/DerivedData/Argo-asybjaazisryjmeuwabufbberqcz/Build/Products/Release-watchos/Argo.framework/Argo normal armv7k
        GenerateDSYMFile /Users/edwardsc/Library/Developer/Xcode/DerivedData/Argo-asybjaazisryjmeuwabufbberqcz/Build/Products/Release-watchos/Argo.framework.dSYM /Users/edwardsc/Library/Developer/Xcode/DerivedData/Argo-asybjaazisryjmeuwabufbberqcz/Build/Products/Release-watchos/Argo.framework/Argo
    (4 failures)
    /Users/edwardsc/dev/Ogra/Carthage/Checkouts/Argo/Argo/Types/Decoded/Applicative.swift:1:8: error: no such module 'Runes'
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    error: cannot parse the debug map for "/Users/edwardsc/Library/Developer/Xcode/DerivedData/Argo-asybjaazisryjmeuwabufbberqcz/Build/Products/Release-watchos/Argo.framework/Argo": No such file or directory
    A shell task failed with exit code 65:
    ** BUILD FAILED **
    
    
    The following build commands failed:
        CompileSwift normal armv7k
        CompileSwiftSources normal armv7k com.apple.xcode.tools.swift.compiler
        Ld /Users/edwardsc/Library/Developer/Xcode/DerivedData/Argo-asybjaazisryjmeuwabufbberqcz/Build/Products/Release-watchos/Argo.framework/Argo normal armv7k
        GenerateDSYMFile /Users/edwardsc/Library/Developer/Xcode/DerivedData/Argo-asybjaazisryjmeuwabufbberqcz/Build/Products/Release-watchos/Argo.framework.dSYM /Users/edwardsc/Library/Developer/Xcode/DerivedData/Argo-asybjaazisryjmeuwabufbberqcz/Build/Products/Release-watchos/Argo.framework/Argo
    (4 failures)
    

    Argo Version

    master (4b57653f7760bd3eedfd1c1fbc821bde191e603d)

    Dependency Manager

    Carthage

    bug 
    opened by edwardaux 23
  • Issue using partial application with curried initializer

    Issue using partial application with curried initializer

    I'm using the same approach as in the iTunes Example Playground to convert a String to a NSDate, like so:

    extension App: Decodable  {
      ...
    
      static func decode(j: JSON) -> Decoded<App> {
        return create
          <^> j <| "trackName"
          <*> j <| "formattedPrice"
          <*> j <|? "averageUserRating"
          <*> (j <| "releaseDate" >>- toNSDate)
      }
    }
    

    However, I've also needed to break up the expression, similar to:

    extension App: Decodable  {
      ...
    
      static func decode(j: JSON) -> Decoded<App> {
        let app = create
          <^> j <| "trackName"
          <*> j <| "formattedPrice"
        return app
          <*> j <|? "averageUserRating"
          <*> (j <| "releaseDate" >>- toNSDate)
      }
    }
    

    This results in the following error message:

    Binary operator '<*>' cannot be applied to operands of type 'Decoded<NSDate -> App>' and 'Decoded<App>'
    
    opened by paulyoung 22
  • Remove reduce usage for better performance

    Remove reduce usage for better performance

    Argo’s performance is quadratic over the size of the collection being decoded, due to the use of reduce (AirspeedVelocity article). This PR removes most usages of reduce in exchange for a for loop of the same functionality. This improves the performance of decoding an array of over 9000 simple models on an iPhone 4S by ~2600% (76.4s to 2.9s). See #295 for my analysis and evolution of this code.

    opened by jshier 20
  • Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions

    Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions

    // // CommentItem.swift // xxxxxxxxxxxxxxx // // Created by xxxxxxx on 10/20/15. // Copyright © 2015 xxxxxx. All rights reserved. //

    import Argo import Curry

    struct CommentItem { let fromUserId: String? let toUserId: String? let content: String? let timestamp: Int64? }

    extension CommentItem: Decodable { static func decode(j: JSON) -> Decoded { return curry(UACCommentItem.init) <^> j <| "fromUserId" <> j <|? "toUserId" <> j <| "content" <*> j <| "timestamp" } }

    Above is code, swift 2.0, Version 7.0.1 (7A1001), i have this problem. the line of problem is "<*> j <| "timestamp""

    opened by zhaodg 20
  • Long compile times

    Long compile times

    I'm using Argo in production app, and I can see that the Swift compile time takes a lot of time in my project. Wondering if this is because of Argo & Argo based models which use a lot of generic code ? Please let me know if you have done any bench marking around this.

    Argo Version

    Argo 3.1

    Dependency Manager

    Carthage

    opened by mohan-win 18
  • Is there any way to decode an array of different types?

    Is there any way to decode an array of different types?

    I have JSON that is analogous to this:

    {
      "animals": [
        { "type": "cat", "name": "kitty", "remainingLives": 4 },
        { "type": "dog", "name": "spot", "trained": false }
      ]
    }
    

    I would love to have an Animal type with a name property and then a subclass for Cat with a remainingLives property and Dog with a trained property.

    It doesn't appear to be possible with Argo. Am I missing anything? If not, is this something that you think might fit into Argo? I would be happy to work on it with a little guidance. (I'm very new to Swift)

    opened by maxschmeling 18
  • [RFC] Remove optional decoding as an explicit operation

    [RFC] Remove optional decoding as an explicit operation

    Previously, we've used a special operator (<|?) for denoting that we were decoding to an optional property. This operator had special behavior that meant it would only fail if the decoding operation itself failed, but would still succeed if the key was missing.

    I think that ultimately, this was a confusing distinction. Although it was nice and concise, it made it difficult to reason about some transformations (like flatMapping into a secondary transformation), and it also meant we needed to double the surface area of the API. The special behavior around when we failed the decoding was also potentially confusing and could lead to unexpected results for people that weren't completely familiar with the distinction between how we handled various decoding failures internally.

    Additionally, we've had another solution to this problem for nearly the entire time this library has existed: Decoded.optional. This is a much simpler transformation, and it simply converts the Decoded to an Optional and then wraps it in .success.

    It seems reasonable, then (especially with the additional API changes currently in flight) to reduce the surface area and the complexity of our API at the same time by removing the <|? operators in favor of explicitly wrapping our extraction operations in a call to .optional.

    Note that this also means we can use conditional conformance to make conform Optional conform to Decoded directly.

    opened by gfontenot 2
  • RFC: Renaming the Decodable protocol

    RFC: Renaming the Decodable protocol

    I've finally gotten some time to work on this, and I'd like to push forward with solving the naming conflict between Swift.Decodable and Argo.Decodable. I've also opened up #473 to rename JSON to Value.

    I'd like to get thoughts from people on the naming of the Decodable protocol. I'm not sure that I have super strong opinions on what to name it, and I'd be willing to bet other people do.

    Prior Art

    One quick data point that we can probably immediately disregard:

    Aeson calls their version of Decodable FromJSON. Their decode function is then called fromJSON. I think that given our move away from using JSON in our naming, it doesn't make sense to follow their lead here.

    Proposal: WeakTypeConvertable

    One idea I keep coming back to is the idea that (from a marketing standpoint) we can push this idea of moving from weak -> strong data types via the protocol. This isn't nearly as catchy a name as Decodable (or even FromJSON), but it seems to be more descriptive. An interface for this might look like:

    public protocol WeakTypeConvertable {
      associatedtype TargetType = Self
      static func decode(_ value: Value) -> Decoded<TargetType>
    }
    

    The one thing (other than the clumsiness of the overall name) I don't like is that it feels like this pulls me down a rabbit hole for the function/result names. It seems to me that we might want to move all the way to something more like:

    public protocol WeakTypeConvertable {
      associatedtype TargetType = Self
      static func fromValue(_ value: Value) -> Converted<TargetType>
    }
    

    It's not too difficult to see how this can start to spiral into a much larger rename where we touch every part of the lib. I'd imagine this level of change would be incredibly painful for end users.

    I'd love to hear thoughts on this from people that have a vested interest in the end result.

    related: #466, #471

    enhancement help wanted question 
    opened by gfontenot 0
  • Rename JSON to Value

    Rename JSON to Value

    We're going to be shifting the marketing focus for Argo away from being a JSON parser and towards being a general purpose parser for transforming loosely typed data models into strongly typed ones. As a part of this change, we can generalize our types a bit, and use the name Value for our input values, instead of JSON. This change is purely cosmetic, but will result in a more general API, letting us break a bit from our ties to JSON.

    Note that we're providing a typealias from JSON to Value here as well. This should make this a non-breaking change (although users will get a deprecation warning). I'd love it if other people could test this with their codebase.

    opened by gfontenot 18
  • Decoding subclasses

    Decoding subclasses

    I'm trying to convert some code to use Argo, and I'm getting stuck where the existing code uses subclasses. I can't get type inference to pass.

    If anyone knows how to get this to work, I'd love some help.

    Error Messages

    error: cannot convert value of type 'Decoded<_>' to specified type 'Decoded<Child>'
        let child: Decoded<Child> = json <| "child"
                                    ~~~~~^~~~~~~~~~
    error: cannot convert value of type 'Decoded<[_]?>' (aka 'Decoded<Optional<Array<_>>>') to specified type 'Decoded<[Child]?>' (aka 'Decoded<Optional<Array<Child>>>')
        let children: Decoded<[Child]?> = json <||? "children"
                                          ~~~~~^~~~~~~~~~~~~~~
    

    Models

    class Parent: Decodable {
      let title: String
    
      init(title: String) {
        self.title = title
      }
    
      typealias DecodedType = Parent
      static func decode(_ json: JSON) -> Decoded<Parent> {
        return curry(Parent.init)
          <^> json <| "title"
      }
    }
    
    class Child: Parent {
      let subtitle: String
    
      init(title: String, subtitle: String) {
        self.subtitle = subtitle
        super.init(title: title)
      }
    
      typealias DecodedType = Child
      static func decode(_ json: JSON) -> Decoded<Child> {
        return curry(Child.init)
          <^> json <| "title"
          <*> json <| "subtitle"
      }
    }
    
    final class Consumer: Decodable {
      let child: Child
      let children: [Child]?
    
      init(child: Child, children: [Child]?) {
        self.child = child
        self.children = children
      }
    
      static func decode(_ json: JSON) -> Decoded<Consumer> {
        // Changing these from Child to Parent makes it work
        let child: Decoded<Child> = json <| "child"
        let children: Decoded<[Child]?> = json <||? "children"
        return curry(self.init)
          <^> child
          <*> children
      }
    }
    

    Argo Version

    Argo 4.1.2 Xcode 8.3.2

    Dependency Manager

    Carthage

    help wanted question 
    opened by mdiep 15
  • Incorrectly parsing numbers as `Null` under Linux

    Incorrectly parsing numbers as `Null` under Linux

    Sample JSON

    {
      "aggregations": {
        "my_aggregation": {
          "value": 9
        }
      }
    }
    

    Models

    let int: Decoded<Int> = json <| ["aggregations", "device_count", "value"]
    // ^ missingKey("value")
    

    Argo Version

    4.1.2

    Dependency Manager

    Swift Package Manager.


    This only occurs under Linux. Locally, there's no problem on MacOS. Under the debugger it seemed to be showing that value was present but its value was null, as if {"value": null}.

    Resolved this way (ugh).

    let dict = json as? [String:Any]
    
    let int = dict.flatMap({ d -> Any? in
        return d["aggregations"]
    }).flatMap({  d -> [String:Any]? in
        return d as? [String:Any]
    }).flatMap({ d -> Any? in
        return d["my_aggregation"]
    }).flatMap({ d -> [String:Any]? in
       return d as? [String:Any]
    }).flatMap({ d -> Any? in
        return d["value"]
    }).flatMap({ d -> Int? in
       return d as? Int
    })
    

    I assume this is related to NSNumber being a shitshow on Linux, and thus isn't really Argo's problem. This issue is more for the benefit of everyone else.

    (Related observation: if NSNumber's crufty addition of so many features is due to years of the "benefits" of ABI stability, I'm terrified for the consequences of Swift 5).

    bug help wanted 
    opened by swizzlr 1
Releases(v5.0.0)
  • v5.0.0(May 22, 2020)

    Yes I did get tired of my lazy naming scheme.

    5.0 adds explicit support for Swift 5 across all dependency management solutions. There are no other user-facing changes.

    Source code(tar.gz)
    Source code(zip)
  • v4.2.0(May 22, 2020)

  • v4.1.2(Jan 24, 2017)

    • [FIXED]: Now using Iterator instead of Generator in our definition of decode for Collections. This was renamed in Swift 3.0, and honestly I'm not positive how this was compiling the way it was.
    Source code(tar.gz)
    Source code(zip)
  • v4.1.1(Dec 5, 2016)

  • v4.1.0(Nov 5, 2016)

  • v4.0.0(Oct 13, 2016)

    Official Swift 3.0 release!

    • [NEW]: Now you can see all the decoding failures at once! Thanks @klaaspieter
    • [Bug Fix]: Optional decoding now behaves as expected. Thanks @pteasima for finding this.

    Thanks @gfontenot, @alexwlchan, @mbrandonw, @gcox, and @klaaspieter for all the changes that went into this release!

    Source code(tar.gz)
    Source code(zip)
  • v3.1.0(Jul 29, 2016)

    3.1 adds support for decoding UInt and UInt64 types. UInt can only be decoded JSON.Number instances, and UInt64 can be decoded from JSON.Number as well as JSON.String. This follows the patterns already set up by Int and Int64.

    Thanks to @gcox for this addition!

    Source code(tar.gz)
    Source code(zip)
  • v3.0.3(Jul 22, 2016)

  • v3.0.2(Jul 20, 2016)

    This release is a back-port of our support for enabling whole module optimization (currently supported on master, but unreleased), as well as support for Xcode 8 using Swift 2.3.

    Source code(tar.gz)
    Source code(zip)
  • v3.0.1(Apr 8, 2016)

  • v3.0.0(Apr 6, 2016)

    The goal for Argo 3.0 was to work on simplifying some of the complexity by removing extraneous API and improving consistency between Argo and other libraries (including the Swift standard lib). In addition, we've added support for Swift 2.2.

    Breaking Changes

    New

    Non-Breaking Changes

    • Update errors for RawRepresentable types. - Paul Young
    • Remove CustomStringConvertible constraint on typeMismatch function - Dapeng Gao
    • Use an autoclosure for the rhs of <|> - Gordon Fontenot
    • Generalize the type for sequence taking a dict - Gordon Fontenot

    Misc

    • (hopefully) the entire public API now has inline documentation!

    Huge thank you to everyone that submitted PRs, opened issues, and reviewed code for this release!

    Source code(tar.gz)
    Source code(zip)
  • v2.3.0(Mar 11, 2016)

    After some really fantastic work by @jshier and @RuiAAPeres, we were able to track down some serious performance issues related to our (internal) use of reduce. @jshier was able to remove all instances of reduce in favor of using for in loops, and ended up with a 2600% improvement in performance. This release is to get that into users hands while we work on moving towards version 3.0, which should introduce even more performance increases as well as reducing the complexity of the library.

    • [FIXED]: Aforementioned performance improvement (Jon Shier and Rui Peres)
    • [NEW]: We've audited the codebase to use @noescape where appropriate (Sid Raval)
    • [NEW]: DecodeError is now Hashable (Matt Diephouse)
    Source code(tar.gz)
    Source code(zip)
  • v2.2.0(Oct 27, 2015)

    Argo 2.2.0 is out!

    [NEW]: Add materialize function for creating Decoded from try, thanks @paulyoung [NEW]: Add tvOS scheme, thanks @nickygerritsen

    [IMPROVEMENT]: Improve documentation that Curry is a separate framework, thanks @gilesvangruisen [IMPROVEMENT]: Remove workaround for memory bug in older versions of Swift, thanks @paulyoung

    [BUG FIX]: Fix signing errors with simulator builds, thanks @gfontenot

    Yay! :tada:

    Source code(tar.gz)
    Source code(zip)
    Argo.framework.zip(2.59 MB)
  • v2.1.0(Oct 3, 2015)

    Argo 2.1.0 coming at you!

    [NEW]: decodeWithRootKey convenience function for easy root key decoding [NEW]: Custom error case Decoded.Custom(String) [NEW]: Failure Coalescing Operator for Decoded, thanks @gfontenot [NEW]: catDecoded for Decoded, thanks @gfontenot [NEW]: DecodeError convenience accessor in Decoded, thanks @jshier [NEW]: Default Decodable implementations for String and Int RawRepresentable enums, thanks @swizzlr

    [IMPROVEMENT]: Documentation!!!!, thanks @jnutting & @gfontenot [IMPROVEMENT]: Extend CollectionType instead of Array, thanks @gfontenot & @gilesvangruisen [IMPROVEMENT]: Extend DictionaryLiteralConvertable instead of Dictionary, thanks @gilesvangruisen

    [BUG FIX]: Fix bitcode error when submitting app, thanks @dmcrodrigues

    Big win!

    Source code(tar.gz)
    Source code(zip)
    Argo.framework.zip(2.37 MB)
  • v2.0.0(Sep 18, 2015)

    Argo 2.0.0 is out!!

    • [NEW]: Swift 2.0 support
    • [NEW]: watchOS targets, thanks @JaviSoto
    • [NEW]: Alternative operator <|> for providing defaults or alternatives, thanks @terhechte
    • [NEW]: Add DecodeError enum for easier conversion to Result, thanks @gfontenot
    • [NEW]: dematerialize function to throw when Decoded is a DecodeError, thanks @paulyoung
    • [NEW]: Default Decodable implementations for String and Int RawRepresentable enums, thanks @swizzlr
    • [IMPROVEMENT]: Remove Box & Runes dependency, thanks @sync & @gfontenot
    • [IMPROVEMENT]: Exposed flatReduce & decodeJSON functions, thanks @edwardaux
    • [IMPROVEMENT]: Performance and Memory impact, thanks @paulyoung
    • [IMPROVEMENT]: Argo operators are overloaded to return Optional as well as Decoded

    And thank you to all those not mentioned above for you commits to help Argo 2.0.0 become reality! @sidraval, @nickygerritsen, @lowell, and @jdhealy

    ford_dance

    Source code(tar.gz)
    Source code(zip)
    Argo.framework.zip(1.27 MB)
  • v1.0.5(Sep 21, 2015)

  • v1.0.4(Jul 15, 2015)

  • v1.0.3(May 26, 2015)

  • v1.0.2(May 20, 2015)

  • v1.0.1(May 1, 2015)

  • v1.0.0(Apr 27, 2015)

    The official 1.0.0 release of Argo. Includes a new Decoded type that allows you to retain decoding failure information for debugging purposes. Also, the new global decode function helps you quickly decode your model objects from the AnyObject returned from NSJSONSerialization.

    Source code(tar.gz)
    Source code(zip)
    Argo.framework.zip(416.79 KB)
  • v0.4.3(Mar 13, 2015)

  • v0.4.2(Feb 18, 2015)

    This release adds a workaround for compiler issues in Swift 1.2 on 32 bit systems that causes an EXC_BAD_ACCESS crash when using partial application of static generic protocol functions, which is just about the weirdest phrase I've ever had to say out loud.

    Source code(tar.gz)
    Source code(zip)
    Argo.framework.zip(308.54 KB)
  • v0.3.4(Feb 17, 2015)

  • v0.4.1(Feb 16, 2015)

    This adds JSONDecodable support for Float properties. Not sure why we didn't do this earlier.

    As an added bonus, we've also enabled the ability to use Argo inside app extensions.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.3(Feb 16, 2015)

  • v0.4.0(Feb 16, 2015)

  • v0.3.2(Feb 16, 2015)

  • v0.3.1(Feb 16, 2015)

  • v0.3(Feb 16, 2015)

Owner
thoughtbot, inc.
We work with organizations of all sizes to design, develop, and grow their web and mobile products.
thoughtbot, inc.
Functional chaining and promises in Swift

Forbind Functional chaining and promises in Swift Note: still in an experimental state. Everything could change. I would love some feedback on this. W

Ulrik Flænø Damm 45 Sep 1, 2022
Functional programming tools and experiments in Swift.

Funky The documentation (courtesy of realm/jazzy) is available here: https://brynbellomy.github.io/Funky Master branch is currently compatible with: S

Bryn Bellomy 12 May 2, 2017
Collection of must-have functional Swift tools

NOTE: This project has been merged with and superceded by Rob Rix's Result µframework. LlamaKit Collection of must-have functional tools. Trying to be

null 619 Aug 5, 2022
A functional utility belt implemented as Swift 2.0 protocol extensions.

Oriole [![CI Status](http://img.shields.io/travis/Tyler Thompson/Oriole.svg?style=flat)](https://travis-ci.org/Tyler Thompson/Oriole) Oriole is a set

Tyler Paul Thompson 11 Aug 10, 2019
Swift µframework of simple functional programming tools

Prelude This is a Swift µframework providing a number of simple functions that I use in many of my other frameworks. Rather than continue to reimpleme

Rob Rix 405 Jun 29, 2022
Functional programming in Swift

Swiftz Swiftz is a Swift library for functional programming. It defines functional data structures, functions, idioms, and extensions that augment the

TypeLift 3.3k Dec 25, 2022
Functional programming in Swift

Swiftz Swiftz is a Swift library for functional programming. It defines functional data structures, functions, idioms, and extensions that augment the

TypeLift 3.3k Jan 6, 2023
Functional data types and functions for any project

Swiftx Swiftx is a Swift library containing functional abstractions and extensions to the Swift Standard Library. Swiftx is a smaller and simpler way

TypeLift 219 Aug 30, 2022
Swift µframework with extensions for the Optional Type

OptionalExtensions Why? Swift's Optional is pretty awesome, but it can always get better. This repository is an humble attempt to add some utility met

Rui Peres 183 Dec 15, 2022
Infix operators for monadic functions in Swift

Indecipherable symbols that some people claim have actual meaning. Please see the documentation for installation instructions. What's included? Import

thoughtbot, inc. 825 Dec 7, 2022
A set of Swift extensions for standard types and classes.

ExSwift Set of Swift extensions for standard types and classes. Installation Because of Xcode errors it's not possible to integrate this project with

Pierluigi D'Andrea 3.4k Dec 27, 2022
Elevate is a JSON parsing framework that leverages Swift to make parsing simple, reliable and composable

Elevate is a JSON parsing framework that leverages Swift to make parsing simple, reliable and composable. Elevate should no longer be used for

Nike Inc. 611 Oct 23, 2022
Swift-json - High-performance json parsing in swift

json 0.1.4 swift-json is a pure-Swift JSON parsing library designed for high-per

kelvin 43 Dec 15, 2022
Ss-json - High-performance json parsing in swift

json 0.1.1 swift-json is a pure-Swift JSON parsing library designed for high-per

kelvin 43 Dec 15, 2022
Elegantly connect to a JSON api. (Alamofire + Promises + JSON Parsing)

⚠ Important Notice: Farewell ws... hello Networking ! Networking is the next generation of the ws project. Think of it as ws 2.0 built for iOS13. It u

Fresh 351 Oct 2, 2022
Keep It Functional - An iOS Functional Testing Framework

IMPORTANT! Even though KIF is used to test your UI, you need to add it to your Unit Test target, not your UI Test target. The magic of KIF is that it

KIF Framework 6.2k Dec 29, 2022
CoreML-Face-Parsing - how to use face-parsing CoreML model in iOS

CoreML-Face-Parsing The simple sample how to use face-parsing CoreML model in iO

MLBoy 6 Oct 25, 2022
[Deprecated] A shiny JSON parsing library in Swift :sparkles: Loved by many from 2015-2021

?? Deprecation Notice ?? Gloss has been deprecated in favor of Swift's Codable framework. The existing Gloss source is not going away, however updates

Harlan Kellaway 1.6k Nov 24, 2022
Developed with use Swift language. As a third party library used SDWebImage. JSON parsing using URLSession with TMDB API. This app provide by the Core Data structure.

Capstone Project ?? About Developed with use Swift language. As a third party library used SDWebImage. JSON parsing using URLSession with TMDB API. Ad

Ensar Batuhan Unverdi 9 Aug 22, 2022
Functional JSON Parser - Linux Ready

Functional JSON Parser Feature Linux Ready Type-safe JSON parsing Functional value transformation Easy to parse nested value Dependency free No define

Ryo Aoyama 117 Sep 9, 2022