After parsing JSON trough an API call i've had trouble converting the parsed JSON into the data that i want to display in my ViewController. I am able to print the JSON data in the console but i am not able to only get the value of "word: .." from the data i want to display. This is an example of a JSON object:
{
"metadata": {},
"results": [
{
"id": "eurhythmic",
"word": "eurhythmic"
}
]
}
The struct i'm using is the following:
// Struct RandomWords
struct StoreRandomWords: Codable {
let results: [Result]
}
struct Result: Codable {
let word: String
}
The code to fetch the data from the API:
func fetchRandomWord(completion: #escaping (StoreRandomWords?) -> Void) {
let language = "en"
let filters = "registers%3DRare%3Bdomains%3DArt?"
let limit = "limit=1"
let url = URL(string: "https://od-api.oxforddictionaries.com:443/api/v1/wordlist/\(language)/\(filters)\(limit)")!
var request = URLRequest(url: url)
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue(appId, forHTTPHeaderField: "app_id")
request.addValue(appKey, forHTTPHeaderField: "app_key")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
do {
let jsonData = try JSONDecoder().decode(StoreRandomWords.self, from: data)
print(jsonData)
} catch {
print(error)
}
} else {
print(error)
print(NSString.init(data: data!, encoding: String.Encoding.utf8.rawValue)!)
}
}
task.resume()
}
And the code from ViewController in which i want to load the "word":
// Do any additional setup after loading the view.
override func viewDidLoad() {
super.viewDidLoad()
// Fetch data for Daily Word.
ContextController.shared.fetchRandomWord( completion: { (storeRandomWord) in
if let storeRandomWord = storeRandomWord {
//
}
})
}
Which gives me this output in the console:
StoreRandomWords(results: [GetContext.Result(word: "eurhythmic")])
And my goal is to literally display the value word which is here "eurhythmic".
(I'm a beginner and not a native speaker of English so any feedback on how to improve the code or the question would be helpful and welcome to. )
You will have to loop the array or access the index science storeRandomWords.results is an array.
For example print the first result:
if let storeRandomWord = storeRandomWord {
print(storeRandomWord.results.first.word)
}
Related
I am able to parse and decode data coming from IMGUR website. However when I try to print out one of the properties from Data it doesn’t show anything. How do I fix this? Also I want to access the contents of images, specifically the links. How can I access the contents Of the image since it’s an array?
struct PhotoResponse:Codable {
let success: Bool
let status: Int
let data: [Data]
}
struct Data:Codable {
let id: String
let title: String
let views: Int
let link: String
let images: [Image]?
let animated: Bool?
}
struct Image: Codable {
let id: String
let imageDescription: String?
let link: String?
let size: Int
}
class NetworkService{
static let shared = NetworkService()
private let baseURL = "https://api.imgur.com/3/gallery"
private init() {}
func getJSON( searchName: String, completion: #escaping([Data]) -> Void){
let endPoints = baseURL + "/search/time/week/?q=\(searchName)"
guard let url = URL(string: endPoints ) else{
return
}
var request = URLRequest(url: url)
let headers = ["Authorization": ""]
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Failed to query database", error)
}
guard let data = data else {
print("Data not received\(String(describing: error))")
return
}
let decoder = JSONDecoder()
do{
let decodedJson = try decoder.decode(PhotoResponse.self, from: data)
DispatchQueue.main.async {
completion(decodedJson.data)
}
}catch let error{
print("Json failed to decode\(String(describing: error))")
return
}
}.resume()
}
}
NetworkService.shared.getJSON(searchName: "cat") { (photos) in
for photo in photos {
print(photo.title)
print(photo.id)
}
Swift already has a Data struct, try renaming yours to something else, like MyData. Do the same with Image.
Essentially I have the following function that responds to POST Request and displays JSON data.
I would like to just print the results of this data by printing the value of del_tex
At the top of the ViewController I define the variable structure as:
var structure = [NotesStructure]()
NotesStructure is the structure of the JSON received:
import UIKit
struct NotesStructure: Codable {
let del_tex: String
}
The following is the JSON function that fetches and processes the data. I try to print the value of del_tex but get the error that structure has no value del_tex
private func fetchJSON() {
guard let url = URL(string: "https://example.com/example/example"),
let value = driverName.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)
else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = "person=\(driverName)&serial=\(peronNum)".data(using: .utf8)
URLSession.shared.dataTask(with: request) { data, _, error in
guard let data = data else { return }
do {
self.structure = try JSONDecoder().decode([NotesStructure].self,from:data)
DispatchQueue.main.async {
print(self.structure.del_tex)
}
}
catch {
print(error)
}
}.resume()
}
Your result is an array so you first need to access the array, either only the first element
do {
self.structure = try JSONDecoder().decode([NotesStructure].self,from:data)
if let first = self.structure.first {
print(first.del_tex)
}
...
or print the whole array
do {
self.structure = try JSONDecoder().decode([NotesStructure].self,from:data)
for item in self.structure {
print(item.del_tex)
}
...
I'M using tableview to parsing JSON data. the parse data in tableview in successful parsed on my tableView but the problem is users click the tableview cell to pass to details ViewController.But the problem is i can't parse JSON in details ViewController in
here is my JSON looks
[
{
"id": "263",
"userId": "2692"
}
]
here is my code
guard let url = URL(string: URL API) else { return }
var request = URLRequest(url: url)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer \(AccessToken!)", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
do {
let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [string: anyobject]
print(json)
label.text = json["id"] as? string
}catch {
}
}.resume()
Please try this codes
do {
if let json = try JSONSerialization.jsonObject(with: data!) as? [[String: String]] {
for data in json {
label.text = data["id"] as? String
}
}
} catch { print(error) }
Parse json in swift4 using Codable protocol.
declare your model like this:
struct Model: Codable {
let id: Double
let userId: Double
enum CodingKeys : String, CodingKey {
case id = "id"
case userId = "userId"
}
}
then, after getting data, use this:
do {
let arrayValue = try JSONDecoder().decode([Model], from: data)
}
catch {
}
Note that your json is array not dictionary!
I am sending an HTTP POST request to an API in swift and it is supposed to respond with:
{
"results": [
{
"alternatives": [
{
"transcript": "how old is the Brooklyn Bridge",
"confidence": 0.98267895
}
]
}
]
}
However, I am receiving this through the print(jsonResponse) function:
Optional({
results = (
{
alternatives = (
{
confidence = "0.9688848";
transcript = "how old is the Brooklyn Bridge";
}
);
}
);
})
Is there any reason why the response is not arriving in the correct format as indicated in the API documentation? I need to Decode the response to obtain the "transcript" value. However, I am receiving the following error:
keyNotFound(CodingKeys(stringValue: "transcript", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"transcript\", intValue: nil) (\"transcript\").", underlyingError: nil))
Maybe my request isn't optimal... Here's my code, any help is appreciated!
let parameters = ["config": ["encoding": "FLAC", "sampleRateHertz": "16000", "languageCode": "en-AU"], "audio": ["uri":"gs://cloud-samples-tests/speech/brooklyn.flac"]]
guard let url = URL(string: "https://speech.googleapis.com/v1/speech:recognize?key=AIzaSyDqYpPQIabwF5L-WibBxtVsWRBrc8uKi4w") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: []) // pass dictionary to nsdata object and set it as request body
} catch let error {
print(error.localizedDescription)
}
URLSession.shared.dataTask(with: request) { (data , response , error) in
guard let data = data else {return}
do {
let jsonResponse = (try? JSONSerialization.jsonObject(with: data, options: []))
print("\(jsonResponse)")
let course = try JSONDecoder().decode(Course.self , from : data)
print(course.transcript)
} catch {
print(error)
}
}.resume()
Here is my Course code block: Do I need to include the other components in the struct as well as the transcript?
struct Course: Decodable {
let transcript: String
enum CodingKeys: String, CodingKey {
case transcript = "transcript"
}
}
jsonResponse is an Optional Dictionary, and thus that's why it's debug description looks like what you printed rather than pure JSON as you were looking for. Your problem likely is that your Decodeable objects are not properly setup - as by the looks of it you only have one Course. You'll likely need two more Response which contains a list of Alternatives. And then in Alternative you have a list of Courses.
Structure your objects like this, and it should do the trick:
struct Response: Decodable {
let results: [Alternative]
}
struct Alternative: Decodable {
let alternatives: [Course]
}
struct Course: Decodable {
let transcript: String
let confidence: Float
}
And then swap this line:
let course = try JSONDecoder().decode(Course.self , from : data)
With this change:
let course = try JSONDecoder().decode(Response.self, from: data).results[0].alternatives[0]
I am new to swift and i am trying to integrate the CCAvenue payment gateway. I am hitting the server to get the payment option list from the CCAvenue server which i an getting in the response but i am not able to parse the data into a JSON object, it is throwing some exception. Thanks in advance for the help
here is my code
override func viewDidLoad() {
super.viewDidLoad()
let urlAsString = "https://test.ccavenue.com/transaction/transaction.do?"
let myRequestString = "command=\(COMMAND)¤cy=\(currency)&amount=\(amount)&access_code=\(accessCode)&customer_identifier=\(customerIdentifier)"
let myRequestData = NSData.init(bytes: myRequestString.cString(using: .utf8), length: myRequestString.count) as Data
let request = NSMutableURLRequest.init(url: URL(string: urlAsString)!)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "content-type")
request.setValue(urlAsString, forHTTPHeaderField: "Referer")
request.setValue("Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", forHTTPHeaderField: "User-Agent")
request.httpMethod = "POST"
request.httpBody = myRequestData
let requestData = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
let responseData = NSString.init(data: data!, encoding: String.Encoding.ascii.rawValue)
if error == nil {
print("\(responseData)")
}
// if request is error free then decode the json using json decoder and assigning the values to the array
guard let data = data else {return}
do{
let a = try JSONDecoder().decode([CCPaymentOption].self, from: data)
print("\(String(describing: a))")
}catch {
print("Error")
}
}.resume()
print("\(requestData)")
}
this is what i am getting in my debugger
Optional({"payOptions":[{"payOpt":"OPTCRDC","payOptDesc":"Credit Card","cardsList":"[{\"cardName\":\"Diners Club\",\"cardType\":\"CRDC\",\"payOptType\":\"OPTCRDC\",\"payOptDesc\":\"Credit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"},{\"cardName\":\"MasterCard\",\"cardType\":\"CRDC\",\"payOptType\":\"OPTCRDC\",\"payOptDesc\":\"Credit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\",\"statusMessage\":\"\"},{\"cardName\":\"Visa\",\"cardType\":\"CRDC\",\"payOptType\":\"OPTCRDC\",\"payOptDesc\":\"Credit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"}]"},{"payOpt":"OPTDBCRD","payOptDesc":"Debit Card","cardsList":"[{\"cardName\":\"MasterCard Debit Card\",\"cardType\":\"DBCRD\",\"payOptType\":\"OPTDBCRD\",\"payOptDesc\":\"Debit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"},{\"cardName\":\"Visa Debit Card\",\"cardType\":\"DBCRD\",\"payOptType\":\"OPTDBCRD\",\"payOptDesc\":\"Debit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"}]"},{"payOpt":"OPTNBK","payOptDesc":"Net Banking","cardsList":"[{\"cardName\":\"AvenuesTest\",\"cardType\":\"NBK\",\"payOptType\":\"OPTNBK\",\"payOptDesc\":\"Net Banking\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\",\"statusMessage\":\"\"}]"}]})
Error
There are many points needed to be checked while decoding the object.
Make sure your CCPaymentOption Model addopt the Protocol Codable.
While Decoding the Data , make sure you are aware of thing that your response is in form of Dictionary or Array
lets say you are getting the Array in response , in that case you can directly use [CCPaymentOption] in JSONDecoder().decode() method.
And if you are getting the Dictionary from the server response then you need to decode the object on that way.
Example of CCPaymentOption Model for point no 3.
struct CCPaymentOption : Codable {
var amount:String // Note down that , please use exact same
// key as you are getting from server side.
}
do {
let arrPaymentOptions = try JSONDecoder().decode([CCPaymentOption].self, from: responseData)
print(arrPaymentOptions)
///... Array of Your Model reference.
} catch {
print(error)
}
Example of CCPaymentOption Model for point no 4.
struct CCPaymentOption : Codable {
var amount:String
}
struct responseDictionary : Codable {
var paymentOption:[CCPaymentOption] // Note down that , please
// use exact same key as you
// are getting from server
// side.
}
do {
let responseDict = try JSONDecoder().decode(responseDictionary.self, from: responseData)
print(responseDict.paymentOption)
// responseDict.paymentOption is the Array of Your
// Model reference.
} catch {
print(error)
}
Please try out the below one if you don't want to use the JSON decoder. :-
URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
guard error == nil else { return }
guard let responseData = data else { return }
do {
if let jsonObject = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String:Any] {
///... All you want is here jsonObject is the Dictionary (required , not an optional)
}
} catch {
print(error)
}
}).resume()
After getting the data from server side , you need to do JSONSerialization with the help of native method. This method will return the Dictionary or Array (Depending on your server response.)