" groovy"访问嵌套字段的方式

时间:2017-03-27 17:31:02

标签: groovy

采取这些对象

class Obj1 {
  Obj2 obj2
}

class Obj2 {
  Obj3 obj3
}

class Obj3 {
  String tryme
}

现在,这个模型的Crud操作正在通过angularjs应用程序发生。角度应用程序发回更改的字段。例如,它可以发送

[
    {
        "jsonPath": "/obj2/obj3/tryme",
        "newValue": "New Name"
    }
]

所以使用groovy,是否有一种简单的方法来访问该嵌套字段?我可以用java反射来做,但这就是很多代码。如果不是pojo的话,这是一个mongodb,所以我想我可以用json slurp这样做,如果它更容易,我只是不知道。任何建议表示赞赏。

所以要显示到目前为止我找到的解决方案的问题。拿这个

Obj1 a = new Obj1​()

使用此

的编辑对象
[
    {
        "jsonPath": "/obj2/obj3/tryme",
        "newValue": "New Name"
    }
]

执行pojo路由,找到obj2的空字段不是问题。问题是我无法知道它是什么类型,以初始化字段并继续走树。

请不要使用Groovy没有类型,我们不会在这里使用def,所有内容都需要静态输入。

所以我也是从JsonSlurp方面尝试这个,只是消除了pojo。但即便如此,这也是有问题的,因为我似乎又回到了迭代地图的地图来到达现场。同样的问题,更容易解决。

class MongoRecordEditor {

  def getProperty(def object, String propertyPath) {
    propertyPath.tokenize('/').inject object, {obj, prop ->
      def retObj = obj[prop]
      if (retObj == null){
        println obj[prop].class
      }
    }
  }

  void setProperty(def object, String propertyPath, Object value) {
    def pathElements = propertyPath.tokenize('/')

    def objectField
    if (pathElements.size() == 1){
      objectField = pathElements[0]
    } else {
      objectField =  pathElements[0..-2].join('/')
    }

    Object parent = getProperty(object, objectField)

    parent[pathElements[-1]] = value
  }
}

是许多想法的顶点。现在让def retObj = obj[prop]运行是件小事。问题是,如果字段没有被初始化,那么retObj总是为空,因此我无法获得它应该初始化它的类型。

是的,我知道,一旦我弄清楚如何使它工作,我会输入它。

2 个答案:

答案 0 :(得分:1)

也许是这样的?

class Obj1 {
    Obj2 obj2
}  

class Obj2 {
    Obj3 obj3
}  

class Obj3 {
    String tryme
}

def a = new Obj1​(obj2: new Obj2(obj3: new Obj3(tryme:"test")))

for (value in "obj2/obj3/tryme".split("/")) {     
    a = a?."${value}"
}

println a

您可以创建特征,然后让Obj1使用它:

trait DynamicPath {
    def get(String path) {
        def target = this
        for (value in path.split("/")) {     
            target = target?."${value}"
        }
        target
    }
}

​class Obj1 implements DynamicPath{
    Obj2 obj2
}  

println a.get("obj2/obj3/tryme");​

答案 1 :(得分:0)

不确定这是否是您想要的......并且它依赖于具有默认构造函数的对象,并且可能有更好的方法来实现它...

除了这些警告,给你:

import groovy.transform.*
import groovy.json.*

@ToString
class Obj1 {
  Obj2 obj2
}

@ToString
class Obj2 {
  Obj3 obj3
}

@ToString
class Obj3 {
  String tryme
}

def changeRequest = '''[
    {
        "jsonPath": "/obj2/obj3/tryme",
        "newValue": "New Name"
    }
]'''

然后,您可以像这样定义一个操纵器:

def change(Object o, String path, String value) {
   Object current = o
   String[] pathElements = path.split('/').drop(1)
   pathElements[0..-2].each { f ->
       if(current."$f" == null) {
           current."$f" = current.class.declaredFields.find { it -> f == it.name }?.type.getConstructor().newInstance()
       }
       current = current."$f"
   }
   current."${pathElements[-1]}" = value
   o
}

并称之为

def results = new JsonSlurper().parseText(changeRequest).collect {
    change(new Obj1(), it.jsonPath, it.newValue)
}

为您提供包含一个新的Obj1实例的列表:

[Obj1(Obj2(Obj3(New Name)))]