在开发时,遇到这样一个问题,问题如下:
原始数据如下,
JSONObject jo = new JSONObject();
jo.put("head", "This is ms");
JSONArray ja = new JSONArray();
Student student = new Student(1, "ms", null, new Date(), new Date());
ja.add(student);
jo.put("body", ja);
需求如下
不改变当前对象的前提下,用它克隆出一个名叫 lm/lx 的学生,当然数据量很大,所以循环去重新给每个键赋值不现实,且对象层层嵌套,还有多个长数组,
如果你有一定的基础,就会知道,如果我们直接按如下操作的话,会导致原数据跟着发生改变
JSONObject lm = new JSONObject();
// 赋值,相当于clone
lm.putAll(jo);
lm.put("head","this is lm");
JSONArray lmbody = lm.getJSONArray("body");
lmbody.forEach((stu) -> {
Student stu1 = (Student) stu;
stu1.setName("lm");
});
查看输出
System.out.println(lm.toString());
// {"head":"this is lm","body":[{"birth":1650962965320,"id":1,"name":"lm","workStart":1650962965320}]}
System.out.println(jo.toString());3
// {"head":"This is ms","body":[{"birth":1650962965320,"id":1,"name":"lm","workStart":1650962965320}]}
// 这里head不一样是因为head是不共享地址的,因为他们是临时声明的
这是因为,两对象虽然有自己的地址,但是为了节省空间,他们再赋值时,将对象的地址赋给了新对象,所以改变新对象的值时,源数据也会跟随发生改变。
它们之间的关系就类似下面这样
所以不管你修改哪个JSONObject对象,另外一个都会跟着发生改变,这也叫浅拷贝,所以目前问题就是,如何复制一份源数据,且不引用源数据地址,即如何实现JSONObject的深拷贝。
解决方案如下
递归复制,这也是最普遍的深拷贝的实现方式,很麻烦。
先将JSONObject转换成String,再new一个String,然后将新的String转换成JSONObject,在修改即可
其实在百度的时候,发现js中的Json也是通过类似的方式实现的(stringify)。
具体实现
// 先将JSONObject转换成String
String s = jo.toString();
JSONObject newjo = JSONObject.parseObject(s);
newjo.put("head","this is lm");
JSONArray body = newjo.getJSONArray("body");
body.forEach((stu) -> {
JSONObject object = ((JSONObject) stu);
object.put("name","lm");
});
输出查看
System.out.println(newjo.toString());
// {"head":"this is lm","body":[{"workStart":1650961569176,"name":"lm","birth":1650961569176,"id":1}]}
System.out.println(jo.toString());
{"head":"This is ms","body":[{"birth":1650961569176,"id":1,"name":"lm","workStart":1650961569176}]}
你以为这就完事了嘛?其实也确实差不多,如果你的数据没有涉及以下数据类型的话。
- 时间 在JSONObject转化成String后,时间类型的数据会转化成时间戳
- null 在JSONObject转化成String后,null值的key会消失的哦,但是这不影响取值,因为你按照空值的key取值取到的仍然是null,
如下实例
JSONObject jo = new JSONObject();
jo.put("head", "This is ms");
jo.put("time",new Date());
jo.put("null值",null);
// 打印查看
{"head":"This is ms","time":1650963827472}
静态类Student
static final class Student {
private Integer id;
private String name;
private String sex;
private Date birth;
private Date workStart;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Date getWorkStart() {
return workStart;
}
public void setWorkStart(Date workStart) {
this.workStart = workStart;
}
public Student(Integer id, String name, String sex, Date birth, Date workStart) {
this.id = id;
this.name = name;
this.sex = sex;
this.birth = birth;
this.workStart = workStart;
}
}