title: Generic derivation for ADTs in Scala with a custom representation
body: <p>I'm paraphrasing <a href="https://gitter.im/circe/circe?at=5b88c203f5402f32aab7047a" rel="noreferrer">a question from the circe Gitter channel</a> here.</p>
  
  <p>Suppose I've got a Scala sealed trait hierarchy (or ADT) like this:</p>
  
  <pre><code>sealed trait Item
  case class Cake(flavor: String, height: Int) extends Item
  case class Hat(shape: String, material: String, color: String) extends Item
  </code></pre>
  
  <p>…and I want to be able to map back and forth between this ADT and a JSON representation like the following:</p>
  
  <pre><code>{ "tag": "Cake", "contents": ["cherry", 100] }
  { "tag": "Hat", "contents": ["cowboy", "felt", "black"] }
  </code></pre>
  
  <p>By default circe's generic derivation uses a different representation:</p>
  
  <pre><code>scala&gt; val item1: Item = Cake("cherry", 100)
  item1: Item = Cake(cherry,100)
  
  scala&gt; val item2: Item = Hat("cowboy", "felt", "brown")
  item2: Item = Hat(cowboy,felt,brown)
  
  scala&gt; import io.circe.generic.auto._, io.circe.syntax._
  import io.circe.generic.auto._
  import io.circe.syntax._
  
  scala&gt; item1.asJson.noSpaces
  res0: String = {"Cake":{"flavor":"cherry","height":100}}
  
  scala&gt; item2.asJson.noSpaces
  res1: String = {"Hat":{"shape":"cowboy","material":"felt","color":"brown"}}
  </code></pre>
  
  <p>We can get a little closer with circe-generic-extras:</p>
  
  <pre><code>import io.circe.generic.extras.Configuration
  import io.circe.generic.extras.auto._
  
  implicit val configuration: Configuration =
     Configuration.default.withDiscriminator("tag")
  </code></pre>
  
  <p>And then:</p>
  
  <pre><code>scala&gt; item1.asJson.noSpaces
  res2: String = {"flavor":"cherry","height":100,"tag":"Cake"}
  
  scala&gt; item2.asJson.noSpaces
  res3: String = {"shape":"cowboy","material":"felt","color":"brown","tag":"Hat"}
  </code></pre>
  
  <p>…but it's still not what we want.</p>
  
  <p>What's the best way to use circe to derive instances like this generically for ADTs in Scala?</p>