Strings fetched with JSON-API to be converted from base64 to UTF8 in Swift









up vote
0
down vote

favorite












I am developing an iOS App that fetches Trivia Questions from Open Trivia Database (API)
After reading the docs and played around with it I think that the best solution is to use base64 encoding (since it seems to be supported in Swift). I have successfully fetched the data and parsed it into structs using a JSONParser. The problem that I have to solve is how to convert the values from base64 to UTF8. (The keys are read correctly, and therefore it maps to my structs)



My first idea was to use decoder.dataDecodingStrategy = .base64, but that does not seem to have any effect at all. And I am not really sure why.



Is that the right way to do it, or should I decode it myself afterwards when the strings are read in to structs?
In short, the result of the Parsing is a struct containing a responseCode as an Int and array containing structs representing the questions with the strings that I want to convert to UTF8 as members



My code for parsing looks like this:



 let urlPath = "https://opentdb.com/api.php?amount=10&encode=base64"
let apiURL = URL(string: urlPath)!

URLSession.shared.dataTask(with: apiURL) (data, response, error) in
guard let data = data else return
do
let decoder = JSONDecoder()
decoder.dataDecodingStrategy = .base64
let questionData = try decoder.decode(Response.self, from: data)
print(questionData)
catch let err
print("Error", err)

.resume()









share|improve this question

























    up vote
    0
    down vote

    favorite












    I am developing an iOS App that fetches Trivia Questions from Open Trivia Database (API)
    After reading the docs and played around with it I think that the best solution is to use base64 encoding (since it seems to be supported in Swift). I have successfully fetched the data and parsed it into structs using a JSONParser. The problem that I have to solve is how to convert the values from base64 to UTF8. (The keys are read correctly, and therefore it maps to my structs)



    My first idea was to use decoder.dataDecodingStrategy = .base64, but that does not seem to have any effect at all. And I am not really sure why.



    Is that the right way to do it, or should I decode it myself afterwards when the strings are read in to structs?
    In short, the result of the Parsing is a struct containing a responseCode as an Int and array containing structs representing the questions with the strings that I want to convert to UTF8 as members



    My code for parsing looks like this:



     let urlPath = "https://opentdb.com/api.php?amount=10&encode=base64"
    let apiURL = URL(string: urlPath)!

    URLSession.shared.dataTask(with: apiURL) (data, response, error) in
    guard let data = data else return
    do
    let decoder = JSONDecoder()
    decoder.dataDecodingStrategy = .base64
    let questionData = try decoder.decode(Response.self, from: data)
    print(questionData)
    catch let err
    print("Error", err)

    .resume()









    share|improve this question























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I am developing an iOS App that fetches Trivia Questions from Open Trivia Database (API)
      After reading the docs and played around with it I think that the best solution is to use base64 encoding (since it seems to be supported in Swift). I have successfully fetched the data and parsed it into structs using a JSONParser. The problem that I have to solve is how to convert the values from base64 to UTF8. (The keys are read correctly, and therefore it maps to my structs)



      My first idea was to use decoder.dataDecodingStrategy = .base64, but that does not seem to have any effect at all. And I am not really sure why.



      Is that the right way to do it, or should I decode it myself afterwards when the strings are read in to structs?
      In short, the result of the Parsing is a struct containing a responseCode as an Int and array containing structs representing the questions with the strings that I want to convert to UTF8 as members



      My code for parsing looks like this:



       let urlPath = "https://opentdb.com/api.php?amount=10&encode=base64"
      let apiURL = URL(string: urlPath)!

      URLSession.shared.dataTask(with: apiURL) (data, response, error) in
      guard let data = data else return
      do
      let decoder = JSONDecoder()
      decoder.dataDecodingStrategy = .base64
      let questionData = try decoder.decode(Response.self, from: data)
      print(questionData)
      catch let err
      print("Error", err)

      .resume()









      share|improve this question













      I am developing an iOS App that fetches Trivia Questions from Open Trivia Database (API)
      After reading the docs and played around with it I think that the best solution is to use base64 encoding (since it seems to be supported in Swift). I have successfully fetched the data and parsed it into structs using a JSONParser. The problem that I have to solve is how to convert the values from base64 to UTF8. (The keys are read correctly, and therefore it maps to my structs)



      My first idea was to use decoder.dataDecodingStrategy = .base64, but that does not seem to have any effect at all. And I am not really sure why.



      Is that the right way to do it, or should I decode it myself afterwards when the strings are read in to structs?
      In short, the result of the Parsing is a struct containing a responseCode as an Int and array containing structs representing the questions with the strings that I want to convert to UTF8 as members



      My code for parsing looks like this:



       let urlPath = "https://opentdb.com/api.php?amount=10&encode=base64"
      let apiURL = URL(string: urlPath)!

      URLSession.shared.dataTask(with: apiURL) (data, response, error) in
      guard let data = data else return
      do
      let decoder = JSONDecoder()
      decoder.dataDecodingStrategy = .base64
      let questionData = try decoder.decode(Response.self, from: data)
      print(questionData)
      catch let err
      print("Error", err)

      .resume()






      json swift utf-8 character-encoding base64






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 10 at 21:06









      Måns Sandberg

      4718




      4718






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          Base64 encoding is used for properties you declared as Data, not as Strings, like so:



          struct Response: Codable 

          let someBaseEncodedString: Data


          var someString: String?
          get
          return String(data: someBaseEncodedString, encoding: .utf8)





          So, for the example you are giving, all the properties that are returned as a base64 encoded string should have the Data type in your struct, and then after that decoded as strings.






          share|improve this answer






















          • This helped me out very much and I did not have to change a lot of my code. Thanks!
            – Måns Sandberg
            Nov 13 at 16:16

















          up vote
          0
          down vote













          As suggested by other answers, you can decode Data or Base-64 String after JSONSerialization or JSONDecoder decoded the API results.



          But if you prefer to write decoding initializer, you can make it as follows:



          This may not be much different from your own Response, I guess.



          struct Response: Codable 
          var responseCode: Int
          var results: [Result]

          enum CodingKeys: String, CodingKey
          case responseCode = "response_code"
          case results




          To prepare to write a decoding initializer for Response, I would like to use some extensions:



          extension KeyedDecodingContainer 
          func decodeBase64(forKey key: Key, encoding: String.Encoding) throws -> String
          guard let string = try self.decode(String.self, forKey: key).decodeBase64(encoding: encoding) else
          throw DecodingError.dataCorruptedError(forKey: key, in: self,
          debugDescription: "Not a valid Base-64 representing UTF-8")

          return string


          func decodeBase64(forKey key: Key, encoding: String.Encoding) throws -> [String]
          var arrContainer = try self.nestedUnkeyedContainer(forKey: key)
          var strings: [String] =
          while !arrContainer.isAtEnd
          guard let string = try arrContainer.decode(String.self).decodeBase64(encoding: encoding) else
          throw DecodingError.dataCorruptedError(forKey: key, in: self,
          debugDescription: "Not a valid Base-64 representing UTF-8")

          strings.append(string)

          return strings




          Using these extensions above, you can define the Result type as follows:



          extension Response 
          struct Result: Codable
          var category: String
          var type: String
          var difficulty: String
          var question: String
          var correctAnswer: String
          var incorrectAnswers: [String]

          enum CodingKeys: String, CodingKey
          case category
          case type
          case difficulty
          case question
          case correctAnswer = "correct_answer"
          case incorrectAnswers = "incorrect_answers"


          init(from decoder: Decoder) throws
          let container = try decoder.container(keyedBy: CodingKeys.self)
          self.category = try container.decodeBase64(forKey: .category, encoding: .utf8)
          self.type = try container.decodeBase64(forKey: .type, encoding: .utf8)
          self.difficulty = try container.decodeBase64(forKey: .difficulty, encoding: .utf8)
          self.question = try container.decodeBase64(forKey: .question, encoding: .utf8)
          self.correctAnswer = try container.decodeBase64(forKey: .correctAnswer, encoding: .utf8)
          self.incorrectAnswers = try container.decodeBase64(forKey: .incorrectAnswers, encoding: .utf8)





          (You have not mentioned if your Response (or other name?) is defined as a nested type or not, but I think you can rename or modify it yourself.)



          With all things above, you can simply decode the API response as:



           do 
          let decoder = JSONDecoder()
          let questionData = try decoder.decode(Response.self, from: data)
          print(questionData)
          catch
          print("Error", error)




          By the way, you say I think that the best solution is to use base64 encoding (since it seems to be supported in Swift), but is that really true?



          Base-64 to Data is supported in JSONDecoder, but it is not what you expect. So, using another encoding can be a better choice.



          But, anyway, JSON string can represent all unicode characters using only ASCII with uXXXX or uHHHHuLLLL. So, I do not understand why the API designers do not provide an option Standard JSON Encoding. If you can contact to them, please tell them to provide the option, that may simplify many client side codes.






          share|improve this answer




















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243404%2fstrings-fetched-with-json-api-to-be-converted-from-base64-to-utf8-in-swift%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote



            accepted










            Base64 encoding is used for properties you declared as Data, not as Strings, like so:



            struct Response: Codable 

            let someBaseEncodedString: Data


            var someString: String?
            get
            return String(data: someBaseEncodedString, encoding: .utf8)





            So, for the example you are giving, all the properties that are returned as a base64 encoded string should have the Data type in your struct, and then after that decoded as strings.






            share|improve this answer






















            • This helped me out very much and I did not have to change a lot of my code. Thanks!
              – Måns Sandberg
              Nov 13 at 16:16














            up vote
            1
            down vote



            accepted










            Base64 encoding is used for properties you declared as Data, not as Strings, like so:



            struct Response: Codable 

            let someBaseEncodedString: Data


            var someString: String?
            get
            return String(data: someBaseEncodedString, encoding: .utf8)





            So, for the example you are giving, all the properties that are returned as a base64 encoded string should have the Data type in your struct, and then after that decoded as strings.






            share|improve this answer






















            • This helped me out very much and I did not have to change a lot of my code. Thanks!
              – Måns Sandberg
              Nov 13 at 16:16












            up vote
            1
            down vote



            accepted







            up vote
            1
            down vote



            accepted






            Base64 encoding is used for properties you declared as Data, not as Strings, like so:



            struct Response: Codable 

            let someBaseEncodedString: Data


            var someString: String?
            get
            return String(data: someBaseEncodedString, encoding: .utf8)





            So, for the example you are giving, all the properties that are returned as a base64 encoded string should have the Data type in your struct, and then after that decoded as strings.






            share|improve this answer














            Base64 encoding is used for properties you declared as Data, not as Strings, like so:



            struct Response: Codable 

            let someBaseEncodedString: Data


            var someString: String?
            get
            return String(data: someBaseEncodedString, encoding: .utf8)





            So, for the example you are giving, all the properties that are returned as a base64 encoded string should have the Data type in your struct, and then after that decoded as strings.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 10 at 21:36

























            answered Nov 10 at 21:28









            Marcel

            4,11011833




            4,11011833











            • This helped me out very much and I did not have to change a lot of my code. Thanks!
              – Måns Sandberg
              Nov 13 at 16:16
















            • This helped me out very much and I did not have to change a lot of my code. Thanks!
              – Måns Sandberg
              Nov 13 at 16:16















            This helped me out very much and I did not have to change a lot of my code. Thanks!
            – Måns Sandberg
            Nov 13 at 16:16




            This helped me out very much and I did not have to change a lot of my code. Thanks!
            – Måns Sandberg
            Nov 13 at 16:16












            up vote
            0
            down vote













            As suggested by other answers, you can decode Data or Base-64 String after JSONSerialization or JSONDecoder decoded the API results.



            But if you prefer to write decoding initializer, you can make it as follows:



            This may not be much different from your own Response, I guess.



            struct Response: Codable 
            var responseCode: Int
            var results: [Result]

            enum CodingKeys: String, CodingKey
            case responseCode = "response_code"
            case results




            To prepare to write a decoding initializer for Response, I would like to use some extensions:



            extension KeyedDecodingContainer 
            func decodeBase64(forKey key: Key, encoding: String.Encoding) throws -> String
            guard let string = try self.decode(String.self, forKey: key).decodeBase64(encoding: encoding) else
            throw DecodingError.dataCorruptedError(forKey: key, in: self,
            debugDescription: "Not a valid Base-64 representing UTF-8")

            return string


            func decodeBase64(forKey key: Key, encoding: String.Encoding) throws -> [String]
            var arrContainer = try self.nestedUnkeyedContainer(forKey: key)
            var strings: [String] =
            while !arrContainer.isAtEnd
            guard let string = try arrContainer.decode(String.self).decodeBase64(encoding: encoding) else
            throw DecodingError.dataCorruptedError(forKey: key, in: self,
            debugDescription: "Not a valid Base-64 representing UTF-8")

            strings.append(string)

            return strings




            Using these extensions above, you can define the Result type as follows:



            extension Response 
            struct Result: Codable
            var category: String
            var type: String
            var difficulty: String
            var question: String
            var correctAnswer: String
            var incorrectAnswers: [String]

            enum CodingKeys: String, CodingKey
            case category
            case type
            case difficulty
            case question
            case correctAnswer = "correct_answer"
            case incorrectAnswers = "incorrect_answers"


            init(from decoder: Decoder) throws
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.category = try container.decodeBase64(forKey: .category, encoding: .utf8)
            self.type = try container.decodeBase64(forKey: .type, encoding: .utf8)
            self.difficulty = try container.decodeBase64(forKey: .difficulty, encoding: .utf8)
            self.question = try container.decodeBase64(forKey: .question, encoding: .utf8)
            self.correctAnswer = try container.decodeBase64(forKey: .correctAnswer, encoding: .utf8)
            self.incorrectAnswers = try container.decodeBase64(forKey: .incorrectAnswers, encoding: .utf8)





            (You have not mentioned if your Response (or other name?) is defined as a nested type or not, but I think you can rename or modify it yourself.)



            With all things above, you can simply decode the API response as:



             do 
            let decoder = JSONDecoder()
            let questionData = try decoder.decode(Response.self, from: data)
            print(questionData)
            catch
            print("Error", error)




            By the way, you say I think that the best solution is to use base64 encoding (since it seems to be supported in Swift), but is that really true?



            Base-64 to Data is supported in JSONDecoder, but it is not what you expect. So, using another encoding can be a better choice.



            But, anyway, JSON string can represent all unicode characters using only ASCII with uXXXX or uHHHHuLLLL. So, I do not understand why the API designers do not provide an option Standard JSON Encoding. If you can contact to them, please tell them to provide the option, that may simplify many client side codes.






            share|improve this answer
























              up vote
              0
              down vote













              As suggested by other answers, you can decode Data or Base-64 String after JSONSerialization or JSONDecoder decoded the API results.



              But if you prefer to write decoding initializer, you can make it as follows:



              This may not be much different from your own Response, I guess.



              struct Response: Codable 
              var responseCode: Int
              var results: [Result]

              enum CodingKeys: String, CodingKey
              case responseCode = "response_code"
              case results




              To prepare to write a decoding initializer for Response, I would like to use some extensions:



              extension KeyedDecodingContainer 
              func decodeBase64(forKey key: Key, encoding: String.Encoding) throws -> String
              guard let string = try self.decode(String.self, forKey: key).decodeBase64(encoding: encoding) else
              throw DecodingError.dataCorruptedError(forKey: key, in: self,
              debugDescription: "Not a valid Base-64 representing UTF-8")

              return string


              func decodeBase64(forKey key: Key, encoding: String.Encoding) throws -> [String]
              var arrContainer = try self.nestedUnkeyedContainer(forKey: key)
              var strings: [String] =
              while !arrContainer.isAtEnd
              guard let string = try arrContainer.decode(String.self).decodeBase64(encoding: encoding) else
              throw DecodingError.dataCorruptedError(forKey: key, in: self,
              debugDescription: "Not a valid Base-64 representing UTF-8")

              strings.append(string)

              return strings




              Using these extensions above, you can define the Result type as follows:



              extension Response 
              struct Result: Codable
              var category: String
              var type: String
              var difficulty: String
              var question: String
              var correctAnswer: String
              var incorrectAnswers: [String]

              enum CodingKeys: String, CodingKey
              case category
              case type
              case difficulty
              case question
              case correctAnswer = "correct_answer"
              case incorrectAnswers = "incorrect_answers"


              init(from decoder: Decoder) throws
              let container = try decoder.container(keyedBy: CodingKeys.self)
              self.category = try container.decodeBase64(forKey: .category, encoding: .utf8)
              self.type = try container.decodeBase64(forKey: .type, encoding: .utf8)
              self.difficulty = try container.decodeBase64(forKey: .difficulty, encoding: .utf8)
              self.question = try container.decodeBase64(forKey: .question, encoding: .utf8)
              self.correctAnswer = try container.decodeBase64(forKey: .correctAnswer, encoding: .utf8)
              self.incorrectAnswers = try container.decodeBase64(forKey: .incorrectAnswers, encoding: .utf8)





              (You have not mentioned if your Response (or other name?) is defined as a nested type or not, but I think you can rename or modify it yourself.)



              With all things above, you can simply decode the API response as:



               do 
              let decoder = JSONDecoder()
              let questionData = try decoder.decode(Response.self, from: data)
              print(questionData)
              catch
              print("Error", error)




              By the way, you say I think that the best solution is to use base64 encoding (since it seems to be supported in Swift), but is that really true?



              Base-64 to Data is supported in JSONDecoder, but it is not what you expect. So, using another encoding can be a better choice.



              But, anyway, JSON string can represent all unicode characters using only ASCII with uXXXX or uHHHHuLLLL. So, I do not understand why the API designers do not provide an option Standard JSON Encoding. If you can contact to them, please tell them to provide the option, that may simplify many client side codes.






              share|improve this answer






















                up vote
                0
                down vote










                up vote
                0
                down vote









                As suggested by other answers, you can decode Data or Base-64 String after JSONSerialization or JSONDecoder decoded the API results.



                But if you prefer to write decoding initializer, you can make it as follows:



                This may not be much different from your own Response, I guess.



                struct Response: Codable 
                var responseCode: Int
                var results: [Result]

                enum CodingKeys: String, CodingKey
                case responseCode = "response_code"
                case results




                To prepare to write a decoding initializer for Response, I would like to use some extensions:



                extension KeyedDecodingContainer 
                func decodeBase64(forKey key: Key, encoding: String.Encoding) throws -> String
                guard let string = try self.decode(String.self, forKey: key).decodeBase64(encoding: encoding) else
                throw DecodingError.dataCorruptedError(forKey: key, in: self,
                debugDescription: "Not a valid Base-64 representing UTF-8")

                return string


                func decodeBase64(forKey key: Key, encoding: String.Encoding) throws -> [String]
                var arrContainer = try self.nestedUnkeyedContainer(forKey: key)
                var strings: [String] =
                while !arrContainer.isAtEnd
                guard let string = try arrContainer.decode(String.self).decodeBase64(encoding: encoding) else
                throw DecodingError.dataCorruptedError(forKey: key, in: self,
                debugDescription: "Not a valid Base-64 representing UTF-8")

                strings.append(string)

                return strings




                Using these extensions above, you can define the Result type as follows:



                extension Response 
                struct Result: Codable
                var category: String
                var type: String
                var difficulty: String
                var question: String
                var correctAnswer: String
                var incorrectAnswers: [String]

                enum CodingKeys: String, CodingKey
                case category
                case type
                case difficulty
                case question
                case correctAnswer = "correct_answer"
                case incorrectAnswers = "incorrect_answers"


                init(from decoder: Decoder) throws
                let container = try decoder.container(keyedBy: CodingKeys.self)
                self.category = try container.decodeBase64(forKey: .category, encoding: .utf8)
                self.type = try container.decodeBase64(forKey: .type, encoding: .utf8)
                self.difficulty = try container.decodeBase64(forKey: .difficulty, encoding: .utf8)
                self.question = try container.decodeBase64(forKey: .question, encoding: .utf8)
                self.correctAnswer = try container.decodeBase64(forKey: .correctAnswer, encoding: .utf8)
                self.incorrectAnswers = try container.decodeBase64(forKey: .incorrectAnswers, encoding: .utf8)





                (You have not mentioned if your Response (or other name?) is defined as a nested type or not, but I think you can rename or modify it yourself.)



                With all things above, you can simply decode the API response as:



                 do 
                let decoder = JSONDecoder()
                let questionData = try decoder.decode(Response.self, from: data)
                print(questionData)
                catch
                print("Error", error)




                By the way, you say I think that the best solution is to use base64 encoding (since it seems to be supported in Swift), but is that really true?



                Base-64 to Data is supported in JSONDecoder, but it is not what you expect. So, using another encoding can be a better choice.



                But, anyway, JSON string can represent all unicode characters using only ASCII with uXXXX or uHHHHuLLLL. So, I do not understand why the API designers do not provide an option Standard JSON Encoding. If you can contact to them, please tell them to provide the option, that may simplify many client side codes.






                share|improve this answer












                As suggested by other answers, you can decode Data or Base-64 String after JSONSerialization or JSONDecoder decoded the API results.



                But if you prefer to write decoding initializer, you can make it as follows:



                This may not be much different from your own Response, I guess.



                struct Response: Codable 
                var responseCode: Int
                var results: [Result]

                enum CodingKeys: String, CodingKey
                case responseCode = "response_code"
                case results




                To prepare to write a decoding initializer for Response, I would like to use some extensions:



                extension KeyedDecodingContainer 
                func decodeBase64(forKey key: Key, encoding: String.Encoding) throws -> String
                guard let string = try self.decode(String.self, forKey: key).decodeBase64(encoding: encoding) else
                throw DecodingError.dataCorruptedError(forKey: key, in: self,
                debugDescription: "Not a valid Base-64 representing UTF-8")

                return string


                func decodeBase64(forKey key: Key, encoding: String.Encoding) throws -> [String]
                var arrContainer = try self.nestedUnkeyedContainer(forKey: key)
                var strings: [String] =
                while !arrContainer.isAtEnd
                guard let string = try arrContainer.decode(String.self).decodeBase64(encoding: encoding) else
                throw DecodingError.dataCorruptedError(forKey: key, in: self,
                debugDescription: "Not a valid Base-64 representing UTF-8")

                strings.append(string)

                return strings




                Using these extensions above, you can define the Result type as follows:



                extension Response 
                struct Result: Codable
                var category: String
                var type: String
                var difficulty: String
                var question: String
                var correctAnswer: String
                var incorrectAnswers: [String]

                enum CodingKeys: String, CodingKey
                case category
                case type
                case difficulty
                case question
                case correctAnswer = "correct_answer"
                case incorrectAnswers = "incorrect_answers"


                init(from decoder: Decoder) throws
                let container = try decoder.container(keyedBy: CodingKeys.self)
                self.category = try container.decodeBase64(forKey: .category, encoding: .utf8)
                self.type = try container.decodeBase64(forKey: .type, encoding: .utf8)
                self.difficulty = try container.decodeBase64(forKey: .difficulty, encoding: .utf8)
                self.question = try container.decodeBase64(forKey: .question, encoding: .utf8)
                self.correctAnswer = try container.decodeBase64(forKey: .correctAnswer, encoding: .utf8)
                self.incorrectAnswers = try container.decodeBase64(forKey: .incorrectAnswers, encoding: .utf8)





                (You have not mentioned if your Response (or other name?) is defined as a nested type or not, but I think you can rename or modify it yourself.)



                With all things above, you can simply decode the API response as:



                 do 
                let decoder = JSONDecoder()
                let questionData = try decoder.decode(Response.self, from: data)
                print(questionData)
                catch
                print("Error", error)




                By the way, you say I think that the best solution is to use base64 encoding (since it seems to be supported in Swift), but is that really true?



                Base-64 to Data is supported in JSONDecoder, but it is not what you expect. So, using another encoding can be a better choice.



                But, anyway, JSON string can represent all unicode characters using only ASCII with uXXXX or uHHHHuLLLL. So, I do not understand why the API designers do not provide an option Standard JSON Encoding. If you can contact to them, please tell them to provide the option, that may simplify many client side codes.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 11 at 2:05









                OOPer

                33.4k46083




                33.4k46083



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243404%2fstrings-fetched-with-json-api-to-be-converted-from-base64-to-utf8-in-swift%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    How to read a connectionString WITH PROVIDER in .NET Core?

                    Node.js Script on GitHub Pages or Amazon S3

                    Museum of Modern and Contemporary Art of Trento and Rovereto