“Old-Style ASCII Property List” to Json in Swift - json

I have a string that looks like following:
{\n \"account_no\" = \"5675672343244\";\n \"account_kind\" = {\n \".tag\" = test,\n };\n country = US;\n disabled = 0;\n email = \"test#gmail.com\";\n \"email_verified\" = 1;\n \"is_paired\" = 0;\n };\n}"
It is similar to NSDictionary when it is printed as description to the console. Especially
some strings are in quotes, some are not. See country = US;\n
they use k-v notation with =. E.g. key = value
they use delimiter ;
Unfortunately I do not have the original object that created the string. I have only the string itself.
My goal is to transform it to a valid JSON string representation, or alternatively back to a NSDictionary. Should be done in Swift 5. I failed so far in doing so, does anyone has sample code that would help?

The description of an NSDictionary produces an “Old-Style ASCII Property List”, and PropertyListSerialization can be used to convert that back to an object.
Note that the format is ambiguous. As an example, 1234 can be both a number or a string consisting of decimal digits only. So there is no guarantee to get the exact result back.
Example:
let desc = "{\n \"account_no\" = \"5675672343244\";\n \"account_kind\" = {\n \".tag\" = test;\n };\n country = US;\n disabled = 0;\n email = \"test#gmail.com\";\n \"email_verified\" = 1;\n \"is_paired\" = 0;\n}"
do {
let data = Data(desc.utf8)
if let dict = try PropertyListSerialization.propertyList(from: data, format: nil) as? NSDictionary {
let json = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
print(String(data: json, encoding: .utf8)!)
} else {
print("not a dictionary")
}
} catch {
print("not a valid property list:", error)
}
Output:
{
"country" : "US",
"email_verified" : "1",
"is_paired" : "0",
"account_no" : "5675672343244",
"email" : "test#gmail.com",
"disabled" : "0",
"account_kind" : {
".tag" : "test"
}
}
(I had to “fix” the description string to make it a valid property list: "test" was followed by a comma instead of a semicolon, and there was an unbalanced } at the end of the string.)

Related

How to convert Cookie String to JSON using Swift

("Global_Data"): {
Created = 574049501;
Domain = "";
Expires = "2019-03-19 02:11:40 +0000";
Name = "Data";
Path = "/";
Value = "%7B%22countryISO%22%3A%22US%22%2C%22cultureCode%22%3A%22en-GB%22%2C%22currencyCode%22%3A%22USD%22%2C%22apiVersion%22%3A%222.1.4%22%7D;
Version = 1;
}
On grabbing a Cookie data from a webview i got the Value => as a string
with some characters knowing these characters represent special characters or letters.
How can i convert it to a JSON format. Thanks
"%7B%22countryISO%22%3A%22US%22%2C%22cultureCode%22%3A%22en-GB%22%2C%22currencyCode%22%3A%22USD%22%2C%22apiVersion%22%3A%222.1.4%22%7D"
Your string is already a JSON string you just have to remove the percent encoding from it, create a custom structure that conform to Decodable and you are all set:
struct Root: Decodable {
let countryISO, cultureCode, currencyCode, apiVersion: String
}
let string = "%7B%22countryISO%22%3A%22US%22%2C%22cultureCode%22%3A%22en-GB%22%2C%22currencyCode%22%3A%22USD%22%2C%22apiVersion%22%3A%222.1.4%22%7D"
let json = string.removingPercentEncoding ?? ""
"{"countryISO":"US","cultureCode":"en-GB","currencyCode":"USD","apiVersion":"2.1.4"}"
do {
let root = try JSONDecoder().decode(Root.self, from: Data(json.utf8))
print(root.countryISO) // "US"
print(root.cultureCode) // "en-GB"
print(root.currencyCode) // "USD"
print(root.apiVersion) // "2.1.4"
} catch {
print(error)
}

Swift - JSON array values

I am getting following JSON values in output:
[["category_title": Shelly], ["category_title": Thaddeus],
["category_title": Chantale], ["category_title": Adara],
["category_title": Mariko], ["category_title": Felicia]]
But I want it like below:
["Shelly","Thaddeus","Chantale", "Adara","Mariko","Felicia"]
I have the following Swift code. Please help me get above output.
func successGetTermsData(response: Any){
var UserRole : String = ""
var arrayOfDetails = response as? [[String: Any]] ?? []
UserRole = arrayOfDetails as? String ?? ""
print(arrayOfDetails)
}
You have to map the array of Dictionary arrayOfDetails to an array of String. flatMap ignores a missing key.
if let arrayOfDetails = response as? [[String: String]] {
let userRole = arrayOfDetails.flatMap { $0["category_title"] }
print(userRole)
}
There are many ways to do this. One way is to use flatmap to get just the values in your array of dictionaries:
let arrayOfValues = arrayOfDetails.flatMap { $0.values }
In order to get this to work, the names need to be inside double quotes: "Shelly", etc.

Cannot subscript a value of a type AnyObject, in Swift

I have this line of code, and I want to extract the "title" key:
var title = jParams["title"] as! String
However it wont let me compile, and if I get this error message in red:
Cannot subscript a value of a type AnyObject with an index of type String
When show the contents of jParams in the log with println(jParams) I get the following content:
INCOMING LIST PARAMETERS (jParameters)
Optional({
title = "Example List";
values = (
{
id = 1;
name = "Line 1";
},
{
id = 2;
name = "Line 2";
},
{
id = 3;
name = "Line 3";
}
);
})
I am new to Swift so I am not familiar with the details of handling JSON to deal with these type of problems. What could be wrong?
//jParams comes from a JSON server response
var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil)
if data != nil {
var jdata = JSON(data: data!)
var jParams=jdata["responseData"]["extraData"]["params"]
In your edit it looks like you're using SwiftyJSON.
If that is indeed the case, you can help the compiler to know what's in the dictionary by using SwiftyJSON's dictionaryValue property:
let jParams = jdata["responseData"]["extraData"]["params"].dictionaryValue
Then you should be able to access your values without downcasting:
let title = jParams["title"]
because SwiftyJSON will have inferred the right type for the values.

SwiftyJSON looping through an array of JSON objects

[
{
"cont": 9714494770,
"id": "1",
"name": "Kakkad"
},
{
"cont": 9714494770,
"id": "2",
"name": "Ashish"
}
]
The one above is a json array filled with JSON objects. I don't know how to parse through this with SwiftyJSON
Example from the SwiftyJSON page, adapted to your data:
let json = JSON(data: dataFromNetworking)
for (index, object) in json {
let name = object["name"].stringValue
println(name)
}
Assuming [{"id":"1", "name":"Kakkad", "cont":"9714494770"},{"id":"2", "name":"Ashish", "cont":"9714494770"}] is assigned to a property named jsonData.
let sampleJSON = JSON(data: jsonData)
let sampleArray = sampleJSON.array sampleArray is an optional array of JSON objects.
let firstDict = sampleArray[0] firstDict is an optional JSON dict.
let name = firstDict["name"] is an optional JSON object
let virtName = name.string is a optional string (In this case "Kakkad").
let realName = name.stringValue realName is a string or an empty string.
You could also use:
let longName = sampleJSON[0]["name"].stringValue
After you initialize the JSON object with data all of the elements are JSON types until you convert them to a swift type.
.string optional (string or null)
.stringValue string or "" empty
string
.dict optional ([String: AnyObject] or null)
.dictValue
([String: AnyObject] or String: AnyObject)
For Swift4 I have updated the code from Moritz answer
if let path : String = Bundle.main.path(forResource: "tiles", ofType: "json") {
if let data = NSData(contentsOfFile: path) {
let optData = try? JSON(data: data as Data)
guard let json = optData else {
return
}
//If it is a JSON array of objects
for (_, object) in json {
let name = object["name"].stringValue
print(name)
}
}
}
Swift 3 or 4 code like this:
let json = JSON(yourData)
for (_, object) in json {
let cont = object["cont"].stringValue
print(cont)
}
You can put index instead of _ if you use is anywhere in your code. If you don't use a variable, it's better to put _ (XCode also gives warnings).

Swift Parsing JSON

I'm able to get JSON data because I can see it being printed out using println. I can also print some individual keys. However I'm having a hard time converting it to string.
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
println(jsonResult.count) // works
numberOfStations.text = String(jsonResult.count)
//latitude.text = jsonResult["latitude"] as String
//var result: String = jsonResult["latitude"] as String
let latitudeData : AnyObject? = jsonResult["latitude"]
let longitudeData: AnyObject? = jsonResult["longitude"]
latitude.text = latitudeData as NSString! // Doesn't work
longitude.text = longitudeData as NSString! // Doesn't work
println("latitude --> \(latitudeData)") // Works prints it ok latitude ---> 40.30303
println("longitude --> \(longitudeData)") //Works prints it ok longitude ---> 37.20202
JSON similar to this
{
latitude: 34.0522342,
longitude: -118.2436849,
station_counts: {
total: 247,
fuels: {
E85: {
total: 0
},
ELEC: {
total: 225,
stations: {
total: 55
}
},
}
}
Your code is attempting to convert the values by simply casting them to strings. You instead need to use a method that returns a string representation of the value. For example:
latitude.text = latitudeData!.description
I would not recommend depending on description() to parse json. This is how I'm parsing json in Swift (beta 4)
//parse Episode Name
if let jsonAsDict = responseObject as? Dictionary<String, AnyObject>
{
if let array: AnyObject = jsonAsDict["episodes"]
{
for item: AnyObject in array as [AnyObject]
{
//put episode name into array
self.episodeNames.append(item["name"] as String)
}
}
}
The json has this format:
episodes: [
{
name: "Episode Name 1"
},
{
name: "Episode Name2"
}
]
self.episodeNames is declared as 'var episodeNames: [String]' in this example
You may want to take a look at SwiftyJSON, an open source library on GitHub that makes JSON processing in Swift real nice.