i would like to ask a little help.
I have a method which call a webservice and get a json object from it.
it's look like this way:
func wsServiceFeedTst() {
println("WS called...")
println("tstFrames count: " + tstFrames.count.description)
let json = JSON(url:"http://79.172.249.175:7001/RestWebServiceApp/webresources/entity.bkkkallerfeedtst")
println(json)
for (k, v) in json["bkkKallerFeedTst"] {
let dateShow : NSDate? = v["feedDate"].asDate
var finalFormatter = NSDateFormatter()
finalFormatter.dateFormat = "yyyy.MM.dd - HH:mm"
let finalDate = finalFormatter.stringFromDate(dateShow!)
tstFrames.append(TimeFrame(text: v["feedText"].description, date: finalDate, image: nil, routeName: v["feedRouteShName"].description, postId: v["id"].description,routType: v["feedImgType"].description))
}
}
After i got the json i'm trying to iterate on it and try to add the nodes of the json to another array but when my json contains only one element it's failed because my json is not an array, this is the line where it's throws exception:
let finalDate = finalFormatter.stringFromDate(dateShow!)
it is waiting for optional, but it get nil caused by this line:
let dateShow : NSDate? = v["feedDate"].asDate
this is how my json looks like when it has only one element:
{"bkkKallerFeedTst":{"feedRouteShName":"143","id":"348","feedLat":"47.5998971180592","feedImgType":"3","feedDate":"2015-06-15T14:07:30+02:00","feedLon":"19.0457082953807","feedText":"Itthon :)”}}
And this is how it looks like when it has more then one elements (now it has two element)
{"bkkKallerFeedTst":[{"feedRouteShName":"H5","id":"349","feedLat":"47.5535475845461","feedImgType":"2","feedDate":"2015-06-15T15:27:02+02:00","feedLon":"19.0458004338391","feedText":"Hév ;)"},{"feedRouteShName":"143","id":"348","feedLat":"47.5998971180592","feedImgType":"3","feedDate":"2015-06-15T14:07:30+02:00","feedLon":"19.0457082953807","feedText":"Itthon :)"}]}
Does anybody has any ide about how to solve this?
Thank you very much!
By the answer i create this:
var bkkKallerFeedTst = json["bkkKallerFeedTst"]
var bkkKallerFeedTstArray : [[NSObject : AnyObject]]
bkkKallerFeedTstArray = []
if bkkKallerFeedTst.isDictionary {
bkkKallerFeedTstArray.append(bkkKallerFeedTst.asDictionary!)
} else {
}
for feed in bkkKallerFeedTstArray {
println(feed["feedRouteShName"]) //now its printing: Optional(143)
}
now it's printing this:
[feedImgType: 3, feedRouteShName: 143, feedLat: 47.5998971180592, feedText: Itthon :), feedLon: 19.0457082953807, id: 348, feedDate: 2015-06-15T14:07:30+02:00]
UPDATE: this is the solution..
var bkkKallerFeedTst = json["bkkKallerFeedTst"]
var bkkKallerFeedTstArray : [JSON]
if bkkKallerFeedTst.isDictionary {
bkkKallerFeedTstArray = [bkkKallerFeedTst] //initialize
} else {
bkkKallerFeedTstArray = bkkKallerFeedTst.asArray!
}
for bkk in bkkKallerFeedTstArray {
let dateShow : NSDate = bkk["feedDate"].asDate!
var finalFormatter = NSDateFormatter()
finalFormatter.dateFormat = "yyyy.MM.dd - HH:mm"
let finalDate = finalFormatter.stringFromDate(dateShow)
tstFrames.append(TimeFrame(text: bkk["feedText"].description, date: finalDate, image: nil, routeName: bkk["feedRouteShName"].description, postId: bkk["id"].description,routType: bkk["feedImgType"].description))
}
It would probably be best to define the JSON object initially so it produces an array with a single value, rather than this way, but otherwise you could check to see if you get a valid date, and if you don't try it another way.
But looking at the API you've used, here https://github.com/dankogai/swift-json, it seems you can do checking to see whether you get a dictionary or an array. So I would cast the dictioanry value to a clearly typed variable for clarity using the '.isDictionary' method.
e.g. something akin to
var bkkKallerFeedTst = json["bkkKallerFeedTst"]
var bkkKallerFeedTstArray : [JSON]
if bkkKallerFeedTst.isDictionary {
bkkKallerFeedTstArray = [bkkKallerFeedTst] //initialize
} else {
bkkKallerFeedTstArray = bkkKallerFeedTst.asArray
}
May not be this exact code - I don't have the api.
Then you can iterate first through the array (for ? in bkkKallerFeedTstArray), then inside through the dictionary contained (as you were doing before)
Basically make sure you have an array of dictionaries first, before doing the operations.
Example with your code:
func wsServiceFeedTst() {
println("WS called...")
println("tstFrames count: " + tstFrames.count.description)
let json = JSON(url:"http://79.172.249.175:7001/RestWebServiceApp/webresources/entity.bkkkallerfeedtst")
println(json)
var bkkKallerFeedTst = json["bkkKallerFeedTst"]
var bkkKallerFeedTstArray : [JSON]
if bkkKallerFeedTst.isDictionary {
bkkKallerFeedTstArray = [bkkKallerFeedTst] //initialize
} else {
bkkKallerFeedTstArray = bkkKallerFeedTst.asArray
}
for bkk in bkkKallerFeedTstArray {
let dateShow : NSDate = bkk["feedDate"].asDate!
var finalFormatter = NSDateFormatter()
finalFormatter.dateFormat = "yyyy.MM.dd - HH:mm"
let finalDate = finalFormatter.stringFromDate(dateShow)
tstFrames.append(TimeFrame(text: v["feedText"].description, date: finalDate, image: nil, routeName: v["feedRouteShName"].description, postId: v["id"].description,routType: v["feedImgType"].description))
}
}
Related
This question already has answers here:
Returning data from async call in Swift function
(13 answers)
Closed last month.
I am retrieving data in JSON format from a URL using URLSession. After decoding the JSON data, I print it for debugging reasons and also populate an array of struct CVE. The array has data, while inside the function jsonDataRequest, but when I try to get its elements from the ViewController, the array is empty. I searched for quite sometime on how to resolve it, but I am a bit stuck. Below is my code:
Inside the class, I have the following code:
The structure
struct CVE : Decodable
{
var CVE : String
var severity : String
var cvss3_score : String? = nil
var public_date : String
var bugzilla_description : String
}
struct CVEdata : Decodable
{
var cves : [CVE]
}
The array I want to use from the ViewController
var arrCVE : [CVE] = []
The function I am calling from ViewController
func jsonDataRequest ()
{
let url = "https://access.redhat.com/hydra/rest/securitydata//cve.json?after=2022-12-26"
let urlObj = URL(string: url)
URLSession.shared.dataTask(with: urlObj!) { (data, response, error) in
do
{
// Json to Array
self.jsonCVE = try JSONDecoder().decode([CVE].self, from: data!)
var strCVE : String
var strSeverity : String
var strCvss3_score : String? = nil
var strPublic_date : String
var strBugzilla_description : String
print(self.jsonCVE)
for oCVE in self.jsonCVE
{
print(oCVE.CVE + " " + oCVE.severity + " " + oCVE.public_date + " " + oCVE.bugzilla_description)
// get each the CVE info
strCVE = oCVE.CVE
strSeverity = oCVE.severity
if (oCVE.cvss3_score != nil)
{
print(oCVE.cvss3_score!)
strCvss3_score = oCVE.cvss3_score
}
else
{
print("")
strCvss3_score = ""
}
strPublic_date = oCVE.public_date
strBugzilla_description = oCVE.bugzilla_description
// save it to the array
self.arrCVE.append(CVE(CVE: strCVE, severity: strSeverity, cvss3_score: strCvss3_score, public_date: strPublic_date, bugzilla_description: strBugzilla_description))
print(self.arrCVE)
}
// Logic after response has arrived
DispatchQueue.main.async
{
print("main.async")
}
} catch
{
print(error)
}
}.resume()
}
From the ViewController I instantiate an object from the class and access the array. I am displaying on a UITextView the array.count to see how many rows it contains
let oRedHatCVEs = RedHatCVEs()
oRedHatCVEs.jsonDataRequest()
txtvJSON.text = "Array elements: " + String(oRedHatCVEs.arrCVE.count)
and the result is Array elements: 0
Does it have to do with the asynchronous way the above code works? How can I finally get the array data back to my ViewController?
You are correct, it is to do with the asynchronous function jsonDataRequest.
There are many ways to deal (i.e wait) for asynchronous function to finish, before using the data.
This sample code shows one way using Swift async/await framework.
It also shortens the code to fetch the data.
class RedHatCVEs {
var arrCVE: [CVE] = []
func jsonDataRequest() async {
if let url = URL(string: "https://access.redhat.com/hydra/rest/securitydata/cve.json?after=2022-12-26") {
do {
let (data, _) = try await URLSession.shared.data(from: url)
arrCVE = try JSONDecoder().decode([CVE].self, from: data)
}
catch {
print(error)
}
}
}
}
Use it like this:
let oRedHatCVEs = RedHatCVEs()
Task {
await oRedHatCVEs.jsonDataRequest()
txtvJSON.text = "Array elements: " + String(oRedHatCVEs.arrCVE.count)
}
I have nested JSON and I'm trying to return an object and update UI. However, I can access properties only from Result array, but can't reach Step from AnalyzedInstactions.
Here are classes that represent data in the JSON. Generated it with https://app.quicktype.io
import UIKit
class ResultArray: Codable {
var results = [Result]()
}
class Result: Codable, CustomStringConvertible {
var title: String = ""
var image = ""
var readyInMinutes: Int? = 0
var servings: Int? = 0
var cuisines = [String]()
var dishTypes = [String]()
var diets = [String]()
var occasions = [String]()
var analyzedInstructions = [AnalyzedInstruction]()
var description: String {
return "\nResults - Name: \(title), Summary: \(String(describing: readyInMinutes ?? nil)), \(String(describing: servings ?? nil)) "
}
}
// MARK: - Steps
class AnalyzedInstruction: Codable {
var name: String? = ""
var steps = [Step]()
}
class Step: Codable {
var number: Int = 0
var step: String = ""
}
Here is my parse method
private func parse(data: Data) -> [Result] {
do {
let decoder = JSONDecoder()
let result = try decoder.decode(ResultArray.self, from: data)
return result.results
} catch {
print("JSON Error: \(error)")
return []
}
}
try this simple code to access your steps from AnalyzedInstructions:
let results: [Result] = parse(data: theData)
if let firstResult = results.first {
if let firstAnaInst = firstResult.analyzedInstructions.first {
for step in firstAnaInst.steps {
print("--> step.step: \(step.step) step.number: \(step.number)")
}
} else { print(" NO analyzedInstructions") }
} else { print(" NO results") }
if you want all steps:
for result in results {
for anaInst in result.analyzedInstructions {
for step in anaInst.steps {
print("--> step.step: \(step.step) step.number: \(step.number)")
}
}
}
PS: if appropriate, you may consider using struct instead of class for your json models.
I'm using latest version of Swift with xcode 10.1. I'm able to encode json from an object fine but decoding a json string back to an object is producing nil.
This is from a hacker noon tutorial and the tutorial source prints nil as well.
Here is the sample object:
class Car: NSObject, Codable {
var name: String = ""
var companyURL: URL? = nil
var yearOfManufacture: Int = 0
var isNew:Bool = true
var otherDetailsData: [String:String]? = nil
var carType: CarType = .Unknown
var carSize: CarSize = CarSize(height: 0, length: 0)
}
struct CarSize: Codable {
var height: Double
var length: Double
}
enum CarType: String, Codable {
case Unknown
case SUV
case Sedan
}
//here is sample json
let jsonString = """
{
"name":"City ZX",
"isNew":true,
"yearOfManufacture":2018,
"companyURL":"www.honda.com",
"carType":"Sedan",
"carSize":{
"height":200,
"height":100
},
"otherDetailsData":{
"color":"Red",
"fuelType":"Petrol"
},
}
"""
//here is where i attempt to create the object from the json string:
if let jsonData = jsonString.data(using: .utf8)
{
//And here you get the Car object back
let carTest = try? JSONDecoder().decode(Car.self, from: jsonData)
print("carObject currently printing nil ", carTest)
}
Your CarSize struct has properites height and length, but in your jsonString you declared just height twice, so you forgot to length which is required for decoding too.
You probably wanted to use length instead of second height in your jsonString
"carSize":{
"height":200,
"length":100
}
or (if your car isn't skyscraper)
"carSize":{
"height":100,
"length":200
}
So I've run into a tiny obstacle and I'm trying to access a variable created inside an Alamofire request function. A bit of background into:
Used SwiftyJSON/Alamofire to access JSON file and parse it, have a variable for a accessing date, but date was in RFC 3339 format and now I created a function to parse the date from RFC 339 to a readable format but i don't now how to access the date variable created in the JSON parse function to use with the Date parse function.
//Get the JSON from server
func getJSON() {
Alamofire.request(.GET, "link goes here").responseJSON { (Response) in
if let value = Response.result.value {
let json = JSON(value)
for anItem in json.array! {
let title: String? = anItem["Title"].stringValue
let date: String? = anItem["Date"].stringValue //trying to access this variable outside the function
let body: String? = anItem["Body"].stringValue
self.tableTitle.append(title!)
self.tableDate.append(date!)
self.tableBody.append(body!)
print(anItem["Title"].stringValue)
print(anItem["Date"].stringValue)
}
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
}
}
}
// this date stuff isn't being used yet, because I have no idea how...
public func dateForRFC3339DateTimeString(rfc3339DateTimeString: String) -> NSDate? {
let enUSPOSIXLocale = NSLocale(localeIdentifier: "en_US_POSIX")
let rfc3339DateFormatter = NSDateFormatter()
rfc3339DateFormatter.locale = enUSPOSIXLocale
rfc3339DateFormatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
rfc3339DateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
return rfc3339DateFormatter.dateFromString(rfc3339DateTimeString)
}
public func userVisibleDateTimeStringForRFC3339DateTimeString(rfc3339DateTimeString: String) -> String? {
let maybeDate = dateForRFC3339DateTimeString(rfc3339DateTimeString)
if let date = maybeDate {
let userVisibleDateFromatter = NSDateFormatter()
userVisibleDateFromatter.dateStyle = NSDateFormatterStyle.MediumStyle
userVisibleDateFromatter.timeStyle = NSDateFormatterStyle.ShortStyle
return userVisibleDateFromatter.stringFromDate(date)
} else {
return nil
}
}
let finalDateStr = userVisibleDateTimeStringForRFC3339DateTimeString(MasterViewController) //now this is where it gets weird, instead of letting me enter the string in the brackets, it defaults to MasterViewController, now I tried to move the date functions to another .swift file (an empty one) and it doesn't do that anymore
So yeah, that's about it, if anyone could help, it would be greatly appreciated.
Try below code, let me know if it works:
func dateForRFC3339Date(rfc3339Date: NSDate) -> NSDate? {
let enUSPOSIXLocale = NSLocale(localeIdentifier: "en_US_POSIX")
let rfc3339DateFormatter = NSDateFormatter()
rfc3339DateFormatter.locale = enUSPOSIXLocale
rfc3339DateFormatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
rfc3339DateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
let dateString = rfc3339DateFormatter.stringFromDate(rfc3339Date)
return rfc3339DateFormatter.dateFromString(dateString)
}
And call it in your getJSON() method like:
let convertedDate = self.dateForRFC3339Date(rfc3339Date: anItem["Date"])
I'm trying to parse out JSON into typed classes for safety/convenience, but it's proving very clunky. I wasn't able to find a library or even a post for Swift (Jastor is as close as I got). Here's a fabricated little snippet to illustrate:
// From NSJSONSerialization or similar and casted to an appropriate toplevel type (e.g. Dictionary).
var parsedJson: Dictionary<String, AnyObject> = [ "int" : 1, "nested" : [ "bool" : true ] ]
class TypedObject {
let stringValueWithDefault: String = ""
let intValueRequired: Int
let nestedBoolBroughtToTopLevel: Bool = false
let combinedIntRequired: Int
init(fromParsedJson json: NSDictionary) {
if let parsedStringValue = json["string"] as? String {
self.stringValueWithDefault = parsedStringValue
}
if let parsedIntValue = json["int"] as? Int {
self.intValueRequired = parsedIntValue
} else {
// Raise an exception...?
}
// Optional-chaining is actually pretty nice for this; it keeps the blocks from nesting absurdly.
if let parsedBool = json["nested"]?["bool"] as? Bool {
self.nestedBoolBroughtToTopLevel = parsedBool
}
if let parsedFirstInt = json["firstInt"] as? Int {
if let parsedSecondInt = json["secondInt"] as? Int {
self.combinedIntRequired = parsedFirstInt * parsedSecondInt
}
}
// Most succinct way to error if we weren't able to construct self.combinedIntRequired?
}
}
TypedObject(fromParsedJson: parsedJson)
There's a number of issues here that I'm hoping to work around:
It's extremely verbose, since I need to wrap every single property in a copy-pasted if-let for safety.
I'm not sure how to communicate errors when required properties are missing (as noted above). Swift seems to prefer (?) using exceptions for show-stopping problems (rather than pedestrian malformed data as here).
I don't know a nice way to deal with properties that exist but are the wrong type (given that the as? casting will fail and simply skip the block, it's not very informative to the user).
If I want to translate a few properties into a single one, I need to nest the let blocks proportional to the number of properties I'm combining. (This is probably more generally a problem with combining multiple optionals into one value safely).
In general, I'm writing imperative parsing logic when I feel like I ought to be able to do something a little more declarative (either with some stated JSON schema or at least inferring the schema from the class definition).
I do this using the Jastor framework:
1) Implement a Protocol that has a single function that returns an NSDictionary response:
protocol APIProtocol {
func didReceiveResponse(results: NSDictionary)
}
2) Create an API class that defines an NSURLConnection object that can be used as a Request URL for iOS's networking API. This class is created to simply return a payload from the itunes.apple.com API.
class API: NSObject {
var data: NSMutableData = NSMutableData()
var delegate: APIProtocol?
func searchItunesFor(searchTerm: String) {
// Clean up the search terms by replacing spaces with +
var itunesSearchTerm = searchTerm.stringByReplacingOccurrencesOfString(" ", withString: "+",
options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil)
var escapedSearchTerm = itunesSearchTerm.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
var urlPath = "https://itunes.apple.com/search?term=\(escapedSearchTerm)&media=music"
var url: NSURL = NSURL(string: urlPath)
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
println("Search iTunes API at URL \(url)")
connection.start()
}
// NSURLConnection Connection failed.
func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
println("Failed with error:\(error.localizedDescription)")
}
// New request so we need to clear the data object.
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
self.data = NSMutableData()
}
// Append incoming data.
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
self.data.appendData(data)
}
// NSURLConnection delegate function.
func connectionDidFinishLoading(connection: NSURLConnection!) {
// Finished receiving data and convert it to a JSON object.
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data,
options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
delegate?.didReceiveResponse(jsonResult)
}
}
3) Create a class with associated properties that inherits from Jastor
NSDictionary response:
{
"resultCount" : 50,
"results" : [
{
"collectionExplicitness" : "notExplicit",
"discCount" : 1,
"artworkUrl60" : "http:\/\/a4.mzstatic.com\/us\/r30\/Features\/2a\/b7\/da\/dj.kkirmfzh.60x60-50.jpg",
"collectionCensoredName" : "Changes in Latitudes, Changes in Attitudes (Ultmate Master Disk Gold CD Reissue)"
}
]
}
Music.swift
class Music : Jastor {
var resultCount: NSNumber = 0
}
4) Then in your ViewController be sure to set the delegate to self and then make a call to the API's searchITunesFor() method.
var api: API = API()
override func viewDidLoad() {
api.delegate = self;
api.searchItunesFor("Led Zeppelin")
}
5) Implement the Delegate method for didReceiveResponse(). Jastor extends your class to set a NSDictionary of the results returned from the iTunes API.
// #pragma - API Delegates
func didReceiveResponse(results: NSDictionary) {
let music = Music(dictionary: results)
println(music)
}
Short version: Since init isn't allowed to fail, validation has to happen outside of it. Optionals seem to be the intended tool for flow control in these cases. My solution is to use a factory method that returns an optional of the class, and use option chaining inside it to extract and validate the fields.
Note also that Int and Bool aren't children of AnyObject; data coming from an NSDictionary will have them stored as NSNumbers, which can't be cast directly to Swift types. Thus the calls to .integerValue and .boolValue.
Long version:
// Start with NSDictionary since that's what NSJSONSerialization will give us
var invalidJson: NSDictionary = [ "int" : 1, "nested" : [ "bool" : true ] ]
var validJson: NSDictionary = [
"int" : 1,
"nested" : [ "bool" : true ],
"firstInt" : 3,
"secondInt" : 5
]
class TypedObject {
let stringValueWithDefault: String = ""
let intValueRequired: Int
let nestedBoolBroughtToTopLevel: Bool = false
let combinedIntRequired: Int
init(intValue: Int, combinedInt: Int, stringValue: String?, nestedBool: Bool?) {
self.intValueRequired = intValue
self.combinedIntRequired = combinedInt
// Use Optionals for the non-required parameters so
// we know whether to leave the default values in place
if let s = stringValue {
self.stringValueWithDefault = s
}
if let n = nestedBool {
self.nestedBoolBroughtToTopLevel = n
}
}
class func createFromDictionary(json: Dictionary<String, AnyObject>) -> TypedObject? {
// Validate required fields
var intValue: Int
if let x = (json["int"]? as? NSNumber)?.integerValue {
intValue = x
} else {
return nil
}
var combinedInt: Int
let firstInt = (json["firstInt"]? as? NSNumber)?.integerValue
let secondInt = (json["secondInt"]? as? NSNumber)?.integerValue
switch (firstInt, secondInt) {
case (.Some(let first), .Some(let second)):
combinedInt = first * second
default:
return nil
}
// Extract optional fields
// For some reason the compiler didn't like casting from AnyObject to String directly
let stringValue = json["string"]? as? NSString as? String
let nestedBool = (json["nested"]?["bool"]? as? NSNumber)?.boolValue
return TypedObject(intValue: intValue, combinedInt: combinedInt, stringValue: stringValue, nestedBool: nestedBool)
}
class func createFromDictionary(json: NSDictionary) -> TypedObject? {
// Manually doing this cast since it works, and the only thing Apple's docs
// currently say about bridging Cocoa and Dictionaries is "Information forthcoming"
return TypedObject.createFromDictionary(json as Dictionary<String, AnyObject>)
}
}
TypedObject.createFromDictionary(invalidJson) // nil
TypedObject.createFromDictionary(validJson) // it works!
I've also done the following to convert to/from:
class Image {
var _id = String()
var title = String()
var subTitle = String()
var imageId = String()
func toDictionary(dict dictionary: NSDictionary) {
self._id = dictionary["_id"] as String
self.title = dictionary["title"] as String
self.subTitle = dictionary["subTitle"] as String
self.imageId = dictionary["imageId"] as String
}
func safeSet(d: NSMutableDictionary, k: String, v: String) {
if (v != nil) {
d[k] = v
}
}
func toDictionary() -> NSDictionary {
let jsonable = NSMutableDictionary()
self.safeSet(jsonable, k: "title", v: self.title);
self.safeSet(jsonable, k: "subTitle", v: self.subTitle);
self.safeSet(jsonable, k: "imageId", v: self.imageId);
return jsonable
}
}
Then I simply do the following:
// data (from service)
let responseArray = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) as NSArray
self.objects = NSMutableArray()
for item: AnyObject in responseArray {
var image = Image()
image.toDictionary(dict: item as NSDictionary)
self.objects.addObject(image)
}
If you want to POST the data:
var image = Image()
image.title = "title"
image.subTitle = "subTitle"
image.imageId = "imageId"
let data = NSJSONSerialization.dataWithJSONObject(image.toDictionary(), options: .PrettyPrinted, error: nil) as NSData
// data (to service)
request.HTTPBody = data;