将对象属性复制到Groovy中的另一个对象 [英] Copy object properties to another object in Groovy

查看:274
本文介绍了将对象属性复制到Groovy中的另一个对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用了一种时髦的方式来执行此操作:
https://stackoverflow.com/a/9072974 / 4470135
所以我的代码是:

  def copyProperties(source,target){
def(sProps,tProps)= [source,target] *。properties * .keySet()
def commonProps = sProps.intersect(tProps) - ['class','metaClass']
commonProps。每个{target [it] = source [it]}
}

我尝试调用一个应该将实体转换为Dto的方法:

lockquote

没有方法的签名:java.util.ArrayList.keySet ()适用于
参数类型:()values:[] \ n可能的解决方案:toSet(),
toSet(),set(int,java.lang.Object),set(int, java.lang.Object),
get(int),get(int)

UPDATE:



我的源代码是一个带有字段的可序列化bean:

  private String passengerName; 
@NotNull
@Size(min = 5,max = 40)
private String destination;
@NotNull
private String departureDate;

我的目标是具有相同字段的JPA实体,但带有额外的@Id字段和稍微不同的日期表示:

  @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
ZonedDateTime departureDate


解决方案

代码正在工作,但是,有些情况可能会中断。 为了解决这个问题,使用方法调用 getProperties()来替换属性访问属性 / code>,这可能足以满足您的需求。为了涵盖所有情况,您需要编写特殊案例的代码(见底部)。

原始版本的工作示例


$ b $

  def copyProperties(source,target){
def(sProps,tProps)= [source,target] *。properties * .keySet ()
def commonProps = sProps.intersect(tProps) - ['class','metaClass']
commonProps.each {target [it] = source [it]}
}

def a = new Expando()
a.foo =foo
a.bar =bar

def b = new Expando()
b.baz =baz
b.bar =old

copyProperties(a,b)

println b

导致问题的示例

如果参数有一个名为属性的属性,我会得到同样的异常(如果值为 List ):

  def c = new Expando()
c.properties = []
c.bar = bar

def d = new Expando()
d.baz = baz
d.bar =old

copyProperties(c,d)

println d

这两种情况都适用:

  def copyProperties(source ,target){
def(sProps,tProps)= [source,target] *。getProperties()* .keySet()
def commonProps = sProps.intersect(tProps) - ['class',' metaClass']
commonProps.each {target [it] = source [it]}
}

不是我在这里使用了对 getProperties 的显式调用,而不是访问属性属性。 / p>

我们仍然可以解决这个问题

  def e = new Object(){
//再次导致相同的异常
def getProperties(){
return []
}

def bar = bar
}

def f = new Expando()
f.baz =baz
f.bar =old

copyProperties(e,f)

您可以修复最后一页通过显式使用metaClass e 的例子

  def copyProperties(source,目标){
def(sProps,tProps)= [source,target] *。getMetaClass()*。properties * .name
def commonProps = sProps.intersect(tProps) - ['class',' metaClass']
commonProps.each {target [it] = source [it]}
}

但是,由于 f

处理特殊情况

$ pre $ def $ get b $ b $ get

$ obj.getProperties()。keySet()
}
$ b $ getProperties(Object obj){
return obj.getMetaClass()*。properties * .name
}

def copyProperties(source ,target){
def(sProps,tProps)= [source,target] .collect {getProperties(it)}
def commonProps = sProps.intersect(tProps) - ['class','metaClass' ]
commonProps.each {target [it] = source [it]}
}

这里我们给出需要特殊处理的对象;)
请注意,这只适用于使用 @CompileDynamic 作为 getProperties 实现被调用的决定将在运行时进行。替代方案是针对所有情况使用 instanceof 进行检查。


I was using a funky way to do it suggested in: https://stackoverflow.com/a/9072974/4470135 So my code is:

def copyProperties(source, target) {
    def (sProps, tProps) = [source, target]*.properties*.keySet()
    def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
    commonProps.each { target[it] = source[it] }
}

What I get when I try to call a method that should convert an Entity into a Dto is:

No signature of method: java.util.ArrayList.keySet() is applicable for argument types: () values: []\nPossible solutions: toSet(), toSet(), set(int, java.lang.Object), set(int, java.lang.Object), get(int), get(int)

UPDATE:

My source is a Serializable bean with fields:

private String passengerName;
@NotNull
@Size(min = 5, max = 40)
private String destination;
@NotNull
private String departureDate;

My target is a JPA Entity with the same fields, but with an additional @Id field and a slightly different date representation:

@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
ZonedDateTime departureDate  

解决方案

The code is working, however, there are corner cases where it may break.

To fix this replace the property access properties with the method call getProperties(), which might be enough for your case. To cover all cases, you will need to write code for special cases (see bottom)

Working example for the original version

def copyProperties(source, target) {
    def (sProps, tProps) = [source, target]*.properties*.keySet()
    def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
    commonProps.each { target[it] = source[it] }
}

def a = new Expando()
a.foo = "foo"
a.bar = "bar"

def b = new Expando()
b.baz = "baz"
b.bar = "old"

copyProperties(a, b)

println b

Example causing problems

If the parameters have a property called properties I get the same exception you got (if the value is a List):

def c = new Expando()
c.properties = []
c.bar = "bar"

def d = new Expando()
d.baz = "baz"
d.bar = "old"

copyProperties(c, d)

println d

What works in both cases:

def copyProperties(source, target) {
    def (sProps, tProps) = [source, target]*.getProperties()*.keySet()
    def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
    commonProps.each { target[it] = source[it] }
}

Not that here I used an explicit call to getProperties rather than just accessing the properties property.

We can still break this

def e = new Object() {
    // causes same Exception again
    def getProperties() {
        return []
    }

    def bar = "bar"
}

def f = new Expando()
f.baz = "baz"
f.bar = "old"

copyProperties(e, f)

You can fix the last example for e by using the metaClass explicitly

def copyProperties(source, target) {
    def (sProps, tProps) = [source, target]*.getMetaClass()*.properties*.name
    def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
    commonProps.each { target[it] = source[it] }
}

However, that will fail due to f.

Handle special cases

def getProperties(Expando obj) {
    return obj.getProperties().keySet()
}

def getProperties(Object obj) {
    return obj.getMetaClass()*.properties*.name
}

def copyProperties(source, target) {
    def (sProps, tProps) = [source, target].collect {getProperties(it)}
    def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
    commonProps.each { target[it] = source[it] }
}

Here we give objects that need a special treatment what they need ;) Note that this only works like this for groovy with @CompileDynamic as the decision which getProperties implementation is called will be made at runtime. The alternative is a check with instanceof for all the cases.

这篇关于将对象属性复制到Groovy中的另一个对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆