freshOS / Arrow

🏹 Parse JSON with style
MIT License
387 stars 27 forks source link

Nested #13

Closed s4cha closed 8 years ago

s4cha commented 8 years ago

This is not meant to be merged yet. This is a work in progress. Here we experiment using a strong JSON Type over AnyObject.

This means we have a better control over what we can do on a JSON object and for instance add features on it.

For example here a subscript has been added so that nested resources can be accessed like so :

meaningOfLife <-- json["nested.nested.nested.nestedValue"]

We can also access array transparently

someObject <-- json[12]

This means we can also do things like this :

value <-- json[1]?["someKey"]?[2]?["something.other"]

Another change is removing the <==fat arrow operator and using <-- everywhere instead

@maxkonovalov I'd love your feedback on the idea of having a strong JSON type ;)

maxkonovalov commented 8 years ago

Hey @s4cha, that's quite big changes! Do you think that it's worth adding a separate JSON class though? It would require an extra step to parse the response, so maybe this could be achieved by still sticking to AnyObject? I'll look into this more and will let you know of my thoughts later.

maxkonovalov commented 8 years ago

Although this one might be a rare case, but what if a JSON value contains a string with another JSON that also needs to be parsed? I came across such issue and worked around it by extending Arrow and introducing a <~~ (a curvy arrow 😀) prefix operator, so the parsing looked like this:

/*
    json = { "json": "{ \"key\": \"value\" }" }
*/
innerJson <-- <~~json["json"]

Not sure if this should be implemented somehow by Arrow... What do you think?

s4cha commented 8 years ago

Thanks to the custom JSON object, the following is now possible :

createdAt <-- json["created_at"]?.dateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ")

This overrides the high level setting and enables to provide a custom date form on a case per case basis

s4cha commented 8 years ago

In order to loop over a JSON we previously had to do this :

if let collection = json.data as? [AnyObject] {
    for entry in collection {
        let jsonEntry = JSON(entry)!
        // Do something
    }
}

we can now write :

if let collection = json.collection {
    for jsonEntry in collection {
        //Do something
    }
}
s4cha commented 8 years ago

@maxkonovalov

That's quite big changes indeed :) I am trying this branch on a production app (with around 30 different models to parse) at the moment and its going great.

I think it needs more testing and discussion but so far I personally think this is worth it.

Concerning the JSON containing another JSON string, I don't really have an opinion, I didn't even know this existed! :) I am curious about what kind of backend would return something like this, and the reason why ?

Cheers,

maxkonovalov commented 8 years ago

Hey @s4cha! I tried out the new changes - they make the lib really powerful indeed! So I like the idea of going on with updating it 😋

What do you think of also being able to parse arrays within nested resources, like this:

x <-- json["nested.array.1"]

Here we can safely check if the resource under "array" key is an array and get its value at index 1, or in the case when it is a dictionary, get its value by "1" key.

On JSON inside JSON - as I told, it might be quite an uncommon scenario, it happened due to some limitations of the backend I use. For the app settings we add user-defined values, that are limited to text only in admin panel. So to be able to add an array for example, we still have to use JSON-formatted string and then parse it in the app. Anyway, not worth adding this to the lib I think, it's rather app-specific usage.

s4cha commented 8 years ago

@maxkonovalov super glad your like the new changes !! Also I love your suggestion about accessing arrays this way x <-- json["nested.array.1"] I think it's a very welcome addition :). I'm going to merge, bump to 2.0 and add this nice sugar syntax :)

s4cha commented 8 years ago

@maxkonovalov

x <-- json["nested.array.1"]

is now possible in v2.0.1 🎉

maxkonovalov commented 8 years ago

Cool, definitely need to try it out 😀