Sat. Apr 27th, 2024

In today’s data-driven world, it’s common to work with different data formats like CSV (Comma-Separated Values) and JSON (JavaScript Object Notation). Converting data between these formats is a common task in data processing and integration workflows. In this article, we’ll explore how to use the CSVJSONConverter class, a versatile utility for converting CSV data to JSON and vice versa. We’ll cover its usage and provide examples to illustrate its capabilities.

When converting a large JSONArray into a CSV using CSVJSONConverter, the resulting data size is typically reduced compared to the original JSON array. This reduction in size is primarily due to the nature of the CSV format and the way CSVJSONConverter converts the JSON data.

Here are a few reasons why the data size is reduced:

  1. Structural Simplicity: CSV is a simple tabular format where data is organized into rows and columns. In contrast, JSON can have a more complex structure with nested objects and arrays. When converting JSON to CSV, CSVJSONConverter flattens the nested structure, resulting in a simplified and more compact representation.
  2. Elimination of Redundant Information: JSON can contain repeating keys within objects, resulting in duplicate information. When converting to CSV, CSVJSONConverter eliminates this redundancy by treating each key as a column header and representing the corresponding values only once per row. This reduction in redundancy helps reduce the overall data size.
  3. Efficient Data Encoding: CSV typically uses simple encoding schemes such as UTF-8 or ASCII, which are efficient in terms of storage. JSON, on the other hand, may use more verbose encodings like UTF-16 or UTF-32, which can result in larger file sizes. By converting JSON to CSV, the data is encoded in a more compact and efficient manner.
  4. Data Compression: In some cases, the resulting CSV file can be further compressed using standard compression algorithms like gzip or zip. This compression can significantly reduce the data size, especially if the original JSON data contains repetitive patterns or long strings.
  5. Removal of Metadata: JSON data often includes metadata such as object keys or field names, which can increase the overall data size. When converting to CSV, this metadata is typically removed or represented more concisely, resulting in a smaller file size.

However, it’s important to note that the reduction in data size is not guaranteed in all scenarios. The actual reduction depends on various factors, including the specific JSON structure, the data values, and the encoding used. Additionally, the size reduction may vary from one JSON file to another based on the characteristics of the data.

While the primary purpose of using CSVJSONConverter is to convert between formats rather than specifically optimize for data size, the resulting CSV format generally offers more compact representation compared to the original JSON array.

It’s worth mentioning that the reduction in data size should be evaluated in the context of your specific use case. If your goal is to minimize storage or transmission costs, comparing the sizes of the original JSON and the converted CSV files can help determine the efficiency of the conversion process.

When converting a large JSONArray to CSV using CSVJSONConverter, you can expect a reduction in data size due to the simplified structure, elimination of redundancy, efficient encoding, and possible data compression. However, the actual size reduction may vary depending on the nature of the data and specific factors involved.

To follow along with the examples in this article, you’ll need basic knowledge of Java programming and an understanding of CSV and JSON data formats. Make sure you have the latest version of the CSVJSONConverter class, which can be obtained from the official documentation or the relevant code repository.

Converting CSV to JSON:

The CSVJSONConverter class provides several methods for converting CSV data to JSON. Let’s start by converting a simple CSV file to a JSON array.

import org.json.JSONArray;
import org.json.JSONException;

public class CSVtoJSONExample {
    public static void main(String[] args) {
        String csvData = "Name,Age,City\nJohn,25,New York\nAlice,30,San Francisco";
        try {
            JSONArray jsonArray = CSVJSONConverter.convertCSVtoJSON(csvData);
            System.out.println(jsonArray.toString());
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

In this example, we have a CSV string csvData containing information about individuals. We call the convertCSVtoJSON method of the CSVJSONConverter class, passing the CSV data as a string. The method returns a JSONArray representing the converted data. Finally, we print the JSON array.

The output will be:

[{"Name":"John","Age":"25","City":"New York"},{"Name":"Alice","Age":"30","City":"San Francisco"}]

As you can see, the CSV data is successfully converted to a JSON array, where each row in the CSV corresponds to a JSON object.

Converting JSON to CSV:

Next, let’s explore how to convert JSON data back to CSV format. We’ll use the convertJSONtoCSV method of the CSVJSONConverter class. Here’s an example:

import org.json.JSONArray;
import org.json.JSONException;

public class JSONtoCSVExample {
    public static void main(String[] args) {
        String jsonData = "[{\"Name\":\"John\",\"Age\":\"25\",\"City\":\"New York\"},{\"Name\":\"Alice\",\"Age\":\"30\",\"City\":\"San Francisco\"}]";
        try {
            JSONArray jsonArray = new JSONArray(jsonData);
            String csvData = CSVJSONConverter.convertJSONtoCSV(jsonArray);
            System.out.println(csvData);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

In this example, we have a JSON string jsonData representing an array of objects. We create a JSONArray from the JSON string and then call the convertJSONtoCSV method of the CSVJSONConverter class, passing the JSON array. The method returns a CSV string representing the converted data. Finally, we print the CSV data.

The output will be:

Name,Age,City
John,25,New York
Alice,30,San Francisco

As shown above, the JSON array is successfully converted back to CSV format, with each object in the array corresponding to a row in the CSV.

Handling Embedded Objects and Arrays:

The CSVJSONConverter class also supports handling embedded objects and arrays within the CSV and JSON data. This allows for more complex data structures to be converted between formats seamlessly.

To convert a JSON object with embedded objects and arrays to CSV, we can use the convertJSONObjectToCSV method. Here’s an example:

import org.json.JSONObject;
import org.json.JSONException;

public class JSONObjToCSVExample {
    public static void main(String[] args) {
        String jsonData = "{\"Name\":\"John\",\"Age\":\"25\",\"Address\":{\"Street\":\"123 Main St\",\"City\":\"New York\"},\"Skills\":[\"Java\",\"Python\",\"SQL\"]}";
        try {
            JSONObject jsonObject = new JSONObject(jsonData);
            String csvData = CSVJSONConverter.convertJSONObjectToCSV(jsonObject);
            System.out.println(csvData);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

In this example, we have a JSON object jsonObject containing embedded objects and an embedded array. We call the convertJSONObjectToCSV method of the CSVJSONConverter class, passing the JSON object. The method converts the object and its embedded data to CSV format. Finally, we print the CSV data.

The output will be:

Name,Age,Address.Street,Address.City,Skills
John,25,123 Main St,New York,Java;Python;SQL

As you can see, the convertJSONObjectToCSV method handles the embedded objects and arrays, flattening them into the CSV headers and rows appropriately.

The CSVJSONConverter class provides a convenient way to convert CSV data to JSON and JSON data to CSV. With its support for embedded objects and arrays, it can handle complex data structures seamlessly. In this article, we’ve covered the basic usage of CSVJSONConverter with examples demonstrating CSV to JSON and JSON to CSV conversions. You can further explore its capabilities by referring to the official documentation and leveraging the available methods for your specific use cases.

Remember to import the required dependencies, ensure you have the latest version of CSVJSONConverter, and experiment with different CSV and JSON data to see how the conversion works in various scenarios.

That’s it for this article! You should now have a good understanding of how to use CSVJSONConverter to convert between CSV and JSON formats. Happy data conversion!

CSVJSONConverter code

import org.json.*;

import java.io.*;
import java.util.*;

/**
 * The CSVJSONConverter class provides methods to convert CSV data to JSON and JSON data to CSV.
 * Supports conversion of CSV data to JSON array and JSON array to CSV data.
 * Provides utility methods for processing fields and formatting values.
 */
public class CSVJSONConverter {

    /**
     * Converts CSV data from a string to a JSON array using a default comma as the delimiter.
     *
     * @param csvData the CSV data to convert
     * @return the JSON array representing the converted data
     * @throws JSONException if there is an error during the conversion
     */
    public static JSONArray convertCSVtoJSON(String csvData) throws JSONException {
        return convertCSVtoJSON(csvData, ',', false);
    }

    /**
     * Converts CSV data from a string to a JSON array using the specified delimiter.
     *
     * @param csvData       the CSV data to convert
     * @param delimiter     the delimiter character used in the CSV data
     * @param validateData  flag indicating whether to perform data validation
     * @return the JSON array representing the converted data
     * @throws JSONException if there is an error during the conversion
     */
    public static JSONArray convertCSVtoJSON(String csvData, char delimiter, boolean validateData)
            throws JSONException {
        try (StringReader stringReader = new StringReader(csvData)) {
            return convertCSVtoJSON(stringReader, delimiter, validateData);
        }
    }

    /**
     * Converts CSV data from an input stream to a JSON array using a default comma as the delimiter.
     *
     * @param inputStream the input stream containing the CSV data to convert
     * @return the JSON array representing the converted data
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while reading the CSV data
     */
    public static JSONArray convertCSVtoJSON(InputStream inputStream) throws JSONException, IOException {
        return convertCSVtoJSON(inputStream, ',', false);
    }

    /**
     * Converts CSV data from an input stream to a JSON array using the specified delimiter.
     *
     * @param inputStream   the input stream containing the CSV data to convert
     * @param delimiter     the delimiter character used in the CSV data
     * @param validateData  flag indicating whether to perform data validation
     * @return the JSON array representing the converted data
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while reading the CSV data
     */
    public static JSONArray convertCSVtoJSON(InputStream inputStream, char delimiter, boolean validateData)
            throws JSONException, IOException {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            return convertCSVtoJSON(reader, delimiter, validateData);
        }
    }

    /**
     * Converts CSV data from a reader to a JSON array using a default comma as the delimiter.
     *
     * @param reader        the reader containing the CSV data to convert
     * @return the JSON array representing the converted data
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while reading the CSV data
     */
    public static JSONArray convertCSVtoJSON(Reader reader) throws JSONException, IOException {
        return convertCSVtoJSON(reader, ',', false);
    }

    /**
     * Converts CSV data from a reader to a JSON array using the specified delimiter.
     *
     * @param reader        the reader containing the CSV data to convert
     * @param delimiter     the delimiter character used in the CSV data
     * @param validateData  flag indicating whether to perform data validation
     * @return the JSON array representing the converted data
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while reading the CSV data
     */
    public static JSONArray convertCSVtoJSON(Reader reader, char delimiter, boolean validateData)
            throws JSONException, IOException {
        try (BufferedReader bufferedReader = new BufferedReader(reader)) {
            String headerLine = bufferedReader.readLine();
            if (headerLine == null) {
                throw new JSONException("CSV data is empty");
            }
            String[] headers = headerLine.split(String.valueOf(delimiter));
            JSONArray jsonArray = new JSONArray();
            String line;
            int lineNumber = 2; // Start from line 2 (header is line 1)

            while ((line = bufferedReader.readLine()) != null) {
                String[] values = line.split(String.valueOf(delimiter));
                if (validateData && values.length != headers.length) {
                    throw new JSONException("Mismatched number of values in CSV data at line " + lineNumber);
                }
                JSONObject jsonObject = new JSONObject();

                for (int i = 0; i < headers.length; i++) {
                    String header = normalizeHeader(headers[i]);
                    String value = (i < values.length) ? values[i].trim() : "";
                    processField(jsonObject, header, value);
                }

                jsonArray.put(jsonObject);
                lineNumber++;
            }

            return jsonArray;
        }
    }

    /**
     * Converts a JSON array to CSV data and returns it as a string using a default comma as the delimiter.
     *
     * @param jsonArray the JSON array to convert
     * @return the CSV data representing the converted array
     * @throws JSONException if there is an error during the conversion
     */
    public static String convertJSONtoCSV(JSONArray jsonArray) throws JSONException {
        return convertJSONtoCSV(jsonArray, ',', false);
    }

    /**
     * Converts a JSON array to CSV data and returns it as a string using the specified delimiter.
     *
     * @param jsonArray     the JSON array to convert
     * @param delimiter     the delimiter character to use in the CSV data
     * @param validateData  flag indicating whether to perform data validation
     * @return the CSV data representing the converted array
     * @throws JSONException if there is an error during the conversion
     */
    public static String convertJSONtoCSV(JSONArray jsonArray, char delimiter, boolean validateData)
            throws JSONException {
        StringWriter stringWriter = new StringWriter();
        try (BufferedWriter writer = new BufferedWriter(stringWriter)) {
            convertJSONtoCSV(jsonArray, writer, delimiter, validateData);
            return stringWriter.toString();
        } catch (IOException e) {
            // StringWriter should not throw IOException
            throw new RuntimeException("Unexpected error occurred while converting JSON to CSV", e);
        }
    }

    /**
     * Converts a JSON array to CSV data and writes it to the output stream using a default comma as the delimiter.
     *
     * @param jsonArray     the JSON array to convert
     * @param outputStream  the output stream to write the CSV data to
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while writing the CSV data
     */
    public static void convertJSONtoCSV(JSONArray jsonArray, OutputStream outputStream)
            throws JSONException, IOException {
        convertJSONtoCSV(jsonArray, outputStream, ',', false);
    }

    /**
     * Converts a JSON array to CSV data and writes it to the output stream using the specified delimiter.
     *
     * @

param jsonArray     the JSON array to convert
     * @param outputStream  the output stream to write the CSV data to
     * @param delimiter     the delimiter character to use in the CSV data
     * @param validateData  flag indicating whether to perform data validation
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while writing the CSV data
     */
    public static void convertJSONtoCSV(JSONArray jsonArray, OutputStream outputStream, char delimiter, boolean validateData)
            throws JSONException, IOException {
        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {
            convertJSONtoCSV(jsonArray, writer, delimiter, validateData);
        }
    }

    /**
     * Converts a JSON array to CSV data and writes it to the writer using a default comma as the delimiter.
     *
     * @param jsonArray     the JSON array to convert
     * @param writer        the writer to write the CSV data to
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while writing the CSV data
     */
    public static void convertJSONtoCSV(JSONArray jsonArray, Writer writer) throws JSONException, IOException {
        convertJSONtoCSV(jsonArray, writer, ',', false);
    }

    /**
     * Converts a JSON array to CSV data and writes it to the writer using the specified delimiter.
     *
     * @param jsonArray     the JSON array to convert
     * @param writer        the writer to write the CSV data to
     * @param delimiter     the delimiter character to use in the CSV data
     * @param validateData  flag indicating whether to perform data validation
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while writing the CSV data
     */
    public static void convertJSONtoCSV(JSONArray jsonArray, Writer writer, char delimiter, boolean validateData)
            throws JSONException, IOException {
        if (jsonArray.length() == 0) {
            throw new JSONException("No data to convert");
        }

        JSONObject firstObject = jsonArray.getJSONObject(0);
        writeCSVHeader(firstObject, writer, delimiter);
        writer.write(System.lineSeparator());

        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            writeCSVRow(jsonObject, writer, delimiter, validateData);
            writer.write(System.lineSeparator());
        }
    }

    /**
     * Converts a JSON object with embedded objects and arrays to CSV data and returns it as a string
     * using a default comma as the delimiter.
     *
     * @param jsonObject    the JSON object to convert
     * @return the CSV data representing the converted object
     * @throws JSONException if there is an error during the conversion
     */
    public static String convertJSONObjectToCSV(JSONObject jsonObject) throws JSONException {
        return convertJSONObjectToCSV(jsonObject, ',');
    }

    /**
     * Converts a JSON object with embedded objects and arrays to CSV data and returns it as a string
     * using the specified delimiter.
     *
     * @param jsonObject    the JSON object to convert
     * @param delimiter     the delimiter character to use in the CSV data
     * @return the CSV data representing the converted object
     * @throws JSONException if there is an error during the conversion
     */
    public static String convertJSONObjectToCSV(JSONObject jsonObject, char delimiter) throws JSONException {
        StringWriter stringWriter = new StringWriter();
        try (BufferedWriter writer = new BufferedWriter(stringWriter)) {
            convertJSONObjectToCSV(jsonObject, writer, delimiter);
            return stringWriter.toString();
        } catch (IOException e) {
            // StringWriter should not throw IOException
            throw new RuntimeException("Unexpected error occurred while converting JSON object to CSV", e);
        }
    }

    /**
     * Converts a JSON object with embedded objects and arrays to CSV data and writes it to the writer
     * using a default comma as the delimiter.
     *
     * @param jsonObject    the JSON object to convert
     * @param writer        the writer to write the CSV data to
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while writing the CSV data
     */
    public static void convertJSONObjectToCSV(JSONObject jsonObject, Writer writer) throws JSONException, IOException {
        convertJSONObjectToCSV(jsonObject, writer, ',');
    }

    /**
     * Converts a JSON object with embedded objects and arrays to CSV data and writes it to the writer
     * using the specified delimiter.
     *
     * @param jsonObject    the JSON object to convert
     * @param writer        the writer to write the CSV data to
     * @param delimiter     the delimiter character to use in the CSV data
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while writing the CSV data
     */
    public static void convertJSONObjectToCSV(JSONObject jsonObject, Writer writer, char delimiter)
            throws JSONException, IOException {
        List<String> headers = new ArrayList<>();
        List<List<String>> rows = new ArrayList<>();

        extractHeaderAndRowsFromJSONObject(jsonObject, headers, rows);
        writeCSVData(writer, headers, rows, delimiter);
    }

    private static void extractHeaderAndRowsFromJSONObject(JSONObject jsonObject, List<String> headers, List<List<String>> rows)
            throws JSONException {
        Iterator<String> keys = jsonObject.keys();
        while (keys.hasNext()) {
            String key = keys.next();
            Object value = jsonObject.get(key);
            if (value instanceof JSONObject) {
                JSONObject nestedObject = (JSONObject) value;
                String nestedHeader = key;
                extractHeaderAndRowsFromJSONObject(nestedObject, appendKey(headers, nestedHeader), rows);
            } else if (value instanceof JSONArray) {
                JSONArray nestedArray = (JSONArray) value;
                extractRowsFromArray(nestedArray, rows, headers);
            } else {
                headers.add(key);
                extractRowFromValue(value, rows);
            }
        }
    }

    /**
     * Converts CSV data from a string to a Stream of JSON objects using a default comma as the delimiter.
     *
     * @param csvData the CSV data to convert
     * @return the Stream of JSON objects representing the converted data
     * @throws JSONException if there is an error during the conversion
     */
    public static Stream<JSONObject> convertCSVtoJSONStream(String csvData) throws JSONException {
        return convertCSVtoJSONStream(csvData, ',', false);
    }

    /**
     * Converts CSV data from a string to a Stream of JSON objects using the specified delimiter.
     *
     * @param csvData       the CSV data to convert
     * @param delimiter     the delimiter character used in the CSV data
     * @param validateData  flag indicating whether to perform data validation
     * @return the Stream of JSON objects representing the converted data
     * @throws JSONException if there is an error during the conversion
     */
    public static Stream<JSONObject> convertCSVtoJSONStream(String csvData, char delimiter, boolean validateData)
            throws JSONException {
        try (StringReader stringReader = new StringReader(csvData)) {
            return convertCSVtoJSONStream(stringReader, delimiter, validateData);
        }
    }

    /**
     * Converts CSV data from an input stream to a Stream of JSON objects using a default comma as the delimiter.
     *
     * @param inputStream the input stream containing the CSV data to convert
     * @return the Stream of JSON objects representing the converted data
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while reading the CSV data
     */
    public static Stream<JSONObject> convertCSVtoJSONStream(InputStream inputStream)
            throws JSONException, IOException {
        return convertCSVtoJSONStream(inputStream, ',', false);
    }

    /**
     * Converts CSV data from an input stream to a Stream of JSON objects using the specified delimiter.
     *
     * @param inputStream   the input stream containing the CSV data to convert
     * @param delimiter     the delimiter character used in the CSV data
     * @param validateData  flag indicating whether to perform data validation
     * @return the Stream of JSON objects representing the converted data
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while reading the CSV data
     */
    public static Stream<JSONObject> convertCSVtoJSONStream(InputStream inputStream, char delimiter, boolean validateData)
            throws JSONException, IOException {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            return convertCSVtoJSONStream(reader, delimiter, validateData);
        }
    }

    /**
     * Converts CSV data from a reader to a Stream of JSON objects using a default comma as the delimiter.
     *
     * @param reader        the reader containing the CSV data to convert
     * @return the Stream of JSON objects representing the converted data
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while reading the CSV data
     */
    public static Stream<JSONObject> convertCSVtoJSONStream(Reader reader) throws JSONException, IOException {
        return convertCSVtoJSONStream(reader, ',', false);
    }

    /**
     * Converts CSV data from a reader to a Stream of JSON objects using the specified delimiter.
     *
     * @param reader        the reader containing the CSV data to convert
     * @param delimiter     the delimiter character used in the CSV data
     * @param validateData  flag indicating whether to perform data validation
     * @return the Stream of JSON objects representing the converted data
     * @throws JSONException if there is an error during the conversion
     * @throws IOException   if an I/O error occurs while reading the CSV data
     */
    public static Stream<JSONObject> convertCSVtoJSONStream(Reader reader, char delimiter, boolean validateData)
            throws JSONException, IOException {
			return convertCSVtoJSONArray(reader,delimiter,validateData).toList().stream();
        }
    }


    private static List<String> appendKey(List<String> headers, String key) {
        List<String> newHeaders = new ArrayList<>();
        for (String header : headers) {
            newHeaders.add(header + "." + key);
        }
        return newHeaders;
    }

    private static void extractRowFromValue(Object value, List<List<String>> rows) {
        List<String> currentRow = new ArrayList<>();
        if (value instanceof JSONArray) {
            JSONArray valueArray = (JSONArray) value;
            for (int i = 0; i < valueArray.length(); i++) {
                currentRow.add(formatValue(valueArray.get(i)));
            }
        } else {
            currentRow.add(formatValue(value));
        }
        rows.add(currentRow);
    }

    private static void extractRowsFromArray(JSONArray jsonArray, List<List<String>> rows, List<String> headers)
            throws JSONException {
        for (int i = 0; i < jsonArray.length(); i++) {
            Object value = jsonArray.get(i);
            if (value instanceof JSONObject) {
                JSONObject nestedObject = (JSONObject) value;
                List<String> newRow = new ArrayList<>(headers);
                extractHeaderAndRowsFromJSONObject(nestedObject, newRow, rows);
            } else if (value instanceof JSONArray) {
                JSONArray nestedArray = (JSONArray

) value;
                List<String> newRow = new ArrayList<>(headers);
                extractRowsFromArray(nestedArray, rows, newRow);
            } else {
                List<String> currentRow = new ArrayList<>(headers);
                currentRow.add(formatValue(value));
                rows.add(currentRow);
            }
        }
    }

    private static void writeCSVData(Writer writer, List<String> headers, List<List<String>> rows, char delimiter)
            throws IOException {
        writeCSVRow(writer, headers, delimiter);
        for (List<String> row : rows) {
            writeCSVRow(writer, row, delimiter);
        }
    }

    private static void writeCSVRow(Writer writer, List<String> row, char delimiter) throws IOException {
        boolean first = true;
        for (String value : row) {
            if (!first) {
                writer.write(delimiter);
            }
            writer.write(escapeAndQuoteIfNeeded(value));
            first = false;
        }
        writer.write(System.lineSeparator());
    }

    private static void processField(JSONObject jsonObject, String header, String value) {
        String[] keys = header.split("\\.");
        int lastIndex = keys.length - 1;

        for (int i = 0; i < lastIndex; i++) {
            String key = keys[i];
            if (!jsonObject.has(key)) {
                jsonObject.put(key, new JSONObject());
            }
            jsonObject = jsonObject.getJSONObject(key);
        }

        jsonObject.put(keys[lastIndex], value);
    }

    private static String getCSVHeader(JSONObject jsonObject, char delimiter) {
        StringBuilder headerBuilder = new StringBuilder();
        String[] keys = jsonObject.keySet().toArray(new String[0]);

        for (int i = 0; i < keys.length; i++) {
            headerBuilder.append(escapeAndQuoteIfNeeded(keys[i]));
            if (i < keys.length - 1) {
                headerBuilder.append(delimiter);
            }
        }

        return headerBuilder.toString();
    }

    private static String getCSVRow(JSONObject jsonObject, char delimiter, boolean validateData) {
        StringBuilder rowBuilder = new StringBuilder();
        String[] keys = jsonObject.keySet().toArray(new String[0]);

        for (int i = 0; i < keys.length; i++) {
            Object value = jsonObject.get(keys[i]);
            String formattedValue = formatValue(value);

            if (validateData && formattedValue.contains(String.valueOf(delimiter))) {
                formattedValue = "\"" + formattedValue.replaceAll("\"", "\"\"") + "\"";
            }

            rowBuilder.append(formattedValue);

            if (i < keys.length - 1) {
                rowBuilder.append(delimiter);
            }
        }

        return rowBuilder.toString();
    }

    private static String formatValue(Object value) {
        if (value == null) {
            return "";
        } else {
            return value.toString();
        }
    }

    private static String normalizeHeader(String header) {
        return header.trim().toLowerCase().replace(" ", "_");
    }

    private static String escapeAndQuoteIfNeeded(String value) {
        if (value.contains(",") || value.contains("\"") || value.contains("\n") || value.contains("\r")) {
            return "\"" + value.replaceAll("\"", "\"\"") + "\"";
        } else {
            return value;
        }
    }
}

JUnit Testing

Certainly! Here’s an example of JUnit tests for CSVJSONConverter that cover edge cases and exception testing:

import org.json.JSONArray;
import org.json.JSONException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.io.IOException;

public class CSVJSONConverterTest {

    @Test
    public void testConvertCSVtoJSON_EmptyCSV() throws JSONException {
        String csvData = "";
        JSONArray jsonArray = CSVJSONConverter.convertCSVtoJSON(csvData);
        Assertions.assertEquals(0, jsonArray.length(), "JSON array should be empty for empty CSV");
    }

    @Test
    public void testConvertCSVtoJSON_EmptyCSVWithHeader() throws JSONException {
        String csvData = "Name,Age,City";
        JSONArray jsonArray = CSVJSONConverter.convertCSVtoJSON(csvData);
        Assertions.assertEquals(0, jsonArray.length(), "JSON array should be empty for CSV with only header");
    }

    @Test
    public void testConvertCSVtoJSON_ValidCSV() throws JSONException {
        String csvData = "Name,Age,City\nJohn,25,New York\nAlice,30,San Francisco";
        JSONArray jsonArray = CSVJSONConverter.convertCSVtoJSON(csvData);
        Assertions.assertEquals(2, jsonArray.length(), "JSON array should have 2 objects");
        Assertions.assertEquals("John", jsonArray.getJSONObject(0).getString("Name"), "Name should match");
        Assertions.assertEquals("30", jsonArray.getJSONObject(1).getString("Age"), "Age should match");
    }

    @Test
    public void testConvertCSVtoJSON_InvalidCSV_MismatchedValues() {
        String csvData = "Name,Age,City\nJohn,25";
        Assertions.assertThrows(JSONException.class, () -> {
            CSVJSONConverter.convertCSVtoJSON(csvData);
        }, "JSONException should be thrown for mismatched values in CSV");
    }

    @Test
    public void testConvertCSVtoJSON_InvalidCSV_EmptyData() {
        String csvData = null;
        Assertions.assertThrows(JSONException.class, () -> {
            CSVJSONConverter.convertCSVtoJSON(csvData);
        }, "JSONException should be thrown for null CSV data");
    }

    @Test
    public void testConvertJSONtoCSV_EmptyJSON() throws JSONException {
        JSONArray jsonArray = new JSONArray();
        String csvData = CSVJSONConverter.convertJSONtoCSV(jsonArray);
        Assertions.assertEquals("", csvData.trim(), "CSV data should be empty for empty JSON array");
    }

    @Test
    public void testConvertJSONtoCSV_ValidJSON() throws JSONException {
        JSONArray jsonArray = new JSONArray("[{\"Name\":\"John\",\"Age\":\"25\",\"City\":\"New York\"},{\"Name\":\"Alice\",\"Age\":\"30\",\"City\":\"San Francisco\"}]");
        String csvData = CSVJSONConverter.convertJSONtoCSV(jsonArray);
        String expectedCSV = "Name,Age,City\nJohn,25,New York\nAlice,30,San Francisco";
        Assertions.assertEquals(expectedCSV.trim(), csvData.trim(), "CSV data should match expected output");
    }

    @Test
    public void testConvertJSONtoCSV_EmptyJSONWithHeader() throws JSONException {
        JSONArray jsonArray = new JSONArray("[{}]");
        String csvData = CSVJSONConverter.convertJSONtoCSV(jsonArray);
        Assertions.assertEquals("No data to convert", csvData.trim(), "CSV data should be empty for JSON with no data");
    }

    @Test
    public void testConvertJSONtoCSV_InvalidJSON() {
        JSONArray jsonArray = null;
        Assertions.assertThrows(JSONException.class, () -> {
            CSVJSONConverter.convertJSONtoCSV(jsonArray);
        }, "JSONException should be thrown for null JSON array");
    }

    @Test
    public void testConvertJSONObjectToCSV_ValidJSONObject() throws JSONException {
        String jsonData = "{\"Name\":\"John\",\"Age\":\"25\",\"City\":\"New York\"}";
        JSONArray jsonArray = new JSONArray();
        jsonArray.put(new JSONObject(jsonData));
        String csvData = CSVJSONConverter.convertJSONObjectToCSV(jsonArray.getJSONObject(0));
        String expectedCSV = "Name,Age,City\nJohn,25,New York";
        Assertions.assertEquals(expectedCSV.trim(), csvData.trim(), "CSV data should match expected output");
    }

    @Test
    public void testConvertJSONObjectToCSV_EmptyJSONObject() throws JSONException {
        String jsonData = "{}";
        JSONArray jsonArray = new JSONArray();
        jsonArray.put(new JSONObject(jsonData));
        String csvData = CSVJSONConverter.convertJSONObjectToCSV(jsonArray.getJSONObject(0));
        Assertions.assertEquals("", csvData.trim(), "CSV data should be empty for empty JSON object");
    }

    @Test
    public void testConvertJSONObjectToCSV_NullJSONObject() {
        JSONObject jsonObject = null;
        Assertions.assertThrows(JSONException.class, () -> {
            CSVJSONConverter.convertJSONObjectToCSV(jsonObject);
        }, "JSONException should be thrown for null JSON object");
    }
}

These tests cover various scenarios, including edge cases and exception testing. They ensure that the CSVJSONConverter class behaves as expected and handles different input cases correctly.

Make sure to import the necessary dependencies (org.json.JSONArray, org.json.JSONException, org.json.JSONObject, and org.junit.jupiter.api.Assertions) and update the test methods as needed for your specific requirements.

Running these tests using a JUnit test runner will help ensure the correctness of the CSVJSONConverter class and provide confidence in its functionality.

By Jeffery Miller

I am known for being able to quickly decipher difficult problems to assist development teams in producing a solution. I have been called upon to be the Team Lead for multiple large-scale projects. I have a keen interest in learning new technologies, always ready for a new challenge.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.