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

JSONDecoder – singleValueContainer fails with Optional<T> values

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Priority: Medium
    • Resolution: Unresolved
    • Component/s: Foundation
    • Labels:
    • Environment:

      Xcode 9.3

      Swift 4.1

      Description

      JSONEncoder can encode a nil single value Optional<String> as JSON "null", but JSONDecoder does is unable to interpret the null correctly.

      Consider:

       

      struct Foo: Codable {
      	
      	struct Value<T: Codable>: Codable {
      		var value: T
      		
      		init(default def: T) {
      			value = def
      		}
      		
      		init(from decoder: Decoder) throws {
      			let container = try! decoder.singleValueContainer()
      			value = try! container.decode(T.self)
      		}
      		
      		func encode(to encoder: Encoder) throws {
      			var container = encoder.singleValueContainer()
      			try! container.encode(value)
      		}
      	}	
      	
      	var test = Value<String?>(default: nil)
      }
      
      
      
      var f1 = Foo()
      let data = try! JSONEncoder().encode(f1)
      print(String(data: data, encoding: .utf8)!) // {"test":null}
      
      let f2 = try! JSONDecoder().decode(Foo.self, from: data)
      

      When the nil Optional<String> value is encoded, it is encoded as a single-value null as expected.

      {"test":null}

      But when decoding, an error is thrown:

      Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.valueNotFound(Swift.Optional<Swift.String>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "test", intValue: nil)], debugDescription: "Expected Optional<String> but found null value instead.", underlyingError: nil)): file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-902.0.48/src/swift/stdlib/public/core/ErrorType.swift, line 184
      

      Note that when switching singleValueContainer to unkeyedContainer, there is no similar error, but the encoded json then looks like:

      {"test":[null]}

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              swillits Seth Willits
            • Votes:
              1 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated: