如何使用反射递归序列化对象?

Saw*_*yer 4 java recursion json

我想导航到对象的第N级,并以String格式序列化它的属性.例如:

class Animal {
   public String name;
   public int weight;
   public Animal friend;
   public Set<Animal> children = new HashSet<Animal>() ;
}
Run Code Online (Sandbox Code Playgroud)

应该像这样序列化:

{name:"Monkey",
 weight:200,
 friend:{name:"Monkey Friend",weight:300 ,children:{...if has children}},
 children:{name:"MonkeyChild1",weight:100,children:{... recursively nested}}
}
Run Code Online (Sandbox Code Playgroud)

您可能会注意到它类似于将对象序列化为json.我知道有很多libs(Gson,Jackson ......)可以做到这一点,你能给我一些关于如何自己写这个的有启发性的想法吗?

Bal*_*usC 7

Google Gson可以在一行中执行此特定任务:

String json = new Gson().toJson(animal);
Run Code Online (Sandbox Code Playgroud)

反过来也顺便说一句:

Animal animal = new Gson().fromJson(json, Animal.class);
Run Code Online (Sandbox Code Playgroud)

我还没有看到另一个JSON序列化程序,它更好地支持泛型,集合/映射和(嵌套)javabeans.

更新:到目前为止,您只需要了解反射API.我建议您首先了解有关该主题Sun教程.概括地说,可以使用Object#getClass()与所提供的所有方法java.lang.Class,java.lang.reflect.Method等来确定一个和其他.Google Gson是开源的,也可以从中受益.


mko*_*ela 5

序列化基本上是深度克隆.

您需要跟踪每个对象引用以获取重新执行(例如,使用IdentityHashMap).什么是你的最终实现方法(如果不是外部库)记得检查对象再现,或者你可能最终在一个非常大的循环中(当对象A引用对象B时再次引用对象A或更复杂的循环对象图).

一种方法是使用类似DFS的算法遍历对象图,并从那里构建克隆(序列化字符串).

这个伪代码有希望解释如何:

visited = {}
function visit(node) {
  if node in visited {
    doStuffOnReoccurence(node)
    return
  }
  visited.add(node)
  doStuffBeforeOthers(node)
  for each otherNode in node.expand() visit(otherNode)
  doStuffAfterOthers(node)
}
Run Code Online (Sandbox Code Playgroud)

示例中的访问集是我将使用标识集(如果有的话)或IdentityHashMap的地方.

反复查找字段(即node.expand()部分)时,请记住通过超类字段.

反思不应该用于"正常"的发展案例.Reflection将代码作为数据处理,您可以忽略所有正常的对象访问限制.我只使用这种反射深拷贝的东西进行测试:

  1. 在测试中检查不同类型的对象以获得深层对象图的相等性

  2. 在分析对象图大小和其他属性的测试中

  • 与普通地图相比的差异在于它使用身份(==)作为关键而不是等于.当你进行深度克隆时,你需要知道某些东西是否真的是同一个对象. (2认同)