John Sullivan
John Sullivan

Reputation: 1311

Scala dynamic tuple type construction from sequence

I'm trying to generate some json using the json4s library which builds json using a dsl based around nested tuple structures. I have a scala Seq that I'd like to be able to convert to a nesting of tuples like so:

// scala Seq
val s = Seq("a", "b", "c", "d")
val rootItem = "id" -> 1234
// desired json
{
  "a" : {
    "b" : {
      "c" : {
        "d" : {
          "id" : 1234
        }
      }
    }
  }
}

If I force it to ignore the types I can produce the desired tuple structure as follows:

// yields ("a", ("b", ("c", ("d", ("id", 1234)))))
s.foldRight[Any](rootItem)(_ -> _) 

but because the type of the result is now denoted as Any the implicit conversion that write this to json don't fire (and throw an exception when called explicitly) despite the actual type being correct. I'm at a loss for how to construct this datastructure in a typesafe way. Ideally I'd like a solution that is able to appropriately build up the type, though I understand that it might be impossible since it requires information only available at runtime (the length of the list). I know that scala supports recursive types, which seem to potentially fit the bill but I haven't been able to understand how to work them in this case and don't know if they are safe for a 'real' system.

Upvotes: 1

Views: 1003

Answers (1)

Travis Brown
Travis Brown

Reputation: 139028

You're not going to be able to do this with a plain old fold, since the accumulator has to be the same type the whole time.

You can make the transformation to JSON as you go, however:

val s = Seq("a", "b", "c", "d")
val rootItem = "id" -> 1234

import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.jackson.JsonMethods._

val json = s.foldRight[JObject](rootItem)(_ -> _)

And then you can do the following, since json is statically typed as a JObject:

scala> pretty(render(json))
res0: String = 
{
  "a" : {
    "b" : {
      "c" : {
        "d" : {
          "id" : 1234
        }
      }
    }
  }
}

(As a footnote, there is a way you could do the fold with tuples and end up with the appropriate static type, but that's almost certainly not what you want in this case.)

Upvotes: 1

Related Questions