Gasper J.
Gasper J.

Reputation: 511

Swift Codable Protocol. String encoding issue

Recently I have faced an issue while encoding an entity, which conforms to Codable protocol.

Here is the code for the Playground:

class Person: Codable {
    var name: String?
    var age: Int?
    var isDev: Bool?
}

let p1 = Person()
p1.name = "John N."
p1.age = 13
p1.isDev = false

let p2 = Person()
p2.name = "Jack"
p2.age = 19
p2.isDev = true

let people = [p1, p2]
let data = try JSONEncoder().encode(people)
let j = try! JSONSerialization.jsonObject(with: data, options: [])

print(j)

This is the output I am getting in the Playground console:

enter image description here

As you can see, the encoded p1 name has the quotation marks, but the p2 doesn't. So my question is why?

P.S. The only one thing I have noticed is that adding e.g. a space symbol or an underscore anywhere when setting the string value adds quotation marks in json. the p1.name contains a space, so it is encoded properly.

Any thoughts are appreciated.

Upvotes: 1

Views: 468

Answers (2)

Vlad Rusu
Vlad Rusu

Reputation: 1479

This answer won't tackle the actual question, but I consider this is what the question author desires to achieve. In the posted code snippet, you are actually printing a dictionary, not a JSON string. You are doing the following things:

  1. Convert the Person object into a JSON data
  2. Convert the JSON data into a Dictionary
  3. Print the dictionary

Recall that the JSON data is in fact the bytes representation of the JSON string.

You can check the JSON string just by doing this:

class Person: Codable {
    var name: String?
    var age: Int?
    var isDev: Bool?
}

let p1 = Person()
p1.name = "John N."
p1.age = 13
p1.isDev = false

let p2 = Person()
p2.name = "Jack"
p2.age = 19
p2.isDev = true

let people = [p1, p2]
let data = try JSONEncoder().encode(people)
let jsonString = String(data: data, encoding: .utf8)

print(jsonString ?? "invalid JSON data")

Upvotes: 2

Sweeper
Sweeper

Reputation: 270860

j is the deserialised JSON object, not the JSON string (encoded data). If you want to see the JSON, convert data to a string, as that is the JSON:

print(String(data: data, encoding: .utf8)!)

j is actually the representation of your JSON data using NSArrays and NSDictionarys. It turns out that if you print NSDictionarys with strings in them, quotes will be added to strings that have spaces and/or other special characters, to tell you where the string actually starts and ends.

Compare:

print(["name": "hello"] as NSDictionary)
print(["name": "hello world"] as NSDictionary)
print(["hello"] as NSArray)
print(["hello world"] as NSArray)

Output:

{
    name = hello;
}
{
    name = "hello world";
}
(
    hello
)
(
    "hello world"
)

Upvotes: 4

Related Questions