nest parsing doesnt work

Hi


i did some searches in the internet but i doesnt found an usefull sample code where my json anser will parsed. i found on apple an similar answer in json and then i adapt it. but the code seems not to work...

xcode doesnt give me an usefull error if i run it...


here is my code:

//
//  ViewController.swift
//  test-api-calls
//
//  Copyright © 2017 Producer. All rights reserved.
//

import UIKit
import Foundation


struct CurrencyStore {
    var name: String
    var currencies: [Currency]

    struct Currency: Codable{
        var symbol1: String
        var maxPrice: Float
        var minPrice: Float
    }
}

let jsonvar = """
{"e":"currency_limits","ok":"ok","data":{"pairs":[{"symbol1":"BTC","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":30,"minPrice":"100","maxPrice":"35000"},{"symbol1":"ETH","symbol2":"USD","minLotSize":0.1,"minLotSizeS2":2.5,"maxLotSize":1000,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BCH","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":30,"minPrice":"50","maxPrice":"5128"},{"symbol1":"BTG","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"2048"},{"symbol1":"DASH","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"XRP","symbol2":"USD","minLotSize":10,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"0.005","maxPrice":"50"},{"symbol1":"ZEC","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BTC","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":30,"minPrice":"100.00","maxPrice":"35000"},{"symbol1":"ETH","symbol2":"EUR","minLotSize":0.1,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"2","maxPrice":"1024"},{"symbol1":"BCH","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"50","maxPrice":"5128"},{"symbol1":"BTG","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"2048"},{"symbol1":"DASH","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"XRP","symbol2":"EUR","minLotSize":10,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"0.005","maxPrice":"50"},{"symbol1":"ZEC","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BTC","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"100","maxPrice":"30000"},{"symbol1":"ETH","symbol2":"GBP","minLotSize":0.1,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"50","maxPrice":"5128"},{"symbol1":"BCH","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"50","maxPrice":"4096"},{"symbol1":"DASH","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"ZEC","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BTC","symbol2":"RUB","minLotSize":0.01,"minLotSizeS2":150,"maxLotSize":null,"minPrice":"10000","maxPrice":"2000000"},{"symbol1":"ETH","symbol2":"BTC","minLotSize":0.1,"minLotSizeS2":0.01,"maxLotSize":1000,"minPrice":"0.001","maxPrice":"2"},{"symbol1":"BCH","symbol2":"BTC","minLotSize":0.1,"minLotSizeS2":0.01,"maxLotSize":30,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"BTG","symbol2":"BTC","minLotSize":0.01,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"DASH","symbol2":"BTC","minLotSize":0.01,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"XRP","symbol2":"BTC","minLotSize":40,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.000003","maxPrice":"0.0005"},{"symbol1":"ZEC","symbol2":"BTC","minLotSize":0.01,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"GHS","symbol2":"BTC","minLotSize":1,"minLotSizeS2":0.01,"maxLotSize":null,"minPrice":"0.00001","maxPrice":"0.01"}]}}
""".data(using: .utf8)!

struct CurrencyStoreService: Decodable {

    let e: String
    let ok: String
    let data: [data]

    struct data: Decodable {
        let pairs: [pairs]
     
        struct pairs: Decodable {
            let pairs: CurrencyStore.Currency
        }
    }
}

extension CurrencyStore {
    init(from CurrencyStoreService: CurrencyStoreService) {
        name = "Test"
        currencies = []
     
        for data in CurrencyStoreService.data {
            for pairs in data.pairs {
                currencies.append(pairs.pairs)
            }
        }
    }
}


class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
     
        let decoder = JSONDecoder()
        let serviceStores = try decoder.decode([CurrencyStoreService].self, from: jsonvar)
     
        let stores = serviceStores.map { CurrencyStore (from: $0) }
     
        for store in stores {
            for Currency in store.currencies {
                print("\(Currency.symbol1) for max \(Currency.maxPrice) or at min \(Currency.minPrice)")
            }
        }

    }

     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}


probably someone has an sipmler way to parse it?

i get the template from here:

https://developer.apple.com/documentation/foundation/archives_and_serialization/using_json_with_custom_types


i dont implement an requst from the internet to make it simpler...

hopefully some one can help me...

feel free to change the complete code...

Accepted Reply

There’s a number of problems with the code you posted. To investigate I first commented out line 23. This cuts out all of the parsing of

Currency
values, so things should just work because it’s only parsing
e
and
ok
. Alas, it did not. The problem was line 49, where you’re passing in
[CurrencyStoreService].self
rather than
CurrencyStoreService.self
. The root of this JSON is a dictionary that maps to your
CurrencyStoreService
type, not an array of such dictionaries.

With that out of the way I returned to

data
. To help me understand your JSON better I reflowed it, and eliminated all but a few of the entries in the
pairs
array:
{
    "e": "currency_limits",
    "ok":"ok",
    "data":{
        "pairs":[
            {
                "symbol1":"BTC",
                "symbol2":"USD",
                "minLotSize":0.01,
                "minLotSizeS2":2.5,
                "maxLotSize":30,
                "minPrice":"100",
                "maxPrice":"35000"
            },
            {
                "symbol1":"ETH",
                "symbol2":"USD",
                "minLotSize":0.1,
                "minLotSizeS2":2.5,
                "maxLotSize":1000,
                "minPrice":"2.5",
                "maxPrice":"1024"
            },
            {
                "symbol1":"BCH",
                "symbol2":"USD",
                "minLotSize":0.01,
                "minLotSizeS2":2.5,
                "maxLotSize":30,
                "minPrice":"50",
                "maxPrice":"5128"
            },
        ]
    }
}

This makes it easy to see that

data
isn’t an array, it’s a single item with a property
pairs
that’s an array. I tweaked your model as follows:
struct CurrencyStoreService: Decodable {

    let e: String
    let ok: String
    let data: NestedData

    struct NestedData: Decodable {
        let pairs: [CurrencyStore.Currency]
    }
}

and now things decode properly.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

— The maxPrice and minPrice values in your JSON source are strings, not numbers. In your CurrencyStore.Currency struct, they're numbers, not strings.


— If JSONDecoder parsing fails, it throws an error. To see what the error is, catch the error and print it.

Thanks you are right!

Some nummbers are stings...

i have now adapt it:


import Foundation


struct CurrencyStore {
    var name: String
    var currencies: [Currency]

    struct Currency: Codable{
        var symbol1: String
        var maxPrice: String
        var minPrice: String
    }
}

let json = """
{"e":"currency_limits","ok":"ok","data":{"pairs":[{"symbol1":"BTC","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":30,"minPrice":"100","maxPrice":"35000"},{"symbol1":"ETH","symbol2":"USD","minLotSize":0.1,"minLotSizeS2":2.5,"maxLotSize":1000,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BCH","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":30,"minPrice":"50","maxPrice":"5128"},{"symbol1":"BTG","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"2048"},{"symbol1":"DASH","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"XRP","symbol2":"USD","minLotSize":10,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"0.005","maxPrice":"50"},{"symbol1":"ZEC","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BTC","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":30,"minPrice":"100.00","maxPrice":"35000"},{"symbol1":"ETH","symbol2":"EUR","minLotSize":0.1,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"2","maxPrice":"1024"},{"symbol1":"BCH","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"50","maxPrice":"5128"},{"symbol1":"BTG","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"2048"},{"symbol1":"DASH","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"XRP","symbol2":"EUR","minLotSize":10,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"0.005","maxPrice":"50"},{"symbol1":"ZEC","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BTC","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"100","maxPrice":"30000"},{"symbol1":"ETH","symbol2":"GBP","minLotSize":0.1,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"50","maxPrice":"5128"},{"symbol1":"BCH","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"50","maxPrice":"4096"},{"symbol1":"DASH","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"ZEC","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BTC","symbol2":"RUB","minLotSize":0.01,"minLotSizeS2":150,"maxLotSize":null,"minPrice":"10000","maxPrice":"2000000"},{"symbol1":"ETH","symbol2":"BTC","minLotSize":0.1,"minLotSizeS2":0.01,"maxLotSize":1000,"minPrice":"0.001","maxPrice":"2"},{"symbol1":"BCH","symbol2":"BTC","minLotSize":0.1,"minLotSizeS2":0.01,"maxLotSize":30,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"BTG","symbol2":"BTC","minLotSize":0.01,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"DASH","symbol2":"BTC","minLotSize":0.01,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"XRP","symbol2":"BTC","minLotSize":40,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.000003","maxPrice":"0.0005"},{"symbol1":"ZEC","symbol2":"BTC","minLotSize":0.01,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"GHS","symbol2":"BTC","minLotSize":1,"minLotSizeS2":0.01,"maxLotSize":null,"minPrice":"0.00001","maxPrice":"0.01"}]}}
""".data(using: .utf8)!

struct CurrencyStoreService: Decodable {

    let e: String
    let ok: String
    let data: [data]

    struct data: Decodable {
        let pairs: [pairs]
     
        struct pairs: Decodable {
            let pairs: CurrencyStore.Currency
        }
    }
}

extension CurrencyStore {
    init(from CurrencyStoreService: CurrencyStoreService) {
        name = CurrencyStoreService.ok
        currencies = []
     
        for data in CurrencyStoreService.data {
            for pairs in data.pairs {
                currencies.append(pairs.pairs)
            }
        }
    }
}

do {
    let decoder = JSONDecoder()
    let serviceStores = try decoder.decode([CurrencyStoreService].self, from: json)
    print(serviceStores)
    let stores = serviceStores.map { CurrencyStore (from: $0) }

    for store in stores {
        for Currency in store.currencies {
            print("\(Currency.symbol1) for max \(Currency.maxPrice) or at min \(Currency.minPrice)")
        }
    }

} catch let jsonErr {
    print(jsonErr)

}


so now i get an error.

typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))


why is it an dictionary and not an array?

There’s a number of problems with the code you posted. To investigate I first commented out line 23. This cuts out all of the parsing of

Currency
values, so things should just work because it’s only parsing
e
and
ok
. Alas, it did not. The problem was line 49, where you’re passing in
[CurrencyStoreService].self
rather than
CurrencyStoreService.self
. The root of this JSON is a dictionary that maps to your
CurrencyStoreService
type, not an array of such dictionaries.

With that out of the way I returned to

data
. To help me understand your JSON better I reflowed it, and eliminated all but a few of the entries in the
pairs
array:
{
    "e": "currency_limits",
    "ok":"ok",
    "data":{
        "pairs":[
            {
                "symbol1":"BTC",
                "symbol2":"USD",
                "minLotSize":0.01,
                "minLotSizeS2":2.5,
                "maxLotSize":30,
                "minPrice":"100",
                "maxPrice":"35000"
            },
            {
                "symbol1":"ETH",
                "symbol2":"USD",
                "minLotSize":0.1,
                "minLotSizeS2":2.5,
                "maxLotSize":1000,
                "minPrice":"2.5",
                "maxPrice":"1024"
            },
            {
                "symbol1":"BCH",
                "symbol2":"USD",
                "minLotSize":0.01,
                "minLotSizeS2":2.5,
                "maxLotSize":30,
                "minPrice":"50",
                "maxPrice":"5128"
            },
        ]
    }
}

This makes it easy to see that

data
isn’t an array, it’s a single item with a property
pairs
that’s an array. I tweaked your model as follows:
struct CurrencyStoreService: Decodable {

    let e: String
    let ok: String
    let data: NestedData

    struct NestedData: Decodable {
        let pairs: [CurrencyStore.Currency]
    }
}

and now things decode properly.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Many thanks for your help!!!


Can you please post the complete code?

i didnt get it to work...

Sorry i am verry new in swift...

Thanks Eskimo, i have implemented that now!


here is the code:


import Foundation


struct CurrencyStore {
    var name: String
    var currencies: [Currency]

    struct Currency: Codable{
        var symbol1: String
        var symbol2: String
        var minLotSize: Double
        var minLotSizeS2: Double
        var maxLotSize: Double?
        var maxPrice: String
        var minPrice: String
    }
}

let json = """
{"e":"currency_limits","ok":"ok","data":{"pairs":[{"symbol1":"BTC","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":30,"minPrice":"100","maxPrice":"35000"},{"symbol1":"ETH","symbol2":"USD","minLotSize":0.1,"minLotSizeS2":2.5,"maxLotSize":1000,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BCH","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":30,"minPrice":"50","maxPrice":"5128"},{"symbol1":"BTG","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"2048"},{"symbol1":"DASH","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"XRP","symbol2":"USD","minLotSize":10,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"0.005","maxPrice":"50"},{"symbol1":"ZEC","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BTC","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":30,"minPrice":"100.00","maxPrice":"35000"},{"symbol1":"ETH","symbol2":"EUR","minLotSize":0.1,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"2","maxPrice":"1024"},{"symbol1":"BCH","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"50","maxPrice":"5128"},{"symbol1":"BTG","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"2048"},{"symbol1":"DASH","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"XRP","symbol2":"EUR","minLotSize":10,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"0.005","maxPrice":"50"},{"symbol1":"ZEC","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BTC","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"100","maxPrice":"30000"},{"symbol1":"ETH","symbol2":"GBP","minLotSize":0.1,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"50","maxPrice":"5128"},{"symbol1":"BCH","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"50","maxPrice":"4096"},{"symbol1":"DASH","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"ZEC","symbol2":"GBP","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BTC","symbol2":"RUB","minLotSize":0.01,"minLotSizeS2":150,"maxLotSize":null,"minPrice":"10000","maxPrice":"2000000"},{"symbol1":"ETH","symbol2":"BTC","minLotSize":0.1,"minLotSizeS2":0.01,"maxLotSize":1000,"minPrice":"0.001","maxPrice":"2"},{"symbol1":"BCH","symbol2":"BTC","minLotSize":0.1,"minLotSizeS2":0.01,"maxLotSize":30,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"BTG","symbol2":"BTC","minLotSize":0.01,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"DASH","symbol2":"BTC","minLotSize":0.01,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"XRP","symbol2":"BTC","minLotSize":40,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.000003","maxPrice":"0.0005"},{"symbol1":"ZEC","symbol2":"BTC","minLotSize":0.01,"minLotSizeS2":0.001,"maxLotSize":null,"minPrice":"0.005","maxPrice":"2"},{"symbol1":"GHS","symbol2":"BTC","minLotSize":1,"minLotSizeS2":0.01,"maxLotSize":null,"minPrice":"0.00001","maxPrice":"0.01"}]}}
""".data(using: .utf8)!

struct CurrencyStoreService: Decodable {

    let e: String
    let ok: String
    let data: NestedData

    struct NestedData: Decodable {
        let pairs: [CurrencyStore.Currency]
    }
}

extension CurrencyStore {
    init(from CurrencyStoreService: CurrencyStoreService) {
        name = CurrencyStoreService.ok
        currencies = []
    }
}

do {
    let decoder = JSONDecoder()
    let serverData = try decoder.decode(CurrencyStoreService.self, from: json)
    print(serverData.data.pairs)

} catch let jsonErr {
    print(jsonErr)

}