Parse csv data and convert to nested json java - java

I'm searching for simplest way or any jar available to read csv file in java and convert to into nested json. I tried searching for various sources, but all the places i could find results for simple json, but my need is i should read csv file which later has to be converted to json string in the below format
{
"studentName": "Foo",
"Age": "12",
"address":{
"city" : "newyork",
"address1": "North avenue",
"zipcode" : "123213"
},
"subjects": [
{
"name": "English",
"marks": "40"
},
{
"name": "History",
"marks": "50"
}
]
}
I'm fine with any format in csv, however after reading csv file i need to create json string like above.
csv file format:
"studentName","Age","address__city","address__address1","address__zipcode","subjects__name","subjects__marks"
"Foo","12","newyork","North avenue","123213","English","40"
"","","","","","History","50"

You can use JackSon to convert CSV to JSON. For example see the following code:
import java.io.File;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
public class CSV2JSON {
public static void main(String[] args) throws Exception {
File input = new File("input.csv");
File output = new File("output.json");
CsvSchema csvSchema = CsvSchema.builder().setUseHeader(true).build();
CsvMapper csvMapper = new CsvMapper();
// Read data from CSV file
List<object> readAll = csvMapper.readerFor(Map.class).with(csvSchema).readValues(input).readAll();
ObjectMapper mapper = new ObjectMapper();
// Write JSON formated data to output.json file
mapper.writerWithDefaultPrettyPrinter().writeValue(output, readAll);
// Write JSON formated data to stdout
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(readAll));
}
}
If you are using maven you can add the Jackson dependency as following:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
<version>2.8.9</version>
</dependency>

Related

how to read a csv to a nested json with jackson java

i have this type of csv :
metric,value,date
temp_a,622.0,1477895624866
temp_a,-3.0,1477916224866
temp_a,365.0,1477917224866
temp_b,861.0,1477895624866
temp_b,767.0,1477917224866
and i want to use java jackson to convert it to json but not any json; it needs to be like this:
[
{
"metric":"temp_a",
"datapoints":[
[622, 1477895624866],
[-3, 1477916224866],
[365, 1477917224866]
]
},
{
"metric":"temp_b",
"datapoints":[
[861, 1477895624866],
[767, 1477917224866]
]
}
]
where dataponits is an array containing the value and the date in the csv .
i have managed to use the jackson to get this result :
{metric=temp_a, value=622.0, date=1477895624866}
{metric=temp_a, value=-3.0, date=1477916224866}
{metric=temp_a, value=365.0, date=1477917224866}
{metric=temp_b, value=861.0, date=1477895624866}
{metric=temp_b, value=767.0, date=1477917224866}
but it is not what i want and the jackson doc is a bit hard for me to understand and play with , may be this is possible with Pojos or annotations but i can't understand them, i couldn't find how to do a nested json.
if i can do this better this something else then jackson please tell me .
thank you for helping.
You do not have to always deserialise CSV to a POJO structure and implement custom serialisers. In this case, you can also:
Deserialise CSV to a Map
Group by elements in a Map to a form metric -> [[...], [...]]
Convert above Map to another form of Map
Serialise Map to a JSON
Example code could look like below:
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectMapper;
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.math.BigDecimal;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class CsvApp {
public static void main(String[] args) throws Exception {
File csvFile = new File("./resource/test.csv").getAbsoluteFile();
CsvMapper csvMapper = CsvMapper.builder().build();
MappingIterator<Map> rows = csvMapper
.readerWithSchemaFor(Map.class)
.with(CsvSchema.emptySchema().withHeader())
.readValues(csvFile);
DataConverter converter = new DataConverter();
List<Map<String, Object>> result = converter.toMetricDataPoints(rows);
ObjectMapper jsonMapper = JsonMapper.builder()
.enable(SerializationFeature.INDENT_OUTPUT)
.build();
jsonMapper.writeValue(System.out, result);
}
}
class DataConverter {
public List<Map<String, Object>> toMetricDataPoints(MappingIterator<Map> rows) {
return toStream(rows)
//group by metric -> [value, date]
.collect(Collectors.groupingBy(map -> map.get("metric"),
Collectors.mapping(map -> Arrays.asList(toNumber(map.get("value")), toNumber(map.get("date"))),
Collectors.toList())))
.entrySet().stream()
// convert to Map: metric + datapoints
.map(entry -> {
Map<String, Object> res = new LinkedHashMap<>(4);
res.put("metric", entry.getKey());
res.put("datapoints", entry.getValue());
return res;
}).collect(Collectors.toList());
}
private Stream<Map> toStream(MappingIterator<Map> rowIterator) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(rowIterator, Spliterator.ORDERED), false);
}
private long toNumber(Object value) {
return new BigDecimal(Objects.toString(value, "0")).longValue();
}
}
Above code prints:
[ {
"metric" : "temp_a",
"datapoints" : [ [ 622, 1477895624866 ], [ -3, 1477916224866 ], [ 365, 1477917224866 ] ]
}, {
"metric" : "temp_b",
"datapoints" : [ [ 861, 1477895624866 ], [ 767, 1477917224866 ] ]
} ]
As you can see, we used only basic Jackson functionality, rest of manipulation on data we implemented using Java 8 API.
See also:
Directly convert CSV file to JSON file using the Jackson library
How to convert an iterator to a stream?
Jackson JSON Deserialization: array elements in each line

Java - Parse Yaml to Json

Python and Ruby have very nice libraries for parsing a Yaml file into a JSON object.
The parser needs to support Yaml Anchor and References.
Input
info: &info
legs: 4 legs
type: pet
dog: *info
cat: *info
Desired output:
{
"info": {
"legs": "4 legs",
"type": "pet"
},
"dog": {
"legs": "4 legs",
"type": "pet"
},
"cat": {
"legs": "4 legs",
"type": "pet"
}
}
I first tried the Jackson YAMLFactory. That library did not generically support anchors and references.
What is a good solution in Java for parsing Yaml into a JSON object?
The following solution seemed to work.
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedHashMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.yaml.snakeyaml.Yaml;
public class YamlParser {
public static void main(String[] argv) {
File f = new File("my.yml");
final Yaml yaml = new Yaml();
try {
final Object loadedYaml = yaml.load(new FileReader(f));
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(loadedYaml,LinkedHashMap.class);
System.out.println(json);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
With the following maven dependencies.
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.21</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>

How to convert json file to excel file in java

I,m given a problem to convert JSON file to excel file, in short to convert JSON data to excel data. Tried mapping JSON keys and values but can't do it.
Tried mapping JSON keys and values but can't do it. I have already used apache POI api.
public class jsontoexcel {
public static void main(String[] args) throws IOException,JSONException {
jsontoexcel json4=new jsontoexcel();
JSONObject json=json4.ReadJson();
JSONArray array =new JSONArray();
JSONObject rowjson=json.getJSONArray("rows").getJSONObject(0);
XSSFWorkbook workbook=new XSSFWorkbook();
XSSFSheet sheet=workbook.createSheet("Company Details");
int len=rowjson.length();
String[] RowArr=new String[len];
Iterator<String> keys = rowjson.keys();
int i=0;
while(keys.hasNext())
{
RowArr[i]=keys.next();
System.out.print("key:"+keys);
i++;
}
List<String> slist= new ArrayList<String>();
slist=json.get(rowjson.toString(keys));
FileOutputStream out=new FileOutputStream(new File("C:\\code\\eclipse\\jsontoexcel\\src\\output.xlsx"));
createHeaderRow(sheet, RowArr);
workbook.write(out);
out.close();
// Map<String,Object> map=new Map<String,Object>();
}
public static void createHeaderRow(XSSFSheet sheet, String[] RowArr)
{
Row row=sheet.createRow(0);
for(int i=0;i<RowArr.length-1;i++)
{
Cell cellTitle=row.createCell(i+1);
String cellVal=RowArr[i];
System.out.print("Cell data" + cellVal);
}
}
}
I expect the output to be stored in an excel file. The headers are getting printed but not the values.
Do not generate Excel file until you really have to. In case, you want to generate data without any specific formatting, charts, macros, etc. just generate CSV file with pure data. To read JSON and generate CSV you can use Jackson library which supports these two data formats. Just assume your JSON looks like below:
{
"rows": [
{
"id": 1,
"name": "Vika",
"age": 27
},
{
"id": 2,
"name": "Mike",
"age": 28
}
]
}
You, need to create POJO model which fits to that structure, deserialise JSON to objects and serialise objects to CSV format. Example solution, could look like below:
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SequenceWriter;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import java.io.File;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper jsonMapper = new ObjectMapper();
Response response = jsonMapper.readValue(jsonFile, Response.class);
CsvMapper csvMapper = new CsvMapper();
CsvSchema schema = csvMapper.schemaFor(Item.class).withHeader();
SequenceWriter sequenceWriter = csvMapper.writer(schema).writeValues(System.out);
sequenceWriter.writeAll(response.getRows());
}
}
class Response {
private List<Item> rows;
// getters, setters
}
#JsonPropertyOrder({"id", "name", "age"})
class Item {
private int id;
private String name;
private int age;
// getters, setters
}
Above code prints:
id,name,age
1,Vika,27
2,Mike,28
See also:
jackson-dataformats-text
Intro to the Jackson ObjectMapper

Is there a way to serialise Java TreeMap into a JSON?

I have a Java TreeMap frutitas inside a custom object on the server side which I want to send to the frontend.
I use javax.ws and jackson to serialise. The data that I get in the frontend looks like this:
{ "frutitas": {
"entry": [
{
"key": "fruto 1",
"value": "el banano"
},
{
"key": "fruto 2",
"value": "el pineapple"
}
]
}
But I want to get something like this, which is actually how I send the "frutitas" map inside the object that I send to the backend when I want to upload it:
{
"frutitas": {
"fruto 1": "el banano",
"fruto 2": "el pineapple"
}
}
Another option is to use gson.
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
And the class containing the map:
public class FrutitasClass {
private Map<String, String> frutitas;
}
The code below would the conversion:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(frutitasClassObject);
Out:
{
"frutitas": {
"fruto 1": "el banano",
"fruto 2": "el pineapple"
}
}
You can convert TreeMap to JSONObject as you expected. Here is the sample so that you can get the idea.
JSONObject jsonObject = new JSONObject(yourTreeMap);
If you print jsonObject, Output will be like this.
{"fruto 1":"el banan","fruto 2":"el pineapple"}
JSONObject main = new JSONObject();
main.put("frutitas", jsonObject);
{
"frutitas": {
"fruto 1": "el banano",
"fruto 2": "el pineapple"
}
}
Library Json-Jackson also known as FasterXML is de-facto standard for JSON serialization-deserialization. It works fast and is widely used. Below is a simple class that I wrote for serializing/de-serializing any Object. But in general you need to look at ObjectMapper class to see how it works. Here is Github link to a project. Here are Maven dependencies you may use:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.9.9</version>
</dependency>
My Class Example
package com.bla.json.utils;
import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class JsonUtil {
private static final ObjectReader objectReader;
private static final ObjectWriter objectWriter;
static {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModules(new JavaTimeModule());
objectMapper.enableDefaultTyping();
objectReader = objectMapper.reader();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectWriter = objectMapper.writer();
}
public static String writeObjectToJsonString(Object object) throws JsonProcessingException {
String jsonData = null;
if (object != null) {
jsonData = objectWriter.writeValueAsString(object);
}
return jsonData;
}
public static <T> T readObjectFromJsonString(String s, Class<T> type) throws IOException {
T data = objectReader.forType(type).readValue(s);
return data;
}
}

how to apply Json serialization or deserialization in request and response to HTTP method of rest api

I am very new to Rest api in java .My Question is how to directly convert json string request to java class object before post or get function ,like
json string : '{"id":3,"name":name}'
rest api post method :
#Post
public Something postData(Something obj) throws Exception {
}
so how to apply json serialization before request to this method.
right now i am converting it inside postData method.
You can use Jackson API to play with JSON.
For the Following JSON data the Java object mapping can be done as follows.
{
"id": 123,
"name": "Pankaj",
"permanent": true,
"address": {
"street": "Albany Dr",
"city": "San Jose",
"zipcode": 95129
},
"phoneNumbers": [
123456,
987654
],
"role": "Manager",
"cities": [
"Los Angeles",
"New York"
],
"properties": {
"age": "29 years",
"salary": "1000 USD"
}
}
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.journaldev.jackson.model.Address;
import com.journaldev.jackson.model.Employee;
public class JacksonObjectMapperExample {
public static void main(String[] args) throws IOException {
//read json file data to String
byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));
//create ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper();
//convert json string to object
Employee emp = objectMapper.readValue(jsonData, Employee.class);
System.out.println("Employee Object\n"+emp);
//convert Object to json string
Employee emp1 = createEmployee();
//configure Object mapper for pretty print
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
//writing to console, can write to any output stream such as file
StringWriter stringEmp = new StringWriter();
objectMapper.writeValue(stringEmp, emp1);
System.out.println("Employee JSON is\n"+stringEmp);
}
public static Employee createEmployee() {
Employee emp = new Employee();
emp.setId(100);
emp.setName("David");
emp.setPermanent(false);
emp.setPhoneNumbers(new long[] { 123456, 987654 });
emp.setRole("Manager");
Address add = new Address();
add.setCity("Bangalore");
add.setStreet("BTM 1st Stage");
add.setZipcode(560100);
emp.setAddress(add);
List<String> cities = new ArrayList<String>();
cities.add("Los Angeles");
cities.add("New York");
emp.setCities(cities);
Map<String, String> props = new HashMap<String, String>();
props.put("salary", "1000 Rs");
props.put("age", "28 years");
emp.setProperties(props);
return emp;
}
}
Source : http://www.journaldev.com/2324/jackson-json-processing-api-in-java-example-tutorial
You can use Gson or do a manually serialization/deserialization using JSONObject/JSONArray classes (example here). There are many other ways/libs to do this.

Categories