Can't convert string into Json object - json

I have a json string (text2):
"{\"MsgType\":103,\"Msg\":\"{\"UserObject\":{\"SecretId\":\"dsofgihsdaoifhad=\",\"FirstName\":\"ASDGF\",\"LastName\":\"hdsa\",\"IsFemale\":0,\"PhoneOffice\":\"\",\"ISDCode\":\"\",\"PhonePersonal\":\"91923426989\",\"Designation\":\"\",\"Company\":\"\",\"TagLine\":\"helping
mplemented\",\"FbId\":\"\",\"FbURL\":\"\",\"FbToken\":\"\",\"GplusId\":\"\",\"GplusURL\":\"\",\"GplusToken\":\"\",\"LinkedinId\":\"\",\"LinkedinURL\":\"\",\"LinkedinToken\":\"\",\"Status\":\"\",\"Email\":\"\",\"DisplayPicture\":\"\",\"IsPrivatePhoneOffice\":0,\"IsPrivatePhonePersonal\":1,\"IsPrivateEmail\":0,\"DeviceType\":\"android\",\"NotificationRegistrationID\":\"APA9HZ_RmEy7gfbQtN-QBxXr7dafG394oT9Dg1HpAv7OaWbUsMOsfpMI1a_7Qa2aNkqBOWB3M29djtsRW0fWl4oZSG0bwVv1zEPDBAseZvv1eHfqVj_JUI8tZixX\",\"Location\":\"\",\"Latitude\":18.69943,\"Longitude\":77.12576,\"IsPrivate\":0},\"ConnectionStatus\":3,\"ConnectionType\":1,\"PreviousMeetings\":[{\"SecretId\":\"sadfosdfjasdf=\",\"FriendSecretId\":\"dsofgihsdaoifhad=\",\"MeetingTime\":1447088420440,\"Status\":\"\",\"MeetingNotes\":\"\",\"Location\":\"\",\"Latitude\":28.6994,\"Longitude\":77.1258,\"ContactType\":\"\"},{\"SecretId\":\"sadfosdfjasdf=\",\"FriendSecretId\":\"dsofgihsdaoifhad=\",\"MeetingTime\":1447088335275,\"Status\":\"\",\"MeetingNotes\":\"\",\"Location\":\"\",\"Latitude\":28.6994,\"Longitude\":77.1258,\"ContactType\":\"\"},{\"SecretId\":\"sadfosdfjasdf=\",\"FriendSecretId\":\"dsofgihsdaoifhad=\",\"MeetingTime\":1447088229120,\"Status\":\"\",\"MeetingNotes\":\"\",\"Location\":\"\",\"Latitude\":28.6994,\"Longitude\":77.1258,\"ContactType\":\"\"},{\"SecretId\":\"sadfosdfjasdf=\",\"FriendSecretId\":\"dsofgihsdaoifhad=\",\"MeetingTime\":1447088014838,\"Status\":\"\",\"MeetingNotes\":\"\",\"Location\":\"\",\"Latitude\":28.6994,\"Longitude\":77.1258,\"ContactType\":\"\"},{\"SecretId\":\"sadfosdfjasdf=\",\"FriendSecretId\":\"dsofgihsdaoifhad=\",\"MeetingTime\":1444547028931,\"Status\":\"\",\"MeetingNotes\":\"\",\"Location\":\"\",\"Latitude\":28.6994,\"Longitude\":77.1258,\"ContactType\":\"\"}]}\"}"
It contains a json object having 2 fields: MsgType and Msg. Msg further containes a serialized json object in form of string.
I need to read the value of MsgType as number and Msg as a json object.
I have tried couple of things:
Firstly:
if let dataFromString = text2.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
let json = JSON(data: dataFromString)
print("swiftyjson:\(json)")
}
Source: https://github.com/SwiftyJSON/SwiftyJSON#initialization
Output:
swiftyjson:null
Secondly:
let data = text2.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
do {
let jsonSys = try NSJSONSerialization.JSONObjectWithData(data, options: [])
print("jsonSys:\(jsonSys)")
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}
Output:
Failed to load: The data couldn’t be read because it isn’t in the
correct format.

Your JSON string is not properly escaped.
The "Msg" opening dictionary { shouldn't be preceded by a double quote, it should be like this:
"{\"MsgType\":103,\"Msg\":{\"UserObject\" ...
Same error at the end, it should be:
... 77.1258,\"ContactType\":\"\"}]}}"

Related

Swift JSON validation fails this data from my web api, I do not know why

Here is the swift code
if JSONSerialization.isValidJSONObject(JSONData) {
print (":Valid json")
} else {
let JSONstring = NSString(data: JSONData, encoding: String.Encoding.utf8.rawValue)
print(JSONstring)
}
which results in the 'else' part being executed, and outputs the JSON data converted to a string as follows:
Optional("[{\"nPropertyID\":4,\"sAddress_1\":\"11 Some street\",\"sAddress_2\":\"Some Road\",\"sAddress_3\":\"Toytown\",\"sPostcode\":\"AB1 9XX\",\"dPurchaseCost\":9999.99,\"dtPurchaseDate\":\"2012-10-23T00:00:00\"}]")
According to Apple documentation you can't use isValidJSONObject with Data or String objects (even if the input parameter is of type Any):
Returns YES if the given object can be converted to JSON data, NO
otherwise. The object must have the following properties:
Top level object is an NSArray or NSDictionary
All objects are NSString, NSNumber, NSArray, NSDictionary, or NSNull
All dictionary keys are NSStrings
NSNumbers are not NaN or infinity
Instead you can use:
let jsonStr = "[{\"nPropertyID\":4,\"sAddress_1\":\"11 Welch House\",\"sAddress_2\":\"Beaconsfield Road\",\"sAddress_3\":\"Enfield\",\"sPostcode\":\"EN3 6UX\",\"dPurchaseCost\":88000.00,\"dtPurchaseDate\":\"2012-10-23T00:00:00\"}]"
if let jsonDataToVerify = jsonStr.data(using: .utf8)
{
do {
_ = try JSONSerialization.jsonObject(with: jsonDataToVerify)
print("JSON is valid.")
} catch {
print("Error deserializing JSON: \(error.localizedDescription)")
}
}
As suggested here.

Swift JSONSerialization implicitly convert double value to string

I want convert a json string which contains a double field to JSON object using JSONSerialization.data function. I print the result json object and it shows the double field as string. The following is the sample code:
let test = "{\"statusCode\":2.334}"
do {
let responseJSON = try JSONSerialization.jsonObject(with: test.data(using: String.Encoding.utf16)!, options: [])
print(responseJSON)
} catch {
print(error)
}
The responseJSON as following:
{
statusCode = "2.334";
}
I have two questions:
Is it, in general, all JSON serialization engine will convert double
value to string or it is only happen in Swift JSON serialization?
Anyway to force JSONSerialization to output double, not string?
This is purely an artifact of how the value is printed out — the value you get is in fact a Double. You can confirm this yourself with the following:
import Foundation
let test = "{\"statusCode\":2.334}"
do {
let responseJSON = try JSONSerialization.jsonObject(with: test.data(using: String.Encoding.utf16)!, options: []) as! [String: Any]
print(responseJSON["statusCode"] is Double) // => true
} catch {
print(error)
}

Receive JSON object in Swift Socket.IO Client

How can I receive a JSON object in the Swift Socket.IO client?
Node.js
From socket.io on Node.js, I emit a json object as in this simplified example:
socket.emit('welcome', { text : 'Hello, World!' });
Swift
In an iOS Swift client, I would like to get this message out of the object.
socket?.on("welcome") {[weak self] data, ack in
print(data)
if let msg = data[0] as? String {
print(msg) // never prints; something's wrong
}
}
The value of data when I print it out is:
[{
text = "Hello, World!";
}]
When I attempt to parse data[0] with the following (from the Apple Developer Blog)...
let json = try? JSONSerialization.jsonObject(with: data[0], options: [])
...I am met with an error message:
Cannot invoke 'jsonObject' with argument list of type '(with: Any, options: [Any])'
Your data is type of [[String: Any]], get text like below.
if let arr = data as? [[String: Any]] {
if let txt = arr[0]["text"] as? String {
print(txt)
}
}

Iterate over AnyObject. Error: Type 'AnyObject' does not conform to protocol 'SequenceType'

I'm using Alamofire to get a data from a JSON file. Example of the output:
[{"image_name":"vacation"},{"image_name":"graduation"}]
I have a problem when I try to access the information from the JSON output.
Alamofire.request(.GET, url).responseJSON { (response) -> Void in
if let JSON = response.result.value {
for json in JSON{
print(json)
}
}
The problem I have is that my JSON output is an AnyObject and I cannt iterate over an AnyObject. If I do the following:
print(JSON[0]["image_name"])
Then I can see the output correctly. How can I iterate over an AnyObject?
You may need to explicitly state the type of JSON as an array of dictionaries:
if let JSON = response.result.value as [[String : AnyObject]] {
// ...
}

Swift - Reading JSON File

I'm new to Swift - trying to read a JSON file from a URL. My attempt below.
The JSON looks valid - I tested it with JSONLint but it keeps crashing.
Thoughts?
func getRemoteJsonFile() -> NSDictionary {
//Create a new url
let remoteUrl:NSURL? = NSURL(string: "http://nfl-api.azurewebsites.net/myplayers.json")
//check if its nil
if let actualRemoteUrl = remoteUrl {
//try to get the data
let filedata:NSData? = NSData(contentsOfURL: actualRemoteUrl)
//check if its nil
if let actualFileData = filedata {
//parse out the dictionaries
let jsonDict = NSJSONSerialization.JSONObjectWithData(actualFileData, options: NSJSONReadingOptions.AllowFragments, error: nil) as NSDictionary
return jsonDict
}
}
return NSDictionary()
}
This took me a second to figure out, so I don't blame you for missing it.
The JSON you linked to is minified, so it's difficult to see the structure. Let's take a look at (a fragment of) it after piping it through a prettifier:
[
{
"PlayerId":2501863,
"PlayerName":"Peyton Manning",
"PlayerTeam":"DEN",
"PlayerPosition":"QB",
"PlayerPassingYards":4727,
"PlayerPassingTDs":39,
"PlayerInterceptions":15,
"PlayerRushingYards":-24,
"PlayerRushingTDs":0,
"PlayerReceivingYards":0,
"PlayerReceivingTDs":0,
"PlayerReturnYards":0,
"PlayerReturnTDs":0,
"PlayerFumbleTDs":0,
"PlayerTwoPointConversions":2,
"PlayerFumblesLost":2,
"PlayerTeamLogo":"http://i.nflcdn.com/static/site/7.0/img/logos/teams-gloss-81x54/den.png"
}
]
Huh. It's encased in brackets, which means that it's an array.
It's an array, so you can't cast it as an NSDictionary. Instead, you could cast it as an NSArray, but why not use native Swift types?
Well, if you don't like types, you're about to find out, but I still think that this is a better way, because it forces you to think about the data you're parsing.
So we have the first part of our type definition for this function; it's an array ([]). What components is our array made up of? We could go with a simple NSDictionary, but we're doing full native types here, so let's use a native Swift dictionary.
To do that, we have to know the types of the dictionary (the syntax for a native dictionary type is [KeyType: ValueType]). Examining the JSON shows that all of the keys are Strings, but the values are of varying types, so we can use AnyObject.
That gives us a dictionary type of [String: AnyObject], and our entire JSON is an array of that, so the final type is [[String: AnyObject]] (wow).
Now that we have the proper type, we can modify the function you're using to parse the JSON a bit.
First of all, let's use our new type for the return and cast values. Then, let's make the return type optional in case something goes wrong and add an error variable to document that.
A cleaned up function would look something like this:
func getData() -> [[String: AnyObject]]? {
let data: NSData? = NSData(contentsOfURL: NSURL(string: "http://nfl-api.azurewebsites.net/myplayers.json")!)
if let req: NSData = data {
var error: NSError?
if let JSON: [[String: AnyObject]] = NSJSONSerialization.JSONObjectWithData(req, options: NSJSONReadingOptions.AllowFragments, error: &error) as? [[String: AnyObject]] {
return JSON
}
}
return nil
}
That's it!
We can now call the function and extract values from our [[String: AnyObject]] (again, wow) like this:
if let data: [[String: AnyObject]] = getData() {
println(data[0]["PlayerName"]!) // Peyton Manning
}
Update your code with this:
func getRemoteJsonFile() -> [NSDictionary] {
// Create a new URL
let remoteUrl:NSURL? = NSURL(string: "http://nfl-api.azurewebsites.net/myplayers.json")
let urlString:String = "\(remoteUrl)"
// Check if it's nil
if let actualRemoteUrl = remoteUrl {
// Try to get the data
let fileData:NSData? = NSData(contentsOfURL: actualRemoteUrl)
// Check if it's nil
if let actualFileData = fileData {
// Parse out the dictionaries
let arrayOfDictionaries:[NSDictionary]? = NSJSONSerialization.JSONObjectWithData(actualFileData, options: NSJSONReadingOptions.MutableContainers, error: nil) as [NSDictionary]?
if let actualArrayOfDictionaries = arrayOfDictionaries {
// Successfully parsed out array of dictionaries
return actualArrayOfDictionaries
}
}
}
return [NSDictionary]()
}
This is working fine for me.