I have a JSON response that I am parsing with the help of codable models.
Even though my models look good, I am getting the following error:
[Result]: FAILURE: keyNotFound(CodingKeys(stringValue: “user”, intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: “No value associated with key CodingKeys(stringValue: \“user\“, intValue: nil) (\“user\“).“, underlyingError: nil))
The JSON response is:
{
“status”: “success”,
“message”: “successfully.“,
“user”: {
“username”: “admin”,
“profileImage”: “/storage/default.png”
},
“data”: {
“cash”: {
“withdrawableCash”: “$999540”,
“outstandingOrders”: “$0”
},
“offering”: [
{
“company”: “ABCD”,
“location”: “San Francisco, CA”,
“amount”: 10
}
],
“history”: [
{
“amount”: 330,
“order_id”: 3,
“order_type”: “preBid”,
“status”: 2,
“message”: “Placed bid with 33 notes, on Auction,
“transaction_time”: “31-07-2018 05:31"
}
]
}
}
The models are:
public struct WalletResponseModel: Codable {
public let status: String
public let message: String
public let user: UserData
public let data: WalletData
}
public struct UserData: Codable {
public let username: String
public let profileImage: URL
enum CodingKeys: String, CodingKey {
case username
case profileImage = "profileImage"
}
}
public struct WalletData: Codable {
public let cash: Cash
public let history: [HistoryItem]
public let offerings: [Offering]
enum CodingKeys: String, CodingKey {
case cash
case history
case offerings = "offering"
}
}
public struct Cash: Codable {
public let withdrawableCash: String
public let outstandingOrders: String
}
public struct HistoryItem: Codable {
public let amount: Int
public let status: Int
public let orderId: Int
public let orderType: String
public let message: String
public let transactionTime: String
enum CodingKeys: String, CodingKey {
case amount, status, message
case transactionTime = "transaction_time"
case orderId = "order_id"
case orderType = "order_type"
}
}
public struct Offering: Codable {
public let company: String
public let amount: Int
public let location: String
}
Your json format is incorrect it contains “ ” instead of " " , the valid one is
{
"status": "success",
"message": "successfully.",
"user": {
"username": "admin",
"profileImage": "/storage/default.png"
},
"data": {
"cash": {
"withdrawableCash": "$999540",
"outstandingOrders": "$0"
},
"offering": [{
"company": "ABCD",
"location": "San Francisco, CA",
"amount": 10
}],
"history": [{
"amount": 330,
"order_id": 3,
"order_type": "preBid",
"status": 2,
"message": "Placed bid with 33 notes, on Auction",
"transaction_time": "31-07-2018 05:31"
}]
}
}
Related
Currently working with an API, and while I have successfully gotten it to decode the full result, I am only interested in the Entities/identifier portion. While I have gotten it working and get what I want/need I feel like this could be done better and more elegant and maybe in a single step. Any insight/suggestions appreciated.
JSON returned from API:
{
"count": 4596,
"entities": [
{
"facet_ids": [
"contact",
"siftery",
"investor",
"ipqwery",
"aberdeen",
"apptopia",
"semrush",
"company",
"rank",
"builtwith",
"bombora",
"key_event"
],
"identifier": {
"uuid": "468bef9f-2f50-590e-6e78-62e3adb05aa1",
"value": "Citi",
"image_id": "v1417152861/pdgwqt8ddecult5ktvdf.jpg",
"permalink": "citigroup",
"entity_def_id": "organization"
},
"short_description": "Citigroup is a diversified financial services holding company that provides various financial products and services."
},
{
"facet_ids": [
"contact",
"siftery",
"investor",
"apptopia",
"semrush",
"company",
"rank",
"builtwith",
"key_event"
],
"identifier": {
"uuid": "031a344b-c2b9-e60b-d950-1ae062026fde",
"value": "Citi",
"image_id": "yzlzhjqpparamrswaqa1",
"permalink": "citi-2",
"entity_def_id": "organization"
},
"short_description": "CITi is an NPO supporting the ICT sector in Western Cape."
},
{
"facet_ids": [
"contact",
"siftery",
"semrush",
"company",
"rank",
"builtwith",
"bombora"
],
"identifier": {
"uuid": "7ce45379-957c-49c5-bca2-c9ffd521f7da",
"value": "CITI",
"image_id": "qbkqndm7d0wgbogxjcrs",
"permalink": "citi-f7da",
"entity_def_id": "organization"
},
"short_description": "CITI trusted gateway to project-based change expertise that major organisations need to thrive, change and innovate."
}
]
}
Structs:
struct Entity: Decodable, Identifiable
{
var id: String
var companyName: String
var permalink: String
var imageID: String
init(from entity: Entities.Entity) throws
{
self.id = entity.identifier?.uuid ?? ""
self.companyName = entity.identifier?.value ?? ""
self.permalink = entity.identifier?.permalink ?? ""
self.imageID = entity.identifier?.image_id ?? ""
}
}
struct Entities: Decodable
{
var count:Int?
var entities: [Entity]?
struct Entity: Decodable
{
var facet_ids:[String]?
var identifier:Identifier?
var short_description:String?
}
struct Identifier:Decodable
{
var permalink:String?
var value:String?
var image_id:String?
var entity_def_id:String?
var uuid:String?
}
}
Call to decode:
if let data = data{
do {
let businessEntities = try decoder.decode(Entities.self, from: data)
let entities:[Entity] = try businessEntities.entities!.compactMap{
entity in
do
{
return try Entity(from: entity)
}
}
Thinking you are just interested in the Entities/identifier, you can simplify your model. Here's an example:
typealias Entities = [Entitie]
struct Entitie: Codable {
let facetIDS: [String]
let identifier: Identifier
let shortDescription: String
enum CodingKeys: String, CodingKey {
case facetIDS = "facet_ids"
case identifier
case shortDescription = "short_description"
}
}
struct Identifier: Codable {
let uuid, value, imageID, permalink: String
let entityDefID: String
enum CodingKeys: String, CodingKey {
case uuid, value
case imageID = "image_id"
case permalink
case entityDefID = "entity_def_id"
}
}
You can access entities object and decode it like this:
guard let data = data,
let jsonDict = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
let entitiesObj = jsonDict["entities"] else { return }
do {
let entitiesData = try JSONSerialization.data(withJSONObject: entitiesObj)
let result = try JSONDecoder().decode(Entities.self, from: entitiesData)
} catch {
print(error.localizedDescription)
}
Obs: I created the CodingKeys because I use camelCase in my projects, you can left it in snake_case just remember to replace variables.
I'm using Alamofire and Decodable for a Google Books API request for performing a search.
I've created a Decodable model which I will add below and it worked up until I try to get any other field below "title" in "volumeInfo" (I've been commenting out properties one by one to check where it fails). The error I get after uncommenting "authors", "publisher" or anything other than "title" inside "volumeInfo" is:
responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "publisher", intValue: nil)
An example response is:
{
"kind": "books#volume",
"id": "Ett09eLWE5oC",
"etag": "WIwTdsmpnhs",
"selfLink": "https://www.googleapis.com/books/v1/volumes/Ett09eLWE5oC",
"volumeInfo": {
"title": "The Picture of Dorian Gray",
"authors": [
"Oscar Wilde"
],
"publisher": "Wordsworth Editions",
"publishedDate": "1992",
"description": "The handsome appearance of dissolute young Dorian Gray remains unchanged while the features in his portrait become distorted as his degeneration progresses",
"industryIdentifiers": [
{
"type": "ISBN_10",
"identifier": "1853260150"
},
{
"type": "ISBN_13",
"identifier": "9781853260155"
}
],
"readingModes": {
"text": false,
"image": true
},
"pageCount": 312,
"printType": "BOOK",
"categories": [
"Fiction"
],
"averageRating": 4.0,
"ratingsCount": 6,
"maturityRating": "NOT_MATURE",
"allowAnonLogging": false,
"contentVersion": "1.1.2.0.preview.1",
"panelizationSummary": {
"containsEpubBubbles": false,
"containsImageBubbles": false
},
"imageLinks": {
"smallThumbnail": "http://books.google.com/books/content?id=Ett09eLWE5oC&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
"thumbnail": "http://books.google.com/books/content?id=Ett09eLWE5oC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api"
},
"language": "en",
"previewLink": "http://books.google.ro/books?id=Ett09eLWE5oC&pg=PA130&dq=9781853260155&hl=&cd=1&source=gbs_api",
"infoLink": "http://books.google.ro/books?id=Ett09eLWE5oC&dq=9781853260155&hl=&source=gbs_api",
"canonicalVolumeLink": "https://books.google.com/books/about/The_Picture_of_Dorian_Gray.html?hl=&id=Ett09eLWE5oC"
}
}
My model:
struct Response: Decodable {
struct VolumeInfo: Decodable {
var title: String
//var authors: [String]
var publisher: String
//var identifiers: [Identifier]
//var image: ImageLink
enum CodingKeys: String, CodingKey {
case title
//case authors
case publisher
//case identifiers = "industryIdentifiers"
//case image = "imageLinks"
}
}
struct Identifier: Decodable {
var type: String
var identifier: String
enum CodingKeys: String, CodingKey {
case type
case identifier
}
}
struct ImageLink: Decodable {
var url: URL
enum CodingKeys: String, CodingKey {
case url = "thumbnail"
}
}
var id: String
var volumeInfo: VolumeInfo
}
I Have the following JSON response from API,
{
"status_code": 1000,
"data": [
{
"id": 3,
"invoice_id": 100000,
"user_id": 1000,
"contact_number": "NA",
"province": 0,
"location": "100000",
"total": 0,
"confirm_code": 1234,
"status": 0,
"created_at": "2020-03-18 22:07:25",
"updated_at": "2020-03-18 22:07:25"
},
{
"id": 4,
"invoice_id": 100000,
"user_id": 1000,
"contact_number": "NA",
"province": 0,
"location": "100000",
"total": 0,
"confirm_code": 1234,
"status": 0,
"created_at": "2020-03-18 22:10:40",
"updated_at": "2020-03-18 22:10:40"
},
{
"id": 5,
"invoice_id": 100000,
"user_id": 1000,
"contact_number": "NA",
"province": 0,
"location": "100000",
"total": 0,
"confirm_code": 1234,
"status": 0,
"created_at": "2020-03-18 22:12:29",
"updated_at": "2020-03-18 22:12:29"
}
],
"message": null
}
and my struct is,
struct Invoice: Codable {
let statusCode: Int
let data: [Datum]
let message: String?
enum CodingKeys: String, CodingKey {
case statusCode
case data, message
}
}
struct Datum: Codable {
let id, invoiceID, userID: Int
let contactNumber: String
let province: Int
let location: String
let total, confirmCode, status: Int
let createdAt, updatedAt: String
enum CodingKeys: String, CodingKey {
case id
case invoiceID
case userID
case contactNumber
case province, location, total
case confirmCode
case status
case createdAt
case updatedAt
}
}
and In View Controller,
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://xxxxx/api/invoices/\(1000)")!
var request = URLRequest(url: url)
request.httpMethod = "get"
let task = session.dataTask(with: request) { (data, response, error) in
guard let data = data else { return }
do {
let jsonData = try JSONDecoder().decode([Invoice].self, from: data)
print(jsonData)
}
catch let jsonerr {
print("error serrializing error",jsonerr)
}
}
task.resume()
}
But Im keeping below error message,
error serrializing error typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array but found a dictionary instead.", underlyingError: nil))
Please what Im missing here ! Any help will be much appreciated
The Codable struct will be like
struct Invoice: Codable {
let statusCode: Int
let data: [Datum]
let message: String?
enum CodingKeys: String, CodingKey {
case statusCode = "status_code"
case data, message
}
}
struct Datum: Codable {
let id, invoiceID, userID: Int
let contactNumber: String
let province: Int
let location: String
let total, confirmCode, status: Int
let createdAt, updatedAt: String
enum CodingKeys: String, CodingKey {
case id = "id"
case invoiceID = "invoice_id"
case userID = "user_id"
case contactNumber = "contact_number"
case province, location, total
case confirmCode = "confirm_code"
case status
case createdAt = "created_at"
case updatedAt = "updated_at"
}
}
And also use
let jsonData = try JSONDecoder().decode(Invoice.self, from: data)
instead of
let jsonData = try JSONDecoder().decode([Invoice].self, from: data)
I have been trying to get json response from url using alamofire. Created model, apirouter and api client class.
its shows error
failure(Alamofire.AFError.responseSerializationFailed(reason:
Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(error:
Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "variables", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"variables\", intValue: nil) (\"variables\").", underlyingError: nil)))))
Here is my postman json response:
[
{
"id": "00602c70-fc8a-11e9-ad1d-2abe2670111d",
"resourceType": "Task",
"name": "My Tasks",
"owner": null,
"query": {
"assigneeExpression": "${currentUser()}",
"taskVariables": [],
"processVariables": [],
"caseInstanceVariables": [],
"orQueries": []
},
"properties": {
"variables": [
{
"name": "loanAmount",
"label": "Loan Amount"
},
{
"name": "firstName",
"label": "First Name"
}
],
"color": "#555555",
"showUndefinedVariable": false,
"description": "Tasks assigned to me",
"refresh": false,
"priority": -10
}
}
]
My trying get values for id, name and properties -> variables -> name and label from json response.
Here is model class:
import Foundation
public struct Filter: Codable {
let id: String
let name: String
let properties: [variables]
}
public struct variables: Codable {
let name: String
let label: String
}
Here is code for alamofire :
private static func performRequest<T:Decodable>(route:APIRouter, decoder: JSONDecoder = JSONDecoder(), completion:#escaping (AFResult<T>)->Void) -> DataRequest {
return AF.request(route)
.responseDecodable (decoder: decoder){ (response: AFDataResponse<T>) in
completion(response.result)
print("framework response::",response.result)
}
}
public static func getFilter(completion:#escaping (AFResult<[Filter]>)->Void) {
let jsonDecoder = JSONDecoder()
performRequest(route: APIRouter.getFilter, decoder: jsonDecoder, completion: completion)
}
Any help much appreciates pls...
your model class should be like the below.
import Foundation
public struct Filter: Codable {
let id: String
let name: String
let properties: Properties
}
public struct Properties: Codable {
let variables: [variables]
let color: String
let showUndefinedVariable: Bool
let description: String
let refresh: Bool
let priority: Int
}
public struct variables: Codable {
let name: String
let label: String
}
Did you try this one? This is what it should be
public struct Filter: Codable {
let id: String
let name: String
let properties: Property
}
public struct Property: Codable {
let variables: [Variable]
}
public struct Variable: Codable {
let name: String
let label: String
}
The error message you're getting is pretty clear: No value associated with key CodingKeys(stringValue: \"variables\"
You're attempting to decode the JSON into the Filter struct, but the JSON has no variables property. You could fix this by introducing a new Properties struct that will wrap the variables property, like this:
struct Filter: Codable {
let id: String
let name: String
let properties: Properties
}
struct Properties: Codable {
let variables: Variables
}
struct Variables: Codable {
let name: String
let label: String
}
Also, as you'll see in this snippet, it's convention to make the write the type names in CamelCase, so struct Variables instead of struct variables.
I am trying to decode an API call and I keep getting an error stating:
keyNotFound(CodingKeys(stringValue: "instruction", intValue: nil),
Swift.DecodingError.Context(codingPath: [], debugDescription: "No
value associated with key CodingKeys(stringValue: \"instruction\",
intValue: nil) (\"instruction\").", underlyingError: nil))
This is the json data
"resourceSets": [
{
"resources": [
{
"routeLegs": [
{
"itineraryItems": [
{
"compassDirection": "south",
"details": [
{
"compassDegrees": 182,
"endPathIndices": [
1
],
"maneuverType":
"DepartStart",
"mode": "Driving",
"names": [
"Infinite Loop"
],
"roadType": "Street",
"startPathIndices": [
0
]
}
],
"iconType": "Auto",
"instruction": {
"formattedText": "<Action>Depart</Action> <RoadName>Infinite Loop</RoadName> toward <Toward>Mariani Ave</Toward>",
"maneuverType": "DepartStart",
"text": "Depart Infinite Loop toward Mariani Ave"
},
Here is my data structs and coding keys
struct TruckRoute: Codable {
let resourceSets: [ResourceSet]
enum CodingKeys: String, CodingKey {
case resourceSets
}
}
// MARK: - ResourceSet
struct ResourceSet: Codable {
let resources: [Resource]
}
// MARK: - Resource
struct Resource: Codable {
let routeLegs: [RouteLeg]
enum CodingKeys: String, CodingKey {
case routeLegs
}
}
// MARK: - RouteLeg
struct RouteLeg: Codable {
let itineraryItems: [ItineraryItem]
enum CodingKeys: String, CodingKey {
case itineraryItems
}
}
// MARK: - ItineraryItem
struct ItineraryItem: Codable {
let instruction: Instruction
private enum CodingKeys: String, CodingKey {
case instruction
}
}
// MARK: - Instruction
struct Instruction: Codable {
let formattedText, maneuverType, text: String
private enum CodingKeys: String, CodingKey {
case formattedText, maneuverType, text
}
}
https://dev.virtualearth.net/REST/v1/Routes/Truck?wp.0=37.33233141,%20-122.0312186&wp.1=33.1956369,%20-117.3784666&key=AhLvBEtcGrKMDAIHHOhIhDm-aMM_dvGqstttp3wLfs8-J2A0UVBgN5bkzvaiZhj8