How to convert csv to json in apache camel - java

I able to convert csv into pojo with the help of camel bindy. But I need to convert the string to json easily?
I able to do my splitting the string.But is there any efficient methods to do it?
My pojo Class:-
#CsvRecord(separator = ",",skipFirstLine = true)
public class Sample
{
//some fields
}
Processor Class:-
String samples=exchange.getIn().getBody(String.class);
String[] strings=samples.split("}");
System.out.println(strings[0]);
for(String strings1:strings)
{
String[] strings2=strings1.split("'");
for(int i=0;i<strings2.length;i++)
{
if(i%2==1) {
System.out.println(strings2[i]);
}
}
}
//Is there is efficient method we can do to convert the String to list of json. Assuming csv contains multiple record
Route Builder :-
public class SimpleRouteBuilder extends RouteBuilder {
private final BindyCsvDataFormat bindy=new BindyCsvDataFormat(com.company.model.Sample.class);;
#Override
public void configure() {
from("file:/path/?fileName=CCO_SUMMARY_20190315_165800 copy.csv&noop=true").unmarshal(bindy).process(new MyProcessor()).
to("file:/path/?fileName=akshay.txt");
}
}
Eager to know if there is any efficient method to solve this?

.json()
see camel json data format ie: .json().log("${body}")
In your scenario for example:
from("file:/path/?fileName=CCO_SUMMARY_20190315_165800 copy.csv&noop=true")
.unmarshal(bindy)
.marshal()
.json(JsonLibrary.Jackson).log("${body}")
.to("file:/path/?fileName=akshay.txt");
where json(JsonLibrary.Jackson) forces the use of the jackson library for the conversion.

You can use camel bindy t unmarshal csv to List of POJO
Do mapping if required base on output format
marshal mapped data using Jacson o Gson in Came route.
from("file:/input/path/?noop=true")
.unmarshal(bindy)
.marshal()
.json(JsonLibrary.Jackson).log("${body}")
.to("file:/path/?fileName=test.txt");

Related

How to convert complex dynamic json to pojo class

I have below json
[{
"Maindata": "{\"SubData\":[{\"Name\":\"a\",\"rollnumber\":1,\"ParentName\":c},{\"Name\":\"b\",\"rollnumber\":2,\"ParentName\":d},{\"Name\":\"m\",\"rollnumber\":3,\"ParentName\":n}],\"schooltime\":123213,\"lunchtime\":2321,\"TeacherName\":\"abc\",\"ClassTeacherName\":\"abc\",\"Subjects\":null,\"ClassName\":\"xyz\",\"PrincipleName\":[\"sdffd\"],\"ClassID\":\"21312\",\"books\":\"\",\"classdata\":{\"scienceclass\":\"2hrs\",\"Projects\":\"True\",\"Games\":\"Nothing\"},\"real\":null,\"classuniqueid\":\"21323234234\",\"schoolbelltime\":21323321}"
}]
In above Json we have
MainData - Main data has two main sections
SubData
ClassData
When i tried to view the above Json viewer it displays MainData as main Json and doesnot display sub data json
Now i want to convert above json to Pojo class, in a way say if i give Name of Subdata as "a" it should give me all details of "a". Now Subdata is dynamic, it has three sections now, it can have 100 when new students data are available or it can have only two. How to write a pojo class which reads this and gives data.
I am using gson and Below is my pojo class
public class MyPojo
{
private String Maindata;
public String getMaindata ()
{
return Maindata;
}
public void setMaindata (String Maindata)
{
this.Maindata = Maindata;
}
#Override
public String toString()
{
return "ClassPojo [Maindata = "+Maindata+"]";
}
}
You can use Jackson to convert JSON data to POJOs and POJOs to JSON data.
For complex JSON data like yours, you will need to create ArrayLists of complex types in your corresponding classes.
Paste your valid JSON into this site and select
Target language: Java
Annotation Style: GSON
and download the Zip file, extract it after that you get all POJO classes of your JSON response

Parse JSON without object name in Java

I am trying to parse this JSON which is coming as the response to a REST API call. Can you please help me parsing it as key value pairs?
The object names are not present. There is nesting as well. There seems to be no new line between records.
The aim is to extract this data and load it into a database.
[
{
"cc_emails":["feedback#xyz.com"],
"fwd_emails":[],
"reply_cc_emails":["feedback#xyz.com"],
"fr_escalated":false,
"spam":false,
"email_config_id":6000038087,
"group_id":6000110481,
"priority":1,
"requester_id":6010410791,
"responder_id":6002817857,
"source":1,
"company_id":null,
"status":2,
"subject":"fare",
"to_emails":["feedback#xyz.com"],
"product_id":null,
"id":45043,
"type":null,
"due_by":"2016-03-12T08:58:02Z",
"fr_due_by":"2016-03-08T08:58:02Z",
"is_escalated":false,
"description":"Dear xyze Team,\r\n\r\nWhy r u increased fair again and againasas0mail.gmail.com</a>.<br>\n",
"custom_fields":
{
"category":null,
"issue":null,
"route_id":null,
"phone_number":null,
"department":null,
"booking_id":null
},
"created_at":"2016-03-07T08:58:02Z",
"updated_at":"2016-03-07T08:58:03Z",
// ...... repeat
}
]
The best way to do this would be to use http://www.jsonschema2pojo.org/
Enter your json there
Change source type to JSON
set the correct class name and package.
The resulting pojo can be directly mapped from the json
If you are using resttemplate to hit the api then you can use getForObject to automatically set the pojo from the output.
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#getForObject-java.lang.String-java.lang.Class-java.lang.Object...-
Using gson you can do this quite simply.
Do a class to match the fields in the json something like:
public class Example {
private List<String> cc_emails;
private List<String> fwd_emails;
private List<String> reply_cc_emails;
private Boolean fr_escalated;
private Boolean spam;
private Integer email_config_id;
...
private CustomFields custom_fields;
private String created_at;
private String updated_at;
}
Then you need to do another to map the custom fields
public class CustomFields {
private String category;
...
}
And using json you can parse it like this:
Type type = new TypeToken<Collection<Example>>(){}.getType();
new Gson().fromJson(json,type);
You have to exaplain to Gson it's a list, if it was a single object it would be this:
new Gson().fromJson(json,Example.class);
This is the aproach I usually take, also in the dates java.sql.Timestamp class might also parse it, you would need to try it though.
You can use Gson (https://github.com/google/gson) or Jackson (https://github.com/FasterXML/jackson) and deserialize it to a Map.

Spring Boot REST application with Jackson - how to handle arbitrary/unknown xml structures passed in?

I am working with a Spring Boot REST application. We are using jackson to handle deserialization of XML as well as JSON passed in the request body. An example of an expected request body looks like this:
<formInput><formNum>999999</formNum><documentData>Completely unknown data structure here!</documentData></formInput>
In the documentData element, we will have a structure that is completely arbitrary/unknown on the server side. We don't care about the structure, because we only want to pass the xml that is nested in documentData on to another service.
The POJO that we are trying to map the request body onto looks like this:
#JsonDeserialize(using=FormInputJsonDeserializer.class)
public class FormInput {
private String formNum
private String documentData
public String getFormNum() {
return formNum
}
public void setFormNum(String formNum) {
this.formNum = formNum
}
public String getDocumentData() {
return documentData;
}
public void setDocumentData(String documentData) {
this.documentData = documentData;
}
}
The custom JsonDeserializer that we are trying to write:
public class FormInputJsonDeserializer extends JsonDeserializer<FormInput> {
#Override
public FormInput deserialize(JsonParser parser, DeserializationContext context)
throws IOException, JsonProcessingException {
FormInput formInput = new FormInput();
String fieldName
JsonToken currentToken
while (parser.nextToken() != null) {
currentToken = parser.getCurrentToken()
if (currentToken.equals(JsonToken.END_OBJECT)) {
continue
}
fieldName = parser.getCurrentName()
// formNum handling not written yet
if ("documentData".equalsIgnoreCase(fieldName)) {
if (parser.getCurrentToken().equals(JsonToken.START_OBJECT)) {
// we are at the start of documentData, and we need to capture the
// entire documentData node as a String since we don't know
// its structure
JsonFactory jfactory = new JsonFactory()
StringWriter jsonStringWriter = new StringWriter()
JsonGenerator jGen = jfactory.createGenerator(jsonStringWriter)
jGen.copyCurrentStructure(parser) // points to END_OBJECT after copy
jGen.close()
String documentDataJsonStr = jsonStringWriter.getBuffer().toString()
println("documentDataJsonStr: " + documentDataJsonStr)
}
}
}
// rest of code omitted
}
}
As I say, if the request body is xml, ideally I'd like to just keep it formatted as xml and assign that to the documentData String property. However I came up with the above custom deserialization code by following some other examples on StackOverflow. This parsing code ends up converting documentData to a JSON formatted String. Since I didn't know how to pass through the raw XML and get it mapped to the String property, I thought I could just convert the JSON formatted String back to a XML formatted String. A problem arises when we pass in a XML structure like this:
<formInput><formNum>9322</formNum><documentData><repeatLevel><subForm1><GROSS_DISTR> 13,004.31</GROSS_DISTR><GROSS_DISTR> 13,004.31</GROSS_DISTR><GROSS_DISTR> 13,004.31</GROSS_DISTR></subForm1></repeatLevel><repeatLevel><subForm1><GROSS_DISTR> 38,681.37</GROSS_DISTR><GROSS_DISTR> 38,681.37</GROSS_DISTR><GROSS_DISTR> 38,681.37</GROSS_DISTR></subForm1></repeatLevel></documentData></formInput>
After documentData is parsed in the deserialize method, the println statement shows the parsed JSON String as:
{"repeatLevel":{"subForm1":{"GROSS_DISTR":" 13,004.31","GROSS_DISTR":" 13,004.31","GROSS_DISTR":" 13,004.31"}},"repeatLevel":{"subForm1":{"GROSS_DISTR":" 38,681.37","GROSS_DISTR":" 38,681.37","GROSS_DISTR":" 38,681.37"}}}
This is actually not strictly valid JSON, due to the duplicate keys. I would have hoped that these would have been converted to JSON arrays, but that is not the case. So, I am unable to turn around and use something like the JSON.org libraries (JsonObject and XML) to convert the JSON String back to XML format (get an exception with a "duplicate key" error).
Does anybody have any suggestions or strategies for handling our situation?
You could try to use a JSONObject, add the #JsonIgnoreProperties("documentData") tag and extract documentData seperately from the raw data using substring()

Populate POJO with array (root JSON node) using Jackson

I'm using Jackson and RESTEasy to hook into an external API. The API mainly returns simple objects which I have managed to successfully populate into POJOs.
I'm hitting a problem where I get an array of objects back e.g.
[
{
"variable1": "someValue1",
"variable2": "someValue2",
"variable3": "someValue3"
}
{
"variable1": "someValue4",
"variable2": "someValue5",
"variable3": "someValue6"
}
{
"variable1": "someValue7",
"variable2": "someValue8",
"variable3": "someValue9"
}
]
I have 2 classes: one called VariableObject which looks like this:
public class VariableObject {
private String variable1;
private String variable2;
private String variable3;
}
and VariableResponse which looks like:
public class VariableResponse {
private List<VariableObject> variableObjects;
}
My client uses JAXRS Response class to read the entity into the class i.e
return response.readEntity(VariableResponse.class);
I get a stack trace which reads:
Caused by: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of VariableResponse out of START_ARRAY token
I understand you can return these as a List of POJOs i.e List quite easily, but this is not what I want to do.
The question really is two parts:
a. Can I possibly populate the VariableResponse POJO using Jackson (some how) preferably without a customer deserialiser? Maybe some annotation exists (this would be ideal)?
b. Is there some way to detect if an Array is being retuned as the root JSON node in the response and then act accordingly?
Help greatly appreciated.
Your JSON is indeed an array of objects.
You can deserialize it with:
response.readEntity(new GenericType<List<VariableObject>>() {});
And then create a new instance of VariableResponse passing resulting List as a constructor parameter like this:
public class VariableResponse {
private final List<VariableObject> variableObjects;
public VariableResponse(List<VariableObject> variableObjects) {
this.variableObject = new ArrayList<>(variableObjects);
}
}
You might forget to add comma after each {..}. After correcting your JSON string, I converted it into ArrayList<VariableObject> using TypeReference and ObjectMapper.
sample code:
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
...
TypeReference<ArrayList<VariableObject>> typeRef = new TypeReference<ArrayList<VariableObject>>() {};
ObjectMapper mapper = new ObjectMapper();
try {
ArrayList<VariableObject> data = mapper.readValue(jsonString, typeRef);
for (VariableObject var: data) {
System.out.println(var.getVariable1()+","+var.getVariable2()+","+var.getVariable3());
}
} catch (Exception e) {
System.out.println("There might be some issue with the JSON string");
}
output:
someValue1,someValue2,someValue3
someValue4,someValue5,someValue6
someValue7,someValue8,someValue9
If you prefer your own response type direct.
Try just extending ArrayList?
public VariableResponse extends ArrayList<VariableObject> {
}

Reusing the Result of a Controller in another Controller in the Play framework

Apologies if this has been answered already - I've had a look and can't find anything.
Using the Play framework, I have defined two controllers - one is a public API that returns JSON, and one is a consumer of this API which presents the JSON as HTML. E.g. my routes file look as follows:
GET /foos controllers.App.foos() #produces HTML
GET /api/foos controllers.API.foos() #produces JSON
A requirement of the project is that our data should only be accessed via our public API. Therefore, the way that I'd like to implement this is to have App.foos() invoke API.foos(), parse the JSON result, and pass it to a template to be rendered. For example:
public App extends Controller {
public static Result foos() {
Result result = API.foos();
// TODO: get the JSON out of the result object
}
}
Can anyone tell me how I can extract the JSON from the result object? I can get the body of the object as an Enumerator using ((SimpleResult)result.getWrappedResult()).body(), but I am still unclear how I can get out the JSON.
Because I am new to the Play framework, perhaps I am going about this wrong and there is an easier/better way to do this?
Many thanks in advance,
James
The easiest way would be to expose the underlying method.
public Api extends Controller {
public static Result foos() {
Ok(foosJson());
}
public static JsValue foosJson() {
// ...
}
}
public App extends Controller {
public static Result foos() {
JsValue json = API.foosJson();
}
}

Categories