Mixmax Makster Mixmax Makster - 8 months ago 180
Swift Question

How to convert Dictionary with Array to String and back?

How can I convert Dictionary with array to string and back?

["http://www.somehost.com":
[
"some_name",
"some_pass",
"date_modification",
"other_stuff"
]
]

// convert it to string

"skdjfsfjkhjsdfjh:sdlfksdfkj / sdlkfjsdfkj / sldkfsdkjfkjh / skjdfsdjhsd"

// convert string back to ["host": ["name","pass","date","other_stuff"]


Can I use JSON for it?

Answer Source

Made one slight tweak to the string, as the dictionary key (http://www.somehost.com) contains the separator you're trying to use (:), so it makes decoding rather fiddly.

Since it's easy to map a Dictionary to a (key, value) tuple, the encoding functions are as simple as:

func encode(_ entry: (key: String, value: [String]), keySeparator: String, arraySeparator: String) -> String
{
    return entry.key + keySeparator + encode(entry.value, separator: arraySeparator)
}

func encode(_ array: [String], separator: String) -> String
{
    return array.joined(separator: separator)
}

Decoding can then simply be:

func decode(_ strings: [String], keySeparator: String, arraySeparator: String) -> [String:[String]]
{
    return strings.reduce([String:[String]]())
    {
        var dict = $0
        guard let decoded = decode($1, keySeparator: keySeparator, arraySeparator: arraySeparator)
            else { return $0 }

        dict[decoded.key] = decoded.value
        return dict
    }
}

func decode(_ string: String, keySeparator: String, arraySeparator: String) -> (key: String, value: [String])?
{
    let split = string.components(separatedBy: keySeparator)

    guard split.count == 2 else { return nil }

    let key = split[0]
    let value = decodeValues(split[1], separator: arraySeparator)
    return (key, value)
}

func decodeValues(_ string: String, separator: String) -> [String]
{
    return string.components(separatedBy: separator)
}

Finally, running everything can be done with:

let dict = ["http://www.somehost.com":
    [
        "some_name",
        "some_pass",
        "date_modification",
        "other_stuff"
    ]
]

let keySeparator = "::"
let arraySeparator = " / "

let encoded = dict.map { encode($0, keySeparator: keySeparator, arraySeparator: arraySeparator) }
print(encoded) // ["http://www.somehost.com::some_name / some_pass / date_modification / other_stuff"]

let decoded = decode(encoded, keySeparator: keySeparator, arraySeparator: arraySeparator)
print (decoded) // ["http://www.somehost.com": ["some_name", "some_pass", "date_modification", "other_stuff"]]

This definite could be neatened up with extensions, but this will get you 80% of the way there.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download