У меня есть образец сообщения 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();
@MichałZiober, даже если CSV будет обновлен, как я могу одновременно избежать csv и json, не меняя разделитель столбцов с «,»?
Вы можете использовать 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?
Не используйте Regex здесь. Просто StringUtils.lastIndexOf и RegExUtils.replaceFirst
Но что, если у нас есть несколько значений json?
@VaibhavTiwari, тогда вам нужно обработать его построчно. Я предполагаю, что каждая строка содержит весь JSON и внутри нет новых строк. В противном случае вам нужно справиться с этим. Как правило, это недопустимый файл CSV, и обработка всех угловых случаев болезненна.
Ваш CSV не работает. Вам нужно немного изменить его. Оберните внутренний JSON экранирующим символом. Например, вы можете установить апостроф (') или вертикальную черту (|). Прочитайте файл CSV, замените { на |{ и } на }|, и CsvMapper должен справиться с этим. Для общего решения взгляните на этот вопрос: напрямую конвертируйте файл CSV в файл JSON, используя библиотеку Джексона