I'm using grpcc, which is based on protobuf.js, to test my grpc service APIs.
My .proto file:
message MyRequest {
string userId = 1;
map<string, string> params = 2;
}
I tried the following json body to send a request:
{userId : "my_user_id" , params: { name: "my_name"}}
{userId : "my_user_id" , params: [{"name":"my_name"}] }
But this gives the following error:
Error: Illegal value for Message.Field....MyRequest.params of type string: object (expected ProtoBuf.Map or raw object for map field)
How to correctly represent a protobuf map as a json?
The proper json body would be the following:
{ "userId": "my_user_id", "params": { "name": "my_name" } }
What you've tried doing is an array of maps, which doesn't really mean anything in the context of protobuf. A map<string, string> is exactly the description of a json object, so more than one value would be represented the following way:
{ "params": { "key1": "value1", "key2": "value2" } }
No need for an array.
Related
We are trying to import test execution result in json format to xray Jira cloud by cloud Rest API call. After importing through Rest API call we are getting below error.
I gone through the solutions but couldn't got working solution.
{"error": "Error retrieving Project from Jira with key "null": No project could be found with key 'null'."}
Below is my code snippet:
public void postAPICall(){
File dataFile = new File("src/main/resources/Payloads/auth.json");
String url ="https://xray.cloud.getxray.app/api/v2/authenticate";
RequestSpecification request = RestAssured.given();
request.header("Content-Type", "application/json");
request.body(dataFile);
Response response = request.post(url);
ResponseBody body = response.getBody();
tokenResult=body.asString();
}
#Test
public void postCallUpdateTestResult(){
postAPICall();
File jsonDataInFile = new File("src/main/resources/Payloads/SimpleExecutionResult.json");
String url ="https://xray.cloud.getxray.app/api/v2/import/execution?testExecKey=XX-XX";
RequestSpecification request = RestAssured.given();
request.header("Content-Type", "application/json");
request.header("Authorization", "Bearer "+tokenResult.substring(1,(tokenResult.length()-1)));
request.body(jsonDataInFile);
Response response = request.post(url);
ResponseBody body = response.getBody();
System.out.println(body.asString());
}
auth.json
{
"client_id": "XXXXXXXXXXXXXXXXXX",
"client_secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
SimpleExecutionResult.json
{
"testExecutionKey": "XX-XX",
"tests": [
{
"testKey": "XX-XX",
"status": "FAILED"
},
{
"testKey": "XX-XX",
"status": "PASSED"
}
]
}
I want my Rocket API to have a route like this:
#[post("create/thing", format = "application/json", data="<thing>")]
When the client sends { "name": "mything" }, everything should be alright and I know how to do that, but when it sends { "name": "foo" } it should respond with something like this:
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"errors": [
{
"status": "422",
"title": "Invalid thing name",
"detail": "The name for a thing must be at least 4 characters long."
}
]
}
How do I respond with a result like a JSON object and a HTTP status code different than 200 in Rocket?
This is what I tried so far:
impl FromRequest for my Thing type. This lets me choose a status code as I can write my own from_request function, but I can't return anything else.
Registering an error catcher like in this example, but this way I only can react to one HTTP status code without context. I have too many failure modes to reserve one HTTP status code for each.
With #hellow's help, I figured it out. The solution is to implement the Responder trait for a new struct ApiResponse, which contains a status code as well the Json. This way I can do exactly what I wanted:
#[post("/create/thing", format = "application/json", data = "<thing>")]
fn put(thing: Json<Thing>) -> ApiResponse {
let thing: Thing = thing.into_inner();
match thing.name.len() {
0...3 => ApiResponse {
json: json!({"error": {"short": "Invalid Name", "long": "A thing must have a name that is at least 3 characters long"}}),
status: Status::UnprocessableEntity,
},
_ => ApiResponse {
json: json!({"status": "success"}),
status: Status::Ok,
},
}
}
Here is the full code:
#![feature(proc_macro_hygiene)]
#![feature(decl_macro)]
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
use rocket::http::{ContentType, Status};
use rocket::request::Request;
use rocket::response;
use rocket::response::{Responder, Response};
use rocket_contrib::json::{Json, JsonValue};
#[derive(Serialize, Deserialize, Debug)]
pub struct Thing {
pub name: String,
}
#[derive(Debug)]
struct ApiResponse {
json: JsonValue,
status: Status,
}
impl<'r> Responder<'r> for ApiResponse {
fn respond_to(self, req: &Request) -> response::Result<'r> {
Response::build_from(self.json.respond_to(&req).unwrap())
.status(self.status)
.header(ContentType::JSON)
.ok()
}
}
#[post("/create/thing", format = "application/json", data = "<thing>")]
fn put(thing: Json<Thing>) -> ApiResponse {
let thing: Thing = thing.into_inner();
match thing.name.len() {
0...3 => ApiResponse {
json: json!({"error": {"short": "Invalid Name", "long": "A thing must have a name that is at least 3 characters long"}}),
status: Status::UnprocessableEntity,
},
_ => ApiResponse {
json: json!({"status": "success"}),
status: Status::Ok,
},
}
}
fn main() {
rocket::ignite().mount("/", routes![put]).launch();
}
You need to build a response. Take a look at the ResponseBuilder. Your response might look something like this.
use std::io::Cursor;
use rocket::response::Response;
use rocket::http::{Status, ContentType};
let response = Response::build()
.status(Status::UnprocessableEntity)
.header(ContentType::Json)
.sized_body(Cursor::new("Your json body"))
.finalize();
I'm calling requesting server for data and getting following response.
{
"success": 1,
"data": [
{
"id": 1,
"name": "Kurti"
},
{
"id": 2,
"name": "Top"
}
],
"message": "Data fetched"
}
Modal class to convert json data coming from server.
class Product {
String categoryName;
int productId;
Product.fromJson(Map<String, dynamic> json) {
categoryName = json["id"];
productId = json["name"];
}
}
So from the server the format will be fix for every call like below...
{
"success": <Int>,
"message": <String>,
"data": <An array of Model class>
}
For that I've created below class...
class ServerResponse<T> {
String message;
int success;
List<T> data;
ServerResponse.fromJson(Map<String, dynamic> json) {
message = json["message"];
success = json["success"];
data = json["product_data"];
}
}
And this is how I'm calling api...
class ServerManager {
final baseUrl = isProduction ? liveServer : stagingServer;
var headers = {"consumer-key": "sdfgdqwrtw34563t545"};
dynamic callWSToGetData({Map<String, String> params}) async {
var client = http.Client();
var url = baseUrl + allProducts;
print("URL = $url");
print("params: $params");
print("header: $headers");
var response = await client.post(url, headers: headers, body: params);
var json = converter.jsonDecode(response.body);
return json;
}
}
Calling api to get data as following.
Map<String, String> params = {"categories_id": "1", "language_id": "1", "type": "Newest", "customers_id": "0", "page_number": "0"};
var response = ServerManager().callWSToGetData(params: params);
var res = ServerResponse<Product>.fromJson(response);
print(res.data);
So when I ran this code I'm getting following error.
type 'Future' is not a subtype of type 'Map'
The question is...
How can I create a single generic class that can be used to handle server responses?
Any help please.
type 'Future' is not a subtype of type 'Map'
This is probably due to missing await call. Your callWSToGetData has async in declaration so it's type will be Future.
To use generics you need to pass the type. So your code will look like this:
var response = await ServerManager().callWSToGetData(); //how can I use generic here
var res = ServerResponse<Product>.fromJson(response);
print(res.data);
I have two different json that I want to cast in a single class "Response".
The first json gives me something like:
[
{
"id": 1,
"name": "asd",
"objects": [
"id" : asd
...
]
}]
and the other something like:
{
id : 2
name : "asd"
}
The class in which I'm trying to put them is
class Response {
String name;
int id;
Objects object;
}
As you can see, the first one gives me back an array of elements, while the second not. I was trying with the factory method, but then I got stuck. So, is what I want to do possibile, or it's better to do in another way?
Take a look at Serializing JSON inside model classes.
factory classes are a good start (I'm not sure what Objects is supposed to be in your example, your JSON is not valid):
factory Response.fromJson(Map<String, dynamic> json) {
return Response(
id: json['id'],
name: json['name'],
object: json['object'] == null ? null : Objects.fromJson(json['object'],
);
}
I need to log in example.com/mobile/shared/default.aspx by using POST request
How do i get current ViewState and sending it after?
That is what i tried
(Alamofire)
func webRequest()
{
let parameters: Parameters = [
"name": "name",
"password": "password",
"enter": "Enter",
]
Alamofire.request("http://example.ru/mobile/shared/default.aspx", parameters: parameters).responseJSON { response in
print(response.request) // original URL request
print(response.response) // HTTP URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
}
I'm using Alamofire like this:
let Parameters = [
"name": "name",
"password": "password",
"enter": "Enter"]
var json : JSON = nil
Alamofire.request(URLString, method: method, parameters: Parameters)
.responseJSON { response in
switch response.result {
case .success(let data):
json = JSON(data)
print(json)
case .failure(let error):
print("Request failed with error: \(error)")
}
}
}
So after that you can parse your json like this for example:
if json != nil {
let token = json["token"].stringValue
}
But all of that depend of your server request params, and request response from your server.
Hope I helped you, Peace