I've created a proto file with all the necessary messages and rpc functions for a REST webservice I intend to generate. Using the protoc-gen-swagger plugin I've managed to compile that proto file into a swagger.json file and all seems well, except for two things, which I can't seem to work out.
All the definitions in the swagger.json file has the name of my proto file's package prefixed onto them. Is there a way to get rid of this?
All of the fields of my messages are "optional". They're not specified explicitly as such but they're not specified to be "required" which, by definition, makes them optional. Proto3 no longer supports required/optional/repeating but even if I use Proto2 and add those keywords, it doesn't seem to affect the swagger.json ouput. How do I specifiy in my proto file that a field is required such that protoc-gen-swagger will add the required section to the json output?
Here is a sample of a very basic proto file:
webservice.proto
syntax = "proto3";
package mypackage;
import "google/api/annotations.proto";
service MyAPIWebService {
rpc MyFunc (MyMessage) returns (MyResponse) {
option (google.api.http) = {
post: "/message"
body: "*"
};
}
}
message MyMessage {
string MyString = 1;
int64 MyInt = 2;
}
message MyResponse {
string MyString = 1;
}
This is then compiled into a swagger.json file with the following command:
protoc -I. -I"%GOPATH%/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis" --swagger_out=logtostderr=true:. webservice.proto
which yields the following output:
webservice.swagger.json
{
"swagger": "2.0",
"info": {
"title": "webservice.proto",
"version": "version not set"
},
"schemes": [
"http",
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/message": {
"post": {
"operationId": "MyFunc",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/mypackageMyResponse"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/mypackageMyMessage"
}
}
],
"tags": [
"MyAPIWebService"
]
}
}
},
"definitions": {
"mypackageMyMessage": {
"type": "object",
"properties": {
"MyString": {
"type": "string"
},
"MyInt": {
"type": "string",
"format": "int64"
}
}
},
"mypackageMyResponse": {
"type": "object",
"properties": {
"MyString": {
"type": "string"
}
}
}
}
}
Notice how MyMessage and MyResponse in the proto file translates to mypackageMyMessage and mypackageMyResponse in the json file.
If I wanted, for instance, MyMessage:MyString to be required, I'd have to add a section to the "mypackageMyMessage" section in "definitions" that looks like this:
"required":[
"MyString"
]
I would definitely prefer if there was a way I could specify that in the proto file already so that I don't have to manually edit the json file every time I compile it.
Posting here for anyone else who comes across this question looking for the same information.
UPDATE
This is where the code defines how definitions are created.
https://github.com/grpc-ecosystem/grpc-gateway/blob/master/protoc-gen-swagger/genswagger/template.go#L859
This is how you can denote fields as required -- add a custom option to your message definition:
message MyMessage {
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_schema) = {
json_schema: {
title: "MyMessage"
description: "Does something neat"
required: ["MyString"]
}
};
string MyString = 1;
int64 MyInt = 2;
}
Your prefix mypackage is a part of namespacing in .proto file. It is coming from line: package mypackage; delete this line and regenerate json
Related
I want to be able to rename classes using dotnet new project templates like
these examples
I want to have files/classes that have the same name as the project with a suffix that automatically rename to match the project
eg [projectname]DbContext, ProjectNameDto so if my template is called MyWebTemplate and it has a class MyWebTempaleDbContext and the user picks a name Of MyWebApp the file and class would be renamed to MyWebAppDbContext.
I am able to do this with parameters, but want to do this for multiple classes and dont want to have to add a parameter for this
here is how it can be done with parameters :
"DBContextName": {
"type": "parameter",
"defaultValue": "WebApplicationDbContext",
"replaces": "WebApplicationDbContext",
"FileRename": "WebApplicationDbContext",
"datatype": "text",
"description": "Db Context Name"
},
Is there a way to do this using RegEx or regex match?
The example they give is :
"symbols": {
"regexExample": {
"type": "generated",
"generator": "regex",
"dataType": "string",
"replaces": "A different message", //The value to replace in the output
"parameters": {
"source": "message", //The name of the symbol whose value should be operated on
"steps": [
{
"regex": "^test", //The regular expression whose matches will be replaced with '[Replaced]`
"replacement": "[Replaced]" //The value to replace matches of the expression '^test' with
},
{
"regex": "test$",
"replacement": "[/Replaced]"
}
]
}
}
}
I also found a file rename example but cant seem to work out how to make the 2 do what i want:
{
...
"symbols": {
"app1Rename": {
"type": "derived",
"valueSource": "name",
"valueTransform": "ValueAfterLastDot",
"fileRename": "Application1",
"description": "A value derived from the 'name' param, used to rename Application1.cs"
}
}
...
"forms": {
"ValueAfterLastDot": {
"identifier": "replace",
"pattern": "^.*\\.(?=[^\\.]+$)", // regex to match everything up to and including the final "."
"replacement": "" // replace it with empty string
}
}
...
}
Thanks
I'm trying to validate JSON response messages according to schema.
But as soon as an attribute has the type "array" or "object", AJV seems to ignore them and does not see the nested attribute within that object or array.
I started trying to break up the schema into multiple smaller ones so all objects/arrays are covered, but this is a tedious task and I'm hoping I'm just using AJV incorrectly.
Example schema (simplified):
{
"type": "object",
"required": [
"MainThing"
],
"properties": {
"MainThing": {
"type": "string",
"description": "Some kind of string.",
"example": "This is some kind of string."
},
"NestedThing": {
"type": "object",
"required": [
"NestedAttribute"
],
"properties": {
"NestedAttribute": {
"type": "String",
"description": "A nested string.",
"example": "This is a nested string"
}
}
}
}
}
If I change the NestedAttribute to an Integer instead of a String, the schema validation in Postman will tell me the response is valid against the schema. While it's not, because the response will contain a NestedAttribute which is a String value.
The following response would be deemed valid, while it's not:
{
"MainThing": "The main thing",
"NestedThing": {
"NestedAttribute": 12345
}
}
My Postman testcode:
var Ajv = require('ajv'),
ajv = new Ajv({logger: console}),
schema = JSON.parse(pm.variables.get("THIS_IS_MY_AWESOME_SCHEMA"));
pm.test('My schema is valid', function() {
var data = pm.response.json();
pm.expect(ajv.validate(schema, data)).to.be.true;
});
If anyone can point me in the right direction, that would be greatly appreciated!
I currently have mongo data stored in two forms (specifically for content key) in a collection. Partial sample data shown below:
Format 1.
{
"type": "text",
"content": "foobar",
"extraTextData": "hello text"
}
Format 2
{
"type": "group",
"content": [
{
"type": "text",
"content": "grouped-foobar"
},
{
"type": "image",
"url": "https://abc.jpg"
},
],
"extraGroupData": "hello group"
}
My attempt to structure this in golang is below.
type C struct {
Type string `json:"type" bson:"type"`
Content ???
*TextC
*GroupC
}
type TextC struct {
ExtraTextData `json:"extraTextData" bson:"extraTextData"`
}
type GroupC struct {
ExtraGroupData `json:"extraGroupData" bson:"extraGroupData"`
}
I am having issues on how to setup the structure for "content" field that works for both the formats, TextC and GroupC.
Content for GroupC can be array of C like - Content []C
Content for TextC can also be string type.
Can someone please help & give an example on how to tackle this situation?
Format2 json is Invalid. You can check it here : https://jsonlint.com/
I have created a sample scenario for your case.
You can try it here: https://go.dev/play/p/jaUE3rjI-Ik
Use interface{} like this:
type AutoGenerated struct {
Type string `json:"type"`
Content interface{} `json:"content"`
ExtraTextData string `json:"extraTextData,omitempty"`
ExtraGroupData string `json:"extraGroupData,omitempty"`
}
And you should also remove comma from Format2:
{
"type": "group",
"content": [
{
"type": "text",
"content": "grouped-foobar"
},
{
"type": "image",
"url": "https://abc.jpg"
}
],
"extraGroupData": "hello group"
}
If you don't remove comma then it will through an error like this:
invalid character ']' looking for beginning of value
I'm using go-restful in combination with go-restful-openapi to generate my swagger doc automatically. However, on testing the tool with the swagger-editor, I get the following error:
$refs must reference a valid location in the document
struct
type Users struct {
# uuid imported from github.com/google/uuid#v1.2.0
RelatedUsers []uuid.UUID `json:"relatedIds" validate:"required"`
}
generated swagger snippet
"Users": {
"required": [
"relatedIds"
],
"properties": {
"relatedIds": {
"type": "array",
"$ref": "#/definitions/uuid.UUID" #this line returns an error
}
}
}
}
Here's the swagger config:
swaggerConfig := restfulspec.Config{
WebServices: restfulContainer.RegisteredWebServices(),
APIPath: "/swagger.json",
PostBuildSwaggerObjectHandler: func(swo *spec.Swagger) {
swo.Info = &spec.Info{
InfoProps: spec.InfoProps{
Title: "User Service",
Description: "An example service for stackoverflow",
Version: "1.0.0",
},
}
},
}
NOTE: If I replace the lines above in the swagger editor as follows the error disappears, however, I couldn't figure out how to configure swagger to do so automatically
"Users": {
"required": [
"relatedIds"
],
"properties": {
"relatedUsers": {
type: array
items:
type: "string"
format: "uuid"
}
}
}
}
Just in case someone is running into this issue: go-restful-openapi cannot resolve imported custom types. To solve this issue add the type to the definitions
swo.Definitions["uuid.UUID"] = spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "uuid",
},
}
I'm new to DynamoDB.
When I read data from the table with AWS.DynamoDB.DocumentClient class, the query works but I get the result in the wrong format.
Query:
{
TableName: "users",
ExpressionAttributeValues: {
":param": event.pathParameters.cityId,
":date": moment().tz("Europe/London").format()
},
FilterExpression: ":date <= endDate",
KeyConditionExpression: "cityId = :param"
}
Expected:
{
"user": "boris",
"phones": ["+23xxxxx999", "+23xxxxx777"]
}
Actual:
{
"user": "boris",
"phones": {
"type": "String",
"values": ["+23xxxxx999", "+23xxxxx777"],
"wrapperName": "Set"
}
}
Thanks!
The [unmarshall] function from the [AWS.DynamoDB.Converter] is one solution if your data comes as e.g:
{
"Attributes": {
"last_names": {
"S": "UPDATED last name"
},
"names": {
"S": "I am the name"
},
"vehicles": {
"NS": [
"877",
"9801",
"104"
]
},
"updatedAt": {
"S": "2018-10-19T01:55:15.240Z"
},
"createdAt": {
"S": "2018-10-17T11:49:34.822Z"
}
}
}
Please notice the object/map {} spec per attribute, holding the attr type.
Means you are using the [dynamodb]class and not the [DynamoDB.DocumentClient].
The [unmarshall] will Convert a DynamoDB record into a JavaScript object.
Stated and backed by AWS. Ref. https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/Converter.html#unmarshall-property
Nonetheless, I faced the exact same use case, as yours. Having one only attribute, TYPE SET (NS) in my case, and I had to manually do it. Next a snippet:
// Please notice the <setName>, which represents your set attribute name
ddbTransHandler.update(params).promise().then((value) =>{
value.Attributes[<setName>] = value.Attributes[<setName>].values;
return value; // or value.Attributes
});
Cheers,
Hamlet