How to Create Objects from Swiftyjson

How to create objects from SwiftyJSON

This is how I would approach the problem.

Step 1

Since your init inside Question does receive non optional objects, I had the feeling that the properties of Questions should be non optional too. I also converted the properties from var to let (tell me if I am wrong).

Step 2

This is the refactored Question class. As you can see I added a class method build that receive a JSON (a SwiftyJSON) and returns a Question (if the json contains correct data), nil otherwise.

Right now I cannot do this with a failable initializer.

extension String {
func toBool() -> Bool? {
switch self.lowercaseString {
case "true", "1", "yes" : return true
case "false", "0", "no" : return false
default: return nil
}
}
}

class Question {

let level: Int
let questionText: String
let answer1: String
let answer2: String
let answer3: String
let answer4: String
let correctAnswer: String
let haveAnswered: Bool

init(level: Int, questionText:String, answer1:String, answer2:String, answer3:String, answer4:String, correctAnswer: String, haveAnswered:Bool) {
self.level = level
self.questionText = questionText
self.answer1 = answer1
self.answer2 = answer2
self.answer3 = answer3
self.answer4 = answer4
self.correctAnswer = correctAnswer
self.haveAnswered = false
}

class func build(json:JSON) -> Question? {
if let
level = json["level"].string?.toInt(),
questionText = json["questionText"].string,
answer1 = json["answer1"].string,
answer2 = json["answer2"].string,
answer3 = json["answer3"].string,
answer4 = json["answer4"].string,
correctAnswer = json["correctAnswer"].string,
haveAnswered = json["haveAnswered"].string?.toBool() {
return Question(
level: level,
questionText: questionText,
answer1: answer1,
answer2: answer2,
answer3: answer3,
answer4: answer4,
correctAnswer: correctAnswer,
haveAnswered: haveAnswered)
} else {
debugPrintln("bad json \(json)")
return nil
}
}
}

Step 3

Now let's look at viewDidLoad.

func viewDidLoad() {
super.viewDidLoad()

let number = arc4random_uniform(1000)

if let
url = NSURL(string: "http://www.wirehead.ru/try-en.json?\(number)"),
data = NSURLConnection.sendSynchronousRequest(NSURLRequest(URL: url), returningResponse: nil, error: nil) {
// line #a
let rootJSON = JSON(data: data)
// line #b
if let questions = (rootJSON["pack1"].array?.map { return Question.build($0) }) {
// now you have an array of optional questions [Question?]...
}

}
}

At line #a I put inside rootJSON the whole data received from the connection (converted into JSON).

What happen at line #b?

Well I try to access the array located inside "pack1".

rootJSON["pack1"].array?

If the array exists I run the map method. This will extract each cell of the array and I will be able to refer to it with the $0 parameter name inside the closure.

Inside the closure I use this json block (that should represent a question) to build a Question instance.

The result will be an array of Question?. There could be ill values if some son data was not valid. If you want I can show you how to remove the nil values from this array

I could not try the code with real data, hope this helps.

SwiftyJSON add array of JSON objects

To create a JSON dictionary, you have to initialize the JSON object on jsonOutput just like you did with birthdaysJSON:

var jsonOutput: JSON = JSON(["birthdays": birthdaysJSON])

CREATE JSON SWIFTYJSON

Use Codable. Since Swift 4 SwiftyJSON became obsolete

struct Object : Encodable {
private enum CodingKeys : String, CodingKey { case name = "user", key = "apikey" }
let name, key : String
}

let obj = [Object(name: "Foo", key: "API123"), Object(name: "Bar", key: "API456")]

do {
let jsonData = try JSONEncoder().encode(obj)
let jsonString = String(data: jsonData, encoding: .utf8)!
print(jsonString)
} catch { print(error) }

How to parse JSON Array Objects with SwiftyJSON?

Actually it would be better to define a struct for object in Array.

public struct Item {

// MARK: Declaration for string constants to be used to decode and also serialize.
private struct SerializationKeys {
static let sno = "sno"
static let title = "title"
static let tableid = "tableid"
}

// MARK: Properties

public var sno: String?
public var title: String?
public var tableid: String?

// MARK: SwiftyJSON Initializers
/// Initiates the instance based on the object.
///
/// - parameter object: The object of either Dictionary or Array kind that was passed.
/// - returns: An initialized instance of the class.
public init(object: Any) {
self.init(json: JSON(object))
}

/// Initiates the instance based on the JSON that was passed.
///
/// - parameter json: JSON object from SwiftyJSON.
public init(json: JSON) {
sno = json[SerializationKeys.sno].string
title = json[SerializationKeys.title].string
tableid = json[SerializationKeys.tableid].string
}
}

And you need to map your array of JSON to Item objects.

var items = [Item]()
if let arrayJSON = json.array
items = arrayJSON.map({return Item(json: $0)})
}

Deserialize JSON array to Swift objects using SwiftyJSON

var jsonObjectArray = JSON(swiftStr).array!
var swiftArray = []
for jsonObject in jsonObjectArray {
var swiftObject = SwiftObject()
swiftObject.propetyName = jsonObject["propertyName"].string!
swiftArry.append(swiftObject)
}

How to Convert an Array of SwiftyJSON objects to a SwiftyJSON object?

If I understood your question and you want to create a SwiftyJSON object from an array you should do like this:

var myJSON:JSON = JSON(myArray)

how build objects with alamofire and SwiftyJSON

Let's fix the issues for parts:

First Error:

According to Apple:

Classes and structures must set all of their stored properties to an appropriate initial value by the time an instance of that class or structure is created. Stored properties cannot be left in an indeterminate state.

You can set an initial value for a stored property within an initializer, or by assigning a default property value as part of the property’s definition.

You're trying to use the default init method in the class RepoSwiftyJSON that inherits from NSObject, it's not recommend use the ! operator to explicit say to the compiler that the object going to have a value in runtime. So one option to solve your problem is use convenience initializer like in the following way:

class RepoSwiftyJSON: NSObject {

let _userId: String
let _title: String

init(userid:String , title:String){
self._userId = userid
self._title = title
}

override convenience init() {
self.init(userid: "a", title: "b")
}
}

let DataArray: RepoSwiftyJSON = RepoSwiftyJSON()
DataArray._title // a
DataArray._userId // b

In the above way you override the default init of the class NSObject and mark it as convenience to allow to call the another init(userid:String , title:String) inside the default init method.

There are many ways of solve your first error, the above is just one.

Second Error:

If we check the variable aryId in his definition :

var aryId = [RepoSwiftyJSON]()

It's an array of RepoSwiftyJSON, and in your following line:

let rowData: JSON = aryId[indexPath.row]

You're trying to assign an element of type RepoSwiftyJSON returned by the above line to another of type JSON and it's not correct.

EDIT:

You can create a JSON using the following function:

let jsonObject: [AnyObject] = [
["name": "John", "age": 21],
["name": "Bob", "age": 35],
]

func createJSON(value: AnyObject) -> String {

let options = NSJSONWritingOptions.PrettyPrinted

guard NSJSONSerialization.isValidJSONObject(value) else {
return ""
}

do {
let data = try NSJSONSerialization.dataWithJSONObject(value, options: options)

if let string = NSString(data: data, encoding: NSUTF8StringEncoding) {
return string as String
}
} catch let error {
print("\(error)")
}
return ""
}

let json = createJSON(jsonObject)

and you will see :

[
{
"age" : 21,
"name" : "John"
},
{
"age" : 35,
"name" : "Bob"
}
]

I hope this help you.



Related Topics



Leave a reply



Submit