Not able to fetch the value of a key from JSON data - json

I am trying to fetch value if "id" from JSON response I got from a POST request.
{
"callId": "87e90efd-eefb-456a-b77e-9cce2ed6e837",
"commandId": "NONE",
"content": [
{
"scenarioId": "SCENARIO-1",
"Channel": "Channel1-1",
"data": {
"section": {
"class": {
"repository": [
{
"export": "export-1",
"modules": "module-1",
"index": "23",
"period": {
"axis": {
"new_channel": "channel-1.1"
},
"points": [
{
"id": "6a5474cf-1a24-4e28-b9c7-6b570443df9c",
"duration": "150",
"v": 1.01,
"isNegligible": false
}
]
}
}
]
}
}
}
}
]
}
I am able to display the entire response json and am also able to get the value of "callId" using below code. Getting error at last line:
Cannot read property '0' of undefined
Code snippet:
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
let responseData = JSON.stringify(body);
//Display the entire response
console.log(responseData);
//Display the callId
console.log(body['callId']);
//Getting error here
console.log(body.content[0].repository[0].points[0].id);
}
}
Any solution to get value of "id" ?

Right now you are trying to log body.content[0].repository[0].points[0].id).
If you look at it carefully the repository[0] is an object and it has no immediate child points.
So repository[0].points would evaluate to undefined and by specifying repository[0].points[0], you are trying to access property 0 of undefined as the error states.
The correct way of accessing id would be as follows :
body.content[0].data.section.class.repository[0].period.points[0].id
If you have confusion regarding parsing JSON try breaking it down by consoling body and then by expanding it in the console or in JSONeditor
PS: It is also recommended that you check at each level if the value exists before trying to access a deeper child elements, since in some cases your body may not contain one of the values, say content for example. In that case trying to access body.content[0] will cause an error. So it is recommended to do checks at each level like follows
if(body){
if(body.content){
if(body.content[0]){
/* and so on*/
}
}
}

Try with
console.log(body.content[0].data.section.class.repository[0].period.points[0].id)

Related

Operator "missing" not working properly in JsonLogic

I am using JsonLogic to validate my input payload with the rules defined using JsonLogic. I am able to test the rules using "Play with it" tool and my rules work perfectly fine against my input data.
But when I run the same rules through my .net Core application by passing payload from Postman the rules always return the else condition even when it should the error from if condition.
{
"if": [
{
"missing": [
"ProposedProjectDetails.IsFreezone",
"ProposedProjectDetails.InterestedToLeaseFrom",
"ProposedProjectDetails.IndustryType",
"ProposedProjectDetails.OtherType",
"ProposedProjectDetails.ProjectDescription",
"ProposedProjectDetails.OutputofFacility",
"ProposedProjectDetails.ProductionCapacity",
"ProposedProjectDetails.ProductionCapacityVolume",
"ProposedProjectDetails.MainRawMaterials",
"ProposedProjectDetails.RawMaterialQuantity",
"ProposedProjectDetails.RawMaterialEstimatedCost",
"ProposedProjectDetails.RawMaterialEstimatedTotInvestment",
"ProposedProjectDetails.AnnualSalesRevenue",
"ProposedProjectDetails.ConstructionStartDate",
"ProposedProjectDetails.Skilledjobs",
"ProposedProjectDetails.TotalAccomodationRequired",
"ProposedProjectDetails.TotalWorkerSalary",
"ProposedProjectDetails.EBITDA",
"ProposedProjectDetails.PortCargoImports",
]
},
"Missing mandatory inputs",
"all good"
]
}
Sample input payload is
{
"companyId": "string",
"serviceCode": "IPA",
"serviceType": "string",
"serviceName": "string",
"crmApplicationId": "string",
"crmReferenceNumber": "string",
"portalReferenceNumber": "string",
"data": {
"proposedProjectDetails": {
"outputofFacility": 2,
"productionCapacity": 0,
"productionCapacityVolume": 0,
"others": "string",
"shiftsPerDay": 0
}
}
}
My .Net code which is evaluating this is
public ValidationResponse Validate(JObject validation, JObject data)
{
var evaluator = new JsonLogicEvaluator(EvaluateOperators.Default);
var result = evaluator.Apply(validation, data);
return new ValidationResponse
{
IsValid = (string.Equals("All Fine", result.ToString(), StringComparison.OrdinalIgnoreCase)),
Message = result
};
}
When I run above code with JsonRules and above Payload, I always get all good in the response. But since I am missing required data in payload, it should get the error Missing mandatory inputs which I do get in JsonLogic "Play with it" tool.
Try keeping the names as json mapping fields camel case once like below
"if": [
{
"missing": [
"proposedProjectDetails.isFreezone",
"proposedProjectDetails.interestedToLeaseFrom",
]
},
"Missing mandatory inputs",
"all good"
]
}

How to allow Optional Key in API Gateway mapping template

I have an API gateway that scans a DynamoDB table. I want to pass LastEvaluatedKey in my request body; if I pass a LastEvaluatedKey then the everything works and I get a response with the expected data - so I'm half way there.
But, of course, the first time I send a request to the API LastEvaluatedKey will not exist, so the ExclusiveStartKey in the mapping template that expects a LastEvaluatedKey must be optional. I've tried a few different ways to get this to be optional but nothing has worked so far. Here is what I have:
#set($hasName = $input.json('$.Name'))
{
"TableName": "MyTable",
#if($hasName && $hasName.length() != 0)
"ExclusiveStartKey": {
"Name": {
"S": $input.json('$.Name')
},
"Date": {
"S": $input.json('$.Date')
}
},#end
"FilterExpression": "begins_with(#dt, :tdt)",
"ExpressionAttributeNames": {
"#dt": "Date"
},
"ExpressionAttributeValues": {
":tdt": {
"S": "$input.params('date')"
}
}
}
As I say, the above works when I do pass a LastEvaluatedKey in my request body, but when I do not I get the error:
{
"__type": "com.amazon.coral.validate#ValidationException",
"message": "The provided starting key is invalid: One or more parameter values were invalid: An AttributeValue may not contain an empty string"
}
...it's still expected the LastEvaluatedKey
I've also tried wrapping Name and Date inside if #if but with no luck at all. I've taken inspiration from other answers such as: this and this, but no luck.
In my example cursor is the LastEvaluatedKey:
#set($hasCursor = $input.params('cursor') != "")
{
"TableName": "my-table"
#if($hasCursor) "ExclusiveStartKey":$util.base64Decode("$input.params('cursor')")
#end
}
It just checks if cursor is passed as a query param (like /my/api?cursor=myencodedlastevaluatedkey), and only adds ExclusiveStartKey to the request if it is.
If you know beforehand that both keys are string type, you can do:
#set($Name = $input.params('Name'))
#set($Date = $input.params('Date'))
{
#if($Name != '' && $Date != '')
"ExclusiveStartKey": {
"Name": {
"S": "$Name"
},
"Date": {
"S": "$Date"
}
},
#end
#if($Date != '')
"FilterExpression": "begins_with(#dt, :tdt)",
"ExpressionAttributeNames": {
"#dt": "Date"
},
"ExpressionAttributeValues": {
":tdt": {
"S": "$Date"
}
}
},
#end
"TableName": "MyTable"
}
This makes the filter optional, only if Date is passed as argument

Firestore REST API starting query

I am struggling with Firestore REST API. Database have a collection with Users. Every user is separate document. I need to get all users with, for example, category equal 1. Here is my attempt (request body):
{
"structuredQuery": {
"where" : {
"fieldFilter" : {
"field": { "fieldPath" : "category" } ,
"op":"EQUAL",
"value": { "integerValue" : 1 }
}
}
}
}
and response error:
"error": {
"code": 400,
"message": "kind is required for filter: category",
"status": "INVALID_ARGUMENT"
}
I have totaly no idea, how "field" inside "fieldFilter" should looks like. Thanks in advance.
I believe if you include the "from" property of the structured query, this will work. If the collection you're querying from is called "users" it would look like this, based on what you posted above:
{
"structuredQuery": {
"where" : {
"fieldFilter" : {
"field": {"fieldPath": "category"},
"op":"EQUAL",
"value": {"integerValue": 1}
}
},
"from": [{"collectionId": "users"}]
}
}

Asserting the values in JSON response through tests in Postman

My JSON response body looks like :
[
{
"_time": "1499996827804",
"properties": {
"length": "80",
"width": "4500"
}
}
]
I am using Postman to write tests to assert on value of length and width and _time.
I wrote :
var data = JSON.parse(responseBody);
tests["Check length value"] = data.length === "80";
But it's failing. Can anyone help ?
If your JSON looks like this:
[ { "_time": "1499996827804", "properties": { "length": "80", "width": "4500" } } ]
Then you need to fix the data.length === "80" part of your test.
Firstly, your JSON is an array, so you need to be selecting data[0] to get the first item in the response (which is { "_time": "1499996827804", "properties": { "length": "80", "width": "4500" } }). Then, it looks like you're trying to check the length part of the response, which is under the properties object. So your selector should now look like this: data[0].properties.
And finally, to access the length part, add .length to the end of your selector: data[0].properties.length.
Put it all together, and you should have:
tests["Check length value"] = data[0].properties.length === "80";
Hope it helps!
Your data is coming back in an array so you need to get the first item of the array. Also length is a sub property of the "properties" object. Try this:
tests["Check length value"] = data[0].properties.length === "80";

How to return a subcollection (or object) in json without including all attributes

I am using mongoose as JSON Schema and node.js with it. Need not say, I am new to both. I have been struggling through the day to get this thing work for me but couldn't. Finally, the only solution was to get help from some real nice people out here.
Here is my schema definition -
UserName = {
"properties": {
userURL: {
"description": "URL of this resource",
"type": "string"
},
userName : {
"description": "UserName",
"type": "string",
"required": true
},
}
}
When I make a get call to it, it returns the response in following format -
[
{
"_id": "54c5ede55c82c4bd6abee50a",
"__v": 0,
"properties": {
"userURL": "http://localhost:3000/54c1d6ae441ae900151a6520",
"userName ": "testUser"
}
}
]
Now my requirement is to return the response in following format -
[
{
"_id": "54c5ede55c82c4bd6abee50a",
"userURL": "http://localhost:3000/54c1d6ae441ae900151a6520",
"userName ": "testUser"
}
]
i.e without version and properties tags. I am able to get away with version using following code but properties seems to be tricky thing -
.get(function(request, response) {
UserSchemaModel.find().select('properties.userURL properties.userName').exec (function (err, resObj) {
if (err)
response.send(err);
else{
response.json(resObj);
}
});
});
But it still has properties field :( -
[
{
"_id": "54c5ede55c82c4bd6abee50a",
"properties": {
"userURL": "http://localhost:3000/54c1d6ae441ae900151a6520",
"userName ": "testUser"
}
}
]
I did some google around select as, alias name in select,population in mongoose but no luck.
Kindly suggest. With best Regards.
Just make a new object
response.json(
{
"_id": resObj["_id"],
"userURL": resObj["properties"]["userUrl"],
"userName": resObj["properties"]["userName"]
}
);
Update: Since resObj is an array (as per your comment), you can use Array.prototype.map() to transform them into the right format like so:
response.json( resObj.map(function(o){
return {
"_id": o["_id"],
"userURL": o["properties"]["userUrl"],
"userName": o["properties"]["userName"]
};
})
);
This will return a list of transformed objects that then get passed into the response.json() method.