Reading URLS in JSON api with swift - swift

For work we have a third party company which supply a JSON api for some functionality. The JSON contains urls which I try to map in my code with URL(string: ...) but this fails on some urls which have spaces.
For example:
var str = "https://google.com/article/test test.html"
let url = URL(string: str) //nil
Should I ask the third party to encode their URLs ?
Is this normal or should I try to add encoding myself?
Encoding myself is hard I think because the path should be encoded different from the query and the host shouldn't be encoded etc.
Or am I overthinking this?

If the URL contains spaces in its path, escape the characters with addingPercentEncoding(withAllowedCharacters passing the urlPathAllowed character set:
let str = "https://google.com/article/test test.html"
if let escapedString = str.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlPathAllowed),
let url = URL(string:escapedString) {
print(url)
} else {
print("url \(str) could not be encoded")
}

What I would do if I were you, is to split the string up on the space, try converting each of the elements to a url, and when that works save it in your variable.
var str = "https://google.com/article/test test.html"
var url: URL? = nil
for urlString in str.components(separatedBy: .whitespacesAndNewlines) {
let url = URL(string: urlString)
if url != nil {
break
}
}
// url might be nil here, so test for value before using it
If each URL that you get from the API is in the format in your example, you can instead just grab the first element after spitting the string.
var str = "https://google.com/article/test test.html"
if let urlString = str.components(separatedBy: .whitespacesAndNewlines).first {
let url = URL(string: urlString)
}
// url might be nil here, so test for value before using it

Related

Issue with turning Wikipedia url string into URL in Swift

The URL I am making is valid and will return the desired JSON when testing on Chrome, but fails in my project.
func createWikipediaURL(place: String) -> URL? {
let _place = place.replacingOccurrences(of: " ", with: "%20")
let urlStr =
"https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts|pageimages&exintro&explaintext&generator=search&gsrsearch=intitle:\(_place)&gsrlimit=1&redirects=1"
if let url = URL(string:urlStr) {
return url
} else {
return nil
}
}
With the parameter "Malibu Beach" the function will create the proper URL, https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts|pageimages&exintro&explaintext&generator=search&gsrsearch=intitle:Malibu%20Beach&gsrlimit=1&redirects=1, but will also result in no URL being returned because this string cannot be casted into a URL. Any suggestions on how to make the string into a URL?
The issue is with the | character in urlStr. I would suggest using Strings addingPercentEncoding method to make the string url safe. Doing so will mean that you won't need to manually replace spaces for place too.
func createWikipediaURL(place: String) -> URL? {
let urlStr = "https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts|pageimages&exintro&explaintext&generator=search&gsrsearch=intitle:\(place)&gsrlimit=1&redirects=1"
// Replaces special characters with their percent encoded counter-parts.
guard let escapedUrlStr = urlStr.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { return nil }
// There's no need for an if statement; URL can be returned as-is.
return URL(string:escapedUrlStr)
}

Prepare String for URL cast in Swift

I have a text Area, the content of which will later be used to create a URL. How can I validate that the url - cast doesn't throw an error? Is there a function that can do that? For example remove all invalid Characters. I cast the String in the following way, but if the user inputs a newline the cast doesn't work:let url: URL = URL(string: urlPath)!
Use optional binding (https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html):
var str = "somescheme://somedata"
if let url = URL(string: str) {
// handle url
} else {
// handle error
}
If you want to strip whitespaces and new line characters, use:
str.trimmingCharacters(in: .whitespacesAndNewlines)

URL Object is nil after creating it with let constant string url

Why does the first example give me a nil and the second example give me a valid URL object. I am trying to use this jsonUrlString constant and it's not working.
1)
let jsonUrlString = """
https://myURI.domain.com/
"""
let temp = URL(string: jsonUrlString)
2)
let temp = URL(string: "https://myURI.domain.com/")
The first example has lots of extra spaces in the URL so it's not valid.
It's the same as:
let temp = URL(string: " https://myURI.domain.com/")
It would work if you had:
let jsonUrlString = """
https://myURI.domain.com/
"""
This defines the string without the extra spaces.

URL constructor doesn't work with some characters

I'm trying to call a php-script from my app using URLRequest.
The Url path is generated in the String-Variable query and for the request I convert it like this
guard let url = URL(string: query) else {
print("error")
return
}
usually it works, but when the request contains characters like ä, ö, ü, ß the error is triggered. How can I make it work?
The URL(string:) initializer doesn't take care of encoding the String to be a valid URL String, it assumes that the String is already encoded to only contain characters that are valid in a URL. Hence, you have to do the encoding if your String contains non-valid URL characters. You can achieve this by calling String.addingPercentEncoding(withAllowedCharacters:).
let unencodedUrlString = "áűáeqw"
guard let encodedUrlString = unencodedUrlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(string: encodedUrlString) else { return }
You can change the CharacterSet depending on what part of your URL contains the characters that need encoding, I just used urlQueryAllowed for presentation purposes.
Split your URL in two separate parts:
let baseURLString = "https://www.example.com"
let pathComponent = "áűáeqw"
let fullURL = URL(string: baseURLString)?.appendingPathComponent(pathComponent)

Delete parameter from json URL with swift3

I have a URL that looks like 123456_https://example.com.
I want to delete every thing before the _https: part. At the end, the URL should look like https://example.com.
How can I achieve that?
If the prefix is always a couple of characters ending with a underscore you can use this regular expression
let url = "123456_https://example.com"
let trimmedURL = url.replacingOccurrences(of: "^\\w+_", with: "", options: .regularExpression)
you can do something like this if you do not know how to use Regular Expressions
// url string
var url = "123456_https://example.com"
// seperate url by "_" and provides 123456 and https://example.com in urlArray
let urlArray = url.components(separatedBy: "_")
// now to be safe
if(urlArray.count == 2){
// here you get your desired string
let myUrl = urlArray[1]
}