title: Using flatMap with dictionaries produces tuples?
body: <p>I have this pretty basic and straight forward mapping of an object into dictionary. I am using and parsing dictionary on the top level. One of its fields is an array of other dictionaries. To set them I use <code>flatMap</code> which seems an appropriate method but since the object inside is not nullable this method suddenly returns tuples (at least it seems that way) instead of dictionaries. </p>
  
  <p>I created a minimum example that can be pasted into a new project pretty much anywhere any of your execution occurs which should give better detail then any description:</p>
  
  <pre><code>func testFlatMap() -&gt; Data? {
  
      class MyObject {
          let a: String
          let b: Int
          init(a: String, b: Int) { self.a = a; self.b = b }
  
          func dictionary() -&gt; [String: Any] {
              var dictionary: [String: Any] = [String: Any]()
              dictionary["a"] = a
              dictionary["b"] = b
              return dictionary
          }
      }
  
      let objects: [MyObject] = [
          MyObject(a: "first", b: 1),
          MyObject(a: "second", b: 2),
          MyObject(a: "third", b: 3)
      ]
  
      var dictionary: [String: Any] = [String: Any]()
      dictionary["objects"] = objects.flatMap { $0.dictionary() }
      dictionary["objects2"] = objects.map { $0.dictionary() }
  
      print("Type of first array: " + String(describing: type(of: dictionary["objects"]!)))
      print("Type of first element: " + String(describing: type(of: (dictionary["objects"] as! [Any]).first!)))
  
      print("Type of second array: " + String(describing: type(of: dictionary["objects2"]!)))
      print("Type of second element: " + String(describing: type(of: (dictionary["objects2"] as! [Any]).first!)))
  
      return try? JSONSerialization.data(withJSONObject: dictionary, options: [])
  }
  _ = testFlatMap()
  </code></pre>
  
  <p>So this code crashes saying </p>
  
  <blockquote>
    <p>'NSInvalidArgumentException', reason: 'Invalid type in JSON write
    (_SwiftValue)'</p>
  </blockquote>
  
  <p>(Using do-catch makes no difference which is the first WTH but let's leave that for now)</p>
  
  <p>So let's look at what the log said:</p>
  
  <pre><code>Type of first array: Array&lt;(key: String, value: Any)&gt;
  Type of first element: (key: String, value: Any)
  Type of second array: Array&lt;Dictionary&lt;String, Any&gt;&gt;
  Type of second element: Dictionary&lt;String, Any&gt;
  </code></pre>
  
  <p>The second one is what we expect but the first just has tuples in there. Is this natural, intentional?</p>
  
  <p>Before you go all out on "why use flatMap for non-optional values" let me explain that <code>func dictionary() -&gt; [String: Any]</code> used to be <code>func dictionary() -&gt; [String: Any]?</code> because it skipped items that were missing some data. </p>
  
  <p>So only adding that little <code>?</code> at the end of that method will change the output to:</p>
  
  <pre><code>Type of first array: Array&lt;Dictionary&lt;String, Any&gt;&gt;
  Type of first element: Dictionary&lt;String, Any&gt;
  Type of second array: Array&lt;Optional&lt;Dictionary&lt;String, Any&gt;&gt;&gt;
  Type of second element: Optional&lt;Dictionary&lt;String, Any&gt;&gt;
  </code></pre>
  
  <p>which means the first solution is the correct one. And on change there are no warnings, no nothing. The app will suddenly just start crashing.</p>
  
  <p>The question at the end is obviously "How to avoid this?" without too much work. Using <code>dictionary["objects"] = objects.flatMap { $0.dictionary() } as [[String: Any]]</code> seems to do the trick to preserve one-liner. But using this seems very silly.</p>