Skip to content

[SR-6112] arrays and dictionaries do not call container encode for the elements #48667

@swift-ci

Description

@swift-ci
Previous ID SR-6112
Radar None
Original Reporter brendanm500henderson (JIRA User)
Type Bug
Status Closed
Resolution Duplicate
Environment

Swift 4

Xcode 9.6 beta

Mac OSX

Additional Detail from JIRA
Votes 0
Component/s Standard Library
Labels Bug, Codable
Assignee None
Priority Medium

md5: 517a5763d90fe8049146529badff5abd

duplicates:

  • SR-5206 [Codable] The encoded results of Optional<URL> are different between Container.encode (_: ...) and Container.encodeIfPresent (_: ...) .

Issue Description:

Arrays and Dictionaries do not call encode on the container protocols and then encodes the values as their underlying encode type.

example 1:

let value = URL(string: "test.com")

try! [value].encode(to: TestEncoder())

// call stack (a url value never gets encoded)

_Encoder unkeyedContainer()

_UnkeyedEncodingContainer superEncoder()

_Encoder singleValueContainer()

_Encoder singleValueContainer()

_Encoder container(keyedBy: ) (CodingKeys in _FB6C8C127CB51A72D58E049FC6F7743F)

_KeyedEncodingContainerProtocol encode(:forKey: ) String test.com relative

example 2:

let value = Date()

try! [1: value].encode(to: TestEncoder())

// call stack (a date value never gets encoded)

_Encoder container(keyedBy: ) _DictionaryCodingKey

_KeyedEncodingContainerProtocol<_DictionaryCodingKey> superEncoder(forKey: ) _DictionaryCodingKey(stringValue: "1", intValue: Optional(1))

_Encoder singleValueContainer()

_Encoder encode Double 529368384.419609

Is there a way to get around this? Like in the JSONEncoder at: https://github.com/apple/swift/blob/1457e4da9ddc55321648a4b602e9f5cdad857797/stdlib/public/SDK/Foundation/JSONEncoder.swift#L1774 line 667 in box_

// code used for testing

class _Encoder: Encoder, SingleValueEncodingContainer {

var codingPath: \[CodingKey\] = \[\]

var userInfo: \[CodingUserInfoKey : Any\] = \[:\]

func encodeNil() throws {fatalError()}

func encode(\_ value: Bool) throws {fatalError()}

func encode(\_ value: Int) throws {fatalError()}

func encode(\_ value: Int8) throws {fatalError()}

func encode(\_ value: Int16) throws {fatalError()}

func encode(\_ value: Int32) throws {fatalError()}

func encode(\_ value: Int64) throws {fatalError()}

func encode(\_ value: UInt) throws {fatalError()}

func encode(\_ value: UInt8) throws {fatalError()}

func encode(\_ value: UInt16) throws {fatalError()}

func encode(\_ value: UInt32) throws {fatalError()}

func encode(\_ value: UInt64) throws {fatalError()}

func encode(\_ value: Float) throws {fatalError()}



// Date stops here.

func encode(\_ value: Double) throws {

    fatalError()

    print(type(of: self), \#function, type(of: value), value)

}



func encode(\_ value: String) throws {fatalError()}

func encode\<T\>(\_ value: T) throws where T : Encodable {fatalError()}



func container\<Key\>(keyedBy type: Key.Type) -\> KeyedEncodingContainer\<Key\> where Key : CodingKey {

    print(Swift.type(of: self), \#function, Key.self)

    return KeyedEncodingContainer(\_KeyedEncodingContainerProtocol\<Key\>())

}



func unkeyedContainer() -\> UnkeyedEncodingContainer {

    print(type(of: self), \#function)

    return \_UnkeyedEncodingContainer()

}



func singleValueContainer() -\> SingleValueEncodingContainer {

    print(type(of: self), \#function)

    return self

}

}

struct _UnkeyedEncodingContainer: UnkeyedEncodingContainer {

var codingPath: \[CodingKey\] = \[\]

var count: Int = 0



mutating func encode(\_ value: Int) throws {fatalError()}

mutating func encode(\_ value: Int8) throws {fatalError()}

mutating func encode(\_ value: Int16) throws {fatalError()}

mutating func encode(\_ value: Int32) throws {fatalError()}

mutating func encode(\_ value: Int64) throws {fatalError()}

mutating func encode(\_ value: UInt) throws {fatalError()}

mutating func encode(\_ value: UInt8) throws {fatalError()}

mutating func encode(\_ value: UInt16) throws {fatalError()}

mutating func encode(\_ value: UInt32) throws {fatalError()}

mutating func encode(\_ value: UInt64) throws {fatalError()}

mutating func encode(\_ value: Float) throws {fatalError()}

mutating func encode(\_ value: Double) throws {fatalError()}

mutating func encode(\_ value: String) throws {fatalError()}

mutating func encode\<T\>(\_ value: T) throws where T : Encodable {fatalError()}

mutating func encode(\_ value: Bool) throws {fatalError()}

mutating func encodeNil() throws {fatalError()}

mutating func nestedContainer\<NestedKey\>(keyedBy keyType: NestedKey.Type) -\> KeyedEncodingContainer\<NestedKey\> where NestedKey : CodingKey {

    fatalError()}

mutating func nestedUnkeyedContainer() -\> UnkeyedEncodingContainer {

    fatalError()}



mutating func superEncoder() -\> Encoder {

    print(type(of: self), \#function)

    return \_Encoder()

}

}

struct _KeyedEncodingContainerProtocol<K: CodingKey>: KeyedEncodingContainerProtocol {

typealias Key = K

var codingPath: \[CodingKey\] = \[\]

mutating func encodeNil(forKey key: K) throws {fatalError()}

mutating func encode(\_ value: Bool, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: Int, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: Int8, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: Int16, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: Int32, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: Int64, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: UInt, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: UInt8, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: UInt16, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: UInt32, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: UInt64, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: Float, forKey key: K) throws {fatalError()}

mutating func encode(\_ value: Double, forKey key: K) throws {fatalError()}



// URL stops here

mutating func encode(\_ value: String, forKey key: K) throws {

    print(type(of: self), \#function, type(of: value), value, key)

}

mutating func encode\<T\>(\_ value: T, forKey key: K) throws where T : Encodable {fatalError()}

mutating func nestedContainer\<NestedKey\>(keyedBy keyType: NestedKey.Type, forKey key: K) -\> KeyedEncodingContainer\<NestedKey\> where NestedKey : CodingKey {

    fatalError()}

mutating func nestedUnkeyedContainer(forKey key: K) -\> UnkeyedEncodingContainer {

    fatalError()}

mutating func superEncoder() -\> Encoder {

    fatalError()}



mutating func superEncoder(forKey key: K) -\> Encoder {

    print(type(of: self), \#function, key)

    return \_Encoder()

}

}

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    CodableArea → standard library: `Codable` and co.bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.standard libraryArea: Standard library umbrella

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions