Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have the following json data and trying to parse it, but I get number of objects, but object itself in the array all are nil.

I do not want to decode the origin in the following json object.

By the way, the following string is first converted to data and then passed it to parse function below.

Data is follows:

[ 
 [
   {"id": "152478", "age": 20},
   {"character": "king","isDead":"no", "canMove" :"yes", "origin" :"south africa"}
 ],
 [
  {"id": "887541", "age": 22},
  {"character": "lion", "isDead":"no", "canMove" :"yes", "origin" :"south america"}
 ]
]

Models

struct A: Codable {
    let id: String?
    let age: Int?

    enum CodingKeys: String, CodingKey {
        case id
        case age
    }
}

struct B: Codable {
    let character, isDead, canMove: String?

    enum CodingKeys: String, CodingKey {
        case character
        case isDead
        case canMove
    }
}

struct AB :Codable {
  let a: A
  let b: B

  init(from decoder: Decoder) throws {
    guard var container = try? decoder.unkeyedContainer() else { 
         //no error here!!!       
         fatalError()   
     }
    print(container)
    guard let a = try? container.decode(A.self),
        let b = try? container.decode(B.self)
      else {
        // throw since we didn't find A first, followed by B
        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: nil)
        )
      }
    self.a = a
    self.b = b
  }
}

ViewModel

private func parse(jsonData : Data){
    do {
        let decoder = JSONDecoder()
        let response = try decoder.decode([AB].self, from: jsonData)
        print(response)
    }
    catch (let error as NSError) {
        print(error)
    }
}

UPDATE: By the way, the following code works. I wonder why above code does not handle?

private func parseData(jsonData : Data)
{
    do {
        response = try JSONSerialization.jsonObject(with: jsonData) as! [[[String: Any]]]
        for i in 0..<response.count
        {
            for j in 0..<response[i].count
            {
                if j == 0
                {
                    let jsonDat = (try? JSONSerialization.data(withJSONObject:response[i][j]))!
                    let b = try JSONDecoder().decode(A.self, from: jsonDat)
                }
                else if j == 1
                {
                    let jsonDatt = (try? JSONSerialization.data(withJSONObject:response[i][j]))!
                    let a = try JSONDecoder().decode(B.self, from: jsonDatt)
                }
            }
        }
        print(response)
    }
    catch let error as NSError {
        print(error)
    }
}

UPDATE II:

If I make the following changes [AB] --> [[AB]], and then I call it as follows, it decodes data, but in the array I end up, A object has values, but B nil, or vice versa.

let response = try decoder.decode([[AB]].self, from: jsonData)


guard var container = try? decoder.singleValueContainer() else
{
    fatalError()
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
141 views
Welcome To Ask or Share your Answers For Others

1 Answer

I just tried this stripped-down version of your code in a playground

let json = """
[
 [
   {"id": "152478", "age": 20},
   {"character": "king","isDead":"no", "canMove" :"yes", "origin" :"south africa"}
 ],
 [
  {"id": "887541", "age": 22},
  {"character": "lion", "isDead":"no", "canMove" :"yes", "origin" :"south america"}
 ]
]
""".data(using: .utf8)!

struct A: Codable {
    let id: String
    let age: Int
}

struct B: Codable {
    let character, isDead, canMove: String
}

struct AB: Codable {
    let a: A
    let b: B

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()

        self.a = try container.decode(A.self)
        self.b = try container.decode(B.self)
    }
}

do {
    let ab = try JSONDecoder().decode([AB].self, from: json)
    print(ab.count)
    print(ab[0].a.id)
    print(ab[0].b.character)

    print(ab[1].a.id)
    print(ab[1].b.character)
} catch {
    print(error)
}

and it works just fine. Maybe this helps figuring out what's going on.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...