Unable to generate example json value from yaml - yaml

I am trying to parse a given yaml to a JSON example like swagger does. I am using the below yaml.
$id: 'https://example.com/person.schema.json'
$schema: 'http://json-schema.org/draft-07/schema#'
title: Person
type: object
properties:
firstName:
type: string
example:MyName
description: The person's first name.
lastName:
type: string
description: The person's last name.
age:
description: Age in years which must be equal to or greater than zero.
type: integer
minimum: 0
I am trying to parse this yaml to its json like the below one. If the example is given in the yaml then it should show the example else it should show a default value.
Person:{
"firstName":"MyName",
"lastName":"string",
"age":0
}
But while parsing I am getting an Exception:
com.fasterxml.jackson.core.JsonParseException: Unrecognized token '$id': was expecting ('true', 'false' or 'null')
at [Source: (String)"$id: 'https://example.com/person.schema.json'
line: 1, column: 4]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804) ~[jackson-core-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:703) ~[jackson-core-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2853) ~[jackson-core-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleOddValue(ReaderBasedJsonParser.java:1899) ~[jackson-core-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:757) ~[jackson-core-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4042) ~[jackson-databind-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:2551) ~[jackson-databind-2.9.8.jar:2.9.8]
at io.swagger.parser.SwaggerCompatConverter.readResourceListing(SwaggerCompatConverter.java:210) [swagger-compat-spec-parser-1.0.44.jar:1.0.44]
at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:123) [swagger-compat-spec-parser-1.0.44.jar:1.0.44]
at io.swagger.parser.SwaggerCompatConverter.readWithInfo(SwaggerCompatConverter.java:94) [swagger-compat-spec-parser-1.0.44.jar:1.0.44]
at io.swagger.parser.SwaggerParser.readWithInfo(SwaggerParser.java:42) [swagger-parser-1.0.44.jar:1.0.44]
at io.swagger.v3.parser.converter.SwaggerConverter.readLocation(SwaggerConverter.java:92) [swagger-parser-v2-converter-2.0.12.jar:2.0.12]
at io.swagger.v3.parser.OpenAPIV3Parser.read(OpenAPIV3Parser.java:90) [swagger-parser-v3-2.0.12.jar:2.0.12]
at io.swagger.v3.parser.OpenAPIV3Parser.read(OpenAPIV3Parser.java:78) [swagger-parser-v3-2.0.12.jar:2.0.12]
at com.pega.yaml.yamlToJsonExample.App.main(App.java:19) [classes/:na]
Exception in thread "main" java.lang.NullPointerException
at io.swagger.v3.parser.OpenAPIV3Parser.read(OpenAPIV3Parser.java:91)
at io.swagger.v3.parser.OpenAPIV3Parser.read(OpenAPIV3Parser.java:78)
at com.pega.yaml.yamlToJsonExample.App.main(App.java:19)
I am using swagger inflector 2.0.5 with the following code:
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.oas.inflector.examples.models.Example;
import io.swagger.oas.inflector.examples.ExampleBuilder;
import java.util.Map;
import com.fasterxml.jackson.databind.module.SimpleModule;
import io.swagger.oas.inflector.processors.JsonNodeExampleSerializer;
import io.swagger.util.Json;
public class App
{
public static void main( String[] args )
{
OpenAPI swagger = new OpenAPIV3Parser().read("Eclipse Workspace1\\yamlToJsonExample\\src\\main\\java\\com\\pega\\yaml\\yamlToJsonExample\\Test.yaml");
Map < String, Schema > definitions = swagger.getComponents().getSchemas();
Schema model = definitions.get("Person");
Example example = ExampleBuilder.fromSchema(model, definitions);
SimpleModule simpleModule = new SimpleModule().addSerializer(new JsonNodeExampleSerializer());
Json.mapper().registerModule(simpleModule);
String jsonExample = Json.pretty(example);
System.out.println(jsonExample);
}
}

Related

Create AWS::Pinpoint::PushTemplate using CF template

Hi I want to create AWS::Pinpoint::PushTemplate using cloudformation template and I am following this link: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-pinpoint-pushtemplate.html.
Type: AWS::Pinpoint::PushTemplate
Properties:
Default:
Action: OPEN_APP
Body: FirstName - {{firstName}}, LastName - {{lastName}}
Title: Title
DefaultSubstitutions:
firstName: default
lastName: default
Tags:
project: project
tashi: "Pinpoint Template"
TemplateName: template_name
I am getting type validation error for`DefaultSubstitutions: Property validation failure: [Value of property {/DefaultSubstitutions} does not match type {String}]
According to docs DefaultSubstitutions is a String.
However, in your case, you set it up as map:
DefaultSubstitutions:
firstName: default
lastName: default
Maybe have to try using it as json string:
DefaultSubstitutions: "{\"firstName"\:\"default\", \"lastName"\:\"default\"}"

OpenApi - Is there a way to have a ComposedSchema with a discriminator part in a contract generated with springdoc-openapi-maven-plugin?

I have a sample SpringBoot API with the following features:
1 controller that exposes a single endpoint invokable with a GET request and that returns a custom class (ContainerClass in my example)
ContainerClass contains a property List
ParentClass is an abstract class that has 2 sub-classes: ChildA and ChildB
I try to generate an OpenApi contract from this API with springdoc-openapi-maven-plugin.
In my pom.xml, I have the following elements:
SpringBoot version: 2.2.6
org.springdoc:springdoc-openapi-ui:1.4.1
org.springdoc:springdoc-openapi-maven-plugin:1.0
Here are my classes I generate schema from.
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
public class ContainerClass {
#ArraySchema(
arraySchema = #Schema(discriminatorProperty = "classType"),
schema = #Schema(implementation = ParentClass.class)
)
public List<ParentClass> elements;
// + Getter/Setter
}
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "classType",
defaultImpl = ParentClass.class,
visible = true)
#JsonSubTypes({
#JsonSubTypes.Type(value = ChildA.class, name = "CHILD_A"),
#JsonSubTypes.Type(value = ChildB.class, name = "CHILD_B")})
#Schema(
description = "Parent description",
discriminatorProperty = "classType",
discriminatorMapping = {
#DiscriminatorMapping(value = "CHILD_A", schema = ChildA.class),
#DiscriminatorMapping(value = "CHILD_B", schema = ChildB.class)
}
)
public abstract class ParentClass {
public String classType;
// + Getter/Setter
}
#io.swagger.v3.oas.annotations.media.Schema(description = " Child A", allOf = ParentClass.class)
public class ChildA extends ParentClass{
}
#io.swagger.v3.oas.annotations.media.Schema(description = " Child B", allOf = ParentClass.class)
public class ChildB extends ParentClass{
}
When I run springdoc-openapi-maven-plugin, I get the following contract file.
openapi: 3.0.1
info:
title: OpenAPI definition
version: v0
servers:
- url: http://localhost:8080
description: Generated server url
paths:
/container:
get:
tags:
- hello-controller
operationId: listElements
responses:
"200":
description: OK
content:
'*/*':
schema:
$ref: '#/components/schemas/ContainerClass'
components:
schemas:
ChildA:
type: object
description: ' Child A'
allOf:
- $ref: '#/components/schemas/ParentClass'
ChildB:
type: object
description: ' Child B'
allOf:
- $ref: '#/components/schemas/ParentClass'
ContainerClass:
type: object
properties:
elements:
type: array
description: array schema description
items:
oneOf:
- $ref: '#/components/schemas/ChildA'
- $ref: '#/components/schemas/ChildB'
ParentClass:
type: object
properties:
classType:
type: string
description: Parent description
discriminator:
propertyName: classType
mapping:
CHILD_A: '#/components/schemas/ChildA'
CHILD_B: '#/components/schemas/ChildB'
Actually, in my context, in order to have not any breaking change with existing consumers, I need items property in ContainerClass schema to contain the discriminator part that is contained in ParentClass schema, like this:
ContainerClass:
type: object
properties:
elements:
type: array
description: array schema description
items:
discriminator:
propertyName: classType
mapping:
CHILD_A: '#/components/schemas/ChildA'
CHILD_B: '#/components/schemas/ChildB'
oneOf:
- $ref: '#/components/schemas/ChildA'
- $ref: '#/components/schemas/ChildB'
When I try to set properties in annotation, I don't manage to do that. And when I debug code of io.swagger.v3.core.jackson.ModelResolver, I don't manage to find a way to do that.
And so far I have not found an example of code that help me.
Is there a way so that a ComposedSchema (array contained in ContainerClass in my case) has a disciminator part generated by springdoc-openapi-maven-plugin execution?
This the default generation structure. Handled directly by swagger-api (and not springdoc-openapi.
The generated OpenAPI description looks coorect.
With springdoc-openapi, you can define an OpenApiCustomiser Bean, where you can change the elements of the components element defined on the OpenAPI level:
https://springdoc.org/faq.html#how-can-i-customise-the-openapi-object-
Here is my solution by defining an OpenApiCustomiser Bean:
#Bean
public OpenApiCustomiser myCustomiser() {
Map<String, String> classTypeMapping = Map.ofEntries(
new AbstractMap.SimpleEntry<String, String>("CHILD_A", "#/components/schemas/ChildA"),
new AbstractMap.SimpleEntry<String, String>("CHILD_B", "#/components/schemas/ChildB")
);
Discriminator classTypeDiscriminator = new Discriminator().propertyName("classType")
.mapping(classTypeMapping);
return openApi -> openApi.getComponents().getSchemas().values()
.stream()
.filter(schema -> "ContainerClass".equals(schema.getName()))
.map(schema -> schema.getProperties().get("elements"))
.forEach(arraySchema -> ((ArraySchema)arraySchema).getItems().discriminator(classTypeDiscriminator));
}
I get the expected result in my contract file.

How to pass hash object in gRPC ruby client

I want to make a Ruby client.
My proto file looks like:
syntax = "proto3";
import "google/protobuf/struct.proto";
import "google/protobuf/duration.proto";
import "discovery/protobuf/shared/v1beta1/metadata.proto";
option java_multiple_files = true;
option ruby_package = "v1beta1";
message Request {
...
google.protobuf.Struct test = 12;
}
In my service_pb.rb file I have:
add_message 'request' do
...
optional :test, :message, 12, 'google.protobuf.Struct'
end
Now I am trying to pass the request params in my client.rb:
params = {xyz: "abc", test: { bar: "296" }}
stub = Message::Stub.new('localhost:9999', :this_channel_is_insecure)
msg = Request.new(params)
while running this I am getting:
ArgumentError: Unknown field name 'bar' in initialization map entry.
I need to pass a Hash object in request params.
One solution is to use Google::Protobuf::Struct.from_hash
Example code:
require 'google/protobuf/well_known_types'
Google::Protobuf::Struct.from_hash({'k' => 123})
=> <Google::Protobuf::Struct: fields: {"k"=><Google::Protobuf::Value: null_value: :NULL_VALUE, number_value: 123.0, string_value: "", bool_value: false, struct_value: nil, list_value: nil>}>

Custom protoc plugin parsing not working for custom options

I am trying to write a protoc plugin that requires me to use custom options. I defined my custom option as shown in the example (https://developers.google.com/protocol-buffers/docs/proto#customoptions):
import "google/protobuf/descriptor.proto";
extend google.protobuf.MessageOptions {
string my_option = 51234;
}
I use it as follows:
message Hello {
bool greeting = 1;
string name = 2;
int32 number = 3;
option (my_option) = "telephone";
}
However, when I read the parsed request, the options field is empty for the "Hello" message.
I am doing the following to read
data = sys.stdin.read()
request = plugin.CodeGeneratorRequest()
request.ParseFromString(data)
When I print "request," it just gives me this
message_type {
name: "Hello"
field {
name: "greeting"
number: 1
label: LABEL_REQUIRED
type: TYPE_BOOL
json_name: "greeting"
}
field {
name: "name"
number: 2
label: LABEL_REQUIRED
type: TYPE_STRING
json_name: "name"
}
field {
name: "number"
number: 3
label: LABEL_OPTIONAL
type: TYPE_INT32
json_name: "number"
}
options {
}
}
As seen, the options field is empty even though I defined options in my .proto file. Is my syntax incorrect for defining custom options? Or could it be a problem with my version of protoc?
I'm making my protobuf python plugin.
I also got the problem like yours and i have found a solution for that.
Put your custom options to a file my_custom.proto
Use protoc to gen a python file from my_custom.proto => my_custom_pb2.py
In your python plugin code, import my_custom_pb2.py import my_custom_pb2
Turns out you need to have the _pb2.py file imported for the .proto file in which the custom option is defined. For example, it you are parsing a file (using ParseFromString) called example.proto which uses a custom option defined in option.proto, you must import option_pb2.py in the Python file that calls ParseFromString.

Internationalization for user defined input

I'm trying to build a localization for user defined input. Example: a user could define categories like soccer but in several languages.
The model entity could have a filed something like this:
#ManyToMany
#MapKeyColumn(name = "locale", insertable = false, updatable = false)
public Map<String, L18n> titles;
I'd like to store the localized strings like this:
#Entity
public class L18n {
#Id
#Constraints.Required
#Formats.NonEmpty
public Integer id;
public String key;
public String locale;
#Column(columnDefinition = "TEXT")
public String text;
}
We use yaml to store the testdata:
category:
- !!models.Category
...
titles:
- !!models.L18n
key: soccer
l18n:
- !!models.L18n
key: soccer
locale: de-CH
text: fdfdfsee
- !!models.L18n
key: soccer
locale: fr-CH
text: dlfkjsdlfj
With this solution I'm getting this error:
[error] Caused by: org.yaml.snakeyaml.error.YAMLException: No suitable constructor with 1 arguments found for interface java.util.Map
[error] at org.yaml.snakeyaml.constructor.Constructor$ConstructSequence.construct(Constructor.java:574)
[error] at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:182)
[error] at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:296)
[error] ... 65 more
I think the problem is you've defined titles as a map, but don't use the YAML mapping syntax to define it. YAML Collections
I think the syntax for titles should look like the example here using langauges: YAML Dictionary Example
titles:
soccer: - !!models.L18n
key: soccer
locale: de-CH
text: fdfdfsee
football: - !!models.L18n
...
If you change the format of your .yml file so that the L18n instances are defined first and use references, the YAML spec calls them Alias Nodes, you could make your titles look a lot more streamlined:
l18n:
- &soccerDE !!models.L18n
key: soccer
locale: de-CH
text: fdfdfsee
- &soccerFR !!models.L18n
key: soccer
locale: fr-CH
text: dlfkjsdlfj
category:
- !!models.Category
...
titles:
soccerDE: *soccerDE
soccerFR: *soccerFR

Resources