考虑提供一个展示 java object的 pb 定义,类似com.taobao.arthas.core.view.ObjectView
。
message JavaField {
string name = 1;
oneof value {
JavaObject objectValue = 2;
BasicValue basicValue = 3;
ArrayValue arrayValue = 4;
NullValue nullValue = 5;
}
}
message JavaObject {
string className = 1;
repeated JavaField fields = 2;
}
message BasicValue {
oneof value {
int32 intValue = 1;
int64 longValue = 2;
float floatValue = 3;
double doubleValue = 4;
bool booleanValue = 5;
string stringValue = 6;
}
}
message ArrayElement {
oneof element {
BasicValue basicValue = 1;
JavaObject objectValue = 2;
ArrayValue arrayValue = 3;
NullValue nullValue = 4;
}
}
message ArrayValue {
string className = 1;
repeated ArrayElement elements = 2;
}
message NullValue {
string className = 1;
}
测试代码:
// ComplexObject.java
public class ComplexObject {
private int id;
private String name;
private double value;
private int[] numbers;
private NestedObject nestedObject;
private ComplexObject[] complexArray;
private int[][] multiDimensionalArray;
private String[] stringArray;
public static class NestedObject {
private int nestedId;
private String nestedName;
private boolean flag;
public int getNestedId() {
return nestedId;
}
public void setNestedId(int nestedId) {
this.nestedId = nestedId;
}
public String getNestedName() {
return nestedName;
}
public void setNestedName(String nestedName) {
this.nestedName = nestedName;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public int[] getNumbers() {
return numbers;
}
public void setNumbers(int[] numbers) {
this.numbers = numbers;
}
public NestedObject getNestedObject() {
return nestedObject;
}
public void setNestedObject(NestedObject nestedObject) {
this.nestedObject = nestedObject;
}
public ComplexObject[] getComplexArray() {
return complexArray;
}
public void setComplexArray(ComplexObject[] complexArray) {
this.complexArray = complexArray;
}
public int[][] getMultiDimensionalArray() {
return multiDimensionalArray;
}
public void setMultiDimensionalArray(int[][] multiDimensionalArray) {
this.multiDimensionalArray = multiDimensionalArray;
}
public String[] getStringArray() {
return stringArray;
}
public void setStringArray(String[] stringArray) {
this.stringArray = stringArray;
}
}
构建对象,解析输出:
public static void main(String[] args) {
ComplexObject ccc = ccc();
JavaObject javaObject = toJavaObject(ccc);
System.err.println(javaObject);
}
public static ComplexObject ccc() {
// 创建一个 ComplexObject 对象
ComplexObject complexObject = new ComplexObject();
// 设置基本类型的值
complexObject.setId(1);
complexObject.setName("Complex Object");
complexObject.setValue(3.14);
// 设置基本类型的数组
int[] numbers = { 1, 2, 3, 4, 5 };
complexObject.setNumbers(numbers);
// 创建并设置嵌套对象
ComplexObject.NestedObject nestedObject = new ComplexObject.NestedObject();
nestedObject.setNestedId(10);
nestedObject.setNestedName("Nested Object");
nestedObject.setFlag(true);
complexObject.setNestedObject(nestedObject);
// 创建并设置复杂对象数组
ComplexObject[] complexArray = new ComplexObject[2];
ComplexObject complexObject1 = new ComplexObject();
complexObject1.setId(2);
complexObject1.setName("Complex Object 1");
complexObject1.setValue(2.71);
ComplexObject complexObject2 = new ComplexObject();
complexObject2.setId(3);
complexObject2.setName("Complex Object 2");
complexObject2.setValue(1.618);
complexArray[0] = complexObject1;
complexArray[1] = complexObject2;
complexObject.setComplexArray(complexArray);
// 创建并设置多维数组
int[][] multiDimensionalArray = { { 1, 2, 3 }, { 4, 5, 6 } };
complexObject.setMultiDimensionalArray(multiDimensionalArray);
// 设置数组中的基本元素数组
String[] stringArray = { "Hello", "World" };
complexObject.setStringArray(stringArray);
// 输出 ComplexObject 对象的信息
System.out.println(complexObject);
return complexObject;
}
public static JavaObject toJavaObject(Object obj) {
JavaObject.Builder objectBuilder = JavaObject.newBuilder();
objectBuilder.setClassName(obj.getClass().getName());
Field[] fields = obj.getClass().getDeclaredFields();
List<JavaField> javaFields = new ArrayList<>();
for (Field field : fields) {
field.setAccessible(true);
JavaField.Builder fileBuilder = JavaField.newBuilder();
fileBuilder.setName(field.getName());
try {
Object fieldValue = field.get(obj);
Class<?> fieldType = field.getType();
if(fieldValue == null) {
fileBuilder.setNullValue(NullValue.newBuilder().setClassName(fieldType.getName()).build());
}
else if (fieldType.isArray()) {
ArrayValue arrayValue = toArrayValue(fieldValue);
fileBuilder.setArrayValue(arrayValue);
} else if (fieldValue != null) {
if (fieldType.isArray()) {
JavaObject nestedArrayObject = toJavaObject(fieldValue);
fileBuilder.setObjectValue(nestedArrayObject);
} else if (fieldType.isPrimitive() || fieldType.equals(String.class)) {
BasicValue basicValue = createBasicValue(fieldValue);
fileBuilder.setBasicValue(basicValue);
} else {
JavaObject nestedArrayObject = toJavaObject(fieldValue);
fileBuilder.setObjectValue(nestedArrayObject);
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
javaFields.add(fileBuilder.build());
}
objectBuilder.addAllFields(javaFields);
return objectBuilder.build();
}
private static ArrayValue toArrayValue(Object a) {
ArrayValue.Builder arrayBuilder = ArrayValue.newBuilder();
Class<?> type = a.getClass().getComponentType();
arrayBuilder.setClassName(type.getName());
for (int i = 0; i < Array.getLength(a); i++) {
Object arrayElement = Array.get(a, i);
if (arrayElement != null) {
if (type.isArray()) {
ArrayValue arrayValue = toArrayValue(arrayElement);
arrayBuilder.addElements(ArrayElement.newBuilder().setArrayValue(arrayValue));
} else if (type.isPrimitive() || type.equals(String.class)) {
BasicValue basicValue = createBasicValue(arrayElement);
arrayBuilder.addElements(ArrayElement.newBuilder().setBasicValue(basicValue));
} else {
JavaObject nestedArrayObject = toJavaObject(arrayElement);
arrayBuilder.addElements(ArrayElement.newBuilder().setObjectValue(nestedArrayObject));
}
}else {
arrayBuilder.addElements(ArrayElement.newBuilder().setNullValue(NullValue.newBuilder().setClassName(type.getName()).build()));
}
}
return arrayBuilder.build();
}
private static BasicValue createBasicValue(Object value) {
Builder builder = BasicValue.newBuilder();
if (value instanceof Integer) {
builder.setIntValue((Integer) value);
} else if (value instanceof Long) {
builder.setLongValue((Long) value);
} else if (value instanceof Float) {
builder.setFloatValue((Float) value);
} else if (value instanceof Double) {
builder.setDoubleValue((Double) value);
} else if (value instanceof Boolean) {
builder.setBooleanValue((Boolean) value);
} else if (value instanceof String) {
builder.setStringValue((String) value);
}
return builder.build();
}
上面的代码还有问题,没有处理循环引用。
- 或许应该考虑为每个对象增加 id , refId 信息,这样子避免循环引用。
- 或者考虑在展开对象时,考虑限制展开层数,比如展开到3层之后,就不再展开。