>

Item 배열을 초기화하려고합니다. json 파일에서 s. 이를 위해, 나는 그것을 수행하는 애플의 튜토리얼을 따라 갔다 : 알고리즘은 data.swift에 있지만 요약 된 버전도 게시 할 것입니다.) 내 문제는 데이터를 가져 오는 API에서 따옴표로 소수점 이하 자릿수를 표시하여 오류가 발생한다는 것입니다.

와이즈 비즈

Apple의 json 디코더가 기대하는 것 :

typeMismatch(Swift.Double, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "average_cost", intValue: nil)], debugDescription: "Expected to decode Double but found a string/data instead.", underlyingError: nil))

[{ "company": "Bioseed", "item_class": "Seeds", "name": "9909", "stock": 0, "average_cost": 0.00, // Doubles without quotation marks "otc_price": 0.00, "dealer_price": 0.00, "ctc_price": 0.00 }] 에 저장된 API의 샘플 데이터 :

items.json

따옴표없이 소수점과 정수를 제공하도록 API를 다시 작성할 수는 있지만 다른 응용 프로그램에서 이미 사용 중이므로 무언가를 깨뜨릴 위험이 없습니다.

따라서 해독 된 사람에게 따옴표를 무시하도록 지시하는 방법이 있습니까?

항목 구조 :

[{
        "company": "Bioseed",
        "item_class": "Seeds",
        "name": "9909",
        "stock": 0,
        "average_cost": "0.00",
        "otc_price": "0.00",
        "dealer_price": "0.00",
        "ctc_price": "0.00"
}]

로드 기능 :

struct Item : Decodable {
    var company: String
    var item_class: String
    var name: String
    var stock: Int
    var average_cost: Decimal
    var otc_price: Decimal
    var dealer_price: Decimal
    var ctc_price: Decimal

전화 :

func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
    let data: Data
    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
        else {
            fatalError("Couldn't find \(filename) in main bundle.")
    }
    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }
    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    }
}

let items: [Item] = load("items.json") print(items)

  • 답변 # 1

    이것을 구현하는 방법은 다음과 같습니다.

    struct Item : Decodable {
        let company: String
        let itemClass: String
        let name: String
        let stock: Int
        let averageCost: Decimal
        let otcPrice: Decimal
        let dealerPrice: Decimal
        let ctcPrice: Decimal
        enum CodingKeys: String, CodingKey {
            case company
            case itemClass = "item_class"
            case name
            case stock
            case averageCost = "average_cost"
            case otcPrice = "otc_price"
            case dealerPrice = "dealer_price"
            case ctcPrice = "ctc_price"
        }
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.company = try container.decode(String.self, forKey: .company)
            self.itemClass = try container.decode(String.self, forKey: .itemClass)
            self.name = try container.decode(String.self, forKey: .name)
            self.stock = try container.decode(Int.self, forKey: .stock)
            guard
                let averageCost = Decimal(string: try container.decode(String.self, forKey: .averageCost))
            else {
                throw DecodingError.dataCorruptedError(forKey: .averageCost, in: container, debugDescription: "not a Decimal.")
            }
            guard
                let otcPrice = Decimal(string: try container.decode(String.self, forKey: .otcPrice))
            else {
                throw DecodingError.dataCorruptedError(forKey: .otcPrice, in: container, debugDescription: "not a Decimal.")
            }
            guard
                let dealerPrice = Decimal(string: try container.decode(String.self, forKey: .dealerPrice))
            else {
                throw DecodingError.dataCorruptedError(forKey: .dealerPrice, in: container, debugDescription: "not a Decimal.")
            }
            guard
                let ctcPrice = Decimal(string: try container.decode(String.self, forKey: .ctcPrice))
            else {
                throw DecodingError.dataCorruptedError(forKey: .ctcPrice, in: container, debugDescription: "not a Decimal.")
            }
    
            self.averageCost = averageCost
            self.otcPrice = otcPrice
            self.dealerPrice = dealerPrice
            self.ctcPrice = ctcPrice
        }
    }
    
    

    또는 모델에 문자열 속성을 유지하고 액세스시 소수로 변환 할 수 있습니다

    struct Item : Decodable {
        let company: String
        let itemClass: String
        let name: String
        let stock: Int
        let _averageCost: String
        let _otcPrice: String
        let _dealerPrice: String
        let _ctcPrice: String
        enum CodingKeys: String, CodingKey {
            case company
            case itemClass = "item_class"
            case name
            case stock
            case _averageCost = "average_cost"
            case _otcPrice = "otc_price"
            case _dealerPrice = "dealer_price"
            case _ctcPrice = "ctc_price"
        }
        var averageCost: Decimal {
            return Decimal(string: _averageCost) ?? .zero
        }
        // ... and so on for the other properties
    }
    
    

  • 이전 javascript - 텍스트 상자에 특정 알파벳 만있는 숫자 만 허용
  • 다음 elixir - 정규식을 사용한 해시 태그 추출