Variable inside JSON string - ios

I am working on an app to make CVs and I have a JSON file with job descriptions the user can choose from. The problem is that the aircraft the user flies can be many and I would like to add a variable I can change inside the JSON string. Something like this:
{
"data":[
{
"jobDescription": "Worldwide Passenger and freighter flights in all weather conditions, on the modern " + yourAirplane + ". I Have gained experience flying to destinations in all continents while working with different nationalities"
}
]
}
I have been googling but I couldn't find anything. I parse the string with the following code:
struct JobDescriptionData : Decodable{
var data:[JobDescritpion]?
}
class JobDescritpion: NSObject, Decodable {
static let shared = JobDescritpion()
var jobDescription : String?
func loadJobDescriptions(completion: ([JobDescritpion]) -> ()){
let path = Bundle.main.path(forResource: "jobDescription", ofType: "json")!
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
data.printJSON()
let decoder = JSONDecoder()
guard let eventResult = try? decoder.decode(JobDescriptionData.self, from: data) else { return }
var array = [JobDescritpion]()
array = eventResult.data!
completion(array)
} catch {
}
}
}
printJSON() (which is my extension to Data to print the json array) works and it returns the array but of course, the guard let fails because jobDescription is not a string.
Any Advice on how I can add a variable and then set it later in the app?

Use String Format for your JSON
example
let stringTemplate = "Worldwide Passenger and freighter flights in all weather conditions, on the modern %#. I Have gained experience flying to destinations in all continents while working with different nationalities"
let formattedString = String(format: stringTemplate , "some value")
print(formattedString)

Keep the JSON as a string:
{
"data": [{
"jobDescription": "Worldwide Passenger and freighter flights in all weather conditions, on the modern <yourAirplane>. I Have gained experience flying to destinations in all continents while working with different nationalities"
}]
}
After decoding:
"description".replacingOccurrences(of: "<yourAirplane>", with: yourAirplane)

Related

How would I work with JSON that has no Key:Value pair in Swift using URLSession? [duplicate]

This question already has answers here:
Decoding a JSON without keys in Swift 4
(3 answers)
Closed 8 months ago.
I am trying to access each title in a returned json. This is the JSON
[
"Hyouka",
"Youjo Senki",
"Bungou Stray Dogs 2nd Season",
"Fullmetal Alchemist: Brotherhood",
"Tokyo Ghoul √A",
"Mahouka Koukou no Rettousei",
"Boku wa Tomodachi ga Sukunai NEXT",
"Joker Game",
"Avatar: The Last Airbender",
"Charlotte"
]
It's just a bunch of values and no key for me to construct my model object. This is how I would plan to do it
struct AllNames {
let name: String
}
But there's no key name for me to access. How would you go about accessing this data to print each name to the console in Swift?
Your json is an array of strings , so no model is here and you only need
do {
let arr = try JSONDecoder().decode([String].self, from: jsonData)
print(arr)
}
catch {
print(error)
}
Convert JSON string to array:
func getArrayFromJSONString(jsonStr: String) -> Array<Any> {
let jsonData: Data = jsonStr.data(using: .utf8)!
let arr = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
if arr != nil {
return arr as! Array<Any>
}
return []
}
Test case:
let jsonStr = """
[
\"Hyouka\",
\"Youjo Senki\",
\"Bungou Stray Dogs 2nd Season\",
\"Fullmetal Alchemist: Brotherhood\",
\"Tokyo Ghoul √A\",
\"Mahouka Koukou no Rettousei\",
\"Boku wa Tomodachi ga Sukunai NEXT\",
\"Joker Game\",
\"Avatar: The Last Airbender\",
\"Charlotte\"
]
"""
let arr = getArrayFromJSONString(jsonStr: jsonStr)
print(arr)
Print log:
[Hyouka, Youjo Senki, Bungou Stray Dogs 2nd Season, Fullmetal Alchemist: Brotherhood, Tokyo Ghoul √A, Mahouka Koukou no Rettousei, Boku wa Tomodachi ga Sukunai NEXT, Joker Game, Avatar: The Last Airbender, Charlotte]

Get correct parameter value from URL in "/:id=" format using regex

What is the best way to get the id value from this url:
URL(string: "urlScheme://search/:id=0001")
I've been trying to route this URL using a deep link request. However, my url routing solution JLRoutes shows the parameters as key = id and value = :id=0001.
I instead need the parameters to be key = id and value = "0001".
In an ideal world I would just be using a URL string like "urlScheme://search/0001" and not have any problem but the ":id=" part has to be in there. George's comment about converting the parameter to a URL in of itself and using .pathComponents.last does work, but I think a regex solution is probably going to scale better going forward.
The answer from #George should work fine, but two things struck me: you decided you wanted a regex solution, and to make this generic seemed to be asking for a recursive solution.
The below approach uses regex to identify up to the last /: delimiter, then has to do a bit of inelegant string handling to split it into the base string and the final pair of (key: value) params. I'd hoped to be able to write a regex that just matches those final parameters as that would be a far cleaner range to work with, but haven't managed it yet!
func paramsFrom(_ str: String) -> [String: String] {
guard let baseRange = str.range(of:#"^.+\/:"#, options: .regularExpression ) else { return [:] }
let base = String(str[baseRange].dropLast(2))
let params = str.replacingCharacters(in: baseRange, with: "").components(separatedBy: "=")
return [params.first! : params.last!].merging(paramsFrom(base)){(current, _) in current}
}
using this on your example string returns:
["id": "0001", "title": "256", "count": "100"]
EDIT:
Managed to dig out the old regex brain cells and match just the final pair of parameters. You could adapt the above to use the regex
(?<=\/:)[a-zA-Z0-9=]+$
and the have slightly cleaner string handling as the shortened base string becomes
String(str.dropLast(str[paramsRange].count))
If your URL is in the form of an actual URL query, e.g. urlScheme://search?id=0001, there is a nice way to do this.
With thanks to vadian, this is really simple. You can just do the following:
let components = URLComponents(string: "urlScheme://search?id=0001&a=2")!
let dict = components.queryItems?.reduce(into: [:]) { partialResult, queryItem in
partialResult[queryItem.name] = queryItem.value
}
Or a slightly more compact version for dict:
let dict = components.queryItems?.reduce(into: [:], { $0[$1.name] = $1.value })
Result from given input:
["id": "0001", "a": "2"]
If you must use the current URL form
You can replace the URL string, such as:
let urlStr = "urlScheme://search/:id=0001/:a=2"
let comps = urlStr.components(separatedBy: "/:")
let newUrl: String
if comps.count > 1 {
newUrl = "\(comps.first!)?\(comps.dropFirst().joined(separator: "&"))"
} else {
newUrl = urlStr
}
print(newUrl)
Prints: urlScheme://search?id=0001&a=2
Original answer (slightly modified)
If you have a URL with queries separated by /: you can use the following:
// Example with multiple queries
let url = URL(string: "urlScheme://search/:id=0001/:a=2")!
let queries = url.lastPathComponent.dropFirst().split(separator: "/:")
var dict = [String: String]()
for query in queries {
let splitQuery = query.split(separator: "=")
guard splitQuery.count == 2 else { continue }
let key = String(splitQuery.first!)
let value = String(splitQuery[1])
dict[key] = value
}
print(dict)
Result is same as before.
You can use next regex approach to enumerate parameters in your url path:
let urlString = "urlScheme://search/:id=0001" as NSString
let regex = try! NSRegularExpression(pattern: "([^:\\/]+)=([0-9]+)")
if let match = regex.matches(in: urlString as String, options: [], range: NSMakeRange(0, urlString.length)).first, match.numberOfRanges == 3 {
let key = urlString.substring(with: match.range(at: 1))
let value = urlString.substring(with: match.range(at: 2))
print(key, ":", value)
}
// Prints
id : 0001

Get array of tuples from txt file

I've txt file with content:
("All our dreams can come true, if we have the courage to pursue them.","Walt Disney")
("The secret of getting ahead is getting started","Mark Twain")
I want to get array of tuples from it with type [(String, String)]. I try to use code:
do {
if let path = Bundle.main.path(forResource: "quotes", ofType: "txt"){
let data = try String(contentsOfFile: path, encoding: .utf8)
let arrayOfStrings = data.components(separatedBy: "\n")
print(arrayOfStrings[0])
}
} catch let err as NSError {
// do something with Error
print(err)
}
But with it I cannot get tuple values. How I can get array of tuples from txt file with Swift?
As already mentioned in comments by Larme it would be better to properly format your text. If you can't change the text format you woill need to manually parse its contents:
let data = """
("All our dreams can come true, if we have the courage to pursue them.","Walt Disney")
("The secret of getting ahead is getting started","Mark Twain")
"""
let tuples = data.split(whereSeparator: \.isNewline)
.compactMap { line -> (Substring,Substring)? in
let comps = line.components(separatedBy: #"",""#)
guard comps.count == 2,
let lhs = comps.first?.dropFirst(2),
let rhs = comps.last?.dropLast(2) else { return nil }
return (lhs,rhs)
}
for tuple in tuples {
print(tuple.0)
print(tuple.1)
}
This will print:
All our dreams can come true, if we have the courage to pursue them.
Walt Disney
The secret of getting ahead is getting started
Mark Twain

How can I decode this json with Alamofire? [duplicate]

This question already has answers here:
How to parse a JSON file in swift?
(18 answers)
Closed 3 years ago.
I want to print just value for key "User_number"
[
{
"User_fullname": null,
"User_sheba": null,
"User_modifiedAT": "2019-01-31T18:37:02.716Z",
"_id": "5c53404e91fc822c80e75d23",
"User_number": "9385969339",
"User_code": "45VPMND"
}
]
I suppose this is some JSON in Data format
let data = Data("""
[ { "User_fullname": null, "User_sheba": null, "User_modifiedAT": "2019-01-31T18:37:02.716Z", "_id": "5c53404e91fc822c80e75d23", "User_number": "9385969339", "User_code": "45VPMND" } ]
""".utf8)
One way is using SwiftyJSON library, but, this is something what I don't suggest since you can use Codable.
So, first you need custom struct conforming to Decodable (note that these CodingKeys are here to change key of object inside json to name of property of your struct)
struct User: Decodable {
let fullname, sheba: String? // these properties can be `nil`
let modifiedAt, id, number, code: String // note that all your properties are actually `String` or `String?`
enum CodingKeys: String, CodingKey {
case fullname = "User_fullname"
case sheba = "User_sheba"
case modifiedAt = "User_modifiedAT"
case id = "_id"
case number = "User_number"
case code = "User_code"
}
}
then decode your json using JSONDecoder
do {
let users = try JSONDecoder().decode([User].self, from: data)
} catch { print(error) }
So, now you have Data decoded as array of your custom model. So if you want to, you can just get certain User and its number property
let user = users[0]
let number = user.number
The following code takes takes in Data and saves "User_number" as an Int
if let json = try? JSONSerialization.jsonObject(with: Data!, options: []) as! NSDictionary {
let User_number= json["User_number"] as! Int
}

How to fetch data from array of Dictionary - swift

How can I fetch data from this array?
Here there is an array which contains some key value pairs, and some keys contain an array of dictionary.
var dataArray = [
["teamName":"Arsenal",
"image":"imageName",
"nextMatch":"in 2 days",
"matches":[
["oppositeTeam":"teamName",
"matchTimings":"121212",
"matchId":"ID 213432"],
["oppositeTeam":"teamName",
"matchTimings":"121212",
"matchId":"ID 213432"]
],
"fixtures":[
["oppositeTeam":"teamName",
"oppositeTeamScore":"7",
"HomeTeamScore":"4",
"HomeTeamCards":"True",
"oppositeTeamCards":"false",
"fixturesId":"ID 213432"],
]
],["teamName":"Chelsea",
"image":"imageName",
"nextMatch":"in 2 days",
"matches":[["oppositeTeam":"teamName",
"matchTimings":"121212",
"matchId":"ID 213432"],["oppositeTeam":"teamName",
"matchTimings":"121212",
"matchId":"ID 213432"]
],"fixtures":[["oppositeTeam":"teamName",
"oppositeTeamScore":"7",
"HomeTeamScore":"4",
"HomeTeamCards":"True",
"oppositeTeamCards":"false",
"fixturesId":"ID 213432"],["oppositeTeam":"teamName",
"oppositeTeamScore":"7",
"HomeTeamScore":"4",
"HomeTeamCards":"True",
"oppositeTeamCards":"false",
"fixturesId":"ID 213432"]
]
],["teamName":"India",
"image":"imageName",
"nextMatch":"null",
"matches":[],
"fixtures":[]
]]
I tried but I was unable to fetch data from this array.
You need to use a Model like this
struct Team {
let teamName:String
let image:String
let nextMatch:String
let matches:[Match]?
let fixtures:[Fixture]?
}
struct Match {
let oppositeTeam:String
let matchTimings:String
let matchId:String
}
struct Fixture {
let oppositeTeam:String
let oppositeTeamScore:String
let HomeTeamScore:String
let HomeTeamCards:String
let oppositeTeamCards:String
let fixturesId:String
}
Next you need to learn about Codeable in swift for which I have attached an article below
Codeable Tutorial in swift
Here is how you can access the arrays/dictionaries defined in your dataArray:
// To access team object at zero index
if let team = dataArray[0] as? [String: Any] {
print("Team: \(team["teamName"])")
// To access matches array of team object at zero index
if let matches = team["matches"] as? [[String: Any]] {
print( matches)
// To access first match
if let match = matches.first {
print(match)
}
}
// Similar to matches access fixtures
if let fixtures = dataArray[0]["fixtures"] as? [[String: Any]] {
print(fixtures)
// To access first fixture
if let fixture = fixtures.first {
print(fixture)
}
}
}
This is ok if you are just prototyping. If you plan to extend this into an actual app creating separate models is the best approach.
You can have a Team model that can contain team name, image and matches and fixtures. For matches you can create a model with matche information in it. Similarly you can create a model for fixtures as well. Your Team class will then contain arrays of Match and Fixture classes like this:
var matches: [Match]
var fixtures: [Fixture]
and your dataArray will be of type
var dataArray: [Team]
Create model for your data using Codable. Parse the data in model using JSON decoder. Then you can use your model wherever you want.
For JSON parsing, you can refer this tutorial:-
https://medium.com/xcblog/painless-json-parsing-with-swift-codable-2c0beaeb21c1
You can fetch data from your Array like this:
for attributesObj in dataArray{
let dicFrmArray = attributesObj as! NSDictionary
if ((dicFrmArray["teamName"] as? NSNull) == nil && dicFrmArray["teamName"] != nil){
print(dicFrmArray[teamName"])
}
}

Resources