Преобразование CSV с вложенным объектом JSON в JSON

У меня есть образец сообщения CSV:

header1,header2,header3
value1,value2,{"name":"John","age":30,"car":null}

Как преобразовать его во встроенный JSON как в:

{
  "header1": "value1",
  "header2": "value2",
  "header3": "{\"name\":\"John\",\"age\":30,\"car\":null}"
}

Я использую построитель схемы Jackson с разделителем столбцов по умолчанию:

CsvSchema.builder().disableQuoteChar().setUseHeader(true).build();
CsvMapper.builder().enable(CsvParser.Feature.IGNORE_TRAILING_UNMAPPABLE, CsvParser.Feature.WRAP_AS_ARRAY).build();

Ваш CSV не работает. Вам нужно немного изменить его. Оберните внутренний JSON экранирующим символом. Например, вы можете установить апостроф (') или вертикальную черту (|). Прочитайте файл CSV, замените { на |{ и } на }|, и CsvMapper должен справиться с этим. Для общего решения взгляните на этот вопрос: напрямую конвертируйте файл CSV в файл JSON, используя библиотеку Джексона

Michał Ziober 10.01.2023 23:57

@MichałZiober, даже если CSV будет обновлен, как я могу одновременно избежать csv и json, не меняя разделитель столбцов с «,»?

Vaibhav Tiwari 12.01.2023 09:37
Как сделать движок для футбольного матча? (простой вариант)
Как сделать движок для футбольного матча? (простой вариант)
Футбол. Для многих людей, живущих на земле, эта игра - больше, чем просто спорт. И эти люди всегда мечтают стать футболистом или менеджером. Но, к...
Знайте свои исключения!
Знайте свои исключения!
В Java исключение - это событие, возникающее во время выполнения программы, которое нарушает нормальный ход выполнения инструкций программы. Когда...
Лучшая компания по разработке спортивных приложений
Лучшая компания по разработке спортивных приложений
Ищете лучшую компанию по разработке спортивных приложений? Этот список, несомненно, облегчит вашу работу!
Blibli Automation Journey - Как захватить сетевой трафик с помощью утилиты HAR в Selenium 4
Blibli Automation Journey - Как захватить сетевой трафик с помощью утилиты HAR в Selenium 4
Если вы являетесь веб-разработчиком или тестировщиком, вы можете быть знакомы с Selenium, популярным инструментом для автоматизации работы...
Фото ️🔁 Radek Jedynak 🔃 on ️🔁 Unsplash 🔃
Фото ️🔁 Radek Jedynak 🔃 on ️🔁 Unsplash 🔃
Что такое Java 8 Streams API? Java 8 Stream API
Деревья поиска (Алгоритм4 Заметки к учебнику)
Деревья поиска (Алгоритм4 Заметки к учебнику)
(1) Двоичные деревья поиска: среднее lgN, наихудшее N для вставки и поиска.
1
2
74
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать JS-библиотеку csv, например json-2-csv.

# Global so it can be called from anywhere
npm install -g json2csv

# or as a dependency of a project
npm install json2csv --save

Вы можете org.json.CDL следующим образом:

        BufferedReader br = new BufferedReader(new FileReader("file.csv"));
        String csvAsString = br.lines().collect(Collectors.joining("\n"));
        String json = CDL.toJSONArray(csvAsString).toString();
        try {
            Files.write(Path.of("src/main/resources/output.json"), json.getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            e.printStackTrace();
        }
Ответ принят как подходящий

Представленный CSV контент поврежден. Значения, которые содержат разделитель столбцов, должны быть заключены в кавычки. Если мы не можем изменить приложение, которое его генерирует, нам нужно изменить его перед процессом десериализации. Этот пример прост, поэтому мы можем просто заменить { на |{ и } на }| и установить | в качестве символа кавычек. Но для JSON полезных нагрузок с внутренними объектами нам нужно заменить только первую { и последнюю } скобки. Код может выглядеть следующим образом:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;

import java.io.File;
import java.nio.file.Files;
import java.util.stream.Collectors;

public class CsvApp {

    public static void main(String[] args) throws Exception {
        File csvFile = new File("./resource/test.csv").getAbsoluteFile();
        String csv = Files.readAllLines(csvFile.toPath()).stream().collect(Collectors.joining(System.lineSeparator()));
        csv = csv.replace("{", "|{").replace("}", "}|");

        CsvMapper csvMapper = CsvMapper.builder().build();

        CsvSchema csvSchema = CsvSchema.builder().setQuoteChar('|').setUseHeader(true).build();
        Object csvContent = csvMapper.readerFor(JsonNode.class).with(csvSchema).readValue(csv);

        JsonMapper mapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build();
        mapper.writeValue(System.out, csvContent);
    }
}

Над кодом печатается:

{
  "header1" : "value1",
  "header2" : "value2",
  "header3" : "{\"name\":\"John\",\"age\":30,\"car\":null}"
}

Нужно ли нам создавать регулярное выражение для вложенного JSON, чтобы идентифицировать первый и последний '{' '}', и это снова не удастся, если у нас будет несколько вложенных JSON?

Vaibhav Tiwari 13.01.2023 15:35

Не используйте Regex здесь. Просто StringUtils.lastIndexOf и RegExUtils.replaceFirst

Michał Ziober 13.01.2023 15:37

Но что, если у нас есть несколько значений json?

Vaibhav Tiwari 13.01.2023 15:40

@VaibhavTiwari, тогда вам нужно обработать его построчно. Я предполагаю, что каждая строка содержит весь JSON и внутри нет новых строк. В противном случае вам нужно справиться с этим. Как правило, это недопустимый файл CSV, и обработка всех угловых случаев болезненна.

Michał Ziober 13.01.2023 17:27

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