以编程方式生成JSONPath或类似于案例类

时间:2017-03-16 23:26:58

标签: scala reflection shapeless jsonpath

我想从给定的case类本身生成所有可能的JSONPath,而不是case类的实例(最好)。

简单嵌套的简单案例类:

case class Inner(innerA: String, innerB: String, innerC: String)
case class TestCase(a: String, b: String, inner: Inner)

对于TestCase,我想制作(更喜欢声明顺序,但不是必须的):

root.a
root.b
root.inner
root.inner.innerA
root.inner.innerB
root.inner.innerC

或者可以轻松转换为有效JSONPath的内容。这样做的目的是为了在Scala中定义多个case class,并为用户提供可用于提取信息的有效JSONPath列表。

现在,做起来没有问题:

  1. case class到JSON
  2. JSON到case class
  3. 使用gatlinghereJsonPath.query(jsonPathString, jsonObj)
  4. 从JSON通过JSONPath(作为字符串)检索值

    使用circe看起来我可以更进一步做root.inner.innerA(请参阅here)并获取/设置值。但是,我无法弄清楚如何使用circegatling生成JSONPath列表(这感觉就像与这些库提供的内容相反)。

    我能想到的另一种选择是递归地通过classOf[TestCase].getDeclaredFields。进一步搜索产生:

    1. Scala. Get field names list from case class
    2. Scala 2.10 reflection, how do I extract the field values from a case class
    3. 然而,看起来我仍然需要递归遍历每个字段,看看是否有任何嵌套。这是最好的方法吗?

      样品:

      • 案例类实例:TestCase(a = "alpha", "beta", inner = Inner(innerA = "innerAlpha", innerB = "innerBeta", innerC = "foo"))
      • 上面制作的JSON:{"a":"alpha","b":"beta","inner":{"innerA":"innerAlpha","innerB":"innerBeta","innerC":"foo"}}
      • JSONPath评估者:http://jsonpath.com/(例如$.inner.innerA

      当前解决方案(?):

      def recursive(members: MemberScope, parent: String): Unit = {
        members.foreach { member =>
          member match {
            case m: MethodSymbol if m.isCaseAccessor =>
              println(s"$parent.${m.name}")
              recursive(m.returnType.members, s"$parent.${m.name}")
            case _ =>
          }
        }
      }
      
      recursive(typeOf[TestCase].members, "$")
      

      产生:

      $.inner
      $.inner.innerC
      $.inner.innerB
      $.inner.innerA
      $.b
      $.a
      

      编辑:据说没有形状可以做到这一点,但我还没弄明白。

0 个答案:

没有答案