Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.jsonparser.JsonParser Maven / Gradle / Ivy
Go to download
The library performs an operation on JSON and returns CSV data in the following output formats: String, File, and Writer.
package com.github.jsonparser;
import com.github.jsonparser.exception.JsonParsingException;
import com.github.jsonparser.model.JsonOrder;
import com.github.jsonparser.util.AppConstants;
import com.github.jsonparser.util.ErrorUtil;
import com.github.jsonparser.util.ExceptionConstants;
import com.github.jsonparser.util.ValidationUtil;
import com.google.gson.JsonElement;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.spi.json.JacksonJsonProvider;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
import com.jayway.jsonpath.spi.mapper.MappingProvider;
import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* This class parse a Json document to csv format. The default separator is "_" and delimiter is ",".
* The separator will be used to divide the json path.
* e.g. if json path user/name then csv column will be user_name.
* The JsonParser supports output in 3 different formats:
* 1. String
* 2. File
* 3. Writer
*
* @author Ram Alapure
* @version 1.0
* @since 17/02/2020
*/
public class JsonParser {
/**
* This method process the json input string and returns a csv string.
*
* @param json - Input json string
* @return Returns a csv string.
* @throws JsonParsingException
*/
public static String parse2Csv(String json) throws JsonParsingException {
ValidationUtil.rejectNull(json, "json");
List records = json2Sheet(json);
headerSeparator(records);
return write2String(records);
}
/**
* This method process the json input string and writes to csv file path provided.
*
* @param json
* @param csvFilePath
* @throws JsonParsingException
*/
public static void parse2Csv(String json, String csvFilePath) throws JsonParsingException {
ValidationUtil.rejectNull(json, "json");
ValidationUtil.rejectNull(csvFilePath, "csv file path");
List records = json2Sheet(json);
headerSeparator(records);
write2csv(records, csvFilePath);
}
/**
* This method process the json input string and writes csv output to writer {@link Writer}.
*
* @param json
* @param writer
* @throws JsonParsingException
*/
public static void parse2Csv(String json, Writer writer) throws JsonParsingException {
ValidationUtil.rejectNull(json, "json");
ValidationUtil.rejectNull(writer, "writer");
List records = json2Sheet(json);
headerSeparator(records);
write(records, writer);
}
/**
* This method process the json input string and returns a csv string.
*
* @param json - The input json
* @param separator - The custom header/column separator key
* @param delimiter - The custom delimiter key
* @return Returns string representation of csv.
* @throws JsonParsingException
*/
public static String parse2Csv(String json, String separator, String delimiter) throws JsonParsingException {
ValidationUtil.rejectNull(json, "json");
if (separator == null) separator = AppConstants.DEFAULT_SEPARATOR;
if (delimiter == null) delimiter = AppConstants.DEFAULT_DELIMITER;
List records = json2Sheet(json);
headerSeparator(records, separator);
return write2String(records, delimiter);
}
/**
* @param json - The input json
* @param csvFilePath - The output csv file path with name
* @param separator - The custom header/column separator key
* @param delimiter - The custom delimiter key
* @throws JsonParsingException
*/
public void parse2Csv(String json, String csvFilePath, String separator, String delimiter) throws JsonParsingException {
ValidationUtil.rejectNull(json, "json");
ValidationUtil.rejectNull(csvFilePath, "csv file path");
if (separator == null) separator = AppConstants.DEFAULT_SEPARATOR;
if (delimiter == null) delimiter = AppConstants.DEFAULT_DELIMITER;
List records = json2Sheet(json);
headerSeparator(records, separator);
write2csv(records, csvFilePath, delimiter);
}
/**
* This method process the json input string and writes csv output to writer {@link Writer}.
*
* @param json - The input json
* @param writer - The writer object to write the csv e.g. StringWriter, FileWriter, etc.
* @param separator - The custom header/column separator key
* @param delimiter - The custom delimiter key
* @throws JsonParsingException
*/
public void parse2Csv(String json, Writer writer, String separator, String delimiter) throws JsonParsingException {
ValidationUtil.rejectNull(json, "json");
ValidationUtil.rejectNull(writer, "writer");
if (separator == null) separator = AppConstants.DEFAULT_SEPARATOR;
if (delimiter == null) delimiter = AppConstants.DEFAULT_DELIMITER;
List records = json2Sheet(json);
headerSeparator(records, separator);
write(records, writer, delimiter);
}
/**
* This method process the input json and used the column/header from xsd schema json string.
*
* @param json - The input json
* @param xsdSchema - The xsd schema json string
* @return Returns string representation of csv.
* @throws JsonParsingException
*/
public String parse2CsvWithXsd(String json, String xsdSchema) throws JsonParsingException {
ValidationUtil.rejectNull(json, "json");
ValidationUtil.rejectNull(xsdSchema, "xsd schema");
List records = json2Sheet(json, xsdSchema);
headerSeparator(records);
return write2String(records);
}
/**
* This method process the input json and used the column/header from xsd schema json string to create csv.
*
* @param json - The input json
* @param xsdSchema - The xsd schema json string
* @param csvFilePath - The output csv file path with name
* @throws JsonParsingException
*/
public void parse2CsvWithXsd(String json, String xsdSchema, String csvFilePath) throws JsonParsingException {
ValidationUtil.rejectNull(json, "json");
ValidationUtil.rejectNull(xsdSchema, "xsd schema");
List records = json2Sheet(json, xsdSchema);
headerSeparator(records);
write2csv(records, csvFilePath);
}
/**
* This method process the input json and used the column/header from xsd schema json string to create csv.
*
* @param json - The input json
* @param xsdSchema - The xsd schema json string
* @param writer - The writer object to write the csv e.g. StringWriter, FileWriter, etc.
* @throws JsonParsingException
*/
public void parse2CsvWithXsd(String json, String xsdSchema, Writer writer) throws JsonParsingException {
ValidationUtil.rejectNull(json, "json");
ValidationUtil.rejectNull(xsdSchema, "xsd schema");
ValidationUtil.rejectNull(writer, "writer");
List records = json2Sheet(json, xsdSchema);
headerSeparator(records);
write(records, writer);
}
/**
* This method does some pre processing and then build csv.
*
* @param json - The input json
* @return Returns list of records.
*/
private static List json2Sheet(String json) {
return processJson(json, null);
}
/**
* This method does some pre processing and then build csv.
*
* @param json - The input json
* @param xsd - The xsd schema json string
* @return Returns list of records.
*/
private List json2Sheet(String json, String xsd) {
return processJson(json, xsd);
}
/**
* This method does some pre processing and then calls buildCsv() to get the
* 2D representation of Json document.
*
* @param json - The input json
* @return Returns list of records.
*/
private List json2Header(String json) {
List records = new ArrayList<>();
configureAndBuildHeader(json, records);
return records;
}
/**
* This method process the input json to csv with the xsd schema if given.
*
* @param json - The input json
* @param xsd - The xsd schema json string can be null
* @return Returns list of records.
*/
private static List processJson(String json, String xsd) {
List records = new ArrayList<>();
List headers;
if (xsd == null) headers = configureAndBuildHeader(json, records);
else headers = configureAndBuildHeader(xsd, records);
//adding all the content of csv
JsonElement ele = com.google.gson.JsonParser.parseString(json);
records.add(buildCsv(new Object[headers.size()], ele, "$", headers, records));
removeDuplicates(records);
return records;
}
/**
* This method removes the duplicate records from list.
*
* @param records - List of records processed from json.
*/
private static void removeDuplicates(List records) {
Object[] last = records.get(records.size() - 1);
Object[] secondLast = records.get(records.size() - 2);
boolean delete = true;
for (Object o : last) {
if (o != null) {
delete = false;
break;
}
}
if (!delete) {
delete = true;
for (int DEL = 0; DEL < last.length; DEL++) {
if (last[DEL] != null && !last[DEL].equals(secondLast[DEL])) {
delete = false;
break;
}
}
}
if (delete) records.remove(records.size() - 1);
}
/**
* This method build configuration for json processing and extracting the headers/columns.
*
* @param json - The input json for processing
* @param records - The input record list to add headers/columns.
* @return Returns he headers/columns.
*/
private static ArrayList configureAndBuildHeader(String json, List records) {
setDefaultConfiguration();
Configuration conf = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL)
.addOptions(Option.SUPPRESS_EXCEPTIONS);
Configuration pathConf = Configuration.defaultConfiguration().addOptions(Option.AS_PATH_LIST)
.addOptions(Option.ALWAYS_RETURN_LIST);
List pathList = JsonPath.using(pathConf).parse(json).read("$..*");
DocumentContext context = JsonPath.using(conf).parse(json);
HashSet primitivePaths = extractPrimitivePaths(context, pathList);
HashSet uniquePrimitivePaths = primitivePaths.stream().map(JsonParser::evaluatePath)
.collect(Collectors.toCollection(LinkedHashSet::new));
ArrayList uniqueHeaders = new ArrayList<>(uniquePrimitivePaths);
addHeaders(uniqueHeaders, records);
return uniqueHeaders;
}
private static void setDefaultConfiguration() {
Configuration.setDefaults(new Configuration.Defaults() {
private final JsonProvider jsonProvider = new JacksonJsonProvider();
private final MappingProvider mappingProvider = new JacksonMappingProvider();
// @Override
public JsonProvider jsonProvider() {
return jsonProvider;
}
// @Override
public MappingProvider mappingProvider() {
return mappingProvider;
}
// @Override
public Set options() {
return EnumSet.noneOf(Option.class);
}
});
}
/**
* This method extracts the primitive paths headers/columns from the json.
*
* @param parse - The json parse document context.
* @param pathList - The input path list.
* @return Returns primitive paths headers/columns.
*/
private static HashSet extractPrimitivePaths(DocumentContext parse, List pathList) {
HashSet primitivePaths = new LinkedHashSet<>();
pathList.forEach(path -> {
Object tmp = parse.read(path);
if (tmp == null) {
primitivePaths.add(path);
} else {
String dataType = tmp.getClass().getSimpleName();
if (dataType.equals("Boolean") || dataType.equals("Integer") || dataType.equals("String")
|| dataType.equals("Double") || dataType.equals("Long")) {
primitivePaths.add(path);
} else {
// its not a primitive data type
}
}
});
return primitivePaths;
}
private static void addHeaders(List unique, List records) {
Object[] headers = new Object[unique.size()];
int i = 0;
for (String header : unique) {
headers[i] = header;
i++;
}
//headers of the csv
records.add(headers);
}
/**
* This function transforms the JSON document to its equivalent 2D representation.
*
* @param old it keeps the old row which is always assigned to the current
* row.
* @param ele this keeps the part of json being parsed to 2D.
* @param path this maintains the path of the Json element being processed.
* @param headers
* @param records
* @return
*/
private static Object[] buildCsv(Object[] old, JsonElement ele, String path, List headers, List records) {
Object[] cur = old.clone();
boolean gotArray;
String tmpPath;
if (ele.isJsonObject()) {
ele = JsonOrder.orderJson(ele);
for (Map.Entry entry : ele.getAsJsonObject().entrySet()) {
if (entry.getValue().isJsonPrimitive()) {
tmpPath = path + "['" + entry.getKey() + "']";
evaluateTempPath(cur, entry, tmpPath, headers);
} else if (entry.getValue().isJsonObject()) {
cur = buildCsv(cur, entry.getValue().getAsJsonObject(),
path + "['" + entry.getKey() + "']", headers, records);
} else if (entry.getValue().isJsonArray()) {
cur = buildCsv(cur, entry.getValue().getAsJsonArray(),
path + "['" + entry.getKey() + "']", headers, records);
}
}
} else if (ele.isJsonArray()) {
int arrIndex = 0;
for (JsonElement jsonElement : ele.getAsJsonArray()) {
if (jsonElement.isJsonPrimitive()) {
tmpPath = path + "['" + arrIndex + "']";
evaluateTempPath(cur, jsonElement, tmpPath, headers);
} else {
if (jsonElement.isJsonObject()) {
gotArray = isInnerArray(jsonElement);
records.add(buildCsv(cur, jsonElement.getAsJsonObject(), path + "[" + arrIndex + "]", headers, records));
if (gotArray) records.remove(records.size() - 1);
} else if (jsonElement.isJsonArray()) {
buildCsv(cur, jsonElement.getAsJsonArray(), path + "[" + arrIndex + "]", headers, records);
}
}
arrIndex++;
}
}
return cur;
}
private static void evaluateTempPath(Object[] cur, Map.Entry entry, String tmpPath, List headers) {
tmpPath = evaluatePath(tmpPath);
if (headers.contains(tmpPath)) {
int index = headers.indexOf(tmpPath);
cur[index] = entry.getValue().getAsJsonPrimitive();
}
}
private static void evaluateTempPath(Object[] cur, JsonElement tmp, String tmpPath, List headers) {
tmpPath = evaluatePath(tmpPath);
if (headers.contains(tmpPath)) {
int index = headers.indexOf(tmpPath);
cur[index] = tmp.getAsJsonPrimitive();
}
}
private static String evaluatePath(String path) {
Pattern pattern = Pattern.compile(AppConstants.REGEX, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(path);
String str;
if (matcher.find()) {
String[] tmp = path.replace("$", "").split(AppConstants.REGEX);
tmp[0] = tmp[0].replaceAll("(\\[[0-9]*\\])", "");
str = "/" + (tmp[0] + matcher.group()).replace("'][", "/");
} else {
str = "/" + path.replace("$", "").replaceAll("(\\[[0-9]*\\])", "");
}
return commonReplace(str);
}
private static String commonReplace(String str) {
return str.replace("[", "")
.replace("]", "")
.replace("''", "/")
.replace("'", "");
}
/**
* This method checks whether object inside an array contains an array or
* not.
*
* @param ele it a Json object inside an array
* @return it returns true if Json object inside an array contains an array
* or else false
*/
private static boolean isInnerArray(JsonElement ele) {
for (Map.Entry entry : ele.getAsJsonObject().entrySet()) {
JsonElement jsonElement = entry.getValue();
if (jsonElement.isJsonArray() && jsonElement.getAsJsonArray().size() > 0) {
for (JsonElement checkPrimitive : jsonElement.getAsJsonArray()) {
if (checkPrimitive.isJsonObject()) return true;
}
}
}
return false;
}
/**
* This method replaces the default header separator i.e. "/" with a underscore.
*
* @return JsonParser
*/
private static void headerSeparator(List records) {
headerSeparator(records, AppConstants.DEFAULT_SEPARATOR);
}
/**
* This method replaces the default header separator i.e. "/" with a custom separator provided by user.
*
* @param records
* @param separator
* @return JsonParser
*/
private static void headerSeparator(List records, String separator) {
int length = records.get(0).length;
for (int I = 0; I < length; I++) {
records.get(0)[I] = records.get(0)[I].toString()
.replaceFirst("^\\/", "")
.replaceAll("/", separator).trim();
}
}
/**
* This method writes the 2D representation in csv format with ',' as
* default delimiter.
*
* @param records
* @param destination it takes the destination path for the csv file.
*/
private static void write2csv(List records, String destination) throws JsonParsingException {
write2csv(records, destination, AppConstants.DEFAULT_DELIMITER);
}
/**
* This method writes the 2D representation in csv format with ',' as
* default delimiter.
*
* @param records
* @return
*/
private static String write2String(List records) throws JsonParsingException {
return write2String(records, AppConstants.DEFAULT_DELIMITER);
}
/**
* This method writes the 2D representation in csv format with custom
* delimiter set by user.
*
* @param records
* @param destination it takes the destination path for the csv file.
* @param delimiter it represents the delimiter set by user.
* @throws FileNotFoundException
* @throws UnsupportedEncodingException
*/
private static void write2csv(List records, String destination, String delimiter) throws JsonParsingException {
PrintWriter writer = null;
try {
writer = new PrintWriter(new File(destination), Charset.defaultCharset().name());
write(records, writer, delimiter);
writer.close();
} catch (FileNotFoundException e) {
ErrorUtil.jsonParsingException(String.format(ExceptionConstants.STR_FILE_EXCEPTION, destination), e);
} catch (UnsupportedEncodingException e) {
ErrorUtil.jsonParsingException(ExceptionConstants.STR_PARSING_EXCEPTION, e);
}
}
private static String write2String(List records, String delimiter) throws JsonParsingException {
StringWriter writer = new StringWriter();
try {
write(records, writer, delimiter);
writer.close();
} catch (IOException e) {
ErrorUtil.jsonParsingException(ExceptionConstants.STR_IO_EXCEPTION, e);
}
return writer.toString();
}
private static void write(List records, Writer writer) throws JsonParsingException {
write(records, writer, AppConstants.DEFAULT_DELIMITER);
}
private static void write(List records, Writer writer, String delimiter) throws JsonParsingException {
try {
for (Object[] data : records) {
boolean comma = false;
for (Object text : data) {
String str;
if (text == null) {
str = comma ? delimiter : "";
} else {
str = comma ? delimiter + text.toString() : text.toString();
}
writer.write(str);
if (!comma) comma = true;
}
writer.write("\n");
}
} catch (IOException e) {
ErrorUtil.jsonParsingException(ExceptionConstants.STR_IO_EXCEPTION, e);
}
}
}