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
Swiftui Hstack with Equal Height
Calculate Time Difference in Swift 4
How to Create Objects from Swiftyjson
Why Does Using Dynamictype on a Force Unwrapped Nil Optional Value Type Work
Make a Type Itself -- Not Its Instances -- Conform to a Protocol
How to Create a Multiline Textfield in Swiftui? Like the Notes App
Can Nscoding and Codable Co-Exist
Using State Variables as Inputs to a Func in Swiftui
Identifiable Protocol in Swift: Class VS Struct
Scaling Down a Text's Font Size to Fit Its Length to Another Text in Swiftui
How Does Let X Where X.Hassuffix("Pepper") Work
Alamofire 3 Custom Encoding to Alamofire 4 Custom Encoding
From the Swift Repl, How to Get a List of Available Modules
Having Trouble with Nstimer (Swift)
Need Detailed Explanation for Memoize Implementation in Swift (Wwdc 14, Session 404)
Ibdesignable and Uitableviewcell