";“groovy”;访问嵌套字段的方法

";“groovy”;访问嵌套字段的方法,groovy,Groovy,拿这些东西 class Obj1 { Obj2 obj2 } class Obj2 { Obj3 obj3 } class Obj3 { String tryme } 现在,这个模型上的Crud操作是通过angularjs应用程序进行的。angular应用程序发回更改的字段。例如,它可能会发送 [ { "jsonPath": "/obj2/obj3/tryme", "newValue": "New Name" } ] 那么,使用

拿这些东西

class Obj1 {
  Obj2 obj2
}

class Obj2 {
  Obj3 obj3
}

class Obj3 {
  String tryme
}
现在,这个模型上的Crud操作是通过angularjs应用程序进行的。angular应用程序发回更改的字段。例如,它可能会发送

[
    {
        "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
总是空的,因此我无法得到初始化它的类型


是的,我知道,一旦我弄明白如何使它工作,我就会把它打出来。

也许是这样的

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
您可以创建trait,然后让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");​

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

撇开这些警告不谈,考虑到你有:

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)))]

我一直在做一些类似的工作,基于此,问题是未初始化的字段。当我访问一个未初始化的字段时,我无法确定它应该是什么类型。我现在正在用json slurper进行实验,想如果我接受我的pojo,slurp它,更新它,回滚到pojo。如果我能做到这一点,我可能会一起消除pojo,或者干脆将其用于验证。还不是很确定。你能不能只用
?。
运算符?我不熟悉那个,我是说我知道的点,但问题是,它是做什么的?它是。更新了我的答案以使用它。好的,我明白这是在做什么了。还有我的二传手问题。如果obj2为null,我找不到初始化它的方法。这里的方法1:?我现在正在尝试类似的方法,但是我对未初始化的字段有问题。我现在正在尝试json方法。我即将放弃,转而使用传统的地图迭代器地图。我想用groovy做这件事会更容易,这让我明白。它应该是。。。你能编辑你的问题来表达你的意思吗?第二天早上,当我手边有一台电脑时,我会看一看:-)