Arrays Swift 4 JSON可解码,具有多维和多类型数组

Arrays Swift 4 JSON可解码,具有多维和多类型数组,arrays,json,multidimensional-array,swift4,decodable,Arrays,Json,Multidimensional Array,Swift4,Decodable,好的,这是我从服务器收到的json格式 现在我想把它解码到我的结构中,但仍然没有运气 { "values":[ [1,1,7,"Azuan Child","Anak Azuan","12345","ACTIVE","Morning",7,12,"2017-11-09 19:45:00"], [28,1,0,"Azuan Child2","Amran","123456","ACTIVE","Evening",1,29,"2017-11-09 19:45:00"] ] } URLSession上的

好的,这是我从服务器收到的json格式

现在我想把它解码到我的结构中,但仍然没有运气

{
"values":[
[1,1,7,"Azuan Child","Anak Azuan","12345","ACTIVE","Morning",7,12,"2017-11-09 19:45:00"],
[28,1,0,"Azuan Child2","Amran","123456","ACTIVE","Evening",1,29,"2017-11-09 19:45:00"]
]
}
URLSession上的调用方方法如下所示

struct ChildrenTable: Decodable {
    var values: [[String]]?
}
我得到的错误是

URLSession.shared.dataTask(with: request) { (data, response, err) in
        guard let data = data else { return }

        let dataAsString = String(data: data, encoding: .utf8)
        print(dataAsString)

        do {
            let children  = try
                JSONDecoder().decode(ChildrenTable.self, from: data)
                print (children)
        } catch let jsonErr {
            print ("Error serializing json: ", jsonErr)
        }
    }.resume()
我知道数组中有一个int,我只为值
var values:[[String]]?
(这个错误弹出的原因)转换字符串,但我不能在我的结构中使用任何多维数组或元组,因为它遵循可解码协议

我也无法将数据转换为字典,因为它将抛出错误“预期解码字典,但找到数组”

有没有解决这个问题的办法?我尝试在数据上转换字符串类型,但仍然没有成功


p/s:如果所有的json格式都是字符串类型,那就没有问题了,但我没有更改的权限,因为我是从API调用它的。

正如您所说,您的json数组是多类型的,但您正在尝试将所有内容解码为
字符串。
字符串
可解码
的默认一致性不允许这样做。我想到的唯一解决办法就是引进新的型号

Error serializing json:  
typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [Vito_Parent.ChildrenTable.(CodingKeys in _1B826CD7D9609504747BED0EC0B7D3B5).values, Foundation.(_JSONKey in _12768CA107A31EF2DCE034FD75B541C9)(stringValue: "Index 0", intValue: Optional(0)), 
Foundation.(_JSONKey in _12768CA107A31EF2DCE034FD75B541C9)(stringValue: "Index 0", intValue: Optional(0))], 
debugDescription: "Expected to decode String but found a number instead.", underlyingError: nil))

正如您所说,您的json数组是多类型的,但您正在尝试将所有内容解码为
字符串。
字符串
可解码
的默认一致性不允许这样做。我想到的唯一解决办法就是引进新的型号

Error serializing json:  
typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [Vito_Parent.ChildrenTable.(CodingKeys in _1B826CD7D9609504747BED0EC0B7D3B5).values, Foundation.(_JSONKey in _12768CA107A31EF2DCE034FD75B541C9)(stringValue: "Index 0", intValue: Optional(0)), 
Foundation.(_JSONKey in _12768CA107A31EF2DCE034FD75B541C9)(stringValue: "Index 0", intValue: Optional(0))], 
debugDescription: "Expected to decode String but found a number instead.", underlyingError: nil))

观察JSON中的内部数组有一个模式化的类型序列,我们知道该序列是什么。内部数组中的类型是按模式顺序排列的:3个整数、5个字符串、2个整数,以及一些可能用作日期的内容。显然,在JSON设计者的心目中,这11个元素中的每一个都有一个固定且已知的含义

这意味着我们可以通过转储程序潜水和手动解码整个JSON表达式,一个接一个地手动提取11个元素

数组有混合类型,Swift不喜欢这样,所以我们必须将它们表示为Any(或AnyObject)的数组;但我们可以获得它们本身,而不必将它们包装在人工的中间结构中

顺便说一下,如果您知道每个元素的含义,那么您可以将内部数组解码为一个结构,其中包含11个命名属性,表示每个元素的含义,而不是任何数组。这将是一个更清晰的结果,但我没有使用它,因为我不知道这11个值的含义

我们开始:

struct IntegerOrString: Decodable {
    var value: Any

    init(from decoder: Decoder) throws {
        if let int = try? Int(from: decoder) {
            value = int
            return
        }

        value = try String(from: decoder)
    }
}

struct ChildrenTable: Decodable {
    var values: [[IntegerOrString]]?
}
structs:Decodable{
变量值:[[任何]]
枚举编码键:字符串,编码键{
案例值
}
init(来自解码器:解码器)抛出{
//去拿字典
让con=try!decoder.container(keyedBy:CodingKeys.self)
//获取数组的“值”数组
var con2=try!con.nestedUnkeyedContainer(forKey:CodingKeys.values)
var bigarr=[[Any]]()

对于uu in 0..观察JSON中的内部数组有一个模式化的类型序列,我们知道该序列是什么。内部数组中的类型是一个模式化的序列:3个整数、5个字符串、2个整数,以及一些可能用作日期的内容。显然,在JSON设计者的头脑中,这11个元素中的每一个都有一个固定的已知的意思

这意味着我们可以通过转储程序潜水和手动解码整个JSON表达式,一个接一个地手动提取11个元素

数组有混合类型,Swift不喜欢这样,因此我们必须将它们表示为任意(或任意对象)的数组;但我们可以将它们作为自身获得,而不必将它们包装在人工中间结构中

顺便说一句,如果你知道每个元素的含义,那么你可以将内部数组解码成一个结构,其中包含11个命名属性,表示每个元素的含义。这将是一个更清晰的结果,但我没有使用它,因为我不知道11个值的含义

我们开始:

struct IntegerOrString: Decodable {
    var value: Any

    init(from decoder: Decoder) throws {
        if let int = try? Int(from: decoder) {
            value = int
            return
        }

        value = try String(from: decoder)
    }
}

struct ChildrenTable: Decodable {
    var values: [[IntegerOrString]]?
}
structs:Decodable{
变量值:[[任何]]
枚举编码键:字符串,编码键{
案例值
}
init(来自解码器:解码器)抛出{
//去拿字典
让con=try!decoder.container(keyedBy:CodingKeys.self)
//获取数组的“值”数组
var con2=try!con.nestedUnkeyedContainer(forKey:CodingKeys.values)
var bigarr=[[Any]]()

对于uu0..我已经尝试在我的项目中使用您的解决方案,它的效果非常好。下面我对其进行了一些修改,以便它可以用于单字符串、单数组和多维数组

struct S : Decodable {
    var values : [[Any]]
    enum CodingKeys : String, CodingKey {
        case values
    }
    init(from decoder: Decoder) throws {
        // get the dictionary
        let con = try! decoder.container(keyedBy: CodingKeys.self)
        // get the "values" array of array
        var con2 = try! con.nestedUnkeyedContainer(forKey: CodingKeys.values)
        var bigarr = [[Any]]()
        for _ in 0..<con2.count! {
            // get a nested array
            var con3 = try! con2.nestedUnkeyedContainer()
            // decode all the elements of the nested array
            var arr = [Any]()
            arr.append(try! con3.decode(Int.self))
            arr.append(try! con3.decode(Int.self))
            arr.append(try! con3.decode(Int.self))
            arr.append(try! con3.decode(String.self))
            arr.append(try! con3.decode(String.self))
            arr.append(try! con3.decode(String.self))
            arr.append(try! con3.decode(String.self))
            arr.append(try! con3.decode(String.self))
            arr.append(try! con3.decode(Int.self))
            arr.append(try! con3.decode(Int.self))
            arr.append(try! con3.decode(String.self))
            bigarr.append(arr)
        }
        // all done! finish initialization
        self.values = bigarr
    }
}

let result = try! JSONDecoder().decode(S.self, from: jdata)
print(result.values)
// [[1, 1, 7, "Azuan Child", "Anak Azuan", "12345", "ACTIVE",
// "Morning", 7, 12, "2017-11-09 19:45:00"], 
// [28, 1, 0, "Azuan Child2", "Amran", "123456", "ACTIVE", 
// "Evening", 1, 29, "2017-11-09 19:45:00"]]
struct-TripModel:可解码{
var tx_结果:任何
变量列:[任何]
变量值:[[任何]]
枚举编码键:字符串,编码键{
案例tx_结果
案例栏
案例值
}
init(来自解码器:解码器)抛出{
var bigarr=[[Any]]()
var arrColumn=[Any]()
//去拿字典
让con=try!decoder.container(keyedBy:CodingKeys.self)
让conResult=try!con.decode(String.self,forKey:CodingKeys.tx\u结果)
var conColumns=try!con.nestedUnkeyedContainer(forKey:CodingKeys.columns)
//打印(字符串(描述:conColumns.count))
//获取数组的“值”数组
var con2=try!con.nestedUnkeyedContainer(forKey:CodingKeys.values)

对于uu0..我已经尝试在我的项目中使用您的解决方案,它的效果非常好。下面我对其进行了一些修改,以便它可以用于单字符串、单数组和多维数组

struct S : Decodable {
    var values : [[Any]]
    enum CodingKeys : String, CodingKey {
        case values
    }
    init(from decoder: Decoder) throws {
        // get the dictionary
        let con = try! decoder.container(keyedBy: CodingKeys.self)
        // get the "values" array of array
        var con2 = try! con.nestedUnkeyedContainer(forKey: CodingKeys.values)
        var bigarr = [[Any]]()
        for _ in 0..<con2.count! {
            // get a nested array
            var con3 = try! con2.nestedUnkeyedContainer()
            // decode all the elements of the nested array
            var arr = [Any]()
            arr.append(try! con3.decode(Int.self))
            arr.append(try! con3.decode(Int.self))
            arr.append(try! con3.decode(Int.self))
            arr.append(try! con3.decode(String.self))
            arr.append(try! con3.decode(String.self))
            arr.append(try! con3.decode(String.self))
            arr.append(try! con3.decode(String.self))
            arr.append(try! con3.decode(String.self))
            arr.append(try! con3.decode(Int.self))
            arr.append(try! con3.decode(Int.self))
            arr.append(try! con3.decode(String.self))
            bigarr.append(arr)
        }
        // all done! finish initialization
        self.values = bigarr
    }
}

let result = try! JSONDecoder().decode(S.self, from: jdata)
print(result.values)
// [[1, 1, 7, "Azuan Child", "Anak Azuan", "12345", "ACTIVE",
// "Morning", 7, 12, "2017-11-09 19:45:00"], 
// [28, 1, 0, "Azuan Child2", "Amran", "123456", "ACTIVE", 
// "Evening", 1, 29, "2017-11-09 19:45:00"]]
struct-TripModel:可解码{
var tx_结果:任何
变量列:[任何]
变量值:[[任何]]
枚举编码键:字符串,编码键{
案例tx_结果
案例栏
案例值
}
init(来自解码器:解码器)抛出{
var bigarr=[[Any]]()
var arrColumn=[Any]()
//去拿字典
让con=try!decoder.container(keyedBy:CodingKeys.self)
让conResult=try!con
struct Response: Decodable {
    var values: [[IntOrString]]
}
if let response = try? JSONDecoder().decode(Response.self, from: data) {
    let values = response.values

    for value in values {
        for intOrString in value {
            switch intOrString {
            case .int(let int): print("It's an int: \(int)")
            case .string(let string): print("It's a string: \(string)")
            }
        }
    }
}
It's an int: 1
It's an int: 1
It's an int: 7
It's a string: Azuan Child
It's a string: Anak Azuan
It's a string: 12345
It's a string: ACTIVE
It's a string: Morning
It's an int: 7
It's an int: 12
It's a string: 2017-11-09 19:45:00
It's an int: 28
It's an int: 1
It's an int: 0
It's a string: Azuan Child2
It's a string: Amran
It's a string: 123456
It's a string: ACTIVE
It's a string: Evening
It's an int: 1
It's an int: 29
It's a string: 2017-11-09 19:45:00
public struct UncertainValue<T: Decodable, U: Decodable>: Decodable {
    public var tValue: T?
    public var uValue: U?

    public var value: Any? {
        return tValue ?? uValue
    }

    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        tValue = try? container.decode(T.self)
        uValue = try? container.decode(U.self)
        if tValue == nil && uValue == nil {
            //Type mismatch
            throw DecodingError.typeMismatch(type(of: self), DecodingError.Context(codingPath: [], debugDescription: "The value is not of type \(T.self) and not even \(U.self)"))
        }

    }
}
{
"results": [{
        "name": "Gala",
        "age": 1,
        "type": "Pug"
    }, {
        "name": "Keira",
        "age": "7",
        "type": "Collie Rough"
    }]
}
struct Dog: Decodable, CustomStringConvertible {
    var name: String
    var age: UncertainValue<Int, String>
    var type: String

    var description: String {
        return "\(name) is a lovely \(type) of \(age.value!) years old"
    }
}