1
votes

I'm writing a simple scala application that opens a flat file of json data, parses it and finally prints it out to the screen.

The next step will require that I stop at each object and add another item (string) to the front of it. My question is how can I add a new string per object in this list?

The following is my JSON implementation (credit goes to the init author here)

import scala.util.parsing.combinator._

class JSON extends JavaTokenParsers {
        def obj: Parser[Map[String, Any]] =
                "{"~> repsep(member, ",") <~"}" ^^ (Map() ++ _)

        def arr: Parser[List[Any]] =
                "["~> repsep(value, ",") <~"]"

        def member: Parser[(String, Any)] =
                stringLiteral~":"~value ^^
                        { case name~":"~value => (name, value) }

        def value: Parser[Any] = (
                obj
                | arr
                | stringLiteral
                | floatingPointNumber ^^ (_.toInt)
                | "null" ^^ (x => null)
                | "true" ^^ (x => true)
                | "false" ^^ (x => false)
                )
}

Next I call this w/ a flat file like so

import java.io.FileReader
import scala23.JSON

class JSONTest extends JSON {
        def main(args: String) {
                val reader = new FileReader(args)
                println(parseAll(value, reader))
        }
}

Then I get a valid println of the json contents. Instead I would like to pass this parse method a String and have it append it or create a new json object that has the string at the front of each object inside

Update

My current attempt looks something like the below

class JSONTest extends JSON {
  def main(args: String) {
    val reader = new FileReader(args)
    val header = ("abc", "def")
//    println(parseAll(value, reader).map(addHeader(_, header)))
    println(parseAll(value, reader).map(addHeader(_.asInstanceOf[Map[String, Any]], header)))
  }
  def addHeader(xyz:Map[String, Any], header:(String, Any)):Map[String, Any] = {
    xyz.map {
      case (k, m:Map[String, Any]) => (k, addHeader(m))
      case e => e
    } + header
  }
}

But I'm currently getting a few errors in Intellij

error: missing parameter type for expanded function ((x$1) => x$1.asInstanceOf[Map[String, Any]]) println(parseAll(value, reader).map(addHeader(_.asInstanceOf[Map[String, Any]], header)))

AND

error: not enough arguments for method addHeader: (xyz: Map[String,Any],header: (String, Any))Map[String,Any]. Unspecified value parameter header. case (k, m:Map[String, Any]) => (k, addHeader(m))

Any help would be much appreciated (thank you in advance!)

1

1 Answers

0
votes

Have you tried using map on the parser output instead.

Edit: this compiles on my machine

import java.io.FileReader
import scala23.JSON


class JSONTest extends JSON {
  def main(args: String) {
    val reader = new FileReader(args)
    val header = ("abc", "def")
//    println(parseAll(value, reader).map(addHeader(_, header)))
    println(parseAll(value, reader).map(addHeader(_, header)))
  }
  def addHeader(xyz:Any, header:(String, Any)):Any = xyz match {
    case obj:Map[String, Any] => obj.map {
      case (k, m:Map[String, Any]) => (k, addHeader(m, header))
      case e => e
    } + header
    case arr:List[Any] => arr.map(addHeader(_, header))
    case e => e
  }
}

It should be handling the varied output of the parse better.