title: How to transform a named JsArray into a JsObject with JsZipper
body: <p>Let's assume either of the following two JSON snippets:</p>
  
  <pre><code>{ "include": ["field1", "field2", "fieldN"] }
  { "exclude": ["field1", "field2", "fieldN"] }
  </code></pre>
  
  <p>I need to transform the <code>include</code> array like this...</p>
  
  <pre><code>{ "field1": 1, "field2": 1, "fieldN": 1 }
  </code></pre>
  
  <p>... and the <code>exclude</code> array like this:</p>
  
  <pre><code>{ "field1": 0, "field2": 0, "fieldN": 0 }
  </code></pre>
  
  <p>[Just for your info: I need to transform input JSON into Mongo's projections.]</p>
  
  <p>Here below is my current solution &ndash; I've implemented it as a <code>JsValue</code> extension:</p>
  
  <pre><code>object testTypeExtensions {
  
    implicit class TestJsExtensions(val json: JsValue) extends AnyVal {
  
      def toProjection: JsValue = {
        if (json \\ "include" nonEmpty)
          JsObject(for (field &lt;- (json \ "include").as[List[JsString]])
          yield (field.value, JsNumber(1)))
        else if (json \\ "exclude" nonEmpty)
          JsObject(for (field &lt;- (json \ "exclude").as[List[JsString]])
          yield (field.value, JsNumber(0)))
        else Json.obj()
      }
    }
  }
  </code></pre>
  
  <p>The code above works...</p>
  
  <pre><code>scala&gt; val p = Json.obj("exclude" -&gt; Json.arr("field1", "field2"))
  p: play.api.libs.json.JsObject = {"exclude":["field1","field2"]}
  
  scala&gt; p.toProjection
  res12: play.api.libs.json.JsObject = {"field1":0,"field2":0}
  </code></pre>
  
  <p>... but I'm sure it could be written much better with <code>JsZipper</code>.</p>
  
  <p>Furthermore it is not very flexible since it only manages the <code>include</code> and <code>exclude</code> keys, whereas I want to also manage other similar cases like sorting objects:</p>
  
  <pre><code>{ "asc": ["field1", "field2"] }
  { "desc": ["field1", "field2"] }
  </code></pre>
  
  <p>... transformed into...</p>
  
  <pre><code>{ "field1": 1, "field2": 1 }
  </code></pre>
  
  <p>... and</p>
  
  <pre><code>{ "field1": -1, "field2": -1 }
  </code></pre>
  
  <p>That said, what I've in mind is a generic method that manages any kind of named JSON array like:</p>
  
  <pre><code>object testypeExtensions {
  
    implicit class TempJsExtensions(val json: JsValue) extends AnyVal {
  
      def namedArrayToObject(keys: String*): JsValue = {
        // how to implement it, possibly with JsZipper
      }
  
    }
  }
  </code></pre>
  
  <p>The <code>namedArrayToObject</code> method should search for the specified <code>keys</code> in the current JSON and generate an object for the <strong>first match</strong> like the ones I described at the beginning of this post, possibly with <code>JsZipper</code>. Here is a simulation of the expected results.</p>
  
  <p>Search for <code>exclude</code> and <code>include</code> and return the first match as a <code>JsObject</code>:</p>
  
  <pre><code>scala&gt; val p = Json.obj("exclude" -&gt; Json.arr("field1", "field2"))
  scala&gt; p.namedArrayToObject("exclude", "include")
  res12: play.api.libs.json.JsObject = {"field1":0,"field2":0}
  </code></pre>
  
  <p>Same as before... but now input JSON contains <code>include</code> instead of <code>exclude</code>:</p>
  
  <pre><code>scala&gt; val p = Json.obj("include" -&gt; Json.arr("field1", "field2"))
  scala&gt; p.namedArrayToObject("exclude", "include")
  res12: play.api.libs.json.JsObject = {"field1":1,"field2":1}
  </code></pre>
  
  <p>Search for <code>asc</code> and <code>desc</code> and return the first match as a <code>JsObject</code>:</p>
  
  <pre><code>scala&gt; val p = Json.obj("desc" -&gt; Json.arr("field1", "field2"))
  scala&gt; p.namedArrayToObject("asc", "desc")
  res12: play.api.libs.json.JsObject = {"field1":-1,"field2":-1}
  </code></pre>
  
  <p>... and so on.</p>
  
  <p>If there is no match, <code>namedArrayToObject</code> should return an empty <code>JsObject</code>. Any suggestion  on how to implement this in the right way would be very appreciated.</p>