'How to convert csv To nested Json in java?
i have a csv file in following format
A_aa,A_ab,A_ac,A_ad,B_BB_ba,B_BB_BBB_bb
1,2,3,4,5,6
and i want to convert it into following Nested json
{
'A':{
'aa' : '1',
'ab' : '2',
'ac' : '4',
'ad' : '5',
}
'B':{
'BB':{
'ba' : '5',
'BBB':{
'bb' : '6'
}
}
}
}
Solution 1:[1]
I wrote you part of solution. Please use maven dependency
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
The java class:
package com.mycompany.app;
import com.google.gson.Gson;
public class Car
{
public A A;
public B B;
public A getA()
{
return A;
}
public void setA(A a)
{
this.A = a;
}
public B getB()
{
return B;
}
public void setB(B b)
{
this.B = b;
}
public class A {
String aa;
String ab;
String ac;
String ad;
public String getAa()
{
return aa;
}
public void setAa(String aa)
{
this.aa = aa;
}
public String getAb()
{
return ab;
}
public void setAb(String ab)
{
this.ab = ab;
}
public String getAc()
{
return ac;
}
public void setAc(String ac)
{
this.ac = ac;
}
public String getAd()
{
return ad;
}
public void setAd(String ad)
{
this.ad = ad;
}
}
public class B {
public BB BB;
public BB getBb()
{
return BB;
}
public void setBb(BB bb)
{
this.BB = bb;
}
public class BB {
String ba;
public BBB BBB;
public String getBa()
{
return ba;
}
public void setBa(String ba)
{
this.ba = ba;
}
public BBB getBbb()
{
return BBB;
}
public void setBbb(BBB bbb)
{
this.BBB = bbb;
}
public class BBB {
public String bb;
public String getBb()
{
return bb;
}
public void setBb(String bb)
{
this.bb = bb;
}
}
}
}
public static void main(String[] args)
{
String line1="A_aa,A_ab,A_ac,A_ad,B_BB_ba,B_BB_BBB_bb";
String line2="1,2,3,4,5,6";
String[] partsLinke1 = line1.split(",");
String[] partsLinke2 = line2.split(",");
Car c=new Car();
Gson gson = new Gson();
int k=0;
for(int i=0; i<partsLinke1.length; i++) {
System.out.println(partsLinke1[i]);
String[] parts=partsLinke1[i].split("_");
for(int j=0; j<parts.length; j++) {
System.out.println(parts[j]);
if(parts[j].equals("A")) {
Car.A aJson=c.new A();
if(parts[j+1].equals("aa")) {
aJson.setAa(partsLinke2[k]);
c.setA(aJson);
}
}
}
}
String json = gson.toJson(c);
System.out.println(json);
}
}
and the output:
A_aa
A
aa
A_ab
A
ab
A_ac
A
ac
A_ad
A
ad
B_BB_ba
B
BB
ba
B_BB_BBB_bb
B
BB
BBB
bb
{"A":{"aa":"1"}}
I think now it will be easier for you to write the rest ;)
Solution 2:[2]
Your question can be divided into 2 sub-questions.
Q1: How to transform the underscore('_') separated string pattern into nested map. Because once you can achieve this, you can convert the map to JSON string by using any one of the most popular Json libraries such as Jackson
or Gson
,
Q2: How to parse a CSV file. I think there are already many articles discussed about this.
For the first sub-question, inspired by @Andreas's answer in Generate Nested Map from Path String in Java, the problem can be solved with following function:
public static void generateNestedMap(Map<String, Object> map, String path, Object value) {
int start = 0;
for (int end; (end = path.indexOf('_', start)) != -1; start = end + 1)
map = (Map<String, Object>) map.computeIfAbsent(path.substring(start, end), k -> new HashMap<String, Object>());
map.put(path.substring(start), value);
}
Then you can store given strings and corresponding values in a map, says Map<String, Object> result
as follows:
Code snippet
Map<String, Object> result = new HashMap<>();
generateNestedMap(result, "A_aa", 1);
generateNestedMap(result, "A_ab", 2);
generateNestedMap(result, "A_ac", 3);
generateNestedMap(result, "A_ad", 4);
generateNestedMap(result, "B_BB_ba", 5);
generateNestedMap(result, "B_BB_BBB_bb", 6);
System.out.println(result.toString());
Console output
{A={aa=1, ab=2, ac=3, ad=4}, B={BB={BBB={bb=6}, ba=5}}}
After that, you can easily convert the map to a JSON string with Jackson
library as follows:
ObjectMapper mapper = new ObjectMapper();
String jsonStr = mapper.writeValueAsString(result);
System.out.println(jsonStr);
And its output should be:
{"A":{"aa":1,"ab":2,"ac":3,"ad":4},"B":{"BB":{"BBB":{"bb":6},"ba":5}}}
For the second sub-question, there are also many libraries such as OpenCSV
or Apache Commons CSV
to handle this and I won't go into details.
Solution 3:[3]
First, split the two lines to get a names
and a values
array:
String line1 = "A_aa,A_ab,A_ac,A_ad,B_BB_ba,B_BB_BBB_bb";
String line2 = "1,2,3,4,5,6";
String[] names = line1.split(",");
String[] values = line2.split(",");
Create a structure of Map
s and add each name/value pair to it:
Map<String,Object> root = new HashMap<>();
for (int i = 0; i < names.length; ++i) {
String name = names[i];
String value = values[i];
addValue(root, name.split("_"), value);
}
Method addValue
looks like this:
private static void addValue(Map<String,Object> map, String[] path,
String value) {
for (int i = 0; i < path.length-1; ++i) {
String elem = path[i];
Object current = map.get(elem);
Map<String,Object> map2;
if (current instanceof Map) {
map2 = (Map<String,Object>)map.get(elem);
} else {
map2 = new HashMap<>();
map.put(elem, map2);
}
map = map2;
}
map.put(path[path.length-1], value);
}
Finally, convert the structure to JSON. Here, library Gson is used:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
gson.toJson(root, System.out);
Solution 4:[4]
The CSV file’s first row contains field headers (the underline is used to represent the hierarchical relationship. Detail data begins from the second row. Your need is to transform the CSV to JSON. The difficulty lies in dynamic parsing because it involves grouping, recursion, loop, conditional judgment and string concatenation. The code will be really lengthy if you try to achieve your task using Java.
It is easy to achieve this using SPL, the open-source Java package. Five lines of code are enough:
A | B | |
---|---|---|
1 | =file("json.csv").import@cw() | |
2 | =i=0,A1(1).(~.split("_")).(~|A1(2)(#)).(~.run(~="\""/~/"\"")) | |
3 | func recurse(AA) | >B1=left(B1,-i)/"{}"/right(B1,i),i+=1,AA.group(~(1)).(if(~.len()==1 && ~(1).len()==2,B1=left(B1,-i)/~(1).concat(":")/right(B1,i),(B1=left(B1,-i)/~(1)(1)/":"/right(B1,i),func(recurse,~.(~.m(2:)))))) |
4 | =func(recurse,A2) | |
5 | =replace(replace(B1,"\"\"","\",\""),"}\"","},\"") |
SPL offers JDBC driver to be invoked by Java. Just store the above SPL script as recurse.splx and invoke it in Java as you call a stored procedure:
…
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
st = con.prepareCall("call recurse()");
st.execute();
…
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Daniel Jab?o?ski |
Solution 2 | |
Solution 3 | Maurice Perry |
Solution 4 |