Изменение локальной переменной после передачи ее методу - PullRequest
0 голосов
/ 15 июня 2019

Я использую 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 Ответ

0 голосов
/ 15 июня 2019

Здесь:

jsonNode = mapper.readTree(deviceShadow);

Это создает в памяти представление ваших данных JSON.Просто какая-то структура данных, которая отражает структуру и содержимое вашей строки JSON.

Это здесь:

JsonNode subNode = jsonNode.get(...

затем обходит эту структуру в памяти и идентифицирует ее подструктуру.Затем вы изменяете эту подструктуру:

node.put("solenoid", 100);

И неудивительно: когда вы изменяете эту структуру данных в памяти, вы изменяете свои данные!

Другими словами:Ваше предположение просто неверно.Представьте, что у вас есть какая-то стандартная реализация Java Tree, которая имеет несколько узлов.Теперь вы идентифицируете конкретный объект Node в этом дереве и изменяете значение этого Node.Конечно, это также меняет содержимое Дерева, потому что этот Узел находится внутри этого Дерева!

Короче говоря: вы читаете данные в память, вы специально предназначаетесь для определенной частиэти данные, вы меняете данные, данные изменяются.Вот и все, что нужно сделать!

И просто для справки: в конце мы говорим о семантике базовой библиотеки JSON.Библиотека, которую вы используете здесь ... просто не копирует и не клонирует данные, когда вы запрашиваете подузел.Он просто дает вам «указатель» прямо на данные.Другие библиотеки могут сделать это по-другому, например, можно представить, что все данные доступны только для чтения, и что изменения выполняются путем возврата совершенно нового объекта Node, отделенного от исходных данных.

Чтобы не изменятьИсходный объект jsonNode , кажется, что единственная опция - это анализ данных дважды .Так что создайте полностью независимый JsonNode, обработав ваш ввод дважды.Что, конечно, удваивает объем работы, выполняемой вашим кодом.

...