trait StringWrites[-A] { def writes(o: A): String } object StringWrites { def apply[A](f: A => String): StringWrites[A] = new StringWrites[A] { def writes(a: A): String = f(a) } } implicit def mapWrites[K, V](implicit kFmt: StringWrites[K], vFmt: Writes[V]) = Writes[Map[K, V]] { map => JsObject(map.map { case (k, v) => (kFmt.writes(k), vFmt.writes(v)) }.toSeq) } case class UserId(value: String) extends AnyVal implicit val userIdFmt: StringWrites[UserId] = StringWrites[UserId] { userId => userId.value } implicit val userIdJsFmt = Json.format[UserId] val map = Map(UserId("one") -> UserId("asd")) //{"one":{"value":"asd"}}