【问题标题】:json manipulation in swift, cant get the data快速操作json,无法获取数据
【发布时间】:2016-02-01 06:32:22
【问题描述】:

我正在编写我的第一个 swift 代码,尝试使用 Json,我使用 GitHub 中的 JSONSerializer 来帮助我将类转换为 json,这部分工作正常,现在我尝试将 Json 字符串转换为字典并获取数据我无法做到这一点,我附上了我的 playGround 代码,有人可以帮我吗?

import UIKit
import Foundation

   /// Handles Convertion from instances of objects to JSON strings.      Also     helps with casting strings of JSON to Arrays or Dictionaries.
public class JSONSerializer {

/**
 Errors that indicates failures of JSONSerialization
 - JsonIsNotDictionary: -
 - JsonIsNotArray:          -
 - JsonIsNotValid:          -
 */
public enum JSONSerializerError: ErrorType {
    case JsonIsNotDictionary
    case JsonIsNotArray
    case JsonIsNotValid
}

//http://stackoverflow.com/questions/30480672/how-to-convert-a-json-string-to-a-dictionary
/**
Tries to convert a JSON string to a NSDictionary. NSDictionary can be easier to work with, and supports string bracket referencing. E.g. personDictionary["name"].
- parameter jsonString: JSON string to be converted to a NSDictionary.
- throws: Throws error of type JSONSerializerError. Either JsonIsNotValid or JsonIsNotDictionary. JsonIsNotDictionary will typically be thrown if you try to parse an array of JSON objects.
- returns: A NSDictionary representation of the JSON string.
*/
public static func toDictionary(jsonString: String) throws -> NSDictionary {
    if let dictionary = try jsonToAnyObject(jsonString) as? NSDictionary {
        return dictionary
    } else {
        throw JSONSerializerError.JsonIsNotDictionary
    }
}

/**
 Tries to convert a JSON string to a NSArray. NSArrays can be iterated and each item in the array can be converted to a NSDictionary.
 - parameter jsonString:    The JSON string to be converted to an NSArray
 - throws: Throws error of type JSONSerializerError. Either JsonIsNotValid or JsonIsNotArray. JsonIsNotArray will typically be thrown if you try to parse a single JSON object.
 - returns: NSArray representation of the JSON objects.
 */
public static func toArray(jsonString: String) throws -> NSArray {
    if let array = try jsonToAnyObject(jsonString) as? NSArray {
        return array
    } else {
        throw JSONSerializerError.JsonIsNotArray
    }
}

/**
 Tries to convert a JSON string to AnyObject. AnyObject can then be casted to either NSDictionary or NSArray.
 - parameter jsonString:    JSON string to be converted to AnyObject
 - throws: Throws error of type JSONSerializerError.
 - returns: Returns the JSON string as AnyObject
 */
private static func jsonToAnyObject(jsonString: String) throws -> AnyObject? {
    var any: AnyObject?

    if let data = jsonString.dataUsingEncoding(NSUTF8StringEncoding) {
        do {
            any = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)
        }
        catch let error as NSError {
            let sError = String(error)
            NSLog(sError)
            throw JSONSerializerError.JsonIsNotValid
        }
    }
    return any
}

/**
 Generates the JSON representation given any custom object of any custom class. Inherited properties will also be represented.
 - parameter object:    The instantiation of any custom class to be represented as JSON.
 - returns: A string JSON representation of the object.
 */
public static func toJson(object: Any) -> String {
    var json = "{"
    let mirror = Mirror(reflecting: object)

    var children = [(label: String?, value: Any)]()
    let mirrorChildrenCollection = AnyRandomAccessCollection(mirror.children)!
    children += mirrorChildrenCollection

    var currentMirror = mirror
    while let superclassChildren = currentMirror.superclassMirror()?.children {
        let randomCollection = AnyRandomAccessCollection(superclassChildren)!
        children += randomCollection
        currentMirror = currentMirror.superclassMirror()!
    }

    let size = children.count
    var index = 0

    for (optionalPropertyName, value) in children {

        /*let type = value.dynamicType
        let typeString = String(type)
        print("SELF: \(type)")*/

        let propertyName = optionalPropertyName!
        let property = Mirror(reflecting: value)

        var handledValue = String()
        if value is Int || value is Double || value is Float || value is Bool {
            handledValue = String(value ?? "null")
        }
        else if let array = value as? [Int?] {
            handledValue += "["
            for (index, value) in array.enumerate() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [Double?] {
            handledValue += "["
            for (index, value) in array.enumerate() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [Float?] {
            handledValue += "["
            for (index, value) in array.enumerate() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [Bool?] {
            handledValue += "["
            for (index, value) in array.enumerate() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [String?] {
            handledValue += "["
            for (index, value) in array.enumerate() {
                handledValue += value != nil ? "\"\(value!)\"" : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [String] {
            handledValue += "["
            for (index, value) in array.enumerate() {
                handledValue += "\"\(value)\""
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? NSArray {
            handledValue += "["
            for (index, value) in array.enumerate() {
                if !(value is Int) && !(value is Double) && !(value is Float) && !(value is Bool) && !(value is String) {
                    handledValue += toJson(value)
                }
                else {
                    handledValue += "\(value)"
                }
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if property.displayStyle == Mirror.DisplayStyle.Class {
            handledValue = toJson(value)
        }
        else if property.displayStyle == Mirror.DisplayStyle.Optional {
            let str = String(value)
            if str != "nil" {
                handledValue = String(str).substringWithRange(Range<String.Index>(start: str.startIndex.advancedBy(9), end: str.endIndex.advancedBy(-1)))
            } else {
                handledValue = "null"
            }
        }
        else {
            handledValue = String(value) != "nil" ? "\"\(value)\"" : "null"
        }

        json += "\"\(propertyName)\": \(handledValue)" + (index < size-1 ? ", " : "")
        ++index
    }
    json += "}"
    return json
}
}

          /***********************************************************************/
/* This is my code                                                     */
/***********************************************************************/
class jsonContainer{
var json:LoginToSend
init(){
    json = LoginToSend(password:"String",email:"String",
    deviceToken:"String",
    os:"String",
    osType:"String",
    ver:"String",
    height:1,
    width:1,
    IP:"String",
    errorCode:1,
    errorText:"String")

}
}
class LoginToSend{
var pType:String = "Login"
var userList :Array<AnyObject> = []
var deviceList :Array<AnyObject> = []
var errorList :Array<AnyObject> = []


//    var userList:UserList
init(password:String,email:String,
    deviceToken:String,
    os:String,
    osType:String,
    ver:String,
    height:Int,
    width:Int,
    IP:String,
    errorCode:Int,
    errorText:String){

        let userLista = UserList(password: password,email: email)
        userList.append(userLista)
        let deviceLista = DeviceList(deviceToken: deviceToken,
            os: os,
            ver: ver,
            osType: osType,
            height: height,
            width: width,
            IP: IP)
        deviceList.append(deviceLista)
        let errorLista = ErrorList(errorCode: errorCode, errorText: errorText)
        errorList.append(errorLista)

}
}
class UserList{
var Password = ""
var Email = ""
init( password:String,  email:String){
    Password = password
    Email = email
 }

}
class DeviceList{
var deviceToken = ""
var os = ""
var ver = ""
var osType = ""
var height = -1
var width = -1
var IP = ""
init(deviceToken:String, os:String, ver:String, osType:String,height:Int,width:Int,IP:String){
    self.deviceToken = deviceToken
    self.os = os
    self.ver = ver
    self.osType = osType
    self.height = height
    self.width = width
    self.IP = IP
}
}
class ErrorList{
var errorCode = -1
var errorText = ""
init(errorCode:Int,errorText:String)
{
    self.errorCode = errorCode
    self.errorText = errorText
}
}
var loginToSend = LoginToSend(password:"String",email:"String",
deviceToken:"String",
os:"String",
osType:"String",
ver:"String",
height:1,
width:1,
IP:"String",
errorCode:1,
errorText:"String")
//*****************************************************
//* Creating json from my classes                     *
//*****************************************************

var json1 = JSONSerializer.toJson(loginToSend)

// next line Create the structure i need **
json1 = "{\"json\":" + json1 + "}"
print("===== print the consructed json ====")

print(json1)

let data = json1.dataUsingEncoding(NSUTF8StringEncoding,     allowLossyConversion: false)!

let json6 = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String: AnyObject]
print("==== print the objects created after converting to NSData and  using NSJSONSerialization.JSONObjectWithData====")

print (json6)
//let j = json6[json]
//let c = j[deviceList]
print (json6["json"]!["deviceList"])
let deviceList = json6["json"]!["deviceList"]?!["IP"]
let ip = deviceList?!["IP"]
print("==== Trying to get internal dta and get nil=====")
print (ip)

这是playGround outPut

===== 打印构造好的 json ==== {“json”:{“pType”:“登录”,“userList”:[{“密码”:“字符串”,“电子邮件”:“字符串”}],“deviceList”:[{“deviceToken”:“字符串","os":"String","ver":"String","osType":"String","height":1,"width":1,"IP":"String"}],"errorList ": [{"errorCode": 1, "errorText": "String"}]}} ==== 打印转换为 NSData 并使用 NSJSONSerialization.JSONObjectWithData 后创建的对象==== [“json”:{ 设备列表 = ( { IP = 字符串; 设备令牌 = 字符串; 高度 = 1; 操作系统 = 字符串; osType = 字符串; 版本 = 字符串; 宽度 = 1; } ); 错误列表 = ( { 错误代码 = 1; 错误文本 = 字符串; } ); pType = 登录; 用户列表 = ( { 电子邮件=字符串; 密码=字符串; } ); }] 可选的(( { IP = 字符串; 设备令牌 = 字符串; 高度 = 1; 操作系统 = 字符串; osType = 字符串; 版本 = 字符串; 宽度 = 1; } )) ==== 试图获取内部数据并得到 nil===== 无

【问题讨论】:

  • 你的代码有什么问题?
  • 我不知道如何获取数据,就像我尝试的那样:let deviceList = json6["json"]!["deviceList"]?!["IP"] let ip = deviceList ?!["IP"] print("==== 试图获取内部数据并得到 nil=====") print (ip)
  • 你得到什么错误?什么意外日志?不要指望我们有一个操场,所以我们可以运行你所有的代码,让问题自己说清楚。
  • 大部分代码是将类转换为 jscon 的实用程序,我的代码标有备注,在最后 3 行中,我尝试提取值“IP”并打印它并获得 null ,但如果你没有 playGround 我认为很难看到它,将游乐场结果添加到原始问题

标签: ios json swift dictionary


【解决方案1】:

我只看了你代码的最后一部分,即与你的问题相关的部分,我看到的是你真的应该使用安全展开

我只是通过消除使用! 展开的所有强制并用安全的可选绑定替换它来使您的代码正常工作。

另外,deviceList 是一个数组,而不是字典。

因此,在let data = json1.dataUsingEncoding..... 行之后,将所有内容替换为该行即可:

if let json6 = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String: AnyObject] {
    if let innerJSON = json6["json"] as? [String: AnyObject], let deviceList = innerJSON["deviceList"] as? [[String: AnyObject]] {
        for device in deviceList {
            print(device["IP"])
        }
    }
}

这个想法是通过可选绑定将对象转换为正确的类型:json6 是一个字典,它的“json”键有一个值字典,而这个字典的“deviceList”键包含一个字典数组包含 IP。

请注意,您的 JSON 数据似乎包含错误。 'IP' 字段包含字符串“String”,我不确定这是您所期望的...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    • 2020-04-27
    相关资源
    最近更新 更多