swift how to add dictionary keys values in array - json

I am working on swift json Parsing where i am recieving json Data from Rest API for eg:
{"baseUrl":"http:\/\/localhost:9010\/",
"pluginOptions":{"values":[{"StartSyncTime":"2020-10-06 17:22:34","uuid":"977a5d03-2cdf-4008-87e6-01594e4369ef","LastSyncTime":"2020-10-06",
"MessageWrapper":{"Routing":"OriginSession","SourceSystem":"Mobile","MessageId":"51152ccd-32c6-475b-86a6-a2c883d551f5",
"UserID":"77ee794e-433d-4b93-bcaa-53408ede50fd","TenantID":"null","TenantName":"visurtest","Payload":"{}",
"DataType":"SQLLiteDDLAsync","MessageKind":"READ"}}],
"database":"structionDB","encrypted":false,"mode":"no-encryption"}}
I am getting as type [String:Any?] from rest api in below code
var pluginOptions : [String: Any]? = call.getObject("pluginOptions")
pluginOptions?[MessageWrapperKeys.DataType] = [DataTypes.SQLLiteDDLAsync]
pluginOptions?[MessageWrapperKeys.MessageKind] = [MessageKinds.READ]
pluginOptions?[MessageWrapperKeys.Payload] = ["{}"]
from above Json Response i need to extract MessageWrapper Dictionary like below
{"Routing":"OriginSession","SourceSystem":"VisurMobile","MessageId":"51152ccd-32c6-475b-86a6-a2c883d551f5",
"UserID":"77ee794e-433d-4b93-bcaa-53408ede50fd","TenantID":"null","TenantName":"visurtest","Payload":"{}",
"DataType":"SQLLiteDDLAsync","MessageKind":"READ"}
where above last 3 key vale i have added from code,Now i have to send Rest Api Call with above request but i did not able to figure it out how i will extraxt MessageWrapper Keys and append above 3 Key Values so that i get final jsonString Request like
{"Routing":"OriginSession","SourceSystem":"Mobile","MessageId":"05086b82-3623-492b-926a-d3bb8d01aa52","UserID":"77ee794e-433d-4b93-bcaa-53408ede50fd","TenantID":"null","TenantName":"test","Payload":"{}","DataType":"SQLLiteDDLAsync","MessageKind":"READ"}
below code i have triyed but not able to access
func readTableFromBackend(_ call: CAPPluginCall) -> Observable<String>{
var swrapper: [[String: Any]] = [[:]]
var pluginOptions : [String: Any]? = call.getObject("pluginOptions")
let json = JSON(pluginOptions)
var arrayNames = json["values"].arrayValue.map {$0["MessageWrapper"].string}
for arrayvalues in json["values"].arrayValue{
for arrayvalues in json["MessageWrapper"].arrayValue{
var string = arrayvalues["UserID"].string
}
var string = arrayvalues["MessageWrapper"].string
print(string)
}
pluginOptions?[MessageWrapperKeys.DataType] = [DataTypes.SQLLiteDDLAsync]
pluginOptions?[MessageWrapperKeys.MessageKind] = [MessageKinds.READ]
pluginOptions?[MessageWrapperKeys.Payload] = ["{}"]
var values = pluginOptions?["values"]
var modes = pluginOptions?["mode"]
for (key,value)in pluginOptions ?? ["":""]{
print("\(key) -> \(value)")
}
var finajsonstring: String = ""
var pluginOptions1: [String:Any] = [MessageWrapperKeys.DataType:DataTypes.SQLLiteDDLAsync, MessageWrapperKeys.MessageKind:MessageKinds.READ,MessageWrapperKeys.Payload: "{}"]
swrapper.append(pluginOptions ?? ["":""])
swrapper.append(pluginOptions1 )
let apidata = PullBackendData()
let plugindata = PluginCallParameterOptions()
var url: String? = call.getString("baseUrl")
// let payload = swrapper
let address = plugindata.getApiUrl(controllerName: Controllers.DataSync, baseUrl: url ?? "")
let jsonData = try? JSONSerialization.data(withJSONObject: pluginOptions)
guard let jsonString = String(data : jsonData!, encoding: .utf8
) else { return Observable.just("Error")}
let data = Data(jsonString.utf8)
do{
let newdata : NSDictionary = try JSONSerialization.jsonObject(with: data, options: []) as! NSDictionary
}
if((newdata.value(forKey: "values")) != nil){
let info : NSArray = newdata.value(forKey: "values") as! NSArray
let info1 : NSArray = info.value(forKey: "MessageWrapper") as! NSArray
var wrapperarray: [[String:Any]] = [[String:Any]]()
wrapperarray = newdata.value(forKey: "values") as! [[String:Any]]
wrapperarray.append(pluginOptions1)
let jsonData: NSData = try JSONSerialization.data(withJSONObject: info1, options: []) as NSData
let jsonData2: NSData = try JSONSerialization.data(withJSONObject: wrapperarray, options: []) as NSData
do {
var jsonstring = try NSString(data: jsonData as Data, encoding: String.Encoding.utf8.rawValue)! as String
var jsonstring2 = NSString(data: jsonData2 as Data, encoding: String.Encoding.utf8.rawValue)! as String
//getting final string and sending to rest api
finajsonstring = jsonstring2 as String
}catch {
print("error")
}
}
} catch let error as NSError{
print(error)
}
let response = apidata.post(_for: address, bodyData: finajsonstring)
return Observable.from(optional: response)
}

Related

Swift reading a json file

I am having this error. Cannot invoke 'jsonObject' with an argument list of type '(with: String, options: [Any])'
I am thinking it has to be a different type for the file but not sure.
I don't think doing bundle.main.url would be the correct way to do this. I had seen that in another question that suggested using url, but also not sure how it'd work. Any help would be appreciated, thanks.
This is code for writing into file in InfoViewController
let fileName: String?
let file: FileHandle? = FileHandle(forWritingAtPath: "fileName.json")
if file != nil {
// Set the data we want to write
do{
if let jsonData = try JSONSerialization.data(withJSONObject: fileName!, options: .init(rawValue: 0))
{
// Check if everything went well
//print(NSString(data: jsonData, encoding: 1)!)
let bookCover = (jsonData as AnyObject).value(forKeyPath: "bookCoverImage.image") as? [UIImage]
let bookTitle = (jsonData as AnyObject).value(forKeyPath: "bookTitleLabel.text") as? [String]
let author = (jsonData as AnyObject).value(forKeyPath: "authorLabel.text") as? [String]
let year = (jsonData as AnyObject).value(forKeyPath: "bookYear.text") as? [String]
let pages = (jsonData as AnyObject).value(forKeyPath: "numberOfPages") as? [String]
let ratingStars = (jsonData as AnyObject).value(forKeyPath: "ratingStars.image") as? [UIImage]
let reviews = (jsonData as AnyObject).value(forKeyPath: "totalReviews.text") as? [String]
let description = (jsonData as AnyObject).value(forKeyPath: "descriptionLabel.text") as? [String]
file?.write(jsonData)
// Do something cool with the new JSON data
}
}
catch {
}
// Write it to the file
// Close the file
file?.closeFile()
}
This is the code where the error is occurring. In favoritesListController.
var path: String?
var favoritesList: String?
var bookCoversDisplay = [UIImage]()
var titlesDisplay = [String]()
var authorsDisplay = [String]()
var yearDisplay = [String]()
var pagesDisplay = [String]()
var starRatingDisplay = [UIImage]()
var reviewsDisplay = [String]()
var descriptionsDisplay = [String]()
var bookCovers: UIImage!
var titles: String = ""
var authors: String = ""
var year: String = ""
var pages: String = ""
var starRating: UIImage!
var reviews: String = ""
var descriptions: String = ""
override func viewDidLoad() {
super.viewDidLoad()
path = Bundle.main.path(forResource: "favoritesList", ofType: "json")
do {
favoritesList = try String(contentsOfFile: path!)
let jsonResult = try? JSONSerialization.jsonObject(with: favoritesList, options: [])
if let array = jsonResult as? [Any] {
if let bookCover = array.first {
bookCoversDisplay = bookCover
} else if let title = array.second {
titlesDisplay = title
} else if let author = array.third {
authorsDisplay = author
} else if let year = array.fourth {
yearDisplay = year
} else if let pages = array.fifth {
pagesDisplay = pages
} else if let starRating = array.sixth {
starRatingDisplay = starRating
} else if let reviews = array.seventh {
reviewsDisplay = reviews
} else if let description = array.eighth {
descriptionsDisplay = description
}
}
maybe can help you:
do{
let data = try Data.init(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "Info", ofType: "json")!))
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
print(json)
}catch{
print(error)
}

Parsing JSON in Swift and accessing values?

I have successfully parsed JSON for:
birthday = "04/10/1986";
id = 202038339983;
location = {
city = Jupiter;
country = "United States";
state = FL;
};
My question is when part of the JSON is:
submissions = {
data = (
{
"created_time" = "2018-02-16T05:11:56+0000";
id = "131448394823824_167398094382256";
viewer = "Any random string and/or emojis";
},
{
"created_time" = "2018-02-14T23:36:41+0000";
id = "809809871824_8908987486899";
message = "vday \Ud83d\Udda4\U2665\Ufe0f";
});}
How am I supposed to access created_time, id, viewer, and message?
I have been able to print the whole submissions JSON response to the console with this code :
guard let jsonD = responseFromServer as? [String : Any] else {return}
let subs1 = (jsonD["submissions"] as? [String : Any])
let accessSubs1 = theSubs1
guard let parsedPost = theSubs1 else {
return
}
My console will display:
["data": <__NSArrayI 0x6040001a86c0>(
{
"created_time" = "2018-02-16T05:11:56+0000";
id = "131448394823824_167398094382256";
viewer = "Any random string and/or emojis";
},
{
"created_time" = "2018-02-14T23:36:41+0000";
id = "809809871824_8908987486899";
message = "vday \Ud83d\Udda4\U2665\Ufe0f";
})]
My question is how should I parse the JSON so I can access the created_time inside submissions?
Here is the HTTP Request:
struct XClass: RequestProtocol {
var Path = "/User"
var parameters: [String : Any]? = ["stuff": "id, birthday, location, submissions"]
var aToken = aToken.current
var httpMethod: RequestHTTPMethod = .GET
var apiVersion: APIVersion = .defaultVersion
struct Response: ResponseProtocol {
var id = String()
var birthday = String()
var city = String()
var state = String()
var country = String()
var viewSubs = [String : Any]()
init(XResponse: Any?) {
guard let jsonD = XResponse as? [String : Any] else {return}
id = (jsonD["id"] as? String)!
birthday = (jsonD["birthday"] as? String)!
let XArr = (jsonD["location"] as? [String : String])
city = XArr!["city"]!
country = XArr!["country"]!
state = XArr!["state"]!
let subs1 = (jsonD["submissions"] as? [String : Any])
let accessSubs1 = theSubs1
guard let parsedPost = theSubs1 else {
return
}
viewSubs = theSubs1
}}}
func getXData(){
let connection = RequestConnection()
connection.add(XClass()) { response, result in
switch result {
case .success(let response):
print("Request Succeeded: \(response)\n\n\n")
case .failed(let error):
print("Request Failed: \(error)")
}}
connection.start()
}
Create a struct
struct Data: Decodable {
var created_time : String
var id : String
var viewer : String
}
call to the api url from URLSession
guard let url = URL(string: "your api url")
URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error.localizedDescription)
} else {
guard let data = data else {return}
var data: [Data]() = JSONDecoder().decode(Data.self, data)
for dat in data{
print(dat.created_time)
print(dat.id)
print(dat.viewer)
}
}
If you are not using Decodable from Swift 4, or still in Swift 3,
then you can specify that the data in "submissions" is an array of dictionaries (double brackets) then you can iterate that.
Change
let subs1 = (jsonD["submissions"] as? [String : Any])
To
let subs1 = (jsonD["submissions"] as? [[String : Any]])
for sub in subs1 {
let time = sub["created_time "] as? [String : Any]
...
}

How to get the multiple data inside the json curly braces? Swift

How to get the multiple data inside the json curly braces in swift3?
Can i use this code to get multiple data? (get "crew_id","crew_name","crew_email")
if let crew = user!["crew"] as? [String:Any], let crewName = crew["crew_name"] as? String {
print(crewName)
JSON
crew ={
"crew_avatar" = "http://ec2-52-221-231-3.ap-southeast-1.compute.amazonaws.com/gv/images/profile_image/Pang_Kang_Ming_916210_0e9.jpg";
"crew_contact" = 0123456789;
"crew_email" = "pang#xover.com.my";
"crew_gender" = Male;
"crew_id" = PP000001;
"crew_name" = "Pang Kang Ming";
"crew_preferred_name" = PKM;
"crew_qrcode" = "images/qrcode/qrcode_085960293a5378a64bec6ebfa3c89bb7.png";
};
message = "Login Sucessfully";
result = success;
Yes you can, just add the values you want to unwrap as below, just be aware that if one of the optional binding does not unwrap, even if others unwrap if statement will not be executed, consider separating the if statements.
Depends on all being returned in the json.
if let crew = user!["crew"] as? [String:Any],
let crewName = crew["crew_name"] as? String,
let crewId = crew["crew_id"] as? String {
print(crewName)
print(crewId)
}
Recommended way, even if some values are not present in the json response, you will be able to get the other values.
if let crew = user!["crew"] as? [String:Any] {
if let crewName = crew["crew_name"] as? String {
print(crewName)
}
if let crewId = crew["crew_id"] as? String {
print(crewId)
}
}
if let file = Bundle.main.url(forResource: "yourJsonFileName", withExtension: "json") {
let data = try Data(contentsOf: file)
let json = try JSONSerialization.jsonObject(with: data, options: [])
let jsonData = json as! [[String:Any]]
DispatchQueue.main.async {
let projectName = jsonData.flatMap { $0["crew_avatar"] as? String }
self.crewAvatarArray = projectName
print(self.crewAvatarArray)
let subTitle = jsonData.flatMap { $0["crew_contact"] as? String }
self.crewContactArray = subTitle
let startDate = jsonData.flatMap { $0["crew_email"] as? String }
self.crewEmailArray = startDate
}
}
Try this code

Convert an array of objects to JsonArray in Swift3

I have my DataModel as this and it has a function name toJSON which converts this object to string representation of JSON
ContactEntry: NSObject {
var name: String!
var phone: String?
var email: String?
func toJson() -> String {
var dict : [String: AnyObject] = [:]
dict["name"] = (self.name ?? "") as AnyObject
dict["phone"] = (self.phone ?? "") as AnyObject
dict["email"] = (self.email ?? "") as AnyObject
guard let data = try? JSONSerialization.data(withJSONObject: dict, options: []) else{
return "{}"
}
guard let jsonString = String(data: data, encoding: String.Encoding.utf8) else {
return "{}"
}
return jsonString
}
}
It works very fine until now as I am getting correct JSON representation for this object.
Now I have to convert an array of ContactEntry to JsonArray.
I am doing this way but I am getting very weird symbols in the result string.
Let's say
var contacts = [ContactEntry]()
var contactsStr = [String]()
...
for contact in contacts{
contactsStr.append(contact.toJson())
}
do{
let data = try? JSONSerialization.data(withJSONObject: contactsStr, options: [])
let jsonString = try? String(data: data!, encoding: String.Encoding.utf8)
print(jsonString)
}
I am getting the output like this
[\n \"{\\\"phone\\\":\\\"+XXXX\\\",\\\"name\\\":\\\"YYYY\\\",\\\"email\\\":\\\"\\\"},\",\n \".........\n]
Please help me to do it in a better and clean way
Thanks for your help
I think you are double serializing your output. That's why I asked for the contact string.
Try:
func toJson() -> [String: AnyObject] {
var dict : [String: AnyObject] = [:]
dict["name"] = (self.name ?? "") as AnyObject
dict["phone"] = (self.phone ?? "") as AnyObject
dict["email"] = (self.email ?? "") as AnyObject
return dict
}
With:
var contactsStr = [[String: AnyObject]]()
And print out the serialization. It should just be singly escaping quotes such as \"name\". Not \\"name\\"

Swift: Implementing Find-or-Create Efficiently

So I set up some data from an API to create a managed object, How do I determine whether the managed object already exists (in my example, every object has a unique id), and create it if it does not.
// set up core data
var appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
var context:NSManagedObjectContext = appDel.managedObjectContext!
// Get data from API
let urlPath = "http://www.example.com"
let url = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
let getMovies = session.dataTaskWithURL(url!, completionHandler: {
data, response, error -> Void in
if error != nil {
println(error)
} else {
// Parse the JSON data from API
var moviesResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary
if let subjects = moviesResult["subjects"] as? [[NSObject:AnyObject]] {
var movies = [[String:NSString]()]
var movie:AnyObject
var newMovieItem:NSManagedObject
// Loop through the arrays returned by API to get each movie
for (var i = 0 ; i < subjects.count ; i++) {
// Initialize the movies array
movies.append([String:NSString]())
movie = subjects[i] as NSDictionary
movies[i]["title"] = movie["title"] as? NSString
movies[i]["id"] = movie["id"] as? NSString
newMovieItem = NSEntityDescription.insertNewObjectForEntityForName("Movies", inManagedObjectContext: context) as! NSManagedObject
newMovieItem.setValue(movies[i]["title"], forKey: "title")
newMovieItem.setValue(movies[i]["id"], forKey: "id")
context.save(nil)
}
var request = NSFetchRequest(entityName: "Movies")
request.returnsObjectsAsFaults = false
var results = context.executeFetchRequest(request, error: nil)
}
}
})
getMovies.resume()