Coder Social home page Coder Social logo

argo's People

Contributors

alexndrejoly avatar alskipp avatar gfontenot avatar gilesvangruisen avatar javisoto avatar jdhealy avatar jnutting avatar jshier avatar klaaspieter avatar kylef avatar leomehlig avatar lowell avatar lutzifer avatar mbrandonw avatar mdiep avatar michaelmcguire avatar mike-burns avatar mjankowski avatar nickygerritsen avatar nvh avatar paulyoung avatar pbrisbin avatar pmanijak avatar raven avatar rlovelett avatar salbertson avatar sidraval avatar swizzlr avatar tonyd256 avatar tysongach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

argo's Issues

Thanks!

I was debating with myself if I should change the previous Optional-based implementation to use some kind of custom type with more info than just "it didn't work", but I thought y'all might be working on that anyway. Turns out you are! Upgraded today, things are much nicer now. Thanks! 👍

Map JSON key name

Is it possible to map a JSON key name to a value with Argo? For example, say I have the following objects I want to map JSON into...

struct Model {
   ...
   let properties: [Property]
}

struct Property {
   let label: String
   let type: String
   let required: Bool
}

...and the corresponding JSON...

    ...   
     "model": {
            "identifier": {
                "type": "Dental",
                "version": "1.0"
            },
            "properties": {
                "patient": {
                    "type": "string",
                    "required": true
                },
                "historyOfPresentIllness": {
                    "type": "string"
                },
                "medicalSurgicalHistory": {
                    "type": "string"
                },
                "physicalExam": {
                    "type": "string"
                },
                ...
            }
        },
       ...

I know I can map the nested type and required values, but since the property keys are dynamic in the JSON (i.e., patient, historyOfPresentIllness, medicalSurgicalHistory, etc, can potentially be any string and are referenced in a different part of the JSON) I want to map them to the label property on the Property object.

Major issues with optimized Release build

Summary: The "Fastest [-O]" optimization level used by a release build breaks Argo, with behavior ranging from incorrect to crashy.


I first noticed this issue when using Argo via Carthage. I linked my code to the Mac framework produced by carthage build (which uses the Release configuration by default). I tried to parse the following JSON:

{
    "from": "Alpha",
    "to": "Omega"
}

The JSON object produced by NSJSONSerialization.JSONObjectWithData() is correct:

{
    from = Alpha;
    to = Omega;
}

However, the output from JSONValue.parse(jsonObject) was:

Object([to: Null, from: Null])

When using a Debug build of the framework (via carthage build --configuration Debug) the output is correct:

Object([to: String(Omega), from: String(Alpha)])

Running Argo's own tests in Release configuration (by changing the Test configuration for the current scheme) leads to several issues. Most of the tests fail before a call to XCTAssertEqual() brings the whole thing crashing to a halt with an EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subdued=0x0).

The cause of the issue seems to be the compiler's optimization. Swapping the SWIFT_OPTIMIZATION_LEVEL setting between Fastest [-O] and None [-Onone] appears to toggle these issues.


Additional info: I'm building with Xcode 6.1.1 (6A2008a) on OS X 10.10.1 (14B25). I haven't tried this yet with the latest Xcode beta.

Has JSONValue been renamed JSON ?

Hi,

I'm implementing for the first time a struct using Argo and I have a strange problem.

struct Shop {
    let name: String
    let displayName: String
    let order: Int
}

extension Shop: JSONDecodable {
    static func create(name: String)(displayName: String)(order: Int) -> Shop {
        return Shop(name: name, displayName: displayName, order: order)
    }

    static func decode(j: JSONValue) -> Shop? {
        return Shop.create
            <*> j <| "name"
            <*> j <| "displayName"
            <^> j <| "order"
    }
}

Tell me if I missed something, but I think everything is ok. The problem is that I have an error saying that 'JSONValue' has been renamed to JSON and because of that the extension is not conform to the protocol 'JSONDecodable'. If I look in the protocol, a JSONValue is required so I don't really understand ...

Argonaut

I have just released Argonaut, a framework that aims to accompany Argo with two main goals in mind:

  1. Add helpers to make it more convenient to parse JSON into JSONDecodeable models, also support parsing models directly from ReactiveCocoa signals.
  2. A collection of extensions for common objets (e.g. NSURL, etc.) to be directly used with Argo/Runes.

I am not sure if this should be part of Argo itself, mainly because it is partly dependent on ReactiveCocoa, but I thought I put it out there just in case someone else might find it useful.

What do you think? Looking forward to get your feedback. ✨

Regression in Argo v0.4.2 - crashes Swift 1.2 app

Installed via carthage, added Argo and Runes frameworks, etc. Build succeeds fine, but get this error when running the app (without using Argo in the code at all):

dyld: Symbol not found: _globalinit_33_06E7F1D906492AE070936A9B58CBAE1C_func2
  Referenced from: /Users/ian/Library/Developer/CoreSimulator/Devices/7F24576E-DDA0-4DAC-95A7-F63A5DF54BD1/data/Containers/Bundle/Application/D42A6048-A58E-44CC-909F-F0C40EE06D14/Headquarters.app/Frameworks/Argo.framework/Argo
  Expected in: /Users/ian/Library/Developer/CoreSimulator/Devices/7F24576E-DDA0-4DAC-95A7-F63A5DF54BD1/data/Containers/Bundle/Application/D42A6048-A58E-44CC-909F-F0C40EE06D14/Headquarters.app/Frameworks/libswiftCore.dylib
 in /Users/ian/Library/Developer/CoreSimulator/Devices/7F24576E-DDA0-4DAC-95A7-F63A5DF54BD1/data/Containers/Bundle/Application/D42A6048-A58E-44CC-909F-F0C40EE06D14/Headquarters.app/Frameworks/Argo.framework/Argo

Convert JSON field to enum value

Hey,

can you give me please an example how I could parse a JSON when one of my struct fields is of an enum type? Lets take the following example:

struct Money {
  let amount: String
  let currecy: CurrencyValue
}

enum CurrencyValue : String {
  case EUR = "EUR"
  case unknown = "unknown"
}

The JSON keys are the same as the struct variable names amount and currency. I get the error

Type 'CurrencyValue' does not conform to protocol 'JSONDecodable'

How can I get rid of this? Can you give me an example how to make an enum conform to this protocol?

Argo from Carthage stuck cloning/fetching runes.

When following the instructions to install Argo using Carthage it hangs on getting the runes package.

> carthage update
*** Cloning Argo
*** Cloning Box
*** Cloning runes

It will sit there (left it overnight) until ^C
Running with the carthage update --verbose flag gives no additional info and after retrying I get this instead:

> carthage update
*** Fetching Argo
*** Fetching Box
*** Fetching runes

I'm running Xcode 6.4 (6E14) command line tools but tried this with the 6.3 with the same result.

Parse a long JSON with Argo

Hey,
I use Argo for parsing a JSON with 16 different elements.
In that case Xcode compiler said that it's too complex to do it.
So I remove one argument in my parsing code to only parse 15 elements and in that case Xcode compile it very slowly.
See below my JSON parsing example:

extension Post: JSONDecodable {
    class func create(post_id: Int)(title: String)(description: String)(author: String)(opinion: String?)(nb_love: Int)(nb_like: Int)(nb_support: Int)(nb_nocare: Int)(nbcomment : Int)(mediaURL_small: String)(mediaURL_medium: String)(mediaURL_big: String)(type_media: Int)(create_date: String)(update_date: String) -> Post {
        return Post(post_id: post_id, title: title, description: description, author: author, opinion: opinion, nb_love: nb_love, nb_like: nb_like, nb_support: nb_support, nb_nocare: nb_nocare, nbcomment: nbcomment, mediaURL_small: mediaURL_small, mediaURL_medium: mediaURL_medium, mediaURL_big: mediaURL_big, type_media: type_media, create_date: create_date, update_date: update_date)
    }

    class func decode(j: JSONValue) -> Post? {
        return Post.create
            <^> j <| "post_id"
            <*> j <| "title"
            <*> j <| "description"
            <*> j <| ["author", "username"]
            <*> j <|? "opinion"
            <*> j <| ["opinions", "love"]
            <*> j <| ["opinions", "like"]
            <*> j <| ["opinions", "support"]
            <*> j <| ["opinions", "nocare"]
            <*> j <| "nbcomments"
            <*> j <| ["media", "url_small"]
            <*> j <| ["media", "url_medium"]
            <*> j <| ["media", "url_big"]
            <*> j <| ["media", "type_id"]
            <*> j <| "create"
            <*> j <| "update"
    }
}

I had this same problem with a big addition. Xcode refuse to compile because make 7 or more addition is to complex to compile on Swift (normal, it's functional language ;) ). The solution was to split the addition in 7 instructions.

So, I have done the same thing to my JSON parsing.
See below my example:

extension Post: JSONDecodable {
    class func create(post_id: Int)(title: String)(description: String)(author: String)(opinion: String?)(nb_love: Int)(nb_like: Int)(nb_support: Int)(nb_nocare: Int)(nbcomment : Int)(mediaURL_small: String)(mediaURL_medium: String)(mediaURL_big: String)(type_media: Int)(create_date: String)(update_date: String) -> Post {
        return Post(post_id: post_id, title: title, description: description, author: author, opinion: opinion, nb_love: nb_love, nb_like: nb_like, nb_support: nb_support, nb_nocare: nb_nocare, nbcomment: nbcomment, mediaURL_small: mediaURL_small, mediaURL_medium: mediaURL_medium, mediaURL_big: mediaURL_big, type_media: type_media, create_date: create_date, update_date: update_date)
    }

    class func decode(j: JSONValue) -> Post? {
        return decode_media(j)
            <*> j <| "create"
            <*> j <| "update"
    }

    class func decode_media(j: JSONValue) -> ((create_date: String) -> (update_date: String) -> Post){
        return (decode_comment(j)
            <*> j <| ["media", "url_small"]
            <*> j <| ["media", "url_medium"]
            <*> j <| ["media", "url_big"]
            <*> j <| ["media", "type_id"])!
    }

    class func decode_comment(j: JSONValue) -> ((mediaURL_small: String) -> (mediaURL_medium: String) -> (mediaURL_big: String) -> (type_media: Int) -> (create_date: String) -> (update_date: String) -> Post){
        return (decode_init(j)
            <*> j <|? "opinion"
            <*> j <| ["opinions", "love"]
            <*> j <| ["opinions", "like"]
            <*> j <| ["opinions", "support"]
            <*> j <| ["opinions", "nocare"]
            <*> j <| "nbcomments")!
    }

    class func decode_init(j: JSONValue) -> ((opinion: String?) -> (nb_love: Int) -> (nb_like: Int) -> (nb_support: Int) -> (nb_nocare: Int) -> (nbcomment : Int) -> (mediaURL_small: String) -> (mediaURL_medium: String)  -> (mediaURL_big: String) -> (type_media: Int) -> (create_date: String) -> (update_date: String) -> Post){
        return (Post.create
            <^> j <| "post_id"
            <*> j <| "title"
            <*> j <| "description"
            <*> j <| ["author", "username"])!
    }
}

Now with this little trick my sources compile faster and without any errors or warnings.
I don't know if this is the better solution for this problem but this trick resolve it.

If a better solution exist, I take it.

Antoine

Root Array decoding to typealiased Array

Howdy, first I wanted to say thanks so much for this library - we are getting a huge amount of use out of it.

We're hitting a third party API that is returning a root array much like how you have in your test suite. Currently, we are typealiasing the plural of the Model like so:

struct Person . . . 
typealias People = [Person]

My question is, is there an easy to way to decode into this? We haven't been able to figure it out syntactically yet. For the Person type, the syntax goes like this

 if let j: AnyObject = body {
                let value = JSONValue.parse(j)
                let person = Person.decode(value)
                callback(.Success(Box(person)))
            }

We even tried giving up on the typealias People = [Person] and used a simple struct w/ one data type and the JSONDecodable extension, but I just can't quite grasp how the global decode function works - Swift 1.2 is most certainly not a fan, claiming it can't find it.

Thanks!

Extending Subclass of NSManagedObject

Hi,

I would switch to I’m trying to implement argo on an NSManagedObject subclass however when I implement JSONDecodable Xcode is unable to finish building.

Is this an issue with how I am trying to use Argo or something else?

Thanks

Use Generics when parsing

The REST API I'm using, uses the same structure to return paged results:

{
    "count": 17,
    "next": "http://52.16.199.142/api/products/12/?format=json&page=2",
    "previous": null,
    "results": [
        {
        }
    ]
}

I would ideally like to model this using generics like this:

public struct Page<T> {
    public let count : Int
    public let next : String?
    public let previous : String?
    public let results : [T]
}

I would not like to expose that T conforms to JSONDecodable in the declaration of the struct, but instead on the extension Page : JSONDecodable.

However, no matter how I write this implementation, the compiler either segfaults or takes forever to fail. Has anyone accomplished something like this yet?

turning back to Json

Is there a recommended way to turn back into JSON?
Or would it be best to use NSJSONSerialization like so:

var params = ["id": id, "name":name, "email":email] as NSDictionary 
var err: NSError?
var stringJSON  = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)

JSON.parse performance

Hello all,

When parsing a huge 200KB JSON file, I'm seeing performance of an order of magnitude higher in Argo than when using Mantle in Objective C. Parsing the same JSON in Mantle+ObjC takes ~70ms and Argo+Swift instead take ~620ms on an iPhone 6 (measured with [XCTestCase measureBlock:])

Profiling the sample app, I can see that the vast majority of the CPU time in my code is in the JSON.parse call:
profile-1

Going deeper, I can see this:

profile-1

I don't think there's a more efficient way of writing this parser, or is there anything you guys have in the roadmap that could make this more performant?

All the best!

Add JSONEncodable as well?

I don't know if it's seen as in the scope of this project, but wouldn't it be nice to have a JSONEncodable protocol as well? Something like this:

public protocol JSONEncodable {
  func encode() -> JSONValue
}

With some smart use of the LiteralConvertible protocols the implementation could look something like this:

extension User: JSONEncodable {
  func encode() -> JSONValue {
    return ["id":id,"name":name,"email":email]
  }
}

I've made an example of this in my fork of Argo: https://github.com/nvh/Argo/blob/master/Argo/Globals/JSONValue.swift#L95

Will this be something worth making a pull request from?

Issue with Argo + Carthage

I am unable to use Argo successfully in a new app using Carthage as my dependency manager.

https://github.com/czeluff/TryArgo

I have taken the standard Xcode new project and incorporated Argo by linking against Runes & Argo. In User.swift, I attempt to write the 'create' method for a User. I receive the error saying that it cannot find the '<*>' operator. If I attempt to 'import Runes' as well to the top of my file, Xcode builds infinitely.

Apologies if this is user error on my part. Based on the solution, I am happy to recommend new instructions for Argo + Carthage installation that make more sense.

Parsing DICTIONARY of JSON Objects

Hi again,

how can I parse a dictionary of JSON objects like that:

"creatures": {
                  "mammal": {
                    "name": "human",
                    "description": "description text"
                  },
                  "fish": {
                    "name": "shark",
                    "description": "attention: snappy"
                  }
}

The destination structure should be [CreatureTypeEnum : Creature]. Is that possible? Of course Creatures and CreatureTypeEnum conforms to JSONDecodable too.

The compiler hangs compiling my struct extension

Hi,

I have a struct that has 16 fields. Is that too large for your library? Here It is:

extension ContractOverview {
                    static func create
                        (status: ContractOverviewStatusValue)
                        (key: ContractKey?)
                        (customerNumber: String?)
                        (customerName: String?)
                        (phoneNumber: String?)
                        (tariffName: String?)
                        (debitor: String?)
                        (endOfBinding: String?)
                        (prepaidBalance: PrepaidBalance?)
                        (consumption: [ConsumptionItem])
                        (cost: CostItem)
                        (pass: Pass?)
                        (hasOpenOrder: ContractOverviewHasOpenOrderValue)
                        (informationservice: Bool)
                        (invoiceType: ContractOverviewInvoiceType)
                        (amount : String?) -> ContractOverview {

                            return ContractOverview(status: status, key: key, customerNumber: customerNumber, customerName: customerName, phoneNumber: phoneNumber, tariffName: tariffName, debitor: debitor, endOfBinding: endOfBinding, prepaidBalance: prepaidBalance, consumption: consumption, cost: cost, pass: pass, hasOpenOrder: hasOpenOrder, informationservice: informationservice, invoiceType: invoiceType, amount: amount)
                    }

                    static func decode(j: JSONValue) -> ContractOverview? {
                        return ContractOverview.create
                            <^> j <|  "status"
                            <*> j <|?  "key"
                            <*> j <|?  "customerNumber"
                            <*> j <|?  "customerName"
                            <*> j <|?  "phoneNumber"
                            <*> j <|?  "tariffName"
                            <*> j <|?  "Debitor"
                            <*> j <|?  "endOfBinding"
                            <*> j <|?  "prepaidBalance"
                            <*> j <|  "consumption"
                            <*> j <|  "currentCost"
                            <*> j <|?  "pass"
                            <*> j <|  "hasOpenOrder"
                            <*> j <|  "informationservice"
                            <*> j <|  "invoiceType"
                            <*> j <|?  "amount"
                }
}

Maybe I made a typo but I already looked at it for about an hour. help

This is the enum:

struct ContractOverview {
    var status = ContractOverviewStatusValue.incomplete
    var key : ContractKey?
    var customerNumber : String?
    var customerName : String?
    var phoneNumber : String?
    var tariffName : String?
    var debitor : String?
    var endOfBinding : String?
    var prepaidBalance : PrepaidBalance?
    var consumption = [ConsumptionItem]()
    var cost: CostItem
    var pass : Pass?
    var hasOpenOrder = ContractOverviewHasOpenOrderValue.indeterminable
    var informationservice = false
    var invoiceType = ContractOverviewInvoiceType.unknown
    var amount: String?
}

OS X framework

I'd love to be able to use Argo within Carthage, but there's currently only an iOS target. 😢

Error: `Decoded.swift` missing module "Box"

When I upgrade an Xcode 6.2 project to 6.3 beta, and update the Podfile to point Argo to GitHub, then I get the error about missing module Box.

In case it's helpful to know, I also have a Podfile entry for Runes, also updated to point to GitHub.

I don't see any definition for "Box" in the Argo source, nor in the Runes source.

Any ideas for a solution?

readme.md examples don't match the code

Hi... first time Argo user, so apologies if I'm misinterpreting things.

The example shown in Argo's readme.md has the following example:

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

However, JSONDecodable's definition is as follows:

static func decode(json: JSON) -> Decoded<DecodedType>

I assume that the correct code is:

static func decode(j: JSON) -> Decoded<User>

Is that correct? I'd submit a pull request, except that as a novice, it is possible (likely?) that I have no clue what I'm doing 😄

Extracting Swift values from JSONValue?

I have 2 stupid questions, using the comment.json file from ArgoTests as sample JSON data:

{
  "id": 6,
  "text": "Cool story bro.",
  "author": {
    "id": 1,
    "name": "Cool User"
  }
}
// Import JSONFileReader from ArgoTests
let jsonData: AnyObject? = JSONFileReader.JSON(fromFile: "comment")

let jsonComment = JSONValue.parse <^> jsonData!

let j = jsonComment!

let id: Int = j["id"]?.value()      // Error: Value of optional type 'Int?' not unwrapped"
let id: Int = j["id"]?.value()!     // Same error message as above
let text: String = j["text"]?.value()    // Ditto
  1. How do I extract the Swift value for j["id"] and j["text"]?
    let id: Int = j["id"]?.value() // Error: Value of optional type 'Int?' not unwrapped, did you mean to use ! or ? I would like id = 6.
  2. How do I extract j["author"] as a Swift Dictionary<[String: JSONValue]>? So I can then iterate over the keys and use my knowledge from question 1, above, to extract the JSONValue's.

I am using Swift 1.1 in Xcode 6.2 latest Beta (6C121). Any help will be greatly appreciated. Thank you

Segmentation fault 11

I think I just ran into another Swift Compiler isse, but want to report it here just to make sure.

// Inside `decode:`
let x = (j <| "valid_until") >>- parseDate
// ...

class func parseDate(dateString: String) -> NSDate? {
        return NSDate()
}

Using Xcode 6.2 beta 4, the above code fails with

Command failed due to signal: Segmentation fault: 11

However, this works as expected

// Inside `decode:`
let x = parseDate(j <| "valid_until")
// ...

class func parseDate(dateString: String?) -> NSDate? { // note optional dateString here
        return NSDate()
}

Handling [String:String] dictionaries

Hi, I've been using Argo in a new Swift project and am loving it so far - it is my first real foray into functional programming so pretty much everything is a learning curve :-)

I've managed to create my own model objects and can successfully parse my JSON except for one last thing - handling [String:String] data. Imagine that my (simplified) model object looks something like this:

struct User {
    let name: String
    let age: Int
    let metadata: [String:String]
}

My JSON would look like this:

{
    "name" : "John Smith",
    "age"  : 42,
    "metadata" : {
        "field1" : "some value",
        "otherField" : "foo bar"
    }
}

The metadata property is really just a collection of random name/value pairs. There could be none, or there could be 50 and I don't know ahead of time what the keys are (hence it is modelled as a [String:String])

Unfortunately, Decoded<[String:String]> is not a supported return type for the <| operator. At the moment, my half-baked solution is to create an object that represents this type of dictionary and then traverse over the JSON values (see below). But it just doesn't feel right. Just curious if there is a better way? Any thoughts or guidance would be much appreciated. Thanks.

struct StringDictionary {
    let values: [String:String]
    init(_ values: [String:String]) {
        self.values = values
    }
}
extension StringDictionary : JSONDecodable {
    static func decode(j: JSON) -> Decoded<StringDictionary> {
        switch j {
        case .Object(let s):
            var values = [String:String]()
            // TODO not sure how to traverse a list of un-named keys
            return .Success(Box(StringDictionary(values)))
        default: return .TypeMismatch("\(j) is not a valid [String:String] dictionary")
        }
    }
}

Get crazy with documentation

Because of the amount of overhead for this library, we really need to up our documentation game. We should add a Documentation directory with tutorials, examples, and explanations.

Expression too long issues in Xcode 6.3 / Swift 1.2

Apologies for the enormous code block - figure I should just show this in its entirety. I've seen previous issues related to this need to break up the object into multiple pieces to make the 'decode' function work properly. However, I also appear to be having an issue with the curried 'create' function - it seems to be giving up around "item3" due to too many parameters.

Some people have shown potential fixes by breaking up 'decode' like so but this is not compiling for me, either.

If I need to break up the object into multiple pieces, I'll have to. Though this can be pretty annoying, requiring more curried 'create' functions.

public struct RawStats {
    let assists: Int
    let barracksKilled: Int
    let championsKilled: Int
    let combatPlayerScore: Int
    let consumablesPurchased: Int
    let damageDealtPlayer: Int
    let doubleKills: Int
    let firstBlood: Int
    let gold: Int
    let goldEarned: Int
    let goldSpent: Int
    let item0: Int
    let item1: Int
    let item2: Int
    let item3: Int
    let item4: Int
    let item5: Int
    let item6: Int
    let itemsPurchased: Int
    let killingSprees: Int
    let largestCriticalStrike: Int
    let largestKillingSpree: Int
    let largestMultiKill: Int
    let legendaryItemsCreated: Int
    let level: Int
    let magicDamageDealtPlayer: Int
    let magicDamageDealtToChampions: Int
    let magicDamageTaken: Int
    let minionsDenied: Int
    let minionsKilled: Int
    let neutralMinionsKilled: Int
    let neutralMinionsKilledEnemyJungle: Int
    let neutralMinionsKilledYourJungle: Int
    let nexusKilled: Bool
    let nodeCapture: Int
    let nodeCaptureAssist: Int
    let nodeNeutralize: Int
    let nodeNeutralizeAssist: Int
    let numDeaths: Int
    let numItemsBought: Int
    let objectivePlayerScore: Int
    let pentaKills: Int
    let physicalDamageDealtPlayer: Int
    let physicalDamageDealtToChampions: Int
    let physicalDamageTaken: Int
    let playerPosition: Int
    let playerRole: Int
    let quadraKills: Int
    let sightWardsBought: Int
    let spell1Cast: Int
    let spell2Cast: Int
    let spell3Cast: Int
    let spell4Cast: Int
    let summonSpell1Cast: Int
    let summonSpell2Cast: Int
    let superMonsterKilled: Int
    let team: Int
    let teamObjective: Int
    let timePlayed: Int
    let totalDamageDealt: Int
    let totalDamageDealtToChampions: Int
    let totalDamageTaken: Int
    let totalHeal: Int
    let totalPlayerScore: Int
    let totalScoreRank: Int
    let totalTimeCrowdControlDealt: Int
    let totalUnitsHealed: Int
    let tripleKills: Int
    let trueDamageDealtPlayer: Int
    let trueDamageDealtToChampions: Int
    let trueDamageTaken: Int
    let turretsKilled: Int
    let unrealKills: Int
    let victoryPointTotal: Int
    let visionWardsBought: Int
    let wardKilled: Int
    let wardPlaced: Int
    let win : Bool
}

extension RawStats: JSONDecodable {
    static func create(assists: Int)(barracksKilled: Int)(championsKilled: Int)(combatPlayerScore: Int)(consumablesPurchased: Int)(damageDealtPlayer: Int)(doubleKills: Int)(firstBlood: Int)(gold: Int)(goldEarned: Int)(goldSpent: Int)(item0: Int)(item1: Int)(item2: Int)(item3: Int)(item4: Int)(item5: Int)(item6: Int)(itemsPurchased: Int)(killingSprees: Int)(largestCriticalStrike: Int)(largestKillingSpree: Int)(largestMultiKill: Int)(legendaryItemsCreated: Int)(level: Int)(magicDamageDealtPlayer: Int)(magicDamageDealtToChampions: Int)(magicDamageTaken: Int)(minionsDenied: Int)(minionsKilled: Int)(neutralMinionsKilled: Int)(neutralMinionsKilledEnemyJungle: Int)(neutralMinionsKilledYourJungle: Int)(nexusKilled: Bool)(nodeCapture: Int)(nodeCaptureAssist: Int)(nodeNeutralize: Int)(nodeNeutralizeAssist: Int)(numDeaths: Int)(numItemsBought: Int)(objectivePlayerScore: Int)(pentaKills: Int)(physicalDamageDealtPlayer: Int)(physicalDamageDealtToChampions: Int)(physicalDamageTaken: Int)(playerPosition: Int)(playerRole: Int)(quadraKills: Int)(sightWardsBought: Int)(spell1Cast: Int)(spell2Cast: Int)(spell3Cast: Int)(spell4Cast: Int)(summonSpell1Cast: Int)(summonSpell2Cast: Int)(superMonsterKilled: Int)(team: Int)(teamObjective: Int)(timePlayed: Int)(totalDamageDealt: Int)(totalDamageDealtToChampions: Int)(totalDamageTaken: Int)(totalHeal: Int)(totalPlayerScore: Int)(totalScoreRank: Int)(totalTimeCrowdControlDealt: Int)(totalUnitsHealed: Int)(tripleKills: Int)(trueDamageDealtPlayer: Int)(trueDamageDealtToChampions: Int)(trueDamageTaken: Int)(turretsKilled: Int)(unrealKills: Int)(victoryPointTotal: Int)(visionWardsBought: Int)(wardKilled: Int)(wardPlaced: Int)(win: Bool) -> RawStats {

            return RawStats(assists: assists, barracksKilled: barracksKilled, championsKilled: championsKilled, combatPlayerScore: combatPlayerScore, consumablesPurchased: consumablesPurchased, damageDealtPlayer: damageDealtPlayer, doubleKills: doubleKills, firstBlood: firstBlood, gold: gold, goldEarned: goldEarned, goldSpent: goldSpent, item0: item0, item1: item1, item2: item2, item3: item3, item4: item4, item5: item5, item6: item6, itemsPurchased: itemsPurchased, killingSprees: killingSprees, largestCriticalStrike: largestCriticalStrike, largestKillingSpree: largestKillingSpree, largestMultiKill: largestMultiKill, legendaryItemsCreated: legendaryItemsCreated, level: level, magicDamageDealtPlayer: magicDamageDealtPlayer, magicDamageDealtToChampions: magicDamageDealtToChampions, magicDamageTaken: magicDamageTaken, minionsDenied: minionsDenied, minionsKilled: minionsKilled, neutralMinionsKilled: neutralMinionsKilled, neutralMinionsKilledEnemyJungle: neutralMinionsKilledEnemyJungle, neutralMinionsKilledYourJungle: neutralMinionsKilledYourJungle, nexusKilled: nexusKilled, nodeCapture: nodeCapture, nodeCaptureAssist: nodeCaptureAssist, nodeNeutralize: nodeNeutralize, nodeNeutralizeAssist: nodeNeutralizeAssist, numDeaths: numDeaths, numItemsBought: numItemsBought, objectivePlayerScore: objectivePlayerScore, pentaKills: pentaKills, physicalDamageDealtPlayer: physicalDamageDealtPlayer, physicalDamageDealtToChampions: physicalDamageDealtToChampions, physicalDamageTaken: physicalDamageTaken, playerPosition: playerPosition, playerRole: playerRole, quadraKills: quadraKills, sightWardsBought: sightWardsBought, spell1Cast: spell1Cast, spell2Cast: spell2Cast, spell3Cast: spell3Cast, spell4Cast: spell4Cast, summonSpell1Cast: summonSpell1Cast, summonSpell2Cast: summonSpell2Cast, superMonsterKilled: superMonsterKilled, team: team, teamObjective: teamObjective, timePlayed: timePlayed, totalDamageDealt: totalDamageDealt, totalDamageDealtToChampions: totalDamageDealtToChampions, totalDamageTaken: totalDamageTaken, totalHeal: totalHeal, totalPlayerScore: totalPlayerScore, totalScoreRank: totalScoreRank, totalTimeCrowdControlDealt: totalTimeCrowdControlDealt, totalUnitsHealed: totalUnitsHealed, tripleKills: tripleKills, trueDamageDealtPlayer: trueDamageDealtPlayer, trueDamageDealtToChampions: trueDamageDealtToChampions, trueDamageTaken: trueDamageTaken, turretsKilled: turretsKilled, unrealKills: unrealKills, victoryPointTotal: victoryPointTotal, visionWardsBought: visionWardsBought, wardKilled: wardKilled, wardPlaced: wardPlaced, win: win)
    }

    public static func decode(j: JSON) -> Decoded<RawStats> {
        return RawStats.create
        <*> j <| "assists"
        <*> j <| "barracksKilled"
        <*> j <| "championsKilled"
        <*> j <| "combatPlayerScore"
        <*> j <| "consumablesPurchased"
        <*> j <| "damageDealtPlayer"
        <*> j <| "doubleKills"
        <*> j <| "firstBlood"
        <*> j <| "gold"
        <*> j <| "goldEarned"
        <*> j <| "goldSpent"
        <*> j <| "item0"
        <*> j <| "item1"
        <*> j <| "item2"
        <*> j <| "item3"
        <*> j <| "item4"
        <*> j <| "item5"
        <*> j <| "item6"
        <*> j <| "itemsPurchased"
        <*> j <| "killingSprees"
        <*> j <| "largestCriticalStrike"
        <*> j <| "largestKillingSpree"
        <*> j <| "largestMultiKill"
        <*> j <| "legendaryItemsCreated"
        <*> j <| "level"
        <*> j <| "magicDamageDealtPlayer"
        <*> j <| "magicDamageDealtToChampions"
        <*> j <| "magicDamageTaken"
        <*> j <| "minionsDenied"
        <*> j <| "minionsKilled"
        <*> j <| "neutralMinionsKilled"
        <*> j <| "neutralMinionsKilledEnemyJungle"
        <*> j <| "neutralMinionsKilledYourJungle"
        <*> j <| "nexusKilled"
        <*> j <| "nodeCapture"
        <*> j <| "nodeCaptureAssist"
        <*> j <| "nodeNeutralize"
        <*> j <| "nodeNeutralizeAssist"
        <*> j <| "numDeaths"
        <*> j <| "numItemsBought"
        <*> j <| "objectivePlayerScore"
        <*> j <| "pentaKills"
        <*> j <| "physicalDamageDealtPlayer"
        <*> j <| "physicalDamageDealtToChampions"
        <*> j <| "physicalDamageTaken"
        <*> j <| "playerPosition"
        <*> j <| "playerRole"
        <*> j <| "quadraKills"
        <*> j <| "sightWardsBought"
        <*> j <| "spell1Cast"
        <*> j <| "spell2Cast"
        <*> j <| "spell3Cast"
        <*> j <| "spell4Cast"
        <*> j <| "summonSpell1Cast"
        <*> j <| "summonSpell2Cast"
        <*> j <| "superMonsterKilled"
        <*> j <| "team"
        <*> j <| "teamObjective"
        <*> j <| "timePlayed"
        <*> j <| "totalDamageDealt"
        <*> j <| "totalDamageDealtToChampions"
        <*> j <| "totalDamageTaken"
        <*> j <| "totalHeal"
        <*> j <| "totalPlayerScore"
        <*> j <| "totalScoreRank"
        <*> j <| "totalTimeCrowdControlDealt"
        <*> j <| "totalUnitsHealed"
        <*> j <| "tripleKills"
        <*> j <| "trueDamageDealtPlayer"
        <*> j <| "trueDamageDealtToChampions"
        <*> j <| "trueDamageTaken"
        <*> j <| "turretsKilled"
        <*> j <| "unrealKills"
        <*> j <| "victoryPointTotal"
        <*> j <| "visionWardsBought"
        <*> j <| "wardKilled"
        <*> j <| "wardPlaced"
        <*> j <| "win"
    }
}

EXC_BAD_ACCESS when running tests on 32-bit simulator

I'm using the Xcode 6.3-Beta and the latest Argo from master. When I'm running tests for example on iPhone 5 simulator it crashes on first attempt to map json property to model property. For example in

EmbeddedJSONDecodingTests.swift:

func testCommentDecodingWithEmbeddedUserName() {
    let json = JSONValue.parse <^> JSONFileReader.JSON(fromFile: "comment")
    self.json2 = json
    let comment = self.json2 >>- Comment.decode

    XCTAssert(comment != nil)
    XCTAssert(comment?.id == "6")
    XCTAssert(comment?.text == "Cool story bro.")
    XCTAssert(comment?.authorName == "Cool User")
  }

Comment.swift:

return Comment.create
      <^> j <| "id" // Crashes on this line
      <*> j <| "text"
      <*> j <| ["author", "name"]

This happens also when running app which uses Argo on the simulator. When running tests on iPhone 6 simulator it does not crash.

Cocoapods problem

I used cocoapods to fetch Argo. It has a dependency on Runes in the JSONOperators file. But Runes doesn't have a Podspec so Argo won't compile..

Have JSONValue conform to JSONDecodable

If JSONValue conforms to JSONDecodable, we can cut the number of operators we define in half in favor of using chained parsing operators.

j <| ["foo", "bar"] would become j <| "foo" <| "bar"

This would also allow us to get rid of subscript, as well as find probably.

There might be performance implications here.

Recursive (boxed) type

Using the example from the README, how would one set up decoding of bestFriend?

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

How to deal with root level Array?

Something like this, that doesn't come wrapped in a root Dictionary with a key to pull it out of...

[
    {
        "id": 12345,
        "foo": "bar"
    },
    {
        "id": 23456,
        "foo": "bar"
    },
    {
        "id": 34567,
        "foo": "bar"
    },
]

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 😄

framework search paths issue when using submodules

When using the Carthage flag --use-submodules and --no-build in a project that depends on Argo, Argo's framework search paths do not exist because they point to the Carthage build directory. However, removing these breaks the build when not using those flags.

This issue can be a discussion on how to fix this.

@paulyoung Please add any info to this issue that I might have missed above.

Parse multiple kind of structs in same array

Is there any way Argo can be used to parse an array where different kind of structs are stored?

Example:

{
    "result": [
        {
            "item": {
                "itemId": 490538
            }

            "collection": {
                "collectionId": 1101
            }
        }
    ]
}

Given off course struct Itemand struct Collection that comply to JSONDecodable protocol.

All the best and thanks for this amazing library!

JSONDecodable Compile Error

The line below in JSONDecodable.swift caused the error:

static func decode(JSONValue) -> DecodedType?

Error: Static methods are only allowed within structs and enums; use 'class' to declare a class method

changing static to class like the error said seems to solve the issue.

Returning some of a JSON array

Let's say the server returns a JSON array of photos. Each photo should have an ID, a URL, and maybe the name of the person who took it.

struct Photo {
   let id: String
   let authorName: String
   let URL: NSURL
}

Now, we don't wanna show a photo in the app if info is missing. A photo without the author's name breaks things, so I don't wanna mark it as optional. However, in it's current form, the decode function would return nil if one photo out of 20 were missing the name.

How complicated would it be to make decode return the 19 valid photos and maybe have information somewhere to say "this one photo was invalid" instead of showing 0 photos in the app when 19 are totally fine to show?

Examples for decoding json array to list?

I can't find any examples of how to decode into an array/list of values. For instance, if I had a json array

[{"foo":"bar"}, {"foo":"bar"}]

and wanted to decode:

let foos: [Foo] = decode(j)

TypeMismatch: "Null is not a Int"

I just updated Argo to 1.0.0 and I'm seeing a regression:

I have a model with some optional values and when I try to parse a JSON containing a null value (an NSNull), I'm getting a TypeMismatch: "Null is not a Int" in runtime.

Here's the model:

public struct Identifiers {
    public let trakt: Int
    public let tvdb: Int?
    public let imdb: String?
    public let tmdb: Int?
    public let tvrage: Int?
    public let slug: String?
}

extension Identifiers: Decodable {
    static func create(trakt: Int)(tvdb: Int?)(imdb: String?)(tmdb: Int?)(tvrage: Int?)(slug: String?) -> Identifiers {
        return Identifiers(trakt: trakt, tvdb: tvdb, imdb: imdb, tmdb: tmdb, tvrage: tvrage, slug: slug)
    }

    public static func decode(j: JSON) -> Decoded<Identifiers> {
        return Identifiers.create
            <^> j <| "trakt"
            <*> j <|? "tvdb"
            <*> j <|? "imdb"
            <*> j <|? "tmdb"
            <*> j <|? "tvrage"
            <*> j <|? "slug"        
    }
}

And the parse itself:

let json: NSDictionary = [
            "trakt": 36440,
            "tvdb": 3254641,
            "imdb": "tt1480055",
            "tmdb": 63056,
            "tvrage": NSNull()
        ]

let value = JSON.parse(json)
 let id = Identifiers.decode(value)

Any thoughts? I could remove the keys with NSNull values from the dictionary, but I think Argo should handle it (as it was before 1.0.0).

`decode` function comparison without Argo

I love Argo but am currently considering whether adding it and its dependencies is appropriate for a framework.

The README says this:

extension User: JSONDecodable {
  static func decode(j: JSONValue) -> User? {
    return User.create
      <^> j <| "id"
      <*> j <| "name"
  }
}

For comparison, this same function without Argo would look like so:

extension User {
  static func decode(j: NSDictionary) -> User? {
    if let id = j["id"] as Int {
      if let name = j["name"] as String {
        return User(id: id, name: name)
      }
    }

    return .None
  }
}

Am I correct in thinking that a full comparison would be something like the following?


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

extension User: JSONDecodable {
  static func decode(j: JSONValue) -> User? {
    return User.create
      <^> j <| "id"
      <*> j <| "name"
      <*> j <|? "email"
      <*> j <| "role"
      <*> j <| ["company", "name"]
      <*> j <|| "friends"
      <*> j <|? ["team", "name"]
      <*> j <||? ["team", "members"]
  }
}

For comparison, this same function without Argo would look like so:

extension User {
  static func decode(j: NSDictionary) -> User? {
    if let id = j["id"] as? Int,
      name = j["name"] as? String,
      email = j["email"] as? String?
      role = j["role"] as? Role,
      companyName = j["company"]["name"] as? String,
      friends = j["friends"] as? [User],
      teamName = j["team"]["name"] as? String?,
      teamMembers = j["team"]["members"] as? [User]? {
        return User(
          id: id,
          name: name,
          email: email,
          role: role,
          companyName: companyName,
          friends: friends,
          teamName: teamName,
          teamMembers: teamMembers
        )
      }

    return .None
  }
}

Converting types when decoding

Hi guys,

I'm trying to use Argo and convert a String to NSURL inside the decode method. I thought that using flatMap (>>-) was enough, but this way the compiler just hangs:

struct JSONParseUtils {
    static func parseURL(URLString: String) -> NSURL? {
        return NSURL(string: URLString)
    }
}

public struct ImagesURLs {
    public let fullImageURL: NSURL?
    public let mediumImageURL: NSURL?
    public let thumbImageURL: NSURL?
}

extension ImagesURLs: JSONDecodable {
    static func create(fullImageURL: NSURL?)(mediumImageURL: NSURL?)(thumbImageURL: NSURL?) -> ImagesURLs {
        return ImagesURLs(fullImageURL: fullImageURL, mediumImageURL: mediumImageURL, thumbImageURL: thumbImageURL)
    }

    public static func decode(j: JSONValue) -> ImagesURLs? {
        return ImagesURLs.create
            <^> j <|? "full"  >>- JSONParseUtils.parseURL
            <*> j <|? "medium" >>- JSONParseUtils.parseURL
            <*> j <|? "thumb" >>- JSONParseUtils.parseURL
    }
}

Changing parseURL to receive an String? (and adapting it) works, but once a field is nil in a JSON, decode returns nil (it should continue evaluating).

NOTE: I solved this by creating an extension on NSURL that conforms to JSONDecodable, but sometimes this may not be possible. For example: I could want to create an NSDate and have two possible formats (e.g. UNIX timestamp and ISO-8601).

Also, it'd be great to include this kind of example on README or some other place.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.