0

I try to convert a JSON response from the server to an object. I use Swift.

This is the result of printing the server response:

(
    {
    1 = Horst;
    2 = Schnitzelhuber;
    3 = "0161 2213310";
    id = 0000040001;
    status = 2;
},
    {
    1 = "Mar\U00f0a";
    3 = "0163 5419374";
    id = 0000040005;
    status = 2;
}
)

This is my model:

class Profil: JSONSerializable {   
  var id: String?    
  required init() {}

  class func map(source: JsonSZ, object: Profil) {
    object.id <= source["id"]
  }
}

I have been using SwiftJZ for parsing so far.

let test: [Profil!]? = serializer.fromJSONArray(response, to: Profil.self)

If I try to print the mapped object:

println(test?[0].id)

=> result is always nil

This is the relevant method from JSONSZ:

public func fromJSONArray<N: JSONSerializable>(JSON: AnyObject,  to type: N.Type) -> [N]? {
    if let string = JSON as? String {
        if let data =  JSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true) {
            let parsed: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil)
      => FAIL if let array = parsed as? [[String: AnyObject]] {
                var objects: [N] = []

                for element in array {
                    self.values = element
                    var object = N()
                    N.map(self, object: object)
                    objects.append(object)
                }

                return objects
            }
        }
    }
    return nil
}

Could you help me to solve this issue fast?
Perhaps another library...
Finally I want to save this objects of the model into Cora Data.

EDIT:

public func fromJSONArray<N: JSONSerializable>(JSON: AnyObject,  to type: N.Type) -> [N]? {
    if let string = JSON as? String {
        if let data =  JSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true) {
            let parsed: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil)

Here is the problem: let parsed is nil. That's why the serialization fails.

1 Answer 1

2

I recently have been doing similar and have built my own fairly basic JSON parsing library.

Here's a little bit from it:

JSON Typealiases

typealias JSON = AnyObject
typealias JSONObject = [String : AnyObject]
typealias JSONArray = [JSON]

JSONDecodable Protocol

// Represents an object that can be imported via JSON
protocol JSONDecodable
{
    func decodeJSON(json: JSONObject)
}

JSON Type Parsing

private let iso8601DateFormatter : NSDateFormatter =
{
    let dateFormatter = NSDateFormatter()

    dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

    return dateFormatter
}()

func jsonString(object: AnyObject?) -> String?
{
    return object as? String
}

func jsonBoolean(object: AnyObject?) -> Bool?
{
    return object as? Bool
}

func jsonInt(object: AnyObject?) -> Int?
{
    return object as? Int
}

func jsonFloat(object: AnyObject?) -> Float?
{
    return object as? Float
}

func jsonDate(object: AnyObject?) -> NSDate?
{
    switch jsonString(object)
    {
    case .Some(let dateString): return iso8601DateFormatter.dateFromString(dateString)
    case .None: return nil
    }
}

func jsonDateString(date: NSDate) -> String
{
    return iso8601DateFormatter.stringFromDate(date)
}

Null Coalesce Assignment Operator (a ??= b)

// Null coalesce-assignment operator (a ??= b)
infix operator ??= { associativity left precedence 90 }

func ??= <T>(inout lhs: T, rhs: T?)
{
    // If the right-hand side is not-nil, assign the value to the left-hand
    if let rhs = rhs { lhs = rhs }
}

JSON Result (Enum)

// Completion handler which receives a JSON result
typealias JSONCompletionHandler = (result: JSONResult) -> Void

enum JSONResult
{
    case Object(JSONObject)  // Dictionary
    case Array(JSONArray)    // Array
    case Null                // No Data
    case Error(NSError)      // Error occurred
}

JSON Data Task (NSURLSession Extension)

extension NSURLSession
{
    func jsonDataTaskWithRequest(request: NSURLRequest, completionHandler: JSONCompletionHandler? = nil) -> NSURLSessionDataTask
    {
        return self.dataTaskWithRequest(request) { data, urlResponse, error in

            // Check for network error
            if let error = error
            {
                completionHandler?(result: .Error(error))
                return
            }

            // Check for non-200 HTTP status
            if let httpResponse = urlResponse as? NSHTTPURLResponse
            {
                if httpResponse.statusCode < 200 || httpResponse.statusCode > 299
                {
                    let httpError = NSError(domain: "JSONDataTask", code: httpResponse.statusCode, userInfo: nil)

                    completionHandler?(result: .Error(httpError))
                    return
                }
            }

            var json : JSON?

            // If there is data available, try to deserialize it as JSON
            if data?.length > 0
            {
                // Deserialize the data into a JSON object
                var jsonError : NSError?
                json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &jsonError)

                if let jsonError = jsonError
                {
                    completionHandler?(result: .Error(jsonError))
                    return
                }
            }

            // Check what kind of JSON object is the root node
            switch json
            {
                // If the root node is a JSON object
            case let jsonObject as JSONObject:
                completionHandler?(result: .Object(jsonObject))

                // If the root node is a JSON array
            case let jsonArray as JSONArray:
                completionHandler?(result: .Array(jsonArray))

                // If there was no JSON data
            default:
                completionHandler?(result: .Null)
            }
        }
    }
}

Example Network Code

let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: NSURL(string: "http://www.digitlabs.us")!)

let task = session.jsonDataTaskWithRequest(request) { result in 

   switch result
   {
     case Object(let object): // JSON dictionary
     case Array(let array): // JSON array
     case Null: // No Data
     case Error(let error): // Error occurred
   }
}

task.resume()

Example NSManagedObject Class

class Message : NSManagedObject, JSONDecodable
{
    @NSManaged var identifier : String
    @NSManaged var subject : String
    @NSManaged var bodyText : String
    @NSManaged var unread : NSNumber
    @NSManaged var dateSent : NSDate

    var isUnread : Bool
    {
        get { return self.unread as Bool }
        set { self.unread = NSNumber(bool: newValue) }
    }

    func decodeJSON(json: JSONObject)
    {
        self.identifier ??= jsonString(json["id"])
        self.subject ??= jsonString(json["subject"])
        self.bodyText ??= jsonString(json["bodyText"])
        self.isUnread ??= jsonBoolean(json["isUnread"])
        self.dateSent ??= jsonDate(json["dateSent"])
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thats everything for parsing? Where do you call "NSJSONSerialization.JSONObjectWithData(...)"? Could you post some code snippet for the array implementation?
Ah right, I have an extension for NSURLSession that I use, I'll edit my post to include it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.