Mapping a Dictionary to a RestKit result - ios

In a JSON model coming from a REST api I have a field that is supposed to be a Dictionary (a map, hashtable, call it whatever you want), e.g.:
"moduleMap": {
"677e55b2-d80c-4b32-bcbb-e99074fbfcf6": {
"id": "677e55b2-d80c-4b32-bcbb-e99074fbfcf6",
"startTime": 1496054599227,
"status": "ACTIVE"
},
"c20acde2-639f-4cb7-9b90-6d8d24c78166": {
"id": "c20acde2-639f-4cb7-9b90-6d8d24c78166",
"startTime": 1496054598997,
"status": "UNAVAILABLE"
}
}
As I understand RestKit (I am a newbie), usually this is mapped to an object in Swift. However, since the keys in this map are arbitrary uuids, I cannot write a class with these properties.
Can anybody point me to a direction of how to get this map into a Swift dictionary using RestKit mapping?
I would like to map it to var moduleMap: [String:DomainObject], or at least var moduleMap: NSMutableDictionary. Also, I need it to be mappable back to the same JSON.

Related

NSDictionary find keyPath

I have a random dictionary, I want to iterate over all objects that are inside that dictionary. Is there a way to find keyPath of object that is inside the dictionary?
Let's say we have this dictionary .
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": [
"GML",
"XML"
]
},
"GlossSee": "markup"
}
}
}
}
}
Now I want to find keyPath of GlossEntry or any other object.
Consider:
You can obtain all the keys in a dictionary and iterate over them. E.g. for (NSString *key in dictionary) {...}
Given a key you can obtain the matching value and test whether it is itself a dictionary.
Recursion is your friend. You could write a function which takes a current key path prefix, a dictionary, and a mutable array to add found key paths to. The implementation of this would involve (1), (2) and a recursive call.
Now write yourself some code. If you get stuck ask a new question, include your code, and explain where you are stuck.
HTH

Getting user's complete information using TwitterKit

I'm using this API to get a user's followers list, and returns the followers in JSON format as described in the documentation. Here is a snippet of a returned object:
{
"users": [
{
"id": 2960784075,
"id_str": "2960784075",
"name": "Jesus Rafael Abreu M",
"screen_name": "chuomaraver",
"location": "",
"profile_location": null,
"url": null,
"description": "",
"protected": false,
"followers_count": 1,
"friends_count": 101,
"listed_count": 0,
"created_at": "Sun Jan 04 19:58:06 +0000 2015",
.....
.....
"default_profile": true,
"default_profile_image": false,
"following": false,
"follow_request_sent": false,
"notifications": false,
"muting": false
},
.....
.....
],
"next_cursor": 1489467234237774933,
"next_cursor_str": "1489467234237774933",
"previous_cursor": 0,
"previous_cursor_str": "0"
}
As you notice, the user object has a lot of properties, and I don't want to
parse them one by one or use a library to do that for me.
The TwitterKit has a class named TWTRUser, and here is it's documentation. To initialize an object of this class, you can just use a constructor that takes a JSON dictionary like this:
let follower = TWTRUser(jsonDictionary: jsonDictionary)
This way I can get the JSON Object the is returned to me parsed and initialize a TWTRUser object.
The problem is that TWTRUser doesn't have all the properties listed in the JSON returned, it only has these properties as listed in the documentation:
userID property
name property
screenName property
isVerified
property
isProtected property
profileImageURL property
profileImageMiniURL property
profileImageLargeURL property
formattedScreenName property
profileURL property
I tried to use valueForKey method that takes a key and returns it value like this:
let createdAt = follower.value(forKey: "created_at")
I thought it would work, but it didn't. When I use it the application crashes and gives me the following message:
Terminating app due to uncaught exception 'NSUnknownKeyException',
reason: '[ valueForUndefinedKey:]: this class
is not key value coding-compliant for the key contributors_enabled.'
What could I do to get all the user's properties using TWTRUser class?
value(forKey:) is a method inherited with NSObject and it is used for Key-Value Coding so it doesn't return results of the JSON. The TWTRUser class only defines 10 properties and that's all you can get with it. If you want to get other properties, you would have to parse the JSON yourself with the following line of code (using the standard library)
let user = try JSONSerialization.jsonObject(with: jsonDictionary) as? [String: Any]
First of all, like it's already been mentioned, don't use value(for key), if the object had that value it probably would expose it through a public property.
My suggestion would be to subclass TWTRUser, add the properties you want to your new class (you can call it something like TwitterUser) and override init(json), there you can see if the dictionary contains the values you want and add them to the object.
After that you'll be able to access those properties like you would with any other properties in the TWTRUser class.

Get object from an array of dictionaries with a specific key value pair?

So if I have a dictionary like the following:
{
"banners": [
{
"imageUrl": "www.google.com",
"destination": "home",
"position": 1
},
{
"imageUrl": "www.reddit.com",
"destination": "work",
"position": 2
},
{
"imageUrl": "www.imgur.com",
"destination": "play",
"position": 3
}
]
}
is there a way for me to say, "Get me the dictionary object where the value for the key 'position' = 3 without using a for loop?
Let's think about it. Oooh, there are a lot of ways! It's amazing what looking for just a moment at the documentation will tell you.
What you have as the value of the banners key is an array of dictionaries. So what you are looking for is an NSArray method. An NSArray method such as filteredArrayUsingPredicate:!
So you can write an NSPredicate that describes position as being equal to 3, and you'll get back an NSArray of all the dictionaries where that is true (in this case, an array of one dictionary).
Oh, here's another possibility: indexOfObjectPassingTest:. With this, you supply a block that specifies that the dictionary's position is 3, and you'll get back the index of that dictionary within this array (namely 2 in this case).
I could go on and on, but wouldn't it be better for you to learn to read the documentation for yourself? Here it is.

SwiftyJSON add array of JSON objects

I am trying to serialize my object graph into JSON using the SwiftyJSON Library. I have a function in a BirthdayEvent class named "toJSON" which converts individual Birthday Events into swiftyJSON objects successfully.
However I am keen to have something like the following structure to the JSON:
"birthdays" : [
{
"eventId": "...",
"date": "01/01/2000",
...
},
{
"eventId": "...",
"date": "01/02/2001",
...
},
...
]
I am finding it difficult to create a JSON dictionary with the String "birthday" as the key and the array of BirthdayEvent JSON items as the value.
I have the following code:
var birthdaysJSON: JSON = JSON(self.events.map { $0.toJSON() })
var jsonOutput : JSON = ["birthdays": birthdaysJSON]
The first line successfully creates a JSON object of the array of events, but I cannot seem to use this in the dictionary literal. I get an error of "Value of type 'JSON' does not conform to expected dictionary value type 'AnyObject'.
Can you tell me where I am going wrong, or am I over-complicating this?
To create a JSON dictionary, you have to initialize the JSON object on jsonOutput just like you did with birthdaysJSON:
var jsonOutput: JSON = JSON(["birthdays": birthdaysJSON])

RestKit JSON Mapping

I have given JSON and cannot parse partial data. It seems dictionary into dictionary:
{
"products": [
{
"id": 6796,
"title": "my title",
"description": "desc",
"code": "12345",
"valueType": "null",
"discounts": [
{
"minPrice": null,
"maxPrice": null,
"value": 20,
"avail": false
}
]
}
]
}
I am using the latest version of RESTKit but I cannot properly parse under discounts.
my RestKit settings are:
responseMapping.addAttributeMappingsFromDictionary([
"id" : "id",
"code" : "code",
"title" : "title",
"valueType" : "valueType",
"description" : "desc",
"discounts.minPrice" : "minPrice",
"discounts.maxPrice" : "maxPrice",
"discounts.value" : "value",
"discounts.avail" : "avail",
])
but all values below discounts always return Nil. What I am doing wrong?
You can't directly map using discounts.XXX because discounts is an array and you have no way to index into that array and extract a single value.
You either need to change the source JSON to compress the values out of the dictionary, or create a custom object that you can map each item in the discounts array to.
Technically you could map the whole discounts array, which would give you an array of dictionaries, that you could then unpack in the setter method, but the array of custom objects is usually a better approach.

Resources