Can't place GraphQL custom type as a Postman variable - post

Has anyone had luck with placing a GraphQL custom type argument as a Postman or Graphql variable? I'm kinda spinning in circles right now, I hope a fresh pair of eyes could point me in the right direction.
What I'm trying to do is to send a mutation request using Postman. The problem I'm having is that the method I'm calling is taking a custom type as an argument. Placing the content of that variable as GraphQL variable or Postman variable is giving me a headache. I can't embedd pictures yet, so here are the links (they are safe).
Schema
This custom type is a JSON-like structure, consisting of two enums and a set of primitive types (strings, ints...). I can screenshot the entire thing but basically that's it: two enums followed by strings, ints...
Custom type definition
What I've tried so far:
Simply hardcoding the request in Postman works but I wish to send multiple requests with varying data
Placing it in a GraphQL variable results in error message
{
"errors": [
{
"message": "Bad request - invalid request body.",
"locations": []
}
],
"data": null
}
Placing the custom type content as a Postman environment variable works, but I'm getting a syntax error (although the request passes...).
Request body is below. Hardcoding it and using a Postman variable produces the same request body, apart from the syntax error.
query: "mutation {
createApplication(request: {
applicationKind: NEW_ISSUANCE,
documentKind: REGULAR_PASSPORT,
personalData: {
timestamp: null,
firstname: "NAME",
lastname: "LASTNAME",
middlename: "MIDDLENAME",
dateOfBirth: "2011-09-28",
citizenshipCountryCode: "USA",
gender: MALE,
personalNumber: "3344",
placeOfBirth: "CHICAGO",
municipalityOfBirth: "SOUTH",
countryCodeOfBirth: "USA"},
addressData:{
street: "WEST",
municipality: "EAST",
place: "CHICAGO",
country: {
code: "USA",
name: null
},
entrance: "б",
flat: "13",
number: "35"}
})
{
__typename
... on AsyncTaskStatus {
taskID
state
payload {
... on ApplicationUpdated {
applicationID
applicationNumber
__typename
}
__typename
}
__typename
}
... on Error {
...errorData
__typename
}
}
}
fragment errorData on Error {
__typename
code
message
}"
Postman variable with a squiggly line
I'm spinning in circles right now. Has anyone had any luck with Postman requests of this kind?
I can post more info, screenshots...just let me know. I'll be watching this topic closely and provide feedback.
Thank you for your time.

please add a the variable in variable section as :
{
"request": {{request}}
}
and then refer this in your query as
$request

Related

Show description or comments for variables in FastAPI autodocs (Swagger UI)

I'm making a function and class for it with POST method.
Since I use FastAPI, it automatically generates API docs (using OpenAPI specification and Swagger UI), where I can see the function's description or example data there.
My class and function are like below:
from pydantic import BaseModel, Field
from typing import Optional, List
#app.post("/user/item")
def func1(args1: User, args2: Item):
...
class User(BaseModel):
name: str
state: List[str]
class Config:
schema_extra = {
"example": {
"name": "Mike",
"state": ["Texas", "Arizona"]
}
}
class Item(BaseModel):
_id: int = Field(..., example=3, description="item id")
Through schema_extra and example attribute in Field, I can see the example value in Request body of function description.
It shows like
{
"args1": {
"name": "Mike",
"state": ["Texas", "Arizona"] # state user visits. <-- I'd like to add this here or in other place.
},
"args2: {
"_id": 3 <-- Here I can't description 'item id'
}
}
However, I'd like to add description or comments to example value, like # state user visits above.
I've tried to add description attribute of pydantic Field, but I think it shows only for parameters of get method.
Is there any way to do this? Any help will be appreciated.
You are trying to pass "comments" inside the actual JSON payload that will be sent to the server. Thus, such an approach wouldn't work. The way to add description to the fields is as shown below. Users/you can see the descriptions/comments, as well as the examples provided, by expanding the corresponding JSON schema of a Pydantic model (e.g., "User") under "Schemas" (at the bottom of the page) when visting OpenAPI at http://127.0.0.1:8000/docs, for instance. Or, by clicking on "Schema", next to "Example Value", above the example given in the "Request Body".
class User(BaseModel):
name: str = Field(..., description="Add user name")
state: List[str] = Field(..., description="State user visits")
class Config:
schema_extra = {
"example": {
"name": "Mike",
"state": ["Texas", "Arizona"]
}
}
Alternatively, you could use Body field in your endpoint, allowing you to add a description that is shown under the example in the "Request body". As per the documentation:
But when you use example or examples with any of the other utilities
(Query(), Body(), etc.) those examples are not added to the JSON
Schema that describes that data (not even to OpenAPI's own version of
JSON Schema), they are added directly to the path operation
declaration in OpenAPI (outside the parts of OpenAPI that use JSON
Schema).
You could add multiple examples (with their associated descriptions), as described in the documentation. Example below:
#app.post("/user/item")
async def update_item(
user: User = Body(
...,
examples={
"normal": {
"summary": "A normal example",
"description": "**name**: Add user name. **state**: State user vistis. ",
"value": {
"name": "Mike",
"state": ["Texas", "Arizona"]
},
}
}
),
):
return {"user": user}

Zapier - add data to JSON response (App development)

We are creating a Zapier app to expose our APIs to the public, so anyone can use it. The main endpoint that people are using returns a very large and complex JSON object. Zapier, it looks like, has a really difficult time parsing nested complex JSON. But it does wonderful with a very simple response object such as
{ "field": "value" }
Our data that is being returned has this structure and we want to move some of the fields to the root of the response so it's easily parsed by Zapier.
"networkSections": [
{
"identifier": "Deductible",
"label": "Deductible",
"inNetworkParameters": [
{
"key": "Annual",
"value": " 600.00",
"message": null,
"otherInfo": null
},
{
"key": "Remaining",
"value": " 600.00",
"message": null,
"otherInfo": null
}
],
"outNetworkParameters": null
},
So, can we do something to return for example the remaining deductible?
I got this far (adding outputFields) but this returns an array of values. I'm not sure how to parse through this array either in the Zap or in the App.
{key: 'networkSections[]inNetworkParameters[]key', label: 'xNetworkSectionsKey',type: 'string'},
ie this returns an array of "Annual", "Remaining", etc
Great question. In this case, there's a lot going on, and outputFields can't quite handle it all. :(
In your example, inNetworkParameters contains an array of objects. Throughout our documentation, we refer to these as line items. These lines items can be passed to other actions, but the different expected structures presents a bit of a problem. The way we've handled this is by letting users map line-items from one step's output to another step's input per field. So if step 1 returns
{
"some_array": [
{
"some_key": "some_value"
}
]
}
and the next step needs to send
{
"data": [
{
"some_other_key": "some_value"
}
]
}
users can accomplish that by mapping some_array.some_key to data.some_other_key.
All of that being said, if you want to always return a Remaining Deductible object, you'll have to do it by modifying the result object itself. As long as this data is always in that same order, you can do something akin to
var data = z.JSON.parse(bundle.response.content);
data["Remaining Deductible"] = data.networkSections[0].inNetworkParameters[1].value;
return data;
If the order differs, you'll have to implement some sort of search to find the objects you'd like to return.
I hope that all helps!
Caleb got me where I wanted to go. For completeness this is the solution.
In the creates directory I have a js file for the actual call. The perform part is below.
perform: (z, bundle) => {
const promise = z.request({
url: 'https://api.example.com/API/Example/' + bundle.inputData.elgRequestID,
method: 'GET',
headers: {
'content-type': 'application/json',
}
});
return promise.then(function(result) {
var data = JSON.parse(result.content);
for (var i=0; i<data.networkSections.length; i++) {
for (var j=0; j<data.networkSections[i].inNetworkParameters.length; j++) {
// DEDUCT
if (data.networkSections[i].identifier == "Deductible" &&
data.networkSections[i].inNetworkParameters[j].key == "Annual")
data["zAnnual Deductible"] = data.networkSections[i].inNetworkParameters[j].value;
} // inner for
} // outer for
return data;
});

How to get a sub-field of a struct type map, in the search response of YQL query in Vespa?

Sample Data:
"fields": {
"key1":0,
"key2":"no",
"Lang": {
"en": {
"firstName": "Vikrant",
"lastName":"Thakur"
},
"ch": {
"firstName": "维克兰特",
"lastName":"塔库尔"
}
}
}
Expected Response:
"fields": {
"Lang": {
"en": {
"firstName": "Vikrant",
"lastName":"Thakur"
}
}
}
I have added the following in my search-definition demo.sd:
struct lang {
field firstName type string {}
field lastName type string {}
}
field Lang type map <string, lang> {
indexing: summary
struct-field key {
indexing: summary | index | attribute
}
}
I want to write a yql query something like this (This doesn't work):
http://localhost:8080/search/?yql=select Lang.en from sources demo where key2 contains 'no';
My temporary workaround approach
I have implemented a custom searcher in MySearcher.java, through which I am able to extract the required sub-field and set a new field 'defaultLang', and remove the 'Lang' field. The response generated by the searcher:
"fields": {
"defaultLang": {
"firstName": "Vikrant",
"lastName":"Thakur"
}
}
I have written the following in MySearcher.java:
for (Hit hit: result.hits()) {
String language = "en"; //temporarily hard-coded
StructuredData Lang = (StructuredData) hit.getField("Lang");
Inspector o = Lang.inspect();
for (int j=0;j<o.entryCount();j++){
if (o.entry(j).field("key").asString("").equals(language)){
SlimeAdapter value = (SlimeAdapter) o.entry(j).field("value");
hit.setField("defaultLang",value);
break;
}
}
hit.removeField("Lang");
}
Edit-1: A more efficient way instead is to make use of the Inspectable interface and Inspector, like above (Thanks to #Jo Kristian Bergum)
But, in the above code, I am having to loop through all the languages to filter out the required one. I want to avoid this O(n) time-complexity and make use of the map structure to access it in O(1). (Because the languages may increase to 1000, and this would be done for each hit.)
All this is due to the StructuredData data type I am getting in the results. StructureData doesn't keep the Map Structure and rather gives an array of JSON like:
[{
"key": "en",
"value": {
"firstName": "Vikrant",
"lastName": "Thakur"
}
}, {
"key": "ch",
"value": {
"firstName": "维克兰特",
"lastName": "塔库尔"
}
}]
Please, suggest a better approach altogether, or any help with my current one. Both are appreciated.
The YQL sample query I guess is to illustrate what you want as that syntax is not valid. Picking a given key from the field Lang of type map can be done as you do in your searcher but deserializing into JSON and parsing the JSON is probably inefficient as StructuredData implements the Inspectable interface and you can inspect it directly without the need to go through JSON format. See https://docs.vespa.ai/documentation/reference/inspecting-structured-data.html

query params dependent on other query params in hapi-swagger

I am building a hapi-swagger interface to my api. One of the query params, type, has another query param subtype that depends on the former. I have figured out how to implement Joi validation for it successfully but am not so successful with the interface. My validation code is
{
type: Joi.string()
.valid('image', 'publication', 'dataset')
.optional(),
subtype: Joi.string()
.optional()
.when('type', {is: 'image', then: Joi.valid('png', 'jpg')})
.when('type', {is: 'publication', then: Joi.valid('newspaper', 'book')})
.description('subtype based on the file_type')
}
But the interface shows only png and jpg for subtype. Suggestions on how I could implement this so the correct subtype shows when the respective type is chosen?
I tried something similar and it works fine for me. Please checkout my code below:
Joi.object().keys({
billFormat: Joi.string().valid('sms', 'email').required(),
email: Joi.string()
.when('ebillFormat', { is: 'sms', then: Joi.valid('a', 'b') })
.when('ebillFormat', { is: 'email', then: Joi.valid('c', 'd') }),
});
And my payload looks like below:
{
"ebillFormat": "email",
"email": "hello"
}
The error I get is as follows:
{
"statusCode": 400,
"error": "Bad Request",
"message": "child \"email\" fails because [\"email\" must be one of [c, d]]",
"validation": {
"source": "payload",
"keys": [
"email"
]
}
}
Please let me know what exactly you are trying to achieve and what issue are you facing.

Laravel 5 dingo api, add multiple transformed objects to the response

Want to add a transformed object along with other response, I have used following code:
$accessToken = Authorizer::issueAccessToken();
$user = User::where('email', $request->get('username'))->with('profile')->first();
if ($user) {
$accessToken['user'] = $this->response->item($user, new UserTransformer);
}
return $accessToken;
Expected Response:
{
"access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"token_type": "Bearer",
"expires_in": 31536000,
"data": {
"id": 1,
"email": "xxxxx",
"profile": {
"data": {
"id": 1,
"first_name": "Muhammad",
"last_name": "Shakeel",
}
}
}
}
but not getting transformed object, there must be some better way to add multiple transformed objects with response. Am I missing something?
Edit
Current response returns user object without transformation and if I return only user transformed object like following, it returns correct transformed object:
return $this->response->item($user, new UserTransformer);
As discussed on the issue tracker(https://github.com/dingo/api/issues/743#issuecomment-160514245), jason lewis responded to the ticket with following:
The only way you could do this at the moment would be to reverse that. So you'd return the response item, then add in the access token data, probably as meta data.
So, something like this.
return $this->response->item($user, new UserTransformer)->setMeta($accessToken);
The response will then contain a meta data key which will contain your access token data.
I got it to work using Internal Requests. https://github.com/dingo/api/wiki/Internal-Requests
So what you can do is
Suppose you have a route that fetches transformed user object at api/users/{email_id}?access_token=...
While issuing the access_token you can do the following :
$dispatcher = app('Dingo\Api\Dispatcher');
$array = Authorizer::issueAccessToken();
$array['user'] = $dispatcher->get('api/users/'.$request->get("username").'?access_token='.$array['access_token']);
return $array;
This will return transformed data.
NOTE : You will need to have a route that fetches user data.
You will have to handle cases in /api/users/{email-id} where email-id does not exist.

Resources