Transform JSONArray values in WSO2 EI - arrays

I am having some transformation logic during mediation in wso2 EI. i have stuck while "#type":"Lead" into "attributes":{"type":"Lead"} transformation.
Note: i know to use payloadfactory to achieve this( Expected format). received at least 1000 JSONObject under getFields Array.
Input:
{
"getDataResponse":{
"result":{
"DataSyncTime":"sometime",
"getFields":[
{
"#type":"Lead",
"FirstName":"Justin"
},
{
"#type":"Lead",
"FirstName":"Manoj"
}
//received atleast 1000 records ie jsonobject here(Dynamic)
],
"Message" :"Text messsage",
"Success":200
}
}
}
Expected:
{
"DataSyncTime":"sometime",
"getEvents":[],
"getFields":[
{
"attributes":{"type":"Lead"},
"FirstName":"Justin"
},
{
"attributes":{"type":"Lead"},
"FirstName":"Manoj"
}
],
"getTask":[],
"Message" :"Text messsage",
"Success":200
}

Trying using Foreach mediator with Payload Factory mediator to loop through the array. If Payload Factory does not satisfy your requirement, you may have to use a Custom Class mediator to achieve your requirement.

Related

How to use custom field in react admin, insted of { data: [...] }

I'm new in react-admin and I'm trying to create a new admin panel for my old API.
So when my data provider do API calls it causes me this error:
The response to 'getList' must be like { data : [...] }, but the received data is not an array. The dataProvider is probably wrong for 'getList'
The responses of my old API has various data fields like { 'posts': [] } or { 'users': [] }. How can I use these name of fields instead of { 'data': [] } ?
The 'data' in this case just refers to the type of information that should be retuned, not the name of the object.
Within your API, you can simply return a list in the following form:
const posts = [
{
"id":1,
"name":"post1"
},
{
"id":2,
"name":"post2"
},
];
return JSON.stringify(posts);
Then return that 'posts' object in your response and don't forget to set the expected ContentRange headers.
Not sure what language you are using, but the principle above should be easy enough to follow and apply in any language.

Spring Boot and Mongo DB: only get latest version of Document

I have a document collection where each unique templateId can have multiple versions:
#Document(collection = "templates")
public class TemplateEntity {
#Id
private String id;
private String templateId;
private int version;
}
Is there an easy way to only get the latest versions for each templateId with a simple MongoRepository interface method?
Here is my current programmatic workaround to explain what I am trying to do and my helper query method to sort the list for my needs:
#GetMapping("/list")
public List<TemplateEntity> listTemplates() {
List<TemplateEntity> filtered = new ArrayList<>();
List<TemplateEntity> allTemplates = repository.findAllByOrderByTemplateIdAscVersionDesc();
String templateId = "";
for (TemplateEntity tpl : allTemplates) {
if (!tpl.getTemplateId().equals(templateId)) {
filtered.add(tpl);
templateId = tpl.getTemplateId();
}
}
return filtered;
}
For this kind of operation you need to make use of the MongoDB Aggregation Framework.
db.getCollection("templates").aggregate([
{ "$group": { "_id": "$templateId", "tmpId": { "$first": "$_id" }, "maxVersion": { "$max": "$version"} } },
{ "$project": {"_id": "$tmpId", "templateId": "$_id", "version": "$maxVersion"} }
])
Spring Data offers support for Aggregations via MongoOperations. Please have a look at the Reference Documentation.
Generally speaking I think having something like an #Aggregate annotation in Spring Data would be benefitial. I've opended DATAMONGO-2153 to investigate that option.

Sending json object as json array to an API

I have an API that accepts data format as [ { "record_id": "TestID3" } ]. I am trying to send record_id field using the form below in my angular project:
html:
<input id="record_id" type="text" class="form-control" [(ngModel)]="member.record_id" name="record_id" #record_id="ngModel" placeholder="Enter Record ID">
component.ts:
export class MembersAddComponent implements OnInit {
member: Array<Object> = [];
constructor(private service: DataService ) { }
ngOnInit() {
}
submit() {
this.service.importRecord(this.member).subscribe(member => {
this.member = member;
}, error => {
console.log(error);
});
}
}
And my service.ts:
importRecord(data): Observable<any> {
const formData = new FormData();
formData.append('token', this.token);
formData.append('content', this.content);
formData.append('format', this.format);
formData.append('returnFormat', this.returnFormat);
formData.append('type', this.type);
formData.append('overwriteBehavior', this.overwriteBehavior);
formData.append('forceAutoNumber', this.forceAutoNumber);
formData.append('data', data);
formData.append('returnContent', this.returnContent);
return this.http.post(this.baseUrl, formData).map(res => res.json())
.catch(this.handleError);
}
The error that I get is below:
{"error":"The data being imported is not formatted correctly. The JSON must be in an array, as in [{ ... }]."}
I also tried member:any = {}, member:Object = {}; but I got the same error. I am thinking that I am unable to format my member object as requested format. But I couldn't make it as desired format.
[ { "record_id": "TestID3" } ]
That is an array, containing a single element, which is an object.
member: Array<Object> = [];
that defines an array with no element at all.
[(ngModel)]="member.record_id"
That will try to read and write the property record_id of member, which is an array. It will not magically add an element to the array and set its property.
So what you need is an object that will be populated by the form. And then you need to put that object into an array before to send the array to the API.
Start by defining an interface to describe your object:
interface Member {
record_id: string;
}
Then use one as the model for your form:
member: Member = {
record_id: '';
};
...
[(ngModel)]="member.record_id"
Then put that member into an array before sending it:
submit() {
const data: Array<Member> = [this.member];
this.service.importRecord(data)...
It's difficult to tell if this is due to an incorrectly formatted response from the POST or the body of the POST.
Things you can do:
Check the network tab in Chrome to verify that the request is being sent, it's content is valid JSON (use an online validator)
Check your API backend to see if the data you're sending is being saved, if so the error is with the format of the JSON in your response.
Verify in Chrome that the response data in the network request is valid JSON.
If all of these are true, you may need to consider using headers such as {requestType: 'json'} as detailed in the Angular docs here: Request/Response Headers
If these are not true, then you will need to change the model of the object you are sending to reflect the object which is expected.

How to access this json object

I'm using express js to send data from mysql. I send it using res.json(theData).
In the client side I get it like this in the console:
{
"data":[
{
"PlazaID":1,
"PlazaName":"fff",
"PlazaAddress":"fff",
"PlazaContactNo":"45645",
"PlazaLanes":"34",
"PlazaStatus":"y",
"ClientID":1
},
{
"PlazaID":2,
"PlazaName":"plaza2",
"PlazaAddress":"p2",
"PlazaContactNo":"000",
"PlazaLanes":"2",
"PlazaStatus":"a",
"ClientID":2
}
],
"status":200,
"config":{
"method":"GET",
"transformRequest":[
null
],
"transformResponse":[
null
],
"url":"/getTollPlaza",
"headers":{
"Accept":"application/json, text/plain, */*"
}
},
"statusText":"OK"
}
I store these values in an array to populate a table using angularjs' ng-repeat like this:
for(i=0;i<response.data.length;i++){
tableArray.push({
plazaid:response.data[i].plazaid,
plazaname:response.data[i].plazaname,
plazaaddress:response.data[i].plazaaddress,
plazacontactnumber:response.data[i].plazacontactnumber,
plazalane:response.data[i].plazalane,
plazastatus:response.data[i].plazastatus,
clientid:response.data[i].clientid
});
}
When I console.log the array the values are undefined.
0: Object
clientid:undefined
plazaaddress:undefined
plazacontactnumber:undefined
plazaid:undefined
plazalane:undefined
plazaname:undefined
plazastatus:undefined
Try this. Please note that variable name are case sensitive.
for(i=0;i<response.data.length;i++){
tableArray.push({
plazaid:response.data[i].PlazaID,
plazaname:response.data[i].PlazaName,
plazaaddress:response.data[i].PlazaAddress,
plazacontactnumber:response.data[i].PlazaContactNo,
plazalane:response.data[i].PlazaLanes,
plazastatus:response.data[i].PlazaStatus,
clientid:response.data[i].ClientID
});
}

extjs4 - is there a non json/xml writer for proxies?

I'm building some models to interact with an existing API from a previous project.
The API relies on standard POST methods to save the data.
I've configured a model and proxy up to the point where it does push the data onto the server but there only seems to be two writer types, json & xml.
proxy: {
/* ... */
reader: {
type: 'json',
root: 'results'
},
writer: {
type: '???' // <-- can only see json or xml in the docs
}
}
Isn't there a standard POST writer that simply submits data in post fields?
I'm surprised that wouldn't be a standard writer type.
(Parsing the json format wouldn't be too hard to implement but that would mean updating a lot of the old api files.)
Ok, I was able to create that writer quite easily by checking the existing writers' source code.
One thing those existing writers are able to do - and that may be why the dev team only implemented a json and xml version - is that they can push multiple records at once.
That could be implemented in POST but would be a bit more complicated.
This writer will work if you're trying to push a single model to an api using POST:
Ext.define('Ext.data.writer.SinglePost', {
extend: 'Ext.data.writer.Writer',
alternateClassName: 'Ext.data.SinglePostWriter',
alias: 'writer.singlepost',
writeRecords: function(request, data) {
request.params = data[0];
return request;
}
});
and the use this for the writer in the proxy:
writer: {
type: 'singlepost'
}
Based on Ben answer I've implemented my own writer that will collect all properties of all models into arrays.
For example if you have model like with some fields:
fields:[
{name:'id', type:'int'}
{name:'name', type:'string'}
{name:'age', type:'date'}
]
A request string will be
id=1&id=2&id=...&name=oleks&name=max&name=...&age=...
Code:
Ext.define('Ext.data.writer.SinglePost', {
extend: 'Ext.data.writer.Writer',
alternateClassName: 'Ext.data.SinglePostWriter',
alias: 'writer.singlepost',
writeRecords: function(request, data) {
if(data && data[0]){
var keys = [];
for(var key in data[0]){
keys.push(key);
}
for(var i=0;i<keys.length;i++){
request.params[keys[i]] = [];
for(var j=0;j<data.length;j++){
request.params[keys[i]].push((data[j])[keys[i]]);
}
}
}
return request;
}
});
For Sencha touch 2.0, change the writeRecords method to:
writeRecords: function (request, data) {
var params = request.getParams() || {};
Ext.apply(params, data[0]);
request.setParams(params);
return request;
}
Here's my version, adapted from answers above:
// Subclass the original XmlWriter
Ext.define('MyApp.utils.data.writer.XmlInAPostParameter', {
extend : 'Ext.data.writer.Xml',
// give it an alias to use in writer 'type' property
alias : 'writer.xml_in_a_post_parameter',
// override the original method
writeRecords : function(request, data) {
// call the overriden method - it will put the data that I
// want into request.xmlData
this.callParent(arguments);
// copy the data in request.xmlData. In this case the XML
// data will always be in the parameter called 'XML'
Ext.apply(request.params, {
XML: request.xmlData
});
// Already copied the request payload and will not send it,
// so we delete it from the request
delete request.xmlData;
// return the modified request object
return request;
}
});
Ext.define("MyApp.model.MyModel", {
extend : "Ext.data.Model",
requires : [
'MyApp.utils.data.writer.XmlInAPostParameter'
],
fields : [ 'field_A', 'field_B' ],
proxy : {
type : 'ajax',
api : {
read : '/mymodel/read.whatever',
update : '/mymodel/write.whatever'
},
reader : {
type : 'xml'
},
writer : {
// use the alias we registered before
type : 'xml_in_a_post_parameter'
}
}
});

Resources