swift struct JSON id warning - ios

So I am getting a warning (and I can't dismiss it because it won't run the JSON if I do)
The warning is for the following
struct Station: Codable, Identifiable {
let id = UUID() // WARNING: Immutable property will not be decoded because it is declared with an initial value which cannot be overwritten
var name : String
var imageurl : String
var listenlive : String
}
The problem is the following
I can't make it UUID as I get the following error
Type 'Station' does not conform to protocol 'Decodable'
// STATION
struct Sdata: Codable {
var data: [Station]
}
struct Station: Codable, Identifiable {
let id = UUID
var name : String
var imageurl : String
var listenlive : String
}
Also technically the let id is wrong because the JSON has it as _id
"_id":"5f52ed668b964609655b48d1"
So How do I make the warning go away while conforming to the correct value type?

In this case, it's not a matter of "getting rid of the warning". What you are doing seems fundamentally wrong.
The way you declared struct Station, every time a new struct is created, its "id" field is set to a new UUID, that is every struct Station has a different id field, that cannot be changed afterwards.
So if we ignore Codeable for the moment, how would you write such a struct to a file and read it back later, getting the same id? Answer: You can't read it back. At some point you create a struct Station with a new, different UUID, and there is no way to store the one that you wrote to a file. So you have a problem here.
So the problem is quite obvious: If you have a "let" property with a non-constant value, Codeable would have to write it, but Decodable cannot read it, so you have a problem. Make "id" a var, possibly with a constructor that sets it to a new UUID, but it must be changeable.

You need to change it to id:String and use enum CodingKeys for the custom name _id
struct Station: Codable , Identifiable {
var id,name,imageurl,listenlive:String
private enum CodingKeys : String, CodingKey {
case id = "_id", name , imageurl , listenlive
}
}

Related

How to use enum values as columns in a GRDB Record?

I want to make record of 4 different types. I have the following code
import GRDB
enum RecordType: Int16 {
case video, image, text, rep
}
extension RecordType: DatabaseValueConvertible {}
struct Record: Codable, FetchableRecord, PersistableRecord {
var id: Int64?
var type: RecordType
}
Right now it complains Type 'Record' does not conform to protocol 'Decodable'
Of course when I remove the type from the struct, that complaint goes away. Since type is technically Int16 why does this make it not Decodable?
When I adopt Codable to the RecordType as well this goes away. Found the answer here
extension RecordType: DatabaseValueConvertible, Codable {}

Model Object Issue

I am trying to create a model object to store json data received from newsAPI. However one of the keys called description matched a reserved keyword in swift. How do I resolve this ? The error message read Error Message: Property 'description' with type 'String?' cannot override a property with type 'String'
class ArticlesData: NSObject {
var author: String?
var title: String?
var description: String?
var publishedAt: String?
var urlImage: String?
var urlWebsite : String?
}
author : Andrew Marino
title : Vergecast: this week’s Section 230 hearing and the season of weird gadgets
description : Nilay, Dieter, and Adi discuss the latest Section 230 congressional hearing featuring the CEOs of Big Tech. Ashley Carman stops by to talk about how gadget makers are turning to shopping channels to market their products.
url : https://www.theverge.com/2020/10/30/21541796/section-230-hearing-gadgets-qvc-razr-2020-review-vergecast-podcast-428
urlToImage : https://cdn.vox-cdn.com/thumbor/sgk9rqbUKhLVhNxKunmuX_Zm6TM=/0x146:2040x1214/fit-in/1200x630/cdn.vox-cdn.com/uploads/chorus_asset/file/19749210/vpavic_200214_3909_samsung_galaxy_Z_flip_0013.jpg
publishedAt : 2020-10-30T14:44:14Z
content : Photo by Vjeran Pavic / The Verge\n\n This week on The Verge’s flagship podcast, The Vergecast: Sen. Ted Cruz (R-TX) yells at Twitter CEO Jack Dorsey, gadget makers are going to QVC, and it is weird ph… [+3098 chars]
Simplest solution: Use a struct, neither a class or even a subclass of NSObject is necessary.
struct ArticlesData {
Otherwise just use a different name.
If you are going to decode the JSON with Decodable add CodingKeys to map the dictionary key to the struct member with a different name.
And don't declare all properties carelessly as optional. Declare only those as optional which can be nil.
I've run into the same 'issue' several times and it's quite annoying indeed. You should rename your property to something else.
How are you mapping your JSON into the object? If you use Codable, you can use custom CodingKeys such as:
class ArticlesData: NSObject, Codable
{
var author: String?
var title: String?
var myDescription: String?
var publishedAt: String?
var urlImage: String?
var urlWebsite: String?
private enum CodingKeys: String, CodingKey
{
case author, title, myDescription = "description", publishedAt, urlImage = "urlToImage", urlWebsite = "url"
}
}
EDIT: As vadian said, you can also use a struct. I actually prefer that solution over renaming the propery to another name than you want.

Dynamic Struct Variable Name

I define a struct as follows:
struct MyModel : Decodable {
var id : Int
var amount: Int
let myNewTableId : Int
let userId : Int
let myNewTable : MyNewTable
}
I then use this struct to convert JSON data into an object using JSONDecoder().decode.
The problem is that the myNewTable part of myNewTableId and myNewTable are based on an alias given to the SQL table they originate from. So if the alias is abc the fields should be abcId and abc and if its def it should be defId and def. I've saved this alias into a variable:
let MY_NEW_TABLE_ALIAS = "myNewT"
Is there a way to construct the variable names in the struct dynamically using MY_NEW_TABLE_ALIAS. Ideally, when the alias changes on the SQL side, I just want to update one variable, instead of having to update every single struct which uses that table.
The simple way is to convert the json first to a string and replace occurrences with the needed key / use CodingKeys and make the struct as it is , btw you can't have dynamic variable names

Trying to parse a string value from an API a JSON object into a struct as an Int

I am new to Swift and I have data I'd like to call from an API through JSON. For some strange reason some of the names are written with whitespaces making it difficult for me to declare variables that'll show the integer type value they hold. Here is a screenshot . I am trying to parse the Int value attached to the type "Anti-social behaviour" but don't seem to know how to declare it appropriately.
You can define your own CodingKeys inside the file. Note that the name should be CodingKeys.
struct Types: Codable {
let buglary: Int
let shoplifting: Int
let drugs: Int
let robbery: Int
let antiSocialBehavior: Int
// Other properties
enum CodingKeys: String, CodingKey {
case buglary = "Buglary"
case shoplifting = "Shoplifting"
case drugs = "Drugs"
case robbery = "Robbery"
case antiSocialBehavior = "Anti-social behavior"
// other coding keys
}
}
Also, note that properties in Swift are always camelcased and not capitalized. So, I also changed the name of your properties. Check the enum inside the struct which actually defines the mapping between property name and their encoding / decoding keys.

Can we create variables with '-' like JS in swift?

I have a service that returns this JSON structure "actual-price": {,
I want to know if it is possible to create a variable like JS with Codable on swift.
PS: I can't change the JSON since the service is not mine
You will need to use a CodingKeys enumeration to map the jSON properties to valid Swift properties. Note that once you introduce a CodingKeys enumeration it must contain all of the properties you wish to map, not just the properties where you want to change the name.
Something like
struct MyStruct: Codable {
var actualPrice: Double
var quantity: Int
enum CodingKeys: String, CodingKey {
case actualPrice = "actual-price"
case quantity = "quantity"
}
}

Resources