0

I'm looking for a way to convert this string into array using Swift 3.0

let arrayString: String = "[\"One\", \"Two\", \"Three\", \"Four\"]"

// Should be converted into:

let array: [String] = [
    "One",
    "Two",
    "Three",
    "Four"
]

If I separate it into token using , as the separator, it will include [ and ] so it won't work. How to convert this properly?

Note:

The question is different from: Simple and clean way to convert JSON string to Object in Swift

I'm not trying to convert an JSON Object that has multiple keys in it.

1

3 Answers 3

7

it's a JSON String, you have to convert it in normal string array by using JSONSerialization.

Swift 3.0

func convertToArray(str: String) -> [String]? {

    let data = str.data(using: .utf8)

    do {
        return try JSONSerialization.jsonObject(with: data!, options: []) as? [String]
    } catch {
        print(error.localizedDescription)
    }

   return nil

 }

let aString: String = "[\"One\", \"Two\", \"Three\", \"Four\"]"

let arrayString = convertToArray(str: aString)

print(arrayString) // ["One", "Two", "Three", "Four"]
Sign up to request clarification or add additional context in comments.

6 Comments

I have to say, very clever :), but you should avoid the optional wrapping and use optional binding instead,
I think the better approach is to uses try? instead try and then chain it using as? [String] to get the optional array.
@EdwardAnthony With my edit for the response of Ujesh you have what you want, mapping and validation. I hope this helps you. For the future try to be more consistent in your question to be able to help you better :)
Thanks Ujesh and Victor Sigler, it really helps!
A conversion to UTF-8 cannot fail.
|
1

Here is custom code to convert into array:

var arrayString: String = "[\"One\", \"Two\", \"Three\", \"Four\"]"
arrayString = arrayString.replacingOccurrences(of: "[", with: "")
arrayString = arrayString.replacingOccurrences(of: "]", with: "")
arrayString = arrayString.replacingOccurrences(of: " ", with: "")
arrayString = arrayString.replacingOccurrences(of: "\"", with: "")
print("\(arrayString)")
var arr: [Any] = arrayString.components(separatedBy: ",")
print("\(arr)")

If you get above string from API and its JSON then use below:

extension String {
    func toJSON(): Any? {
        guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil }
        return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
    }
}

Comments

1

There can be a bunch of ways to achieve what you want, but I think one of the most easy is the following:

let newArray = arrayString
 .replacingOccurrences(of: "[", with: "")
 .replacingOccurrences(of: "]", with: "")
 .replacingOccurrences(of: "\"", with: "")
 .components(separatedBy: ",")

And the output should be:

["One", " Two", " Three", " Four"]

EDIT: As @MartinR suggested the previous answer doesn't work if any of the strings contains a comma or a square bracket. So to fix that you can remove the square brackets supposing that always are there of course at the beginning and in the end and then use regex to match everything inside the \"()\" like in the following code:

Let's use the following function to match regex:

func matches(for regex: String, in text: String) -> [String] {
   do {
       let regex = try NSRegularExpression(pattern: regex)
       let nsString = text as NSString
       let results = regex.matches(in: text, range: NSRange(location: 0, length: nsString.length))
       return results.map { nsString.substring(with: $0.range)}
   } catch let error {
       print("invalid regex: \(error.localizedDescription)")
       return []
   }
}

For more reference, you can see the @MartinR answer here

With that function we can use the following code to achieve what we want:

let str = "[\"One[\",\"T,w,o,\",\"Thr,ee,,,\",\"Fo,ur,,,\"]"

// remove the square brackets from the array
let start = str.index(str.startIndex, offsetBy: 1)
let end = str.index(str.endIndex, offsetBy: -1)
let range = start..<end
let newString = str.substring(with: range)

// match the regex 
let matched = matches(for: "(?<=\")(.*?)(?=\")", in: newString) // ["One[", ",", "T,w,o,", ",", "Thr,ee,,,", ",", "Fo,ur,,,"] 

But the previous matched include the "," in the array so let's fix that with the following code:

let stringArray = matched.enumerated()
       .filter { $0.offset % 2 == 0 }
       .map { $0.element }

With the following output:

["One[", "T,w,o,", "Thr,ee,,,", "Fo,ur,,,"]

I hope this helps you.

4 Comments

It works but we can't check if the value resembles an array, for example if the user put [[[1,] or some other string that doesn't have array format, it won't return optional value.
Yes, you're right but your question was not about that isn't? My answer solves your question, you never said anything about that. Again the bunch of ways of solve that is big, for that you can regular expressions to validate the input and then mapping it.
This is fragile. It does not work correctly if any of the strings contains a comma or a square bracket.
@MartinR You're completely right, thanks for the observation

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.