Изменение локальной переменной после передачи ее методу
Я использую com.fasterxml.jackson.databind.JsonNode
библиотека Java для разбора JSON
и выполнить некоторые манипуляции на 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
}
}
}
}
}
Почему это происходит? Я думал, что любые изменения в "subNode" не должны отражаться на "jsonNode
". Есть ли недопонимание с моей стороны?
1 ответ
Вот:
jsonNode = mapper.readTree(deviceShadow);
Это создает в памяти представление ваших данных JSON. Просто какая-то структура данных, которая отражает структуру и содержание вашей строки JSON.
Это здесь:
JsonNode subNode = jsonNode.get(...
затем пересекает эту структуру в памяти и идентифицирует ее подструктуру. Затем вы модифицируете эту подструктуру:
node.put("solenoid", 100);
И не удивительно: когда вы изменяете эту структуру данных в памяти, вы изменяете свои данные!
Другими словами: ваше предположение просто неверно. Представьте, что у вас есть какая-то стандартная реализация Java Tree, которая имеет несколько узлов. Теперь вы идентифицируете конкретный объект Node в этом дереве и изменяете значение этого Node. Конечно, это также меняет содержимое дерева, потому что этот узел находится внутри этого дерева!
Короче говоря: вы читаете данные в память, вы специально предназначаетесь для определенной части этих данных, вы меняете данные, данные изменяются. Вот и все, что нужно сделать!
И просто для записи: в конце мы говорим о семантике базовой библиотеки JSON. Библиотека, которую вы используете здесь... просто не копирует и не клонирует данные, когда вы запрашиваете подузел. Он просто дает вам "указатель" прямо на данные. Другие библиотеки могут сделать это по-другому, например, можно представить, что все данные доступны только для чтения, и что изменения выполняются путем возврата совершенно нового объекта Node, отделенного от исходных данных.
Чтобы не изменять исходный объект jsonNode, кажется, что единственная возможность состоит в том, чтобы дважды проанализировать ваши данные. Так что создайте полностью независимый JsonNode, обработав ваш ввод два раза. Что, конечно, удваивает объем работы, выполняемой вашим кодом.