I have to convert JSON files into CSV and vice-versa, i use the Jackson library.
Going from JSON to CSV works well, for every type of data, including nested objects, but the counter way is much more harder, as the CSVMapper parse the CSV in a map, thus a couple .
Even if my actual works for simple CSV files, it doesn't for CSV that should produce JSON objects like this
JSON File
[
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
]
CSV file after the conversion
batters.batter[1].id;batters.batter[1].type;batters.batter[2].id;batters.batter[2].type;batters.batter[3].id;batters.batter[3].type;batters.batter[4].id;batters.batter[4].type;id;name;ppu;topping[1].id;topping[1].type;topping[2].id;topping[2].type;topping[3].id;topping[3].type;topping[4].id;topping[4].type;topping[5].id;topping[5].type;topping[6].id;topping[6].type;topping[7].id;topping[7].type;type
1001;Regular;1002;Chocolate;1003;Blueberry;1004;Devil's Food;0001;Cake;0.55;5001;None;5002;Glazed;5005;Sugar;5007;Powdered Sugar;5006;Chocolate with Sprinkles;5003;Chocolate;5004;Maple;donut
CSV to JSON converter
File csvFile = new File(CSV_File) ;
// Get the name of the file, for the new one in JSON
// String file_name = csvFile.getName().replaceFirst("[.][^.]+$", "");;
CsvMapper mapper = new CsvMapper();
mapper.disable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
CsvSchema schema = CsvSchema.emptySchema().withHeader(); // use first row as header; otherwise defaults are fine
MappingIterator<Map<String,String>> it = mapper.readerFor(Map.class)
.with(schema)
.readValues(csvFile);
// We extract a list from the mapping Iterator
List<Map<String, String>> readObjectsFromCsv = it.readAll() ;
// Clean the list
readObjectsFromCsv = cleanCSV(readObjectsFromCsv) ;
// Build the JSON file
try {
ObjectMapper mapperObject = new ObjectMapper() ;
// Write JSON formated data to output.json file
mapperObject.writerWithDefaultPrettyPrinter().writeValue(new File(JSON_File),readObjectsFromCsv);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The output of this code
[ {
"batters.batter[1].id" : "1001",
"batters.batter[1].type" : "Regular",
"batters.batter[2].id" : "1002",
"batters.batter[2].type" : "Chocolate",
"batters.batter[3].id" : "1003",
"batters.batter[3].type" : "Blueberry",
"batters.batter[4].id" : "1004",
"batters.batter[4].type" : "Devil's Food",
"id" : "0001",
"name" : "Cake",
"ppu" : "0.55",
"topping[1].id" : "5001",
"topping[1].type" : "None",
"topping[2].id" : "5002",
"topping[2].type" : "Glazed",
"topping[3].id" : "5005",
"topping[3].type" : "Sugar",
"topping[4].id" : "5007",
"topping[4].type" : "Powdered Sugar",
"topping[5].id" : "5006",
"topping[5].type" : "Chocolate with Sprinkles",
"topping[6].id" : "5003",
"topping[6].type" : "Chocolate",
"topping[7].id" : "5004",
"topping[7].type" : "Maple",
"type" : "donut"
} ]
Related
I have Json schema as input I want to know whether there is a method by which I can generate sample json output. Do we have any such library in java which I can use?
{
"title": "InputSchema",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
}
},
"required": ["firstName", "lastName"]
}
output =>
{
"firstName" : "FirstName",
"lastName" : "LastName"
}
I would like to modify the data inside nested json (Map<String, Object>) by using java.util.stream.
This is Json Data
{
"schoolId": "10928391",
"schoolName": "school A",
"teachers" : [
{
"teacherId": "00001",
"teacherName:": "teacher A",
"subject": "Computer Science",
"lectures": [
{
"id": "CS102",
"name": "Algorithm"
},
{
"id": "CS330",
"name": "Data Communications and Networking"
}
]
},
{
"teacherId": "00002",
"teacherName:": "teacher B",
"subject": "Computer Science",
"lectures": [
{
"id": "CS103",
"name": "Data Structure"
},
{
"id": "CS104",
"name": "Data Structures in C++"
}
]
},
{
"teacherId": "00003",
"teacherName:": "teacher C",
"subject": "Computer Science",
"lectures": [
{
"id": "CS100",
"name": "Introduction to Programming (Java)"
},
{
"id": "CS401",
"name": "Object Oriented Programming"
}
]
}
]
}
--
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> schoolInfo = mapper.converValue(restTemplate.exchange(url, HttpMethod.GET, .... ).getBody(), HashMap.class);
the Json data above is inside schoolInfo
the data what I want to access and modify is lectures.
I tried to modify all the elements inside lectures(array).
for example,
"lectures": [
{
"id": "CS102",
"name": "Algorithm"
},
{
"id": "CS330",
"name": "Data Communications and Networking"
}
]
Replace all lecture information in the lecture data as follows.
"lectures": [
{
"lectureId": "CS102",
"lectureName": "Algorithm",
"lectureRoom": "Room A-1"
},
{
"lectureId": "CS330",
"lectureName": "Data Communications and Networking",
"lectureRoom": "Room A-2"
}
]
with map, filter I could access to "teachers" object
but I couldn't figure out how to get "lectures" objects inside the "teachers"
System.out.println(jsonMap.entrySet().stream()
.filter(map -> map.getKey().equals("teachers")).collect(Collectors.toList()).toString());
Any advice would be very helpful !
This is my sample Json
{
"State": {
"version": "1",
"SName": "Test",
"shippingDetails": {
"Address1": "AP",
"ZipCode": "1236"
},
"Directions": {
"routes": [
{
"taxAmount": "0.0",
"Quantity": "5",
"bounds": {
"SerialVersion": [
{
"text": "1.7 km",
"value": "1729",
"time": "02633"
},
{
"text": "1.9 km",
"value": "1829",
"time": "02353"
},
{
"text": "17 km",
"value": "1059",
"time": "02133"
}
]
}
}
]
}
}
}
I want to update SName, ZipCode,taxAmount,Quantity, and text[1] values
are there any way to do this. I am taking JSON in a file and update tags are taking into HashMap
JSONObject jsonObject = new JSONObject("Your_JSON_String");
JSONObject jsonObjectForState = jsonObject.getJSONObject(“State”);
jsonObjectForState.put("Sname", "New_Value_Here");
put(...) will replace the current value with new value. Similarly, you can update the other values. Once you are done, you can convert it back using:
jsonObject.toString();
And write it back to the file.
I need to extract a json in required format from input json. i'm using jayway json path library. How to achieve it ?
Input Json:
{
"ccid": [
{
"id": 13,
"src": {
"sname": "XA-SXXD",
"lname": "John",
"identifier": 2,
"StatusCode": "C"
}
},
{
"id": 14,
"src": {
"sname": "XB-SXXD",
"lname": "Cena",
"identifier": 3,
"StatusCode": "C",
}
}
]
}
Required Format:
[ {
"id": "13",
"sources": {
"sname": "XA-SXXD",
"lname": "John",
"identifier": 2
}
},
{
"id": "14",
"sources": {
"sname": "XB-SXXD",
"lname": "Cena",
"identifier": 3
}
}]
Query that i use:
$.ccid[*].src[?(#.identifier!=null)].['identifier','sname']
Output that i get:
[
{
"identifier" : 2,
"sname" : "XA-SXXD"
},
{
"identifier" : 3,
"sname" : "XB-SXXD"
}
]
Kindly help me to modify my query to get the required format. The string "sources" in the required format can be hardcoded.
I think I managed to solve this :)
$.ccid[*].[?(#.src.identifier!=null)].['id', 'src']
Give it a try.
Input tested on:
{
"ccid": [
{
"id": 13,
"src": {
"sname": "XA-SXXD",
"lname": "John",
"StatusCode": "C"
}
},
{
"id": 14,
"src": {
"sname": "XB-SXXD",
"lname": "Cena",
"identifier": null,
"StatusCode": "C",
}
}
]
}
Output received:
[
{
"id" : 13,
"src" : {
"sname" : "XA-SXXD",
"lname" : "John",
"StatusCode" : "C"
}
}
]
Only problem is saw is if identifier tag is not available it's essentially treated as not-null. Hence we are getting 13 as an output. But if value is explicitly null then it's fine. So the needs to be enhanced a bit more.
Hope this helps.
hi i need to convert all json elements into csv . json is dynamic file, number of field and names will change from file to file.
i tried different methods but most cases i need to mention field names in scripts to pull data into csv
JSON file
[
{
"system": "Application",
"id": "12345",
"version": 1,
"event": "NEW",
"keywords": {
"ProductType": "ALL",
"Business": "USA",
},
"product": {
"type": "INS",
"startDate": 20190102,
"endDate": 20190104,
"cash": 100000.00,
"sub": {
"type": "Life",
"productId": 987,
"maturityDate": 20260421,
},
"paymentCalendar": [
"Monthly"
],
"duration": "20Y",
"Amount": 1000.00,
"cashFlows": [
{
"startDate": 20190102,
"endDate": 20190104,
"paymentDate": 20190104,
}
],
"principalFlows": [
{
"startDate": 20190102,
"endDate": 20190104,
"paymentDate": 20190102,
"currency": "USA",
"amount": 400.0
},
{
"startDate": 20190104,
"endDate": 20190104,
"paymentDate": 20190104,
"currency": "USA",
"amount": 600.0
}
]
},
"EventDate": 20190108,
"maturityDate": 20190104
}
]
above fields are not constant, all filed will keep changing.
expected output is below
Using Jackson ObjectMapper and Apache Commons CSV you can implement the functionality you require by reading the JSON and then visiting all the nodes.
If the node is a collection then visit all its children with the field or array index appended to the prefix
Note that arrays and objects need to be handled independently
If the node is a not a collection then add it to the CSV output
public void jsonToCsv(String json, Appendable appendable) throws IOException {
JsonNode root = new ObjectMapper().reader().readTree(json);
CSVPrinter printer = CSVFormat.DEFAULT.print(appendable);
appendNode(root.get(0), "", printer);
}
private void appendNode(JsonNode node, String prefix, CSVPrinter printer) throws IOException {
if (node.isArray()) {
for (int i = 0; i < node.size(); ++i) {
appendNode(node.get(i), String.format("%s/%d", prefix, i), printer);
}
} else if (node.isContainerNode()) {
Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> field = fields.next();
appendNode(field.getValue(), String.format("%s/%s", prefix, field.getKey()), printer);
}
} else {
printer.printRecord(prefix.substring(1), node.asText());
}
}