java - 将局部变量值传递给方法后发生变化
问题描述
我正在使用com.fasterxml.jackson.databind.JsonNode
java 库来解析 aJSON
并对JSON
字符串执行一些操作,如下所示 -
public static void main(String[] args) {
{
String jsonString = "{\"state\":{\"reported\":{\"deviceParams\":{\"deviceStatus\":{\"solenoid\":10,\"airFlow\":20}}}}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = null;
try {
jsonNode = mapper.readTree(jsonString);
} catch (IOException e) {
e.printStackTrace();
}
JsonNode subNode = jsonNode.get("state").get("reported").get("deviceParams").get("deviceStatus");
//Now subNode = {"solenoid":10,"airFlow":20}
modifySubNode((ObjectNode) subNode);
//type-casting JsonNode to ObjectNode since JSON manipulation like deletion and addition of nodes is only allowed in ObjectNode, not JsonNode
}
private static void modifySubNode(ObjectNode node) {
if (node.get("solenoid") != null) {
node.put("solenoid", 100);
}
}
在函数调用之后modifySubNode()
,我希望 的值jsonNode
保持为
{
"state":
{
"reported":
{
"deviceParams":
{
"deviceStatus":
{
"solenoid": 10,
"airFlow": 20
}
}
}
}
}
但相反,它变成了这个
{
"state":
{
"reported":
{
"deviceParams":
{
"deviceStatus":
{
"solenoid": 100,
"airFlow": 20
}
}
}
}
}
为什么会这样?我认为对“子节点”的任何更改都不应该反映在“ jsonNode
”上。是不是我的理解有误?
解决方案
这里:
jsonNode = mapper.readTree(deviceShadow);
这会创建JSON 数据的内存表示。只是某种反映JSON 字符串结构和内容的数据结构。
这里:
JsonNode subNode = jsonNode.get(...
然后遍历该内存结构并识别它的子结构。然后修改该子结构:
node.put("solenoid", 100);
毫不奇怪:当你修改内存中的数据结构时,你修改了你的数据!
换句话说:你的假设是完全错误的。想象一下,你有一些标准的 Java Tree 实现,它有一堆节点。现在您在该树中识别一个特定的 Node 对象,并更改该 Node 的值。当然,这也改变了树的内容,因为那个节点位于树里面!
长话短说:您将数据读入内存,您专门针对该数据的某个部分,您更改数据,数据被更改。这就是全部!
仅作记录:最后,我们讨论的是底层 JSON 库的语义。您在这里使用的库......当您请求子节点时,根本不会复制或克隆数据。它只是给你一个直接进入数据的“指针”。其他库可能会以不同的方式执行此操作,例如,可以想象所有数据都是只读的,并且通过返回一个全新的 Node 对象来完成修改,与初始数据分离。
为了不更改初始jsonNode对象,唯一的选择似乎是解析您的数据两次。因此,通过两次处理您的输入来创建完全独立的 JsonNode。这当然会使您的代码所做的工作量翻倍。
推荐阅读
- javascript - 当所有 json 数据都经过循环时如何运行 then()
- pandas - 将月份名称替换为月份编号
- django - 如何用正确的域替换电子邮件中的 localhost 以用于 django 重置密码?
- android - 为什么我不能发布游戏?
- roku - 如何摆脱 Scenegraph Developer 扩展中的默认悬垂
- vba - 更改计划日期格式
- android - Android自定义视图一次获取宽度
- r - 在 R 中运行 powershell 时出现转义字符
- django - Django Admin:如何在调用特定函数下载文件时将 url 显示为链接
- python - Django Cusom 用户管理器单元测试 - NoneType 对象不可调用