2023-10-20 13:28:17 update
这个问题是 alibaba 的 fastjson 库进行 JSON.toJSONString() 时出现的循环引用问题。
临时解决方案,使用时加上 SerializerFeature.DisableCircularReferenceDetect
的序列化特性。
String reqBody = JSONObject.toJSONString(cidto, SerializerFeature.DisableCircularReferenceDetect);
全局解决就是 new 一个类,在类中执行这个特性就行(类似于全局拦截器的理念),此处不给出了。
生成JSON字符串
来自你的消息:
java11,这个方法打印出来的 json string 为什么是这样的
the result json string is
{"aarch64":{"os_info":{"os_ver":"22.03","os_name":"dkk"}},"x86_64":{"$ref":"$.aarch64"}}
private void testJson() {
String tmpArch = "x86_64,aarch64";
boolean multiArch = tmpArch.contains(",");
JSONObject osObj = new JSONObject();
JSONObject infoObj = new JSONObject();
infoObj.put("os_name", "dkk");
infoObj.put("os_ver", "22.03");
osObj.put("os_info", infoObj);
//final String osObjStr = JSONObject.toJSONString(osObj);
JSONObject customizedObj = new JSONObject();
if (multiArch) {
String[] archSplit = tmpArch.split(",");
for (int i = 0; i < archSplit.length; i++) {
String archItem = archSplit[i];
//JSONObject tmpObj = JSONObject.parseObject(osObjStr);
customizedObj.put(archItem, osObj);
}
}
System.out.println("the result json string is\n" + JSONObject.toJSONString(customizedObj));
}
来自 ChatGPT 的消息:
这是因为在testJson()
方法中,首先创建了一个JSONObject
对象osObj
,并在其中放置了一个infoObj
对象,该对象包含了os_name
和os_ver
两个属性。然后,如果tmpArch
包含逗号,就将其拆分为多个架构,并将每个架构作为键,将osObj
作为值放入customizedObj
对象中。最后,使用JSONObject.toJSONString()
方法将customizedObj
对象转换为JSON字符串。
因此,在这个例子中,tmpArch
包含x86_64
和aarch64
,因此customizedObj
对象包含两个属性,分别是x86_64
和aarch64
。x86_64
的值是一个$ref
属性,它引用了aarch64
的值,而aarch64
的值包含一个os_info
属性,它又包含了os_name
和os_ver
两个属性。因此,最终的JSON字符串就是:
{
"aarch64": {
"os_info": {
"os_ver": "22.03",
"os_name": "dkk"
}
},
"x86_64": {
"$ref": "$.aarch64"
}
}
来自你的消息:
为什么 x86_64
的值是一个 $ref
属性,并且这个属性的值是 $.aarch64
呢
来自 ChatGPT 的消息:
在本次对话中,我们推测这个 JSON 字符串是使用 Jackson 库将一个 Java 对象转换成的。在这个 Java 对象中,可能存在一个类型为 Map<String, Object>
的属性,其中包含了两个键值对,分别是 x86_64
和 aarch64
。其中,x86_64
的值是 $ref
属性,它引用了 aarch64
的值。这是因为在 Java 对象中,x86_64
和 aarch64
实际上是指向同一个对象的引用,因此在转换成 JSON 字符串时,x86_64
的值会被替换成 $ref
属性,指向 aarch64
的值。
而 $ref
属性的值为 $.aarch64
,是因为在转换成 JSON 字符串时,Jackson 库会为每个对象生成一个唯一的标识符,用于标识该对象在 JSON 字符串中的位置。在这个 JSON 字符串中,aarch64
的值是一个对象,它包含了 os_info
属性,因此它的标识符为 $.aarch64
。而 x86_64
的值是 $ref
属性,它引用了 aarch64
的值,因此它的标识符为 $.x86_64
。
来自你的消息:
private void testJson() {
String tmpArch = "x86_64,aarch64";
boolean multiArch = tmpArch.contains(",");
JSONObject osObj = new JSONObject();
JSONObject infoObj = new JSONObject();
infoObj.put("os_name", "dkk");
infoObj.put("os_ver", "22.03");
osObj.put("os_info", infoObj);
final String osObjStr = JSONObject.toJSONString(osObj);
JSONObject customizedObj = new JSONObject();
if (multiArch) {
String[] archSplit = tmpArch.split(",");
for (int i = 0; i < archSplit.length; i++) {
String archItem = archSplit[i];
JSONObject tmpObj = JSONObject.parseObject(osObjStr);
customizedObj.put(archItem, tmpObj);
}
}
System.out.println("the result json string is\n" + JSONObject.toJSONString(customizedObj));
}
我这样写就能确保生成的 json string 正确
the result json string is
{"aarch64":{"os_info":{"os_ver":"22.03","os_name":"dkk"}},"x86_64":{"os_info":{"os_ver":"22.03","os_name":"dkk"}}}
来自 ChatGPT 的消息:
是的,您的代码能够确保生成的 JSON 字符串符合预期。在您的代码中,首先将 tmpArch
字符串按照逗号分隔成多个架构类型。然后,对于每个架构类型,创建一个新的 JSONObject
对象,并将 osObjStr
字符串解析成一个 JSONObject
对象,然后将这个对象作为当前架构类型的值,存入 customizedObj
对象中。最终,将 customizedObj
对象转换成 JSON 字符串并输出。
这样的代码逻辑确保了每个架构类型都有一个独立的 os_info
对象,而不是多个架构类型共享同一个 os_info
对象。因此,生成的 JSON 字符串中不会出现 $ref
属性,而是直接包含了所有的属性和值。