简体   繁体   中英

how to parse postman-collection?

Goal :

I am trying to parse the postman_echo collection json and persist the result into a new json copy on disk, resulting the same file as the original one.

I prefer built-in data structure from the language, but using json library should be good too. Not sure Antlr4 is a better way.

follow-up question
is it possible to allow any valid nested json in the body of post request?

update: https://github.com/chakpongchung/postman-parser In the end we come up with this satisfactory solution.

An alternative to what zoran mentioned is to create a case class if the structure is not too dynamic (with Play JSON). This would make it easier to compare the result.

case class MyObject(
  queryString: List[KeyValue],
  method: String,
  url: String,
  httpVersion: String
) ... and so on

object MyObject {
    implicit val format: Format[MyObject] = Json.format
}

case class KeyValue(name: String, value: String)

object KeyValue {
    implicit val format: Format[KeyValue] = Json.format
}

Then, you just need to do:

object JsonParser extends App {
  val postman_collections = "./scala_input.json"
  val jsonifiedString = scala.io.Source.fromFile(postman_collections).mkString

  val myJsonData = Try(Json.parse(jsonifiedString)).map(_.as[MyObject])

  myJsonData match {
    case Success(myValue) => // compare your case class here
    case Failure(err) => println("none")
  }
}

There are multiple problems in your parser and most of them are that you are trying to use default parser to handle Json object as string. For example, in Request you are handling header as Seq[String] when it's actually Seq of (key, value) pairs. For this particular case, you should change it to something like this:

case class Request(
                method: String,
                header: Seq[HeaderItem], // header: []
                url: Option[Url] = None,
                description: String = ""
              )
object Request {
   implicit val format: Format[Request] = Json.using[Json.WithDefaultValues].format

case class HeaderItem(key: String, value: String)

object HeaderItem {
   implicit val format: Format[HeaderItem] = Json.format
 }

You can convert header to Seq[String] if you want, but you will have to write custom Read for that. In the above case you also have cases when description is missing, so you want to handle that with default values. You have such problems to handle in few other places as well, eg "response".

Another problem that I've noticed is a way how you handle "type" property from Json string. Type is reserved keyword, and you can handle it by wrapping it in ``, eg

case class Script(
    `type`: String,
     exec: Seq[String]
)

I'm not sure if I understand your question well, but if you are trying to iterate over json string, you might try something like this:

  import play.api.libs.json.{JsObject, JsValue, Json}
  import scala.util.{Failure, Success, Try}


  object JsonParser extends App {
    val postman_coolections = "./resources/scala_input.json"
    val jsonifiedString = scala.io.Source.fromFile(postman_coolections).mkString

    val json: JsValue = Try(Json.parse(jsonifiedString)) match {
      case Success(js) => js
      case Failure(ex) => throw new Exception("Couldn't parse json", ex)
   }
 json.asInstanceOf[JsObject].fields.foreach{
   case (key: String, value: JsValue)=>
      println(s"Key:$key value:${value.toString}")
      writeFile(s"$key.json", Json.prettyPrint(value))
 }

//writing the whole postman input as a single file

writeFile("postmanInputFormatted.json", Json.prettyPrint(json))
writeFile("postmanInput.json", Json.stringify(json))

// To access individual property one option is to use this approach

val lookedValue = json \ "postData" \ "params" \ 1 \ "hello" \ "test"

lookedValue match {
  case JsDefined(value) => println(s"Test value is $value")
  case JsUndefined() => println("Didn't find test value")
}
// or
val lookedValueAlt = (json \ "postData" \ "params" \ 1 \ "hello" \ "test").getOrElse(throw SomeException)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM