Swift 4 Json Parse - json

I need to throw this json data into the "arrayCategory" array above. How can I do it ?
"Elektronik" and "Hobi" titles are not fixed. It is variable.
Json Data
{
"Elektronik": [
{
"kategoriisim": "Akıllı Saatler",
"uyevarmi": "1"
},
{
"kategoriisim": "Anakart",
"uyevarmi": "1"
} ],
"Hobi": [
{
"kategoriisim": "Drone Multikopter",
"uyevarmi": "1"
}
]
}
Struct and Array . I need to fill in the "dimensionalArray" array
ExpandableNames "baslik" = The future of "Elektronik" data in json data
ExpandableNames "kategori" = The sub-elements of the "Elektronik" circuit will come
struct ExpandableNames {
let baslik : String
let kategori: [cellKategorilerData]
}
struct cellKategorilerData {
var kategoriisim : String?
var uyevarmi : String?
}
var dimensionalArray = [ExpandableNames]()
var arrayKategoriData = [cellKategorilerData]()
-
static func jsonSonucGetir(servlet:String,parametre:String) {
let connectString = Connect.ConnectInfo
var request = URLRequest(url: URL(string:connectString.conString + "/" + servlet)!)
request.httpMethod = "POST"
var postString = parametre
postString = postString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil
{
print("error" , error)
}
if let urlContent = data
{
do
{
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
???
}
catch
{
print("server hatasi")
}
}
}
task.resume()
}

If the keys are dynamic I recommend to decode the object as dictionary ([String:[CellKategorilerData]])
let jsonString = """
{
"Elektronik": [
{"kategoriisim": "Akıllı Saatler", "uyevarmi": "1"},
{"kategoriisim": "Anakart", "uyevarmi": "1"}
],
"Hobi": [
{"kategoriisim": "Drone Multikopter", "uyevarmi": "1"}
]
}
"""
struct CellKategorilerData : Decodable {
let kategoriisim : String
let uyevarmi : String
}
do {
let data = Data(jsonString.utf8)
let result = try JSONDecoder().decode([String:[CellKategorilerData]].self, from: data)
for (key, value) in result {
print("key", key, "value", value)
}
} catch { print(error) }

Related

Array JSON decoding in swift

I am trying to decode this json array and I got the following code to work, initially but it is a bit buggy.
the json is structured as following:
{
"prices": [
[
1595642361269,
180.62508267006177
],
[
1596642361269,
190.1
]
],
"market_caps": [
[
1595642361269,
3322122955.6677375
],
[
1596642361269,
3332122955.6677375
]
],
"total_volumes": [
[
1595642361269,
590499490.5115521
],
[
1595642361269,
590499490.5115521
]
]
}
my swift object is structured as:
struct MarketChart: Decodable {
let prices: [[Double]]
let market_caps: [[Double]]
let total_volumes: [[Double]]
}
I dont think it is optimal but as the json doesn't have keys for the timestamps and values I was a bit confused on how to structure it.
the following is my playground code:
func getJSON<T: Decodable>(urlString: String, completion: #escaping (T?) -> Void) {
guard let url = URL(string: urlString) else {
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
print(error.localizedDescription)
completion(nil)
return
}
guard let data = data else {
completion(nil)
return
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
guard let decodedData = try? decoder.decode(T.self, from: data) else {
completion(nil)
return
}
completion(decodedData)
}.resume()
}
struct MarketChart: Decodable {
let prices: [[Double]]
let market_caps: [[Double]]
let total_volumes: [[Double]]
}
var priceArray: [Double] = []
print(priceArray)
getJSON(urlString: "https://api.coingecko.com/api/v3/coins/bitcoin-cash-sv/market_chart?vs_currency=usd&days=1") { (data: MarketChart?) in
if let data = data {
for item in data.prices {
priceArray.append(item.first!)
}
}
}
print(priceArray)
I am trying to get all the values into an array and it did work initially but now just keeps printing an empty array. my end goal is to crate a graph of the values over time in a project and I did it successfully the first time but now I keep getting an error saying it can't get the value from an empty array.
my Xcode project file is as follows:
import SwiftUI
import SwiftUICharts
import Combine
struct CoinGeckoBSVMarketChart: View {
#State var jsonData = [MarketChart]()
#State var priceArray = [Double]()
#State var volumeArray: [Double] = []
private let last24hpricesURL: String = "https://api.coingecko.com/api/v3/coins/bitcoin-cash-sv/market_chart?vs_currency=usd&days=1"
var body: some View {
ZStack {
VStack {
LineView(data: priceArray)
.padding()
Text("Reset")
.onTapGesture {
}
}
}
.onAppear {
getJSON(urlString: last24hpricesURL) { (data: MarketChart?) in
if let data = data {
for item in data.prices {
priceArray.append(item.last!)
}
}
}
}
}
}
struct MarketChart: Decodable {
let prices: [[Double]]
let market_caps: [[Double]]
let total_volumes: [[Double]]
}
struct CoinGeckoBSVMarketChart_Previews: PreviewProvider {
static var previews: some View {
CoinGeckoBSVMarketChart()
.preferredColorScheme(.dark)
}
}
any help with either improving the json object model or getting all the items in an array would be great
You have to print out the priceArray inside the completion block of getJSON method right after appending.
getJSON(urlString: "https://api.coingecko.com/api/v3/coins/bitcoin-cash-sv/market_chart?vs_currency=usd&days=1") { (data: MarketChart?) in
if let data = data {
for item in data.prices {
priceArray.append(item.first!)
}
print(priceArray)
}
}

Swift: how to parse json to a dictionary

I have the following as a json output in console
{
cash_machine = "0.08924368023872375488";
dishwasher = "0.06437973678112030029";
modem = "0.04461396858096122742";
monitor = "0.28455805778503417969";
nematode = "0.04982925951480865479";
screen = "0.05664909631013870239";
television = "0.03846205398440361023";
}
My code is
let session = URLSession.shared.dataTask(with: r) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
} catch {
print(error)
}
}
// experiment here
// if statement ends here
} .resume()
I was wondering how I'd parse this into a dictionary: {"key1" : "value1", "key2" : "value2", "key3" : "value3", ..., "key_n", "value_n"}
Try something along these lines
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String: String]
for key in json.keys {
print("\(key) : \(json[key])")
}
}

Swift JSON Parsing Wunderground

i am a beginner with swift an Progrmamming i need values from the JSON it looks Like this:
{
"response": {
"version":"0.1",
"termsofService":"http://www.wunderground.com/weather/api/d/terms.html",
"features": {
"astronomy": 1
}
}
, "moon_phase": {
"percentIlluminated":"23",
"ageOfMoon":"5",
"phaseofMoon":"Erstes Viertel",
"hemisphere":"North",
"current_time": {
"hour":"8",
"minute":"28"
},
"sunrise": {
"hour":"6",
"minute":"55"
},
"sunset": {
"hour":"19",
"minute":"50"
},
"moonrise": {
"hour":"9",
"minute":"50"
},
"moonset": {
"hour":"0",
"minute":"06"
}
},
"sun_phase": {
"sunrise": {
"hour":"6",
"minute":"55"
},
"sunset": {
"hour":"19",
"minute":"50"
}
}
}
i will get the hour & minute from sunset and sunrise to a variable!
my code :
var sunriseHour: [String] = []
var sunriseMinute: [String] = []
var sunsetHour: [String] = []
var sunsetMinute: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
let url=URL(string:"http://api.wunderground.com/api/dbd539bd631e/astronomy/lang:DL/q/DL/iphofen.json")
do {
let allData = try Data(contentsOf: url!)
let data = try JSONSerialization.jsonObject(with: allData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject]
if let arrJSON = data["moon_phase"] {
if let sunriseData = arrJSON["sunrise"]{
print(sunriseData)
}
if let sunsetData = arrJSON["sunset"]{
print(sunsetData)
}
}
print("hour: ",sunriseHour)
print("minute: ",sunriseMinute)
print("hour: ",sunsetHour)
print("minute: ",sunsetMinute)
}
catch {
}
}
i get with print(sunriseData) and print(sunsetData) the right data from this :
Optional({
hour = 6;
minute = 55; }) Optional({
hour = 19;
minute = 50; }) hour: [] minute: [] hour: [] minute: []
How do i get it in the variable sunriseHour, sunriseMinute, sunsetHour, sunsetMinute..
thanks from your help..!
All hour and minute values are (single) String not [String] (array).
Declare all variables as empty strings
var sunriseHour = ""
var sunriseMinute = ""
var sunsetHour = ""
var sunsetMinute = ""
Then do not load data synchronously from a remote URL, use always an asynchronous way:
let url = URL(string:"http://api.wunderground.com/api/dbd539bd631e/astronomy/lang:DL/q/DL/iphofen.json")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
} else {
do {
guard let jsonData = try JSONSerialization.jsonObject(with:data!) as? [String:Any],
let moonPhase = jsonData["moon_phase"] as? [String:Any] else { return }
let sunrise = moonPhase["sunrise"] as! [String:String]
let sunset = moonPhase["sunset"] as! [String:String]
sunriseHour = sunrise["hour"]!
sunriseMinute = sunrise["minute"]!
sunsetHour = sunset["hour"]!
sunsetMinute = sunset["minute"]!
print("Sunrise - \(sunriseHour):\(sunriseMinute)"
print("Sunset - \(sunsetHour):\(sunsetMinute)"
} catch {
print(error)
}
}
}
task.resume()
The data for sunrise and sunset are in dictionaries derived from moon_phase. All values are forced unwrapped because sunrise and sunset are supposed to exist every day ;-)
PS : Consider to define more descriptive variable names, arrJSON is not very meaningful.

Swift 3: NSArray element failed to match the Swift Array Element type

I am trying to parse JSON in swift 3 below is my JSON file. And try to get in a array of class which i have declared. But getting error: fatal error: NSArray element failed to match the Swift Array Element type.
{
"Headers": [
{
"headerName": "Home",
"sortByNo" : 1,
"headerImageName": "header0",
"viewCotrollerName": "InitialViewController"
},
{
"headerName": "About",
"sortByNo" : 2,
"headerImageName": "header1",
"viewCotrollerName": ""
},
{
"headerName": "Timing",
"sortByNo" : 3,
"headerImageName": "header3",
"viewCotrollerName": "TimingViewController"
}
]
}
// Class Type
class JsonObjectClass {
var headerName = ""
var sortByNo = ""
var headerImageName = ""
var viewControllerName = ""
}
var array = [JsonObjectClass]() // my array of class type
//JSON Parsing Code
func parseLocalFile() {
let url = Bundle.main.url(forResource: "HeaderFileD", withExtension: "json")
let data = NSData(contentsOf: url!)
do {
let jsonData = try JSONSerialization.jsonObject(with: data! as Data, options: .mutableContainers) as! NSDictionary
array = jsonData.object(forKey: "Headers") as! [JsonObjectClass]
// I am getting error here "fatal error: NSArray element failed to match the Swift Array Element type"
for arr in array {
print(arr)
}
} catch {
}
}
You cannot assign an array or dictionary to a custom class directly.
You need to map the array by creating instances of your class.
I changed the class to a struct to get the member-wise initializer. By the way, the value for key sortByNo is an Int
struct JsonObjectClass {
var headerName = ""
var sortByNo = 0
var headerImageName = ""
var viewControllerName = ""
}
var array = [JsonObjectClass]() // my array of class type
//JSON Parsing Code
func parseLocalFile() {
guard let url = Bundle.main.url(forResource: "HeaderFileD", withExtension: "json") else { return }
do {
let data = try Data(contentsOf: url)
let jsonData = try JSONSerialization.jsonObject(with: data, options: []) as! [String:Any]
let jsonArray = jsonData["Headers"] as! [[String:Any]]
array = jsonArray.map { JsonObjectClass(headerName: $0["headerName"] as! String,
sortByNo: $0["sortByNo"] as! Int,
headerImageName: $0["headerImageName"] as! String,
viewControllerName: $0["viewCotrollerName"] as! String)}
for arr in array {
print(arr)
}
} catch let error as NSError {
print(error)
}
}
PS: Consider the typo viewControllerName vs viewCotrollerName

building objects from json response using NSJSONSerialization

Using swift 1.2, xcode 6.3 and IOS 8, Im trying to build an object from a json response using NSJSONSerialization class.
the json response is:
[{
"_id" : "5470def9e0c0be27780121d7",
"imageUrl" : "https:\/\/s3-eu-west-1.amazonaws.com\/myapi-static\/clubs\/5470def9e0c0be27780121d7_180.png",
"name" : "Mondo",
"hasVip" : false,
"location" : {
"city" : "Madrid"
}
}, {
"_id" : "540b2ff281b30f3504a1c72f",
"imageUrl" : "https:\/\/s3-eu-west-1.amazonaws.com\/myapi-static\/clubs\/540b2ff281b30f3504a1c72f_180.png",
"name" : "Teatro Kapital",
"hasVip" : false,
"location" : {
"address" : "Atocha, 125",
"city" : "Madrid"
}
}, {
"_id" : "540cd44581b30f3504a1c73b",
"imageUrl" : "https:\/\/s3-eu-west-1.amazonaws.com\/myapi-static\/clubs\/540cd44581b30f3504a1c73b_180.png",
"name" : "Charada",
"hasVip" : false,
"location" : {
"address" : "La Bola, 13",
"city" : "Madrid"
}
}]
the object class (Club.swift) with the NSJSONSerialization.JSONObjectWithData implementation is:
class Club: NSObject {
var id: String = ""
var name: String = ""
var imageUrl: String = ""
var hasVip: Bool = false
var desc: String = ""
var location: [Location] = []
init(JSONString: String) {
super.init()
var error : NSError?
let JSONData = JSONString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let JSONDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(JSONData!, options: nil, error: &error) as! NSDictionary
self.setValuesForKeysWithDictionary(JSONDictionary as [NSObject : AnyObject])
}
}
and finally the ApiClient class is
class ApiClient {
func getList(completionHandler: ([JSON]) -> ()) {
let URL = NSURL(string: "https://myapi.com/v1/clubs")
let mutableURLRequest = NSMutableURLRequest(URL: URL!)
mutableURLRequest.setValue("Content-Type", forHTTPHeaderField: "application/json")
mutableURLRequest.HTTPMethod = "GET"
mutableURLRequest.setValue("Bearer R01.iNsG3xjv/r1LDkhkGOANPv53xqUFDkPM0en5LIDxx875fBjdUZLn1jtUlKVJqVjsNwDe1Oqu2WuzjpaYbiWWhw==", forHTTPHeaderField: "Authorization")
let manager = Alamofire.Manager.sharedInstance
let request = manager.request(mutableURLRequest)
request.responseJSON { (request, response, json , error) in
if (json != nil){
var jsonObj = JSON(json!)
if let data = jsonObj["hits"].arrayValue as [JSON]?{
var aClub : Club = Club(JSONString: data)
println(aClub.name)
completionHandler(data)
}
}
}
}
}
but the problem is when I try to println(aClub.name) the error is
"cannot invoke initializer for type'Club' with an argument list of type (JSONString [JSON])"
I dont know, how could I use NSJSONSerialization class with a complex JSON response.
The jsonObj would appear to be a SwiftyJSON object, or something like that, which one uses in lieu of NSJSONSerialization, not in conjunction with it. The data variable is an array of JSON objects (i.e. it's a [JSON]), not a string.
But you're using Alamofire's responseJSON method, which does the JSON parsing for you. So you don't need to use either NSJSONSerialization or SwiftyJSON. It's already parsed it into an array of dictionaries.
If you want an array of Club objects, you could do can just iterate through this array, building Club objects from the dictionaries:
class ApiClient {
func getList(completionHandler: ([Club]?, NSError?) -> ()) {
let URL = NSURL(string: "https://myapi.com/v1/clubs")
let mutableURLRequest = NSMutableURLRequest(URL: URL!)
mutableURLRequest.setValue("Content-Type", forHTTPHeaderField: "application/json")
mutableURLRequest.HTTPMethod = "GET"
mutableURLRequest.setValue("Bearer R01.iNsG3xjv/r1LDkhkGOANPv53xqUFDkPM0en5LIDxx875fBjdUZLn1jtUlKVJqVjsNwDe1Oqu2WuzjpaYbiWWhw==", forHTTPHeaderField: "Authorization")
let manager = Alamofire.Manager.sharedInstance
let request = manager.request(mutableURLRequest)
request.responseJSON { (request, response, json, error) in
var clubs = [Club]()
if let arrayOfDictionaries = json as? [[String: AnyObject]] {
for dictionary in arrayOfDictionaries {
clubs.append(Club(dictionary: dictionary))
}
completionHandler(clubs, nil)
} else {
completionHandler(nil, error)
}
}
}
}
You obviously have to change Club to handle the dictionary object:
class Club {
var id: String!
var name: String!
var imageUrl: String!
var hasVippler: Bool!
var location: [String: String]!
init(dictionary: [String: AnyObject]) {
id = dictionary["_id"] as? String
name = dictionary["name"] as? String
imageUrl = dictionary["imageUrl"] as? String
hasVippler = dictionary["hasVip"] as? Bool
location = dictionary["location"] as? [String: String]
}
}
Finally, your table view controller could call the API:
let apiClient = ApiClient()
var clubs: [Club]!
override func viewDidLoad() {
super.viewDidLoad()
apiClient.getList() { clubs, error in
if clubs != nil {
self.clubs = clubs
self.tableView.reloadData()
} else {
println(error)
}
}
}