JSONEncoder().encode is always empty

599 views Asked by At

I have a class that it has the next

import UIKit

final class PruebaModel: Codable {
    
    let a: String?
    let b: String?
    let c: [D]?
    let f: String?
    
    
    enum CodingKeys: String, CodingKey {
        case a = "a"
        case b = "b"
        case c = "c"
        case f = "f"
    }
    
    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        a = try values.decodeIfPresent(String.self, forKey: .a)
        b = try values.decodeIfPresent(String.self, forKey: .b)
        c = try values.decodeIfPresent([D].self, forKey: .c)
        f = try values.decodeIfPresent(String.self, forKey: .f)
    }
    
    required init()  {
        a = ""
        b = ""
        c = Array<D>()
        f = ""
    }
}


import Foundation

struct D: Codable {
    let l: String
    let m: String
    
    enum CodingKeys: String, CodingKey {
        case l = "l"
        case m = "m"
    }
    
    init(from decoder: Decoder) throws {
        let value = try decoder.container(keyedBy: CodingKeys.self)
        l = try value.decode(String.self, forKey: .l)
        m = try value.decode(String.self, forKey: .m)
    }
    
    public func encode(to encoder: Encoder) throws {
        //Implement when needed
    }
}

The json is the next

{
     
     "a": "a",
     "b": "b",
     "c": [
       {
         "l": "¿Cuál es el mi color favorito?",
         "m":"QAUY.15"
       }
    ],
    "f": "f"
     
}

The class is perfect, it has the object with parameters, but when i try to convert the class for json. The array is empty

Code

let jsonData = try! JSONEncoder().encode(PruebaModel)
let jsonString = String(data: jsonData, encoding: .utf8)!

Result when i evaluated the expression

po String(data: try! JSONEncoder().encode(PruebaModel), encoding: .utf8)!

"{"a":"a","b":"b","c":[{}],"f":"f"}"

Why c is empty?. it has an object inside the array.

If The object is inside the array doesn't have special character, the decode shows the object

1

There are 1 answers

4
matt On

Unclear what you're asking. For one thing, you've got way too much code. For another, the code you've shown makes no sense. The JSON you've shown, on the other hand, is perfectly well decodable into a PruebaModel, and a correctly constructed PruebaModel is encodable into your JSON:

struct D: Codable {
    let l: String
    let m: String
}
struct PruebaModel: Codable {
    let a: String?
    let b: String?
    let c: [D]?
    let f: String?
}
let jsonString = """
{
    "a": "a",
    "b": "b",
    "c": [
        {
            "l": "¿Cuál es el mi color favorito?",
            "m":"QAUY.15"
        }
    ],
    "f": "f"
    }
"""
let jsonData = jsonString.data(using: .utf8)!
let result = try? JSONDecoder().decode(PruebaModel.self, from: jsonData)
print(result?.c?.first?.l) // Optional("¿Cuál es el mi color favorito?")
// let's also try encoding
let d = D(l: "¿Cuál es el mi color favorito?", m: "QAUY.15")
let myPruebaModel = PruebaModel(a: "a", b: "b", c: [d], f: "f")
let jsonData2 = try? JSONEncoder().encode(myPruebaModel)
print(String(data: jsonData2!, encoding: .utf8)!)
// {"b":"b","c":[{"l":"¿Cuál es el mi color favorito?","m":"QAUY.15"}],"a":"a","f":"f"}