zumzum
zumzum

Reputation: 20138

Swift base64EncodedString produces different values from same string?

I am running this code in swift:

var testBody = [String:Any]()
testBody["f1"] = "1234"
testBody["f2"] = "4321"
var o2 = [String:Any]()
o2["ttnn"] = "wedcfqv w"
o2["ttnn1"] = "mwkcd wmd 234"
testBody["o2"] = o2
        
let bodyData1:Data = try JSONSerialization.data(withJSONObject:testBody,options: JSONSerialization.WritingOptions.prettyPrinted)
let bodyDataBase641 = bodyData1.base64EncodedString()
        
print("bodyData1: \(bodyDataBase641)")

First run bodyData1 print gives this:

bodyData1: ewogICJmMSIgOiAiMTIzNCIsCiAgImYyIiA6ICI0MzIxIiwKICAibzIiIDogewogICAgInR0bm4xIiA6ICJtd2tjZCB3bWQgMjM0IiwKICAgICJ0dG5uIiA6ICJ3ZWRjZnF2IHciCiAgfQp9

Second run bodyData1 print gives this:

bodyData1: ewogICJvMiIgOiB7CiAgICAidHRubiIgOiAid2VkY2ZxdiB3IiwKICAgICJ0dG5uMSIgOiAibXdrY2Qgd21kIDIzNCIKICB9LAogICJmMiIgOiAiNDMyMSIsCiAgImYxIiA6ICIxMjM0Igp9

My original expectation was to be able to obtain the exact same encoded base 64 string as long as I am encoding the same body data.

However, running this code twice, returns two different base 64 encoded strings as shown in the bodyData1 logs.

So, how can I ensure that as long as the body stays the same, the encoded 64 string will also always be the same?

Upvotes: 1

Views: 330

Answers (2)

valosip
valosip

Reputation: 3402

Thats because you're storing the values in a dictionary and a dictionary is:

Every dictionary is an unordered collection of key-value pairs.

print(testBody) before encoding and you'll see that the order changes.

Check out Apple's documentation on dictionaries for more info: Docs

Upvotes: 3

Sweeper
Sweeper

Reputation: 270980

Decoding the strings using an online base 64 decoder shows you what's happening. The first decodes to:

{
  "f1" : "1234",
  "f2" : "4321",
  "o2" : {
    "ttnn1" : "mwkcd wmd 234",
    "ttnn" : "wedcfqv w"
  }
}

The second decodes to:

{
  "o2" : {
    "ttnn" : "wedcfqv w",
    "ttnn1" : "mwkcd wmd 234"
  },
  "f2" : "4321",
  "f1" : "1234"
}

JSON keys are by default unordered. If you want the same string, one way is to sort the keys by providing the option sortedKeys:

try JSONSerialization.data(
    withJSONObject: testBody, 
    options: [.prettyPrinted, .sortedKeys]
)

Upvotes: 2

Related Questions