基于点注释的Java嵌套POJO更新

基于点注释的Java嵌套POJO更新,java,Java,我有一个嵌套的POJO结构,定义如下 public class Employee { private String id; private Personal personal; private Official official; } 我从一个带有点注释的服务中得到更新,例如 id change --> id=100 address change --> personal.address=123 Main Street hourly salary c

我有一个嵌套的POJO结构,定义如下

public class Employee {
    private String id;
    private Personal personal;
    private Official official;
}



我从一个带有点注释的服务中得到更新,例如

id change --> id=100
address change --> personal.address=123 Main Street 
hourly salary change --> official.salary.hourly=100

该POJO结构的深度可能为3-4层。我需要查找这个传入的更改值,并在POJO中更新相应的值。最好的方法是什么?

如果要创建允许编辑字段的Java对象。可以使用公共/默认/受保护的访问修饰符指定对象字段。这将使您能够获取和设置诸如
个人.地址
官方.工资.小时

这种方法通常不受欢迎,因为对象不再被封装,并且欢迎任何调用方法来操作对象。如果这些字段没有用getter和setter封装,那么对象就不再是
POJO

public
提供从任何地方访问的功能

default
提供从任何包的访问

protected
提供从包或子类的访问

public class Employee {
    public String id;
    public Personal personal;
    public Official official;
}

public class Personal {
    public String fName;
    public String lName;
    public String address;
}

下面是一种使用反射动态设置字段的快速方法。它肯定不是,也不可能是干净的。如果我是你,我会为此使用脚本引擎(假设这样做是安全的)

如果您使用的是setter(甚至可能不是),那么使用LambaMetafactory可能会导致最快的执行。这是我不太熟悉的东西,所以不能提供更多的信息,只有和。尽管您可能需要关于字段的其他信息(我认为输入验证/过滤需要这些信息)
public class Salary {
    private double hourly;
    private double monthly;
    private double yearly;
}
id change --> id=100
address change --> personal.address=123 Main Street 
hourly salary change --> official.salary.hourly=100
public class Employee {
    public String id;
    public Personal personal;
    public Official official;
}

public class Personal {
    public String fName;
    public String lName;
    public String address;
}
private static void setValueAt(Object target, String path, String value) 
        throws Exception {
    
    String[] fields = path.split("\\.");
    if (fields.length > 1) {
        setValueAt(readField(target, fields[0]), 
                path.substring(path.indexOf('.') + 1), value);
        return;
    }

    Field f = target.getClass()
            .getDeclaredField(path);
    f.setAccessible(true);
    f.set(target, parse(value, f.getType())); // cast or convert value first
}

//Example code for converting strings to primitives
private static Object parse(String value, Class<?> type) {
    if (String.class.equals(type)) {
        return value;
    } else if (double.class.equals(type) || Double.class.equals(type)) {
        return Long.parseLong(value);
    } else if (boolean.class.equals(type) || Boolean.class.equals(type)) {
        return Boolean.valueOf(value);
    }
    return value;// ?
}

private static Object readField(Object from, String field) throws Exception {
    Field f = from.getClass()
            .getDeclaredField(field);
    f.setAccessible(true);
    return f.get(from);
}
Employee e = new Employee();
e.setOfficial(new Official());
e.setPersonal(new Personal());
e.getOfficial().setSalary(new Salary());

ObjectMapper mapper = new ObjectMapper();
setValueAt(e, "id", "123");
// {"id":"123","personal":{},"official":{"active":false,"salary":{"hourly":0.0,"monthly":0.0,"yearly":0.0}}}

setValueAt(e, "personal.address", "123 Main Street");
// {"id":"123","personal":{"address":"123 Main Street"},"official":{"active":false,"salary":{"hourly":0.0,"monthly":0.0,"yearly":0.0}}}

setValueAt(e, "official.salary.hourly", "100");
// {"id":"123","personal":{"address":"123 Main Street"},"official":{"active":false,"salary":{"hourly":100.0,"monthly":0.0,"yearly":0.0}}}