Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从SwiftyJSON创建对象_Swift_Swifty Json - Fatal编程技术网

如何从SwiftyJSON创建对象

如何从SwiftyJSON创建对象,swift,swifty-json,Swift,Swifty Json,我有一个代码,解析JSON的问题列表,我可以得到每个属性。如何遍历整个文件并为每个问题创建一个对象 class ViewController: UIViewController { var hoge: JSON? override func viewDidLoad() { super.viewDidLoad() let number = arc4random_uniform(1000) let url = NSURL(string: "http://www.wire

我有一个代码,解析JSON的问题列表,我可以得到每个属性。如何遍历整个文件并为每个问题创建一个对象

class ViewController: UIViewController {

var hoge: JSON?

override func viewDidLoad() {
    super.viewDidLoad()

    let number = arc4random_uniform(1000)
    let url = NSURL(string: "http://www.wirehead.ru/try-en.json?\(number)")
    var request = NSURLRequest(URL: url!)
    var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil)
    if data != nil {
        hoge = JSON(data: data!)
        let level = hoge!["pack1"][0]["level"].intValue
        let questionText = hoge!["pack1"][0]["questionText"].stringValue
        let answer1 = hoge!["pack1"][0]["answer1"].stringValue
        let answer2 = hoge!["pack1"][0]["answer2"].stringValue
        let answer3 = hoge!["pack1"][0]["answer3"].stringValue
        let answer4 = hoge!["pack1"][0]["answer4"].stringValue
        let correctAnswer = hoge!["pack1"][0]["correctAnswer"].stringValue
        let haveAnswered = hoge!["pack1"][0]["haveAnswered"].boolValue

    }
  }
}
我想在下面创建哪些对象的问题模型

class Question {

    var level : Int?
    var questionText : String?
    var answer1 : String?
    var answer2 : String?
    var answer3 : String?
    var answer4 : String?
    var correctAnswer : String?
    var haveAnswered : Bool = false

    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
    }

}

这就是我处理这个问题的方法

第一步 由于您的
init
内部
Question
确实接收到
非可选
对象,我觉得问题的属性也应该是非可选的。我还将属性从
var
转换为
let
(如果我错了,请告诉我)

步骤2 这是重构的
问题
类。如您所见,我添加了一个类方法
build
,它接收一个
JSON
(a
SwiftyJSON
),并返回一个
问题(如果JSON包含正确的数据),否则返回nil

现在,我无法使用
可失败的初始值设定项来执行此操作

步骤3 现在让我们看看
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?]...
        }

    }
}
在第a行,我将从连接接收到的所有数据(转换为
JSON
)放入
rootJSON

b线发生了什么

我尝试访问
“pack1”
中的数组

如果数组存在,我运行map方法。这将提取数组的每个单元格,我将能够在闭包中用
$0
参数名引用它

在闭包中,我使用这个json块(应该表示一个问题)来构建一个
question
实例

结果将是一组
问题?
。如果某些子数据无效,则可能存在错误值。如果需要,我可以演示如何从此数组中删除
nil

我无法用真实数据尝试代码,希望这能有所帮助

for (item, content) in hoge {
    let level = content["level"].intValue
}

这应该会起作用

步骤1。我们将创建一个协议,其中包含一个构造函数方法和模型类

protocol JSONable {
    init?(parameter: JSON)
}

class Style: JSONable {
    let ID              :String!
    let name            :String!

    required init(parameter: JSON) {
        ID            = parameter["id"].stringValue
        name          = parameter["name"].stringValue
    }

    /*  JSON response format
    {
      "status": true,
      "message": "",
      "data": [
        {
          "id": 1,
          "name": "Style 1"
        },
        {
          "id": 2,
          "name": "Style 2"
        },
        {
          "id": 3,
          "name": "Style 3"
        }
      ]
    }
    */
}
第二步。我们将创建JSON的扩展,该扩展将JSON转换为模型类类型对象

extension JSON {
    func to<T>(type: T?) -> Any? {
        if let baseObj = type as? JSONable.Type {
            if self.type == .array {
                var arrObject: [Any] = []
                for obj in self.arrayValue {
                    let object = baseObj.init(parameter: obj)
                    arrObject.append(object!)
                }
                return arrObject
            } else {
                let object = baseObj.init(parameter: self)
                return object!
            }
        }
        return nil
    }
}
我希望这将是有用的

有关这方面的更多信息,请参阅此链接。

您可以使用专门为此目的设计的SwiftyJSONModel。因此,在您的情况下,模型如下所示:

class Question: JSONObjectInitializable {
    enum PropertyKey: String {
        case level, questionText
        case answer1, answer2, answer3, answer4
        case correctAnswer, haveAnswered
    }

    var level : Int?
    var questionText : String?
    var answer1 : String?
    var answer2 : String?
    var answer3 : String?
    var answer4 : String?
    var correctAnswer : String?
    var haveAnswered : Bool = false

    required init(object: JSONObject<PropertyKey>) throws {
        level = object.value(for: .level)
        questionText = object.value(for: .questionText)
        answer1 = object.value(for: .answer1)
        answer2 = object.value(for: .answer2)
        answer3 = object.value(for: .answer3)
        answer4 = object.value(for: .answer4)
        correctAnswer = object.value(for: .correctAnswer)
        haveAnswered = object.value(for: .haveAnswered) ?? false
    }   
}
let rootJSON = JSON(data: data)
let questions = rootJSON.arrayValue.flatMap { try? Question(json: $0) }
该框架为您提供了几个不错的功能:

  • 所有密钥都存储在单独的enum
    PropertyKey
  • 没有类似于
    stringValue
    intValue
    等的样板文件
  • JSON
    无效,框架将给出一个详细的错误,您将立即看到到底出了什么问题

  • 我看到您正在将您的属性(除了
    haveresponse
    )声明为
    可选的
    。另一方面,
    init
    的所有参数都是
    非可选的
    。哪一个是正确的?回答得很好。我正在为一个类似的类建模,这确实帮助了我。@damianesteban谢谢。这是一个解决方案,在过去的一年里我改进了好几次。非常感谢!不幸的是,我得到了错误的json。我检查了JSON,它通过了验证。你能看看有什么问题吗?数据在原始JSON中,级别值是一个
    字符串
    。因此,我们无法直接将其作为
    Int
    检索。我将更新我的答案;-)同样的结果,糟糕的json:(这个答案非常好。我没有这样做就导致了内存泄漏,而这实际上是唯一帮助我的解决方案!谢谢!
    Alamofire.request(.GET, url).validate().responseJSON { response in
            switch response.result {
                case .success(let value):
                    let json = JSON(value)
    
                    var styles: [Style] = []
                    if let styleArr = json["data"].to(type: Style.self) {
                        styles = styleArr as! [Style]
                    }
                    print("styles: \(styles)")
                case .failure(let error):
                    print(error)
            }
     }
    
    class Question: JSONObjectInitializable {
        enum PropertyKey: String {
            case level, questionText
            case answer1, answer2, answer3, answer4
            case correctAnswer, haveAnswered
        }
    
        var level : Int?
        var questionText : String?
        var answer1 : String?
        var answer2 : String?
        var answer3 : String?
        var answer4 : String?
        var correctAnswer : String?
        var haveAnswered : Bool = false
    
        required init(object: JSONObject<PropertyKey>) throws {
            level = object.value(for: .level)
            questionText = object.value(for: .questionText)
            answer1 = object.value(for: .answer1)
            answer2 = object.value(for: .answer2)
            answer3 = object.value(for: .answer3)
            answer4 = object.value(for: .answer4)
            correctAnswer = object.value(for: .correctAnswer)
            haveAnswered = object.value(for: .haveAnswered) ?? false
        }   
    }
    
    let rootJSON = JSON(data: data)
    let questions = rootJSON.arrayValue.flatMap { try? Question(json: $0) }