Nested JSON on WireMock Response - json

Is there any way to dynamically include JSON from the request body in the response?
Input Request
{
"id":"1234",
"message":"{\"key\":\"value\"}"
}
Expected Output
{
"status":"CREATED",
"id":"1234",
"message":"{\"key\":\"value\"}"
}
The message and id fields are dynamic and need to be picked from the request.
I have tried the below mapping to dynamically load the response from the request but \" inside message json is converted to "
{
"request": {
"method": "POST",
"urlPath": "/test"
},
"response": {
"status": 200,
"transformers": [
"response-template"
],
"jsonBody": {
"status": "CREATED",
"id": "{{jsonPath request.body '$.id'}}",
"message": "{{jsonPath request.body '$.message'}}"
}
}
}
This returns message as {"key":"value"}.
Even, I have tried changing the mapping to {{{jsonPath request.body '$.message'}}}. But this messes up the whole response json and message value is being returned as "{"key":"value"}" without escape characters.
I'm looking for suggestions to map message dynamically. Thanks in advance.

Related

Reading a section in a json result and adding to a python list

I received the json below as response from an api call
{
"apiStatusInfo": {
"apiStatus": "Success",
"apiStatusCode": 0
},
"errors": [
{
"userEmail": "man.done.banner.com",
"error": "Invalid input parameters in request"
},
{
"userEmail": "ban.super.banner.com",
"error": "Invalid input parameters in request"
}
]
}
I want to be able to read the errors section and append it to a list so I can send it
out via email. I created this function
def testbobo():
my_data = f'''{
"apiStatusInfo": {
"apiStatus": "Success",
"apiStatusCode": 0
},
"errors": [
{
"userEmail": "man.done.banner.com",
"error": "Invalid input parameters in request"
},
{
"userEmail": "ban.super.banner.com",
"error": "Invalid input parameters in request"
}
]
}'''
converter = json.load(my_data)
for i in converter['errors']:
print(i)
testbobo()
All I have been getting is "ValueError: Invalid format specifier"
what is wrong with this? How can I extract the errors section and add to a python list?
Two problems:
You are defining an F-string, but the accolades {} have special significance, so they should be escaped (doubled) like this: {{. Or simply removing the leading f should be enough to fix the problem.
And then you need to write: json.loads(my_data) instead of: json.load(my_data) because you are loading a dict from a string, not from a file.
But I don't think you are doing any string interpolation here, so you don't need a string in the first place, just a regular dict. In other words, you should be able to cast the response as dict right away.
Try:
import json
data = """\
{
"apiStatusInfo": {
"apiStatus": "Success",
"apiStatusCode": 0
},
"errors": [
{
"userEmail": "man.done.banner.com",
"error": "Invalid input parameters in request"
},
{
"userEmail": "ban.super.banner.com",
"error": "Invalid input parameters in request"
}
]
}"""
data = json.loads(data)
errors = []
emails = []
for e in data.get("errors", []):
err = e.get("error", "N/A")
errors.append(err)
em = e.get("userEmail", "N/A")
emails.append(em)
for err, em in zip(errors, emails):
print(em, err)
Prints:
man.done.banner.com Invalid input parameters in request
ban.super.banner.com Invalid input parameters in request

Post List <int> in http Flutter

I want to send a data like this :
{
"ad_title": "test",
"year": "2019",
"class": "Highline",
"files": [ 212]
}
To api in flutter. I tried to do that
var data = {
"year": selectedYear,
"class": _classController.text.toString(),
"files": json.encode(carfilesids),
};
final response = await http.post(url, body: data,headers:
{'Accept': 'application/json'});
However there's no errors in run time and when I print the value of json.encoder.convert(carfilesids) it gives me List, I got a response status code of 422 and it tells me " {"message":"The given data was invalid.","errors":{"files":["The files must be an array."]}} ". I also tried to json.encode the whole data but it goes wrong with the other data attributes.
You must use jsonEncode on your map, or else the http package will treat it as form data.
From the documentation:
If body is a Map, it's encoded as form fields using encoding. The content-type of the request will be set to "application/x-www-form-urlencoded"; this cannot be overridden.
final response = await http.post(url,
body: {
"ad_title": "test",
"year": "2019",
"class": "Highline",
"files": [ 212 ]
},
headers: {
'Accept': 'application/json'
}
);

Ajax post request to google NLP

Im trying to do a post request to GCP Natural Language for sentiment analysis.
When I try the data format on the code explorer on google it works fine but when I run it on a html page I get an error that reads
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"document[type]\": Cannot bind query parameter. Field 'document[type]' could not be found in request message.\nInvalid JSON payload received. Unknown name \"document[content]\": Cannot bind query parameter. Field 'document[content]' could not be found in request message.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"document[type]\": Cannot bind query parameter. Field 'document[type]' could not be found in request message."
},
{
"description": "Invalid JSON payload received. Unknown name \"document[content]\": Cannot bind query parameter. Field 'document[content]' could not be found in request message."
}
]
}
]
}
}
My code is:
<!DOCTYPE html>
<html>
<body>
<h1> Testing sentiment Analysis </h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var APIKEY = "AN API KEY";
$.ajax({
type : "POST",
url : "https://language.googleapis.com/v1/documents:analyzeSentiment?key="+APIKEY,
data : {
"document": {
"type": "PLAIN_TEXT",
"content": "Hello I am great"
},
"encodingType": "UTF8",
},
success: function(res) {
console.log(res);
alert(res['message']);
},
error: function(res) {
console.log(res['message']);
alert(res);
},
});
</script>
</body>
</html>
UPDATE:
A colleague has pointed me to the MISTAKE I was making. We have to use JSON.stringify() in order to send the request. The code should be like this:
$.ajax({
type : "POST",
url : "https://language.googleapis.com/v1/documents:analyzeEntitySentiment?key=YOUR-API-KEY",
contentType : "application/json; charset=utf-8",
data :
JSON.stringify({
"document": {
"type": "PLAIN_TEXT",
"language": "en",
"content": "Hola Victor"
},
"encodingType": "UTF8"}),
success : function(_result){
if (_result) {
alert('SUCCESS');
} else {
alert('ERROR');
}
},
error : function(_result){
}
});
I have tested it and it works.

Use Apps Script URLFetchApp to access Google Datastore Data

I want to experiment with Google Datastore via Apps Script because I have a current solution based on Google sheets that runs into timeout issues inherent in constantly transacting with Drive files. I've created a test project in Google cloud with a service account and enabled library MZx5DzNPsYjVyZaR67xXJQai_d-phDA33
(cGoa) to handle the Oauth2 work. I followed the guide to start it up here and got all the pertinent confirmation that it works with my token (and that removing the token throws an 'authentication failed prompt').
Now I want to start with a basic query to display the one entity I already put in. I can use the API Explorer here and run this query body:
{
"query": {}
}
and get this result:
{
"batch": {
"entityResultType": "FULL",
"entityResults": [
{
"entity": {
"key": {
"partitionId": {
"projectId": "project-id-5200707333336492774"
},
"path": [
{
"kind": "Transaction",
"id": "5629499534213120"
}
]
},
"properties": {
"CommentIn": {
"stringValue": "My First Test Transaction"
},
"Status": {
"stringValue": "Closed"
},
"auditStatus": {
"stringValue": "Logged"
},
"User": {
"stringValue": "John Doe"
},
"Start": {
"timestampValue": "2017-08-17T18:07:04.681Z"
},
"CommentOut": {
"stringValue": "Done for today!"
},
"End": {
"timestampValue": "2017-08-17T20:07:38.058Z"
},
"Period": {
"stringValue": "08/16/2017-08/31/2017"
}
}
},
"cursor": "CkISPGogc35whh9qZWN0LWlkLTUyMDA3MDcwODA1MDY0OTI3NzRyGAsSC1RyYW5zYWN0aW9uGICAgICAgIAKDBgAIAA=",
"version": "1503004124243000"
}
],
"endCursor": "CkISPGogc35wcm9qZWN0LWlkLTUyMDAxxDcwODA1MDY0OTI3NzRyGAsSC1RyYW5zYWN0aW9uGICAgICAgIAKDBgAIAA=",
"moreResults": "NO_MORE_RESULTS"
}
}
I try to do the same thing with this code:
function doGet(e)
{
var goa = cGoa.GoaApp.createGoa('Oauth2-Service-Account',
PropertiesService.getScriptProperties()).execute(e);
if(goa.hasToken()) {var token = goa.getToken();}
var payload = {"query":{}}
;
var result = UrlFetchApp.fetch('https://datastore.googleapis.com/v1/projects/project-id-5200707333336492774:runQuery',
{
method: "POST",
headers: {authorization: "Bearer " + goa.getToken()},
muteHttpExceptions : true,
payload: payload
});
Logger.log(result.getBlob().getDataAsString());
}
and get this error in the logger:
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"query\": Cannot bind query parameter. 'query' is a message type. Parameters can only be bound to primitive types.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"query\": Cannot bind query parameter. 'query' is a message type. Parameters can only be bound to primitive types."
}
]
}
]
}
}
If I try to use another word such as 'resource' or 'GqlQuery', I get this error:
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"GqlQuery\": Cannot bind query parameter. Field 'GqlQuery' could not be found in request message.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"GqlQuery\": Cannot bind query parameter. Field 'GqlQuery' could not be found in request message."
}
]
}
]
}
}
I can't tell from the API Documentation what my syntax is supposed to be. Can anyone tell me how to compile a functional request body from Apps Script to Datastore?
You need to set the contentType of your payload as well as stringify your JSON payload as follows:
var result = UrlFetchApp.fetch(
'https://datastore.googleapis.com/v1/projects/project-id-5200707333336492774:runQuery',
{
'method':'post',
'contentType':'application/json',
'headers': {authorization: "Bearer " + goa.getToken()},
'payload':JSON.stringify(payload)
}
);

Returning json in Wiremock using JSONPath based on attribute value

I'm trying to do stubbing with Wiremock to provide a response based upon the body that is sent in the post request.
For example, when sending this json:
{
"person": {
"firstName": "paul",
"age": "50"
}
}
I want to send pauldata.json
This is my request/ response json below:
{
"request": {
"method": "POST",
"url": "/api/test1",
"bodyPatterns": [
{
"matchesJsonPath": "$.person[?(#.firstName=='paul')]"
}
]
},
"response": {
"status": 200,
"bodyFileName": "pauldata.json",
"headers": {
"Content-Type": "application/json"
}
}
}
However this results in an error:
JSON path expression '$.person[?(#.firstName=='paul')]' failed to match document because of error 'net.minidev.json.JSONObject cannot be cast to java.util.List
this expression: $.person[?(#.firstName=='paul')] matches the json with the Jayway implementatin at http://jsonpath.herokuapp.com/, but not the Goessner implementation which Wiremock uses.
I noticed that if I just do $.person.firstName in jayway it returns "paul",
but when I do the same thing in Goessner I get ["paul"].
How can I match on the value of key using the Goessner implementation of JSONPath so I can return a custom json based on the value of a key in my data?
WireMock does not accept all JSONPath expressions, although they do work in online testers. I had the same problem, and solved it using the following:
{
"request": {
"method": "POST",
"url": "/api/test1",
"bodyPatterns": [
{
"matchesJsonPath": "$..[?(#.firstName=='paul')]"
}
]
},
"response": {
"status": 200,
"bodyFileName": "pauldata.json",
"headers": {
"Content-Type": "application/json"
}
}
}
The only thing that changed is from:
$.person[?(#.firstName=='paul')]
To:
$..[?(#.firstName=='paul')]
This is because .. notation searches through all input recursively.
In case you need to query a root element, meaning one that doesn't have a parent element, the same JSONPath will do. For example, imagine you have another element like so:
{
"person": {
"firstName": "paul",
"age": "50"
},
"test": "true"
}
In case you want to match for "test": "true" you would need JSONPath as follows:
$..[?(#.test=='true')]
I tested everything in my WireMock so it should work.