Converting Nested Json files to CSV in java - java

{
"Employee": [
{
"empMID": "mock:1",
"comments": [],
"col1": "something",
"contact": [{"address":"2400 waterview", "freetext":true}
],
"gender": "male"
},
{
"empMID": "mock:2",
"comments": [],
"col1": "something",
"contact": [{"address":"2200 waterview", "freetext":true}
],
"gender": "female"
}
],
"cola": false,
"colb": false
}
This is how my Json file looks .I m required to convert this json to a csv .(I m trying to convert a multi-dimesional data to 2d).I m using gson for my purpose.I cannot use gson.fromgson() function to object map with a template because it should be generic .
I know we can use CDL to convert jsonarray to csv format but It wont work in my case .
my csv format looks like
Employee*
empMID,comment.$,contact.address,contact.freetext,gender
mock:1,,2400 waterview,TRUE,male
mock:123,,2200 waterview,TRUE,female
colA#
TRUE
colB#
FALSE
I tried using google-GSON api to convert to this format .But I m not able to convert to this format .I have used * to represent its a json array and # to represent its a primitive type and contact.address to represent nested array inside another json array .I having problem relating this nested structure .I m able to traverse everything recursively like a column. Thanks in advance
public static void main(String[] args) throws IOException{
BufferedReader reader=null;
StringBuilder content=null;
String result=null;
reader = new BufferedReader(new FileReader("temp.json"));
String line = null;
content= new StringBuilder();
while ((line = reader.readLine()) != null) {
content.append(line);
}
reader.close();
result= content.toString();
JsonElement jelement = new JsonParser().parse(result);
printJsonRecursive(jelement);
}
public static void printJsonRecursive(JsonElement jelement){
if(jelement.isJsonPrimitive()){
System.out.println(jelement.getAsString());
return;
}
if(jelement.isJsonArray()){
JsonArray jarray= jelement.getAsJsonArray();
for(int i=0;i<jarray.size();i++){
JsonElement element= jarray.get(i);
printJsonRecursive(element);
}
return;
}
JsonObject jobject= jelement.getAsJsonObject();
Set<Entry<String, JsonElement>> set= jobject.entrySet();
for (Entry<String, JsonElement> s : set) {
printJsonRecursive(s.getValue());
}
}
}

You can achieve this thru reflection if you have a object mapped to the json.
use gson/jackson to convert json to java object
append fields using reflection by iterating the class and get any field you interested in.
append value with reflection by getting value from the target object.
More detail look at my blog post below:
vcfvct.wordpress.com/2015/06/30/converting-nested-json-files-to-csv-in-java-with-reflection/

You are not printing the key. This should fix it.
for (Entry<String, JsonElement> s : set) {
System.out.println(s.getKey()); //Added
printJsonRecursive(s.getValue());
}
You can take care of \ns from here.
EDIT
If you want to print the keys just once for repeating json objects, create a Java bean to hold the data and populate it during your recursion. Once the bean is complete, add a method there to print all the data in the format you want (printing keys only once and so on).

You can use the library json2flat for converting your JSON to CSV.
This library doesn't require any POJO's. It simply takes your JSON as string and returns a 2D representation of it in the format of List<Object[]>.
For example for the JSON:
{
"Employee": [
{
"empMID": "mock:1",
"comments": [],
"col1": "something",
"contact": [{"address":"2400 waterview", "freetext":true}
],
"gender": "male"
},
{
"empMID": "mock:2",
"comments": [],
"col1": "something",
"contact": [{"address":"2200 waterview", "freetext":true}
],
"gender": "female"
}
],
"cola": false,
"colb": false
}
It gives an output:
/cola,/colb,/Employee/empMID,/Employee/col1,/Employee/gender,/Employee/contact/address,/Employee/contact/freetext
,,"mock:1","something",,"2400 waterview",true
,,"mock:2","something",,"2200 waterview",true
false,false,,,,,

/**
* Get separated comlumns used a separator (comma, semi column, tab).
*
* #param headers The CSV headers
* #param map Map of key-value pairs contains the header and the value
*
* #return a string composed of columns separated by a specific separator.
*/
private static String getSeperatedColumns(Set<String> headers, Map<String, String> map, String separator) {
List<String> items = new ArrayList<String>();
for (String header : headers) {
String value = map.get(header) == null ? "" : map.get(header).replaceAll("[\\,\\;\\r\\n\\t\\s]+", " ");
items.add(value);
}
return StringUtils.join(items.toArray(), separator);
}

Related

Update Json value in json Array in Java

{
"page": {
"size": 2,
"number": 2
},
"places": [
{
"eventName": "XYZ",
"createdByUser": "xyz#xyz.com",
"modifiedDateTime": "2021-03-31T09:59:48.616Z",
"modifiedByUser": "xyz#xyz.com"
}
]}
I am trying to update the "eventName" field with new String. I tried with the following code, It updates the field but returns only four fields in the json array.
public String modifyJson() throws Exception{
String jsonString = PiplineJson.payload(PiplineJson.filePath());
System.out.println(jsonString);
JSONObject jobject = new JSONObject(jsonString);
String uu = jobject.getJSONArray("places")
.getJSONObject(0)
.put("eventName", randomString())
.toString();
System.out.println(uu);
return uu;
}
This is what the above code does.
{
"eventName": "ABCD",
"createdByUser": "xyz#xyz.com",
"modifiedDateTime": "2021-03-31T09:59:48.616Z",
"modifiedByUser": "xyz#xyz.com"
}
I am trying to get the complete json once it updates the eventName filed.
{
"page": {
"size": 2,
"number": 2
},
"places": [
{
"eventName": "ABCD",
"createdByUser": "xyz#xyz.com",
"modifiedDateTime": "2021-03-31T09:59:48.616Z",
"modifiedByUser": "xyz#xyz.com"
}
]}
The problem is the way that you are chaining the operations together. The problem is that you are calling toString() on the result of the put call. The put calls returns the inner JSONObject that it was called on. So you end up serializing the wrong object.
Changing this:
String uu = jobject.getJSONArray("places")
.getJSONObject(0)
.put("eventName", randomString())
.toString();
to
jobject.getJSONArray("places")
.getJSONObject(0)
.put("eventName", randomString());
String uu = jobject.toString();
should work.
That's because you are returning the first element you extracted from "places" array. You should return "jobject.toString()" instead.

Generate a String from all values of a specific key from List<Map> in Java?

Suppose I have a list of Map such as:
(Using json format just for demonstration)
List<Map> myList = [
{
"id": 12,
"name": "Harie"
},
{
"id": "Forty",
"location": "Earth"
},
{
"name": "Potah"
},
{
"id": "0"
}
]
Now I want all the "id" values in a single String object, separated by a separator.
For example, the above map should give me:
"12#Forty#0"
Note:
The order in which they are indexed in the list has to be maintained.
I know I can do it like this:
StringBuilder result = new StringBuilder();
for (Map map : myList) {
if (map.get("id") instanceof String) {
if(result.length()>0){
result.append('#');
}
result.append(map.get("id"));
}
}
//Use result.toString() for output
But I want a more readable and simplified code, preferably using Java stream api.
You can use stream and join all the key id values which are not null
String keyString = myList.stream()
.map(map->map.get("id"))
.filter(Objects::nonNull)
.map(Object::toString)
.collect(Collectors.joining("#"));
In case if you want to check if the value is String instance you can filter
filter(val-> val!=null && val instance String)
StringBuilder sb = new StringBuilder();
myList.stream().map((mapping) => {
sb.append(mapping.get(id))
sb.append("#")
}
You can add extra logic within the lambda function!

How do I read multiple JSON objects in Java?

So this is my sample Json Text,
{
"Date": [
1545,
"20 January 2014"
],
"docText": "ABCD",
"docSource": "",
"docID": 99,
"docDate": "",
"Date": [
1930,
"1995/11",
"past decade",
"today",
"Today"
],
"docText": "JJJJJJJ\"",
"Organization": [
"x",
"y",
"z"
],
"docSource": "",
"docID": 98,
"docDate": "",
"Person": "xxxxxx"
}
Now I need a Java code to Read from this file and Display all the docText, docID Entities. I'm able to retrieve only one Entity.
This is the part of the code im using.
JSONParser jsonParser = new JSONParser();
try {
FileReader fileReader = new FileReader(jsonFilePath);
JSONObject jsonObject = (JSONObject) jsonParser.parse(fileReader);
String docid = (String) jsonObject.get("docText");
System.out.println("DocText: " +docid);
long members = (long) jsonObject.get("docID");
System.out.println("docID: " + members);
JSONArray names = (JSONArray) jsonObject.get("Organization");
Iterator i = names.iterator();
while (i.hasNext()) {
System.out.println("Organization: "+i.next());
I really need this working soon! Thank you
The JSON file has duplicate keys so you probably can't read them all using a standard parser.
From http://www.ietf.org/rfc/rfc4627.txt:
An object structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members). A name is a string. A single colon comes after each name, separating the name from the value. A single comma separates a value from a following name. The names within an object SHOULD be unique.
Instead, I'd expect each entity to be a separate object within an array.
AFAIK there is no option to fetch multiple values from a JSON object in a single get...

Parsing generic tag in JSON from GSON

I have a JSON which contains generic values. I tried it by using Maps but couldn't get the results. My problem is the generic tags starts from second level. Here is the JSON I am trying to parse through gson.
{
"success": true,
"status": 200,
"events": {
"Sep 2013": [
{
"artist_id": 1,
"created_at": "2013-05-18T15:21:00Z",
"duration": 2,
"end_time": "2013-09-19T22:00:00Z",
"event_desc": "",
"event_facebook_link": "",
"event_link": "https://www.smtickets.com/marketing/view/1316",
"feature_small": false,
"featured_status": false,
"id": 90,
In this JSON tag after "events" is generic i.e., "Sep 2013".
What I am trying right now is:
public Event event ;
public class Event {
public ArrayList<Map<String, String>> dates;
}
And I'm accessing it:
obj = gson.fromJson(reader, AllShowsActivityData.class);
Can anyone tell me that how can I make a class of dates. So Gson can serialize it. Or is there any other way to iterate first level tag and then I can declare it something like this
Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
gson.toJson(foo, fooType);
You can indeed use a Map, but you're not using it correctly. Note that what you have is a field "events", which is an object that contains a number of pairs string and array of objects:
{ "events": { "Sep 2013": [ {}, {}, ... ], ... } }
To parse your JSON you'd need a class structure like this (in pseudo-code):
class AllShowsActivityData
Map<String, List<Event>> events
class Event
int artist_id
String created_at //parsing as String to simplify...
int duration
...
And then your code to parse:
AllShowsActivityData obj = gson.fromJson(reader, AllShowsActivityData.class);
And finally, if what you want is to access the dates, you'll have all of them in:
Set<String> dates = obj.getEvents().keySet(); //"Sep 2013", ...
Note: in fact, if you only want those dates, you don't even need the class Event and you could use just Map<String, List<Object>> events...

Different JSON array response

I have problems parsing two different JSON responses.
1: This is the JSON response I get from a RESTful API:
{
"gear": [
{
"idGear": "1",
"name": "Nosilec za kolesa",
"year": "2005",
"price": "777.0"
}, {
"idGear": "2",
"name": "Stresni nosilci",
"year": "1983",
"price": "40.0"
}
]
}
2: This response I get from my testing client. I was added some values to the list and then I used gson.toJson for testing output.
[
{
"idGear": "1",
"name": "lala",
"year": 2000,
"price": 15.0
}, {
"idGear": "2",
"name": "lala2",
"year": 2000,
"price": 125.0
}
]
They are both valid, but the second one was successfully deserialize to object like this:
Type listType = new TypeToken<List<Gear>>() {}.getType();
List<Gear> gears= (List<Gear>) gson.fromJson(json, listType);
With the first one, I was trying to deserialize the same way but I get error.
EDIT
API Method:
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Gear> getGear() {
List<Gear> gears = gearDAO.getGears();
if (!gears.isEmpty()) {
return gears;
} else
throw new RuntimeException("No gears");
}
CLIENT serialization code:
List<Gear> list = new ArrayList<Gear>();
Gear o = new Gear();
o.setPrice(15);
o.setYear(2000);
o.setName("asds");
Type listTypes = new TypeToken<List<Gear>>() {}.getType();
gson.toJson(list, listTypes);
The JSON responses are different!
The first one is an object, surrounded by { }, which contains a field "gear" that is in turn a list of objects, surrounded by [ ].
The second one is directly a list of objects, because it's surrounded by [ ]. Namely, the whole 2nd response is equivalent to the field in the 1st response.
So, obviously they can't be parsed in the same way...
The 2nd one is being parsed correctly because you are using a List and it is a list. But for the 1st one you need another class that contains a field that contains in turn a list... That is, you just need to create a class structure that represents your JSON responses...
public class Response {
private List<Gear> gears;
//getters & setters
}
Now you can parse your 1st response with:
Gson gson = new Gson();
Response response = gson.fromJson(json, Response .class);
List<Gear> gears = response.getGears();
I suggest you to take a brief look at json.org in order to understand JSON syntax, which is pretty simple...
Basically these are the possible JSON elements:
object
{}
{ members }
members
pair
pair , members
pair
string : value
array
[]
[ elements ]
elements
value
value , elements
value
string
number
object
array
true
false
null

Categories