L oop для создания JSON - PullRequest
       2

L oop для создания JSON

3 голосов
/ 20 июня 2020

Я использую Java SpringBoot для создания приложения RestAPI. Я застрял с l oop ниже. Проблема возникает с sub1_arr.add (subResult1);

Я выполнил несколько тестов:

  1. Распечатайте SubResult1 для каждой итерации: println показывает правильный элемент, но когда добавить в sub1_arr, он станет дубликатом.

  2. Тест 1 (как показано в коде): это предположим, что исходный код, который я написал. Вывод неверен с дублированием вывода

  3. Тест 2 (как показано в коде): с правильным выводом, но в строковой форме.

    while(rs.next())
    {
        if(rs.getString("status").equals("FAILED")) {
            obj.put("result", "failed"); 
            obj.put("msg", rs.getString("msg"));
        } 
        else {

            //mainResult - ignore for a while
            mainResult.put("layer1_id", rs.getString("layer1_id"));
            mainResult.put("layer1_name", rs.getString("layer1_name"));

            //subResult - layer2
            subResult1.put("layer2_id", rs.getString("layer2_id"));
            subResult1.put("layer2_name", rs.getString("layer2_name"));

            //test 1 - having incorrect output with all the element become duplicate
            sub1_arr.add(subResult1);

            //test 2 - having correct output but the output become string with \"xxx\"
            sub1_arr.add(subResult1.toString());
        }

    }

    //adding sub array to main result
    mainResult.set("layer2", sub1_arr);

Получить результат (неожиданно)

{"layer2":[
   {"layer2_id" : "3", "layer2_name" : "name_3"},
   {"layer2_id" : "3", "layer2_name" : "name_3"},
   {"layer2_id" : "3", "layer2_name" : "name_3"} 
]}

Ожидаемый результат

{"layer2":[
   {"layer2_id" : "1", "layer2_name" : "name_1"},
   {"layer2_id" : "2", "layer2_name" : "name_2"},
   {"layer2_id" : "3", "layer2_name" : "name_3"} 
]}

Ответы [ 2 ]

1 голос
/ 20 июня 2020

Это связано с тем, что объект subResult1 имеет тип Map, и значения переопределяются в каждом l oop, поскольку ключ - будучи таким же - переопределяется. Поскольку все элементы sub1_arr указывают на один и тот же объект, все они покажут вам один и тот же результат .

Вместо этого вы можете попробовать что-то вроде этого (лучше способ получить результат json - не изобретайте колесо заново):

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.createObjectNode();
ArrayNode arrayNode = mapper.createArrayNode();

while(rs.next()) {
    ObjectNode layer = mapper.createObjectNode();   
    layer.put("layer2_id", rs.getString("layer2_id"));
    layer.put("layer2_name", rs.getString("layer2_name"));
    arrayNode.add(layer);
}

((ObjectNode) rootNode).set("layer2", arrayNode);
String jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode);
System.out.println(jsonString);

Это мой тест:

package com.example;

import java.util.Arrays;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class Main {

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.createObjectNode();

        ObjectNode layer1 = mapper.createObjectNode();
        layer1.put("layer2_id", "1");
        layer1.put("layer2_name", "name_1");

        ObjectNode layer2 = mapper.createObjectNode();
        layer2.put("layer2_id2", "2");
        layer2.put("layer2_name2", "name_2");

        ObjectNode layer3 = mapper.createObjectNode();
        layer3.put("layer2_id2", "3");
        layer3.put("layer2_name2", "name_3");

        ArrayNode arrayNode = mapper.createArrayNode();
        arrayNode.addAll(Arrays.asList(layer1, layer2, layer3));

        ((ObjectNode) rootNode).set("layer2", arrayNode);

        String jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode);
        System.out.println(jsonString);
    }
}

Вывод:
{"layer2": [
{"layer2_id": "1", "layer2_name": "name_1"},
{"layer2_id": "2", "layer2_name": "name_2"},
{"layer2_id": "3", "layer2_name": "name_3"}
]}

0 голосов
/ 20 июня 2020

Это обычная проблема для начинающих разработчиков, когда я был репетитором по программированию, это была одна из самых распространенных проблем после того, как люди поняли, как использовать циклы и массивы. Проблема заключается в том, что subresult1 на самом деле является ссылкой на объект. Когда вы используете эту строку sub1_arr.add(subResult1), это всегда одна и та же ссылка в памяти, поэтому к тому времени, когда вы дойдете до последней итерации, все значения будут такими же, потому что вы обновляли тот же объект в памяти. Вы можете решить эту проблему, добавив new к объекту subResult1. Я не знаю, какой у вас тип объекта, потому что он не включен в образец, но предположим, что выше у вас есть это:

Map<String, String> subResult1 = new HashMap<String, String>();

В свой код вам нужно будет добавить это:

// subResult - layer2 subResult1 = new HashMap ();

Это по существу перезаписывает ссылку памяти на исходную карту и создает новую со ссылкой на новую карту. Теперь старая карта все еще там, потому что вы добавили ее в sub1_arr. Но когда вы присваиваете значения с помощью 'put', он будет назначать их вашему новому объекту.

Есть много способов улучшить это, но для начала я обычно объявляю переменные как близко к тому, что они мне нужны, как могу (не создавая лишнего беспорядка). Поэтому я бы переместил ваше объявление subresult1 в то же место и просто удалил его выше l oop. Вот так:

//subResult - layer2
Map<String, String> subResult1 = new HashMap<String, String>();

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...