如何解析邮递员收藏?

时间:2019-11-16 18:45:55

标签: javascript java python json scala

目标

我正在尝试解析postman_echo集合json,并将结果持久保存到磁盘上的新json副本中,从而得到与原始文件相同的文件。

(实际上,我最初的问题是将邮递员收藏转换为其他格式。但是,如果我可以将邮递员收藏解析为新的副本,那么我的原始问题就可以简化为此发布的问题)

如何测试
成功解析之后,您应该能够使用解析结果来构造json的新副本,然后将其写入磁盘,从而得到相同的json文件。

我更喜欢语言中的内置数据结构,但是使用json库也应该很好。不确定Antlr4是不是更好的方法。

一些帮助

以下是基本的scala代码,您可能会从以下内容开始有所帮助: https://github.com/chakpongchung/postman-parser

您还可以通过提供邮递员集合json文件,使用此工具为您生成案例类: https://transform.tools/json-to-scala-case-class

后续问题
是否可以在发布请求的正文中允许任何有效的嵌套json?

3 个答案:

答案 0 :(得分:1)

解析器中存在多个问题,其中大多数是您尝试使用默认解析器将Json对象作为字符串处理。例如,在Request中,当实际上是(键,值)对的Seq时,您将标头作为Seq [String]处理。对于这种特殊情况,您应该将其更改为以下内容:

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
 }

如果需要,可以将标头转换为Seq [String],但是您必须为此编写自定义Read。 在上述情况下,您还会遇到缺少描述的情况,因此您希望使用默认值进行处理。 您在其他一些地方也有此类问题需要解决,例如“响应”。

我注意到的另一个问题是如何处理Json字符串中的“ type”属性。 Type是保留关键字,您可以通过将其包装在``中来处理它,例如

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

答案 1 :(得分:0)

我不确定我是否很好地理解了您的问题,但是如果您尝试遍历json字符串,则可以尝试如下操作:

  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)

答案 2 :(得分:0)

zoran提到的一种替代方法是,如果结构不是太动态(使用Play JSON),则创建一个case类。这样可以更轻松地比较结果。

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
}

然后,您只需要执行以下操作:

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")
  }
}