creating RAML file for dynamic key/values for get/post - json

I was using a Mule application to get data from another system which is invoked by an HTTP endpoint, used java with jersey api to get the rest component.
Sample input data is given below, here keys and values are not fixed, it may vary based on user request. Array size will increase may be 2 to n entries. It is working fine with Mule and Java rest based component.
Input JSON data:
[
{
"Company": "BEG1",
"Account": "10011",
"Deptid": "111",
"Location": "SM1",
"Transaction Date": "2014-07-15",
"Description": "Invoice1",
"Debit": 0,
"Credit": 13.46,
"Invoice Nbr": "16824321"
},
{
"Company": "BEG92",
"Account": "10092",
"Deptid": "222",
"Location": "SL2",
"Transaction Date": "2014-07-19",
"Description": "Invoice End2",
"Debit": 13.46,
"Credit": 0,
"Invoice Nbr": "168243292"
}
]
Planning to migrate to APIkit with RAML: how can I make a RAML template for above case? Since keys are dynamic, this doesn't seem straightforward.
2) With same approach for GET, I will get the data for my get request, I am not sure what is the key and its corresponding values, only I was doing is get the data, parse it and send it to the user. How do I create RAML template on this situation.Will mule APIkit with RAML will work here?
My existing code:
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public List<GLExport> postOperation(#Payload String content) throws ParseException {
JSONParser jsonParser = new JSONParser();
Object jsonObjectInstance =null;
jsonObjectInstance = jsonParser.parse(new StringReader(content));
...
return glExportList;
<http:inbound-endpoint exchange-pattern="request-response" host="${hostname}" port="${glport}" path="QBJournalExport/QBGLRest" doc:name="HTTP"/>
<jersey:resources doc:name="REST">
<component class="com.qb.rest.GLExportService"/>
</jersey:resources>

It seems your question is more about JSON Schema than RAML. In essence, you are asking how to support unknown fields in a JSON Schema.
The answer is by adding:
"additionalProperties": true
to your JSON Schema object definition.
I strongly suggest that if there is set of fields are known, you declare them explicitly in your schema: users of your API will thank you for that.
Also, if some of these fields are guaranteed to be present, mark them as required as well.
APIkit should have no trouble dealing with additional properties.

Related

422 error trying to save json data to the database

I'm trying to save data to my MySql db from a Node method. This includes a field called attachments.
console.log(JSON.stringify(post.acf.attachments[0])); returns:
{
"ID": 4776,
"id": 4776,
"title": "bla",
"filename": "bla.pdf",
"filesize": 1242207,
"url": "https://example.com/wp-content/uploads/bla.pdf",
"link": "https://example.com/bla/",
"alt": "",
"author": "1",
"description": "",
"caption": "",
"name": "bla",
"status": "inherit",
"uploaded_to": 0,
"date": "2020-10-23 18:05:13",
"modified": "2020-10-23 18:05:13",
"menu_order": 0,
"mime_type": "application/pdf",
"type": "application",
"subtype": "pdf",
"icon": "https://example.com/wp-includes/images/media/document.png"
}
This is indeed the data I want to save to the db:
await existing_post.save({
...
attachments: post.acf.attachments[0],
)};
However, the attachments field produces a 422 server error (if I comment out this field, the other fields save without a problem to the db). I'm not getting what is causing this error. Any ideas?
I've also tried
await existing_post.save({
...
attachments: post.acf.attachments,
)};
but then it seems to just save "[object Object]" to the database.
The field in the database is defined as text. I've also tried it by defining the field as json, but that made no difference.
exports.up = function (knex, Promise) {
return knex.schema.table("posts", function (table) {
table.longtext("attachments");
});
};
The 422 error code is about the server unable to process the data you are sending to it. In your case, your table field is longtext when post.acf.attachments seems like an object. That's why it saves [object Object] to your db (It is the return value of the toString() method).
Try using
await existing_post.save({
...
attachments: JSON.stringify(post.acf.attachments),
)};
MySQL and knex both support the JSON format, I'd suggest you change the field to json. (See knex docs and mysql 8 docs). You'll stiil need to stringify your objects tho.
EDIT: I just saw that Knex supports jsonInsert (and plenty other neat stuff) as a query builder that should be useful for you.
Mysql also support a large range of cool stuffs for handling jsons
In addition, when you fetch the results in the database, you'll need to parse the JSON result to get an actual JSON object:
const acf = await knex('posts').select('acf').first();
const attachment = JSON.parse(acf.attachment;
Knex also provide jsonExtract that should fill your needs (See also the mysql json_extract

How to parse nested JSON, within a string, using Kusto

I have a Python Azure Function that produces custom logging messages when the Function executes. I need to pull out some of the JSON values nested in the logging message.
How can I use Kusto to access the nested JSON within the logging message string?
Example logging message:
Desired values marked with <----------
####### EventGrid trigger processing an event:
{
"id": "long-guid",
"data": {
"api": "FlushWithClose",
"requestId": "long-guid",
"eTag": "long-guid",
"contentType": "application/octet-stream",
"contentLength": 16264, <----------------------
"contentOffset": 0,
"blobType": "BlockBlob",
"blobUrl": "https://function.blob.core.windows.net/parentdir/childdir/file.name",
"url": "https://function.dfs.core.windows.net/parentdir/childdir/file.name", <---- JUST FILE.NAME here
"sequencer": "long-guid",
"identity": "long-guid",
"storageDiagnostics": {
"batchId": "long-guid"
}
},
"topic": "/subscriptions/long-guid/resourceGroups/resourceGroup/providers/Microsoft.Storage/storageAccounts/accountName",
"subject": "/blobServices/default/containers/containerName/blobs/childDir/file.name",
"event_type": "Microsoft.Storage.BlobCreated"
} #######
I imagine it has something to do with the Kusto extend function, but piping in...
| extend parsedMessage = todynamic(message)
| project timestamp, test = parsedMessage["id"]
...yields only an empty test column
message in your specific case isn't a valid JSON payload - as it has the ###... EventGrid trigger processing an event: prefix (and a somewhat similar suffix).
That is why todynamic() isn't able to process it and why you're not able to reference properties in the JSON payload that's included in it.
Ideally, you would change the payload you ingest to be a valid JSON payload, and re-type the target column to dynamic instead of string.
If you can't do that, you can use the substring() function or parse operator to get everything but the aforementioned prefix/suffix, and parse the output of that using todynamic()
though note that doing that each time you query the data bears runtime overhead that could be avoided by following the advice above.

WSO2 Enterprise Integrater 6.6.0 Response transform XML to Json using XSLT

I got a response from endpoint in WSO2 enterprise Integrator as a XML. I can get it as a Json too. but I need to make suitable response (add more parameters) for my client application. this is the xml response i got from endpoint.
<jsonObject>
<ddd>
<__type>Title</__type>
<AccountNo/>
<AccountExists>1</AccountExists>
<Name>user name</ConsumerName>
<Address> user address</ConsumerAddress>
<TotalDue>1000.38</TotalDue>
<LastBillingCycleAmount/>
<ID>150</ID>
</d>
and also this is the json output i can retrieve from endpoint
{
"ddd": {
"__type": "Title",
"AccountNo": null,
"AccountExists": 1,
"Name": "user name",
"Address": "address",
"TotalDue": "1000.38",
"LastBillingCycleAmount": null,
"ID": 150
}
}
I need transform response like this.
{
"AccountNo": "response_data",
"ConsumerName": "response_data",
"ConsumerAddress": "response_data",
"TotalDue": "response_data",
"additional_para1": "my_data", // parameter that i want to add manually
"additional_para2": "my_data", // parameter that i want to add manually
}
You can use a data mapper mediator [1] to map the input to the desired output. Then use a enrich mediator [2] to enrich the generated payload by adding your own values
[1]-https://ei.docs.wso2.com/en/7.1.0/micro-integrator/references/mediators/data-Mapper-Mediator/
[2]-https://docs.wso2.com/display/EI620/Enrich+Mediator

App Engine Servlet: how to parse a request body containing a JSON-encoded message?

I use the Cloud Storage Object Change Notification to notify my App Engine server that a new file has been uploaded. The Object Change Notification is sent as a POST request to a servlet in App Engine.
The body of the request contains a JSON-encoded message as shown in the following example of notification request, directly copied from Google Documentation (https://cloud.google.com/storage/docs/object-change-notification):
{
"kind": "storage#object",
"id": "BucketName/ObjectName",
"selfLink": "https://www.googleapis.com/storage/v1/b/BucketName/o/ObjectName",
"name": "ObjectName",
"bucket": "BucketName",
"generation": "1367014943964000",
"metageneration": "1",
"contentType": "binary/octet-stream",
"updated": "2013-04-26T22:22:23.832Z",
"size": "10",
"md5Hash": "xHZY0QLVuYng2gnOQD90Yw==",
"mediaLink": "https://www.googleapis.com/storage/v1/b/BucketName/o/ObjectName?generation=1367014943964000&alt=media",
....
}
My question is what would be the best solution for parsing the JSON content to java object(s)? I guess the best would be to use a library like e.g. Google gson, but is there any one particularly recommended to be used with App Engine? Or any other better way?
Thanks!
Finally I've used the Google gson library and since I only want to parse a couple of elements of the JSON I've used the following code:
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(req.getReader()).getAsJsonObject();
String objectName = obj.get("name").getAsString();
String objectBucket = obj.get("bucket").getAsString();
It works perfectly.

Ember-Data: How to get properties from nested JSON

I am getting JSON returned in this format:
{
"status": "success",
"data": {
"debtor": {
"debtor_id": 1301,
"key": value,
"key": value,
"key": value
}
}
}
Somehow, my RESTAdapter needs to provide my debtor model properties from "debtor" section of the JSON.
Currently, I am getting a successful call back from the server, but a console error saying that Ember cannot find a model for "status". I can't find in the Ember Model Guide how to deal with JSON that is nested like this?
So far, I have been able to do a few simple things like extending the RESTSerializer to accept "debtor_id" as the primaryKey, and also remove the pluralization of the GET URL request... but I can't find any clear guide to reach a deeply nested JSON property.
Extending the problem detail for clarity:
I need to somehow alter the default behavior of the Adapter/Serializer, because this JSON convention is being used for many purposes other than my Ember app.
My solution thus far:
With a friend we were able to dissect the "extract API" (thanks #lame_coder for pointing me to it)
we came up with a way to extend the serializer on a case-by-case basis, but not sure if it really an "Ember Approved" solution...
// app/serializers/debtor.js
export default DS.RESTSerializer.extend({
primaryKey: "debtor_id",
extract: function(store, type, payload, id, requestType) {
payload.data.debtor.id = payload.data.debtor.debtor_id;
return payload.data.debtor;
}
});
It seems that even though I was able to change my primaryKey for requesting data, Ember was still trying to use a hard coded ID to identify the correct record (rather than the debtor_id that I had set). So we just overwrote the extract method to force Ember to look for the correct primary key that I wanted.
Again, this works for me currently, but I have yet to see if this change will cause any problems moving forward....
I would still be looking for a different solution that might be more stable/reusable/future-proof/etc, if anyone has any insights?
From description of the problem it looks like that your model definition and JSON structure is not matching. You need to make it exactly same in order to get it mapped correctly by Serializer.
If you decide to change your REST API return statement would be something like, (I am using mock data)
//your Get method on service
public object Get()
{
return new {debtor= new { debtor_id=1301,key1=value1,key2=value2}};
}
The json that ember is expecting needs to look like this:
"debtor": {
"id": 1301,
"key": value,
"key": value,
"key": value
}
It sees the status as a model that it needs to load data for. The next problem is it needs to have "id" in there and not "debtor_id".
If you need to return several objects you would do this:
"debtors": [{
"id": 1301,
"key": value,
"key": value,
"key": value
},{
"id": 1302,
"key": value,
"key": value,
"key": value
}]
Make sense?