2

I need to convert all keys and their values of a class in lowercase. For example,

class Person : Encodable {
    var firstName: String
    var lastName: String
     var city: String
}

 var person = Person(firstName: "David", lastName: "Gill", city: 
 "Toronto")
 let encoder = JSONEncoder()
 encoder.keyEncodingStrategy = .convertToLowerCase
 let encoded = try encoder.encode(person)
 print(String(decoding: encoded, as: UTF8.self))

Where convertToLowerCase is a method I have added in extension of JSONEncoder.KeyEncodingStrategy to convert keys into lowercase.

It prints - {"city":"Toronto","firstname":"David","lastname":"Gill"}

What I need to print is - {"city":"toronto","firstname":"david","lastname":"gill"}

Can someone please help here?

Ahmad F
  • 30,560
  • 17
  • 97
  • 143
NChoudhary
  • 23
  • 3

3 Answers3

3

Like this:

struct Person : Codable {
    var firstName: String
    var lastName: String
    var city: String
    enum CodingKeys : String, CodingKey {
        case firstName = "firstname"
        case lastName = "lastname"
        case city
    }
    func encode(to encoder: Encoder) throws {
        var con = encoder.container(keyedBy: CodingKeys.self)
        try! con.encode(self.firstName.lowercased(), forKey: .firstName)
        try! con.encode(self.lastName.lowercased(), forKey: .lastName)
        try! con.encode(self.city.lowercased(), forKey: .city)
    }
}

Testing it:

let person = Person(firstName: "David", lastName: "Gill", city:
    "Toronto")
let encoder = JSONEncoder()
let encoded = try encoder.encode(person)
print(String(decoding: encoded, as: UTF8.self))
// {"firstname":"david","lastname":"gill","city":"toronto"}

You can probably incorporate your .convertToLowerCase to save some work.

matt
  • 515,959
  • 87
  • 875
  • 1,141
0

You could convert each value first:

var firstName = "David"
var lastName = "Gill"
var city = "Toronto"

var editedFirst = firstName.lowercased()
var editedLast = lastName.lowercased()
var editedCity = city.lowercased()

 var person = Person(firstName: editedFirst, lastName: editedLast, city: 
 editedCity)

 let encoder = JSONEncoder()
 encoder.keyEncodingStrategy = .convertToLowerCase
 let encoded = try encoder.encode(person)
 print(String(decoding: encoded, as: UTF8.self))

It doesn't enable you to convert the entire object's attributes in one go, but it will get your values converted along with the keys.

As far as your question about whether or not we can loop over this for each attribute in the class: How about adding the lowerCased version of each attribute to the class instead?

Something like this:

class Person : Encodable {
    var firstName: String
    var lastName: String
     var city: String

  let editedFirst = firstName.lowercased()
  let editedLast = lastName.lowercased()
  let editedCity = city.lowercased()
}

And then you could access that lowercased value when you need to.

Levi Yoder
  • 177
  • 9
0

This is not perfect answer but it's too long to type in a comment.

but here's what I'd try:

  1. Convert your object to dictionary (with something like this https://stackoverflow.com/a/46049763/503527)

  2. Map the dictionary values to be lower cased (this is a good answer for mapping dictionary values https://stackoverflow.com/a/24219069/503527)

  3. Once you have the mapped dictionary, JSONencode and you should have what you need.

Nitin Alabur
  • 5,812
  • 1
  • 34
  • 52