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.
Related
I'm trying to hook some function in an class it works fine but I want to view one argumant that is an class instance and this class has field that is String type, but when I try to get this field I get some really weird type instead of the string
Here is the code:
var someclass = Java.use('com.myapp.classes.someclass.a');
// String (Object, String, Boolean)
someclass.getData.overload('com.myapp.classes.ClassContext',
'java.lang.String', 'java.lang.Boolean').implementation = function (a, b, c) {
console.log('com.myapp.classes.ClassContext.stringify: ',
JSON.stringify(a.fieldWithStringData), '\r\n');
}
But instead of string I get some weird object when I used JSON.stringify on this object I got string like this (pretty printed for this question):
{
"_p": ["<instance: com.myapp.classes.ClassContext>", 2, {
"className": "java.lang.String",
"name": "Ljava/lang/String;",
"type": "pointer",
"size": 1,
"defaultValue": "0x0"
}, "0xa3144614", "0xc2aaa8b0", "0xc2aace70"]
}
What is this object and how to get actual string from it, can some one help?
You can use like this: a.fieldWithStringData.value
I'm using the FSharp.Data.TypeProvider but I have an optional property that is not rendered as such.
I have this example JSON:
[
{
"error": {
"message": "Error validating access token: Session has expired on Friday, 24-Jul-20 16:00:00 PDT. The current time is Friday, 24-Jul-20 16:06:14 PDT.",
"type": "OAuthException",
"code": 190,
"error_subcode": 463,
"fbtrace_id": "A0yQG8l8ggauD5PMbYSnEyA"
}
},
{
"error": {
"message": "Error validating access token: Session has expired on Friday, 24-Jul-20 16:00:00 PDT. The current time is Friday, 24-Jul-20 16:06:14 PDT.",
"type": "OAuthException",
"code": 190,
"error_subcode": 463,
"fbtrace_id": "A0yQG8l8ggauD5PMbYSnEyA"
}
},
{
"data": [
{
"id": "17841511906082530"
}
]
}
]
The field error is read as Optional<Error> meanwhile the field data is Datum [], It should be Optional<Data>, this error seems to have something to do with the array, if I change the value of data to another type, like a number, it correctly infers the type.
Maybe is some cache that's wrong? How could I reset the TypeProvider cache?
OR am I doing something else wrong?
This issue is also reported in the github project: https://github.com/fsharp/FSharp.Data/issues/1322
That's expected behavior.
In your JSON string, data is an array, an empty array indicates None, thus the field Data is read as array. That makes sense.
The fact that each element of that array belongs to type Datum also makes sense because Datum is the single form of Data (plural form). Indeed, if you rename data to dogs you will see it is read as Dog [].
Update: I don’t think we can tell the type provider to infer the field data as Option<Datum[]>. To check whether it is actually an empty array or not existed, we need to examine the JsonValue field:
match node.JsonValue with
| JsonValue.Record [|("data", _)|] ->
// yep, we have field data here
| _ ->
// nope, field data is missed
I have an optional parameter in my web-service response which can or can not return null. What will be the best what to manage those?
As if I pass null in creator lets say for this structure:
{
"email": "test#test.com",
"profilePicture": null,
"firstTime": true,
"preference1": {
"$id": "26",
"$values": []
},
"Preference2": {
"$id": "27",
"$values": []
}
}
Now profilePicture is set to JSONNull and next time when I actually get profile URL it will not parse that and my response data to LNUser is nil. If I set this variable to String and null received response get set to nil.
You need
let profilePicture:URL?
quicktype needs an exhaustive set of examples, so make sure one of your samples includes a non-null value. Like this: https://app.quicktype.io?share=ldXiDP9cIKB1Q7CPJ7Id
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.
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])