Uploaded image for project: 'Swift'
  1. Swift
  2. SR-9385

Encoded data was lost when trying to encode with 2 separated nested keys container with 2 difference Coding Keys on the same key with JSONEncoder and PListEncoder

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Medium
    • Resolution: Done
    • Component/s: Standard Library
    • Labels:
    • Environment:

      Xcode 10.1 Swift 4.2 macOS 10.14.1

      Description

      I think I found an edge case bug of the JSONEncoder and the PListEncoder in Swift Standard Library

      I have a model for an API of our service which will return a JSON data in a specific format. I'm trying to design a Swift model to conform to the Swift API Design guideline. In order to achieve that, we want to flatten the properties up to the type. We can use the nestedKey variant for that. However since we have some specific properties based on the type of the data, we decide to have another type for holding those information. The bug is that we need to call nestedKey variant on the same key but for 2 Coding Keys types while encoding the type, the second container will always replace the data encoding by the first container. I believe that it's due to This line of code where the JSONEncoder will create a new container when the nestedKeys method is called.

      However the decoding works correctly

      {
        "installment_boa": {
          "currencies": [
            "USD"
          ],
          "allowed_installment_terms": [
            3,
            4,
            6,
            9,
            10
          ],
          "amount": {
            "min": 2000,
            "max": 100000000
          }
        }
      }
      

      We want to convert the above JSON data to be something like this

      public struct Payment: Codable, Equatable {
        public let channel: Channel
        public let limit: Limit?
        public let supportedCurrencies: Set<Currency>
        
        public enum Channel : Equatable {
          case card(Set<CardBrand>)
          case installment(InstallmentBrand, availableNumberOfTerms: IndexSet)
          case mobile(Mobile)
          case alipay
        }
        
        public struct Limit : Codable, Equatable, Hashable {
          public let max: Int64
          public let min: Int64
          
          public var range: ClosedRange<Int64> {
            return min...max
          }
        }
      }
      
      

      I think we should fix the Encoders logic not to replace the value encoded by the prior container, this will match with the behavior of the Decoder

        Attachments

          Activity

            People

            • Assignee:
              itaiferber Itai Ferber
              Reporter:
              pitiphong.p Pitiphong Phongpattranont
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: