Java Jackson обновляет экземпляр второго значения json в массиве

Привет всем, я пытаюсь понять, как обновить часть моего json. До сих пор я не нашел нигде, где показано, как это сделать.

Например, вот что мне нужно обновить:

{
    "lastUpdated": "",
    "firetvs": [
        {
            "name": "lr",
            "ip": "",
            "mac": "",
            "token": ""
        },
        {
            "name": "mbr",
            "ip": "",
            "mac": "",
            "token": ""
        },...ETC....

Поэтому мне нужно обновить данные в разделе

"name": "mbr"
 "mac": ""

часть, в которой мне нужно будет обновить Mac-адрес примерно так:

"name": "mbr"
 "mac": "C1:41:Q4:E8:S1:98:V1"

Я нашел код, который позволяет мне обновлять стандартное значение, такое как мой LastUpdated, но не для чего-то, что является частью массива:

String jsonObject = "{" + 
    "\"lastUpdated\": \"\"," +
    "\"firetvs\": [" +
        "{" +
            "\"name\": \"lr\"," +
            "\"ip\": \"\"," +
            "\"mac\": \"\"," +
            "\"token\": \"\"" +
        "}," +
        "{" +
            "\"name\": \"mbr\"," +
            "\"ip\": \"\"," +
            "\"mac\": \"\"," +
            "\"token\": \"\"" +
        "}" +
    "]" +
"}";

ObjectMapper objectMapper = new ObjectMapper();
ObjectNode objectNode = null;

try {
    objectNode = objectMapper.readValue(jsonObject, ObjectNode.class);
    objectNode.put("lastUpdated", "02-08-2024");
    Log.d("test", objectNode.toPrettyString());
} catch (JsonProcessingException e) {
    throw new RuntimeException(e);
}

Я нашел это:

objectNode.with("firetvs").put("mac", "C1:41:Q4:E8:S1:98:V1");

Но это не сработает, поскольку он просто найдет первый экземпляр «mac» и обновит это значение вместо обновления второго его экземпляра. И я также получаю сообщение об ошибке:

Свойство firetvs имеет значение, не относящееся к типу ObjectNode (но com.fasterxml.jackson.databind.node.ArrayNode).

Итак, как бы мне это сделать?

Я думаю, это может сработать для вас: 1. используйте метод objectNode.get("firetvs") и приведите его к объекту ArrayNode. 2. Возьмите второй элемент объекта ArrayNode и приведите его обратно к ObjectNode. 3. Теперь вы можете использовать метод put("mac", "C1:41:Q4:E8:S1:98:V1") для объекта, созданного во втором пункте.

Igorovics 27.03.2024 16:00

Вам нужно поставить один и тот же mac-адрес всем элементам массива firetvs или только определенным?

dani-vta 27.03.2024 17:02

@dani-vta это будет что-то конкретное. У меня есть больше массива, но я сократил его до 2, чтобы он не занимал так много места в моем вопросе.

StealthRT 27.03.2024 17:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете попробовать библиотеку JSON Josson.

https://github.com/octomix/josson

Josson josson = Josson.fromJsonString(
    "{" +
        "\"lastUpdated\": \"\"," +
        "\"firetvs\": [" +
            "{" +
                "\"name\": \"lr\"," +
                "\"ip\": \"\"," +
                "\"mac\": \"\"," +
                "\"token\": \"\"" +
            "}," +
            "{" +
                "\"name\": \"mbr\"," +
                "\"ip\": \"\"," +
                "\"mac\": \"\"," +
                "\"token\": \"\"" +
            "}" +
        "]" +
    "}");
Map<String, JsonNode> params = Map.of(
    "$date", TextNode.valueOf("02-08-2024"),
    "$key", TextNode.valueOf("mbr"),
    "$val", TextNode.valueOf("C1:41:Q4:E8:S1:98:V1")
);
JsonNode node = josson.getNode("field(lastUpdated:$date, firetvs.field(mac:if ([name=$key],$val,mac)))", params);
System.out.println(node.toPrettyString());

Выход

{
  "lastUpdated" : "02-08-2024",
  "firetvs" : [ {
    "name" : "lr",
    "ip" : "",
    "mac" : "",
    "token" : ""
  }, {
    "name" : "mbr",
    "ip" : "",
    "mac" : "C1:41:Q4:E8:S1:98:V1",
    "token" : ""
  } ]
}

Спасибо за пример и ссылку, Рэймонд!

StealthRT 27.03.2024 21:50

Если вам нужно обновить MAC-адрес элементов firetvs только при определенных условиях, например, если name равен mbr, я предлагаю альтернативное решение с потоками.

По сути, элементы firetvs передаются через Iterable, затем фильтруются, сохраняя только те, у которых mbr являются name, и, наконец, обновляются с использованием правильного MAC-адреса.

В следующем примере я добавил всего пару элементов внутри firetvs, чтобы не загромождать код. Однако здесь, в oneCompiler, я включил больше элементов, показывающих желаемый результат.

public class Main {
    public static void main(String[] args) throws JsonProcessingException {
        String json = "{\n" +
                "    \"lastUpdated\": \"\",\n" +
                "    \"firetvs\": [\n" +
                "        {\n" +
                "            \"name\": \"lr\",\n" +
                "            \"ip\": \"\",\n" +
                "            \"mac\": \"\",\n" +
                "            \"token\": \"\"\n" +
                "        },\n" +
                "        {\n" +
                "            \"name\": \"mbr\",\n" +
                "            \"ip\": \"\",\n" +
                "            \"mac\": \"\",\n" +
                "            \"token\": \"\"\n" +
                "        }\n" +
                "    ]\n" +
                "}";

        String mac = "C1:41:Q4:E8:S1:98:V1";

        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode rootNode = objectMapper.readValue(json, ObjectNode.class);
        ArrayNode firetvsNode = (ArrayNode) rootNode.get("firetvs");

        //Creating an Iterable form the Iterator of the firetvs' nodes
        Iterable<JsonNode> iterable = () -> firetvsNode.iterator();

        StreamSupport.stream(iterable.spliterator(), false)     //Streaming the firetvs' nodes
                .filter(node -> node.get("name").asText().equals("mbr"))    //Keeping only the elements with mbr as their name
                .forEach(node -> ((ObjectNode) node).put("mac", mac));  //Updating the mac address of each element

        String jsonMacReplaced = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode);
        System.out.println(jsonMacReplaced);
    }
}

Другие вопросы по теме

Похожие вопросы