jsonschema2pojo gives 1 Properties.java with new POJO for each Json element - jsonschema2pojo

I am using Java API like this
public void convertJsonToJavaClass(URL inputJsonUrl, File outputJavaClassDirectory, String packageName, String javaClassName) throws IOException {
com.sun.codemodel.JCodeModel jcodeModel = new com.sun.codemodel.JCodeModel();
GenerationConfig config = new DefaultGenerationConfig() {
#Override
public boolean isGenerateBuilders() {
return true;
}
#Override
public SourceType getSourceType() {
return SourceType.JSON;
}
};
SchemaMapper mapper = new SchemaMapper(new RuleFactory(config, new Jackson2Annotator(config), new SchemaStore()), new SchemaGenerator());
mapper.generate(jcodeModel, javaClassName, packageName, inputJsonUrl);
jcodeModel.build(outputJavaClassDirectory);
}
The input Json schema file has properties that look like this:
{
"type": "object",
"properties": {
"Market": {
"type": "string"
},
"Dealer": {
"type": "integer"
},
"Side": {
"type": "string",
"enum": ["Buy", "Sell", "Pay", "Receive", "Undisclosed"]
},
"Package": {
"type": "string",
"enum": ["Y", "N"]
}
},
"required": ["Market", "Side"]
}
The default output is 5 POJO classes, 1 for each Json element with a Properties.java to collect all the POJO. Whereas I would like 1 POJO with the Json elements converted to Java primitives. What to do please? Is this Json schema layout and Java API code the best practise for jsonschema2pojo? Thanks

The problem was using return SourceType.JSON; for a JsonSchema.
When I changed to return SourceType.JSONSCHEMA; it created the 1 POJO class.

Related

Swagger Codegen OneOf generating incorrectly

I am generating a JavaClient using an OpenAPISpec document. I have used swagger-codegen 3.0 to generate the code. The OpenAPISpec version is 3.0.1.
Below is the OpenAPI snippet I am facing problems with:
"RequestWithInsuranceInfo": {
"type": "object",
"description": "This request schema will produce a response containing an out of pocket estimate for the given service using the patient's insurance information.",
"additionalProperties": false,
"properties": {
"insuranceInfo": {
"$ref": "#/components/schemas/InsuranceInfo"
},
"service": {
"type": "object",
"additionalProperties": false,
"description": "Schema to use when the patient's benefit info is not given in the request.",
"properties": {
"codes": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ServiceCode"
}
},
"provider": {
"$ref": "#/components/schemas/Provider"
},
"costs": {
"$ref": "#/components/schemas/ServiceCosts"
}
},
"required": [
"codes",
"provider",
"costs"
]
}
}
},
"InsuranceInfo": {
"description": "Information about the payer, plan, and members.",
"additionalProperties": false,
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"title": "Option 1: Patient Is Policy Holder",
"description": "Schema to use when the patient the primary on the insurance plan.",
"properties": {
"payer": {
"$ref": "#/components/schemas/Payer"
},
"policyHolderInfo": {
"$ref": "#/components/schemas/PolicyHolderInfo"
}
},
"required": [
"payer",
"policyHolderInfo"
]
},
{
"type": "object",
"additionalProperties": false,
"title": "Option 2: Patient Is Dependent",
"description": "Schema to use when the patient is a dependent on the insurance plan.",
"properties": {
"payer": {
"$ref": "#/components/schemas/Payer"
},
"dependentMemberInfo": {
"$ref": "#/components/schemas/DependentMemberInfo"
},
"policyHolderInfo": {
"$ref": "#/components/schemas/PolicyHolderInfo"
}
},
"required": [
"payer",
"dependentMemberInfo",
"policyHolderInfo"
]
}
]
},
Below is the code which gets generated:
public class InsuranceInfo implements OneOfInsuranceInfo {
#Override
public boolean equals(java.lang.Object o) {..}
#Override
public int hashCode() {..}
#Override
public String toString() {..}
private String toIndentedString(java.lang.Object o) {..}
}
public interface OneOfInsuranceInfo {
}
public class RequestWithInsuranceInfo implements OneOfRequest {
#SerializedName("insuranceInfo")
private InsuranceInfo insuranceInfo = null;
#SerializedName("service")
private RequestWithInsuranceInfoService service = null;
..
}
public class Payer {
#SerializedName("id")
private String id = null;
..
}
public class PolicyHolderInfo {
#SerializedName("memberId")
private String memberId = null;
#SerializedName("firstName")
private String firstName = null;
#SerializedName("lastName")
private String lastName = null;
#SerializedName("dateOfBirth")
private LocalDate dateOfBirth = null;
..
}
public class DependentMemberInfo {
#SerializedName("memberId")
private String memberId = null;
#SerializedName("firstName")
private String firstName = null;
#SerializedName("lastName")
private String lastName = null;
#SerializedName("dateOfBirth")
private LocalDate dateOfBirth = null;
..
}
As shown, the InsuranceInfo object implements the OneOfInsuranceInfo interface but has no variables. Payer, PolicyHolderInfo and dependentMemberInfo class are generated but they are not linked to the InsuranceInfo class anyhow. How do I populate the InsuranceInfo class?
The issue is probably that the InsuranceInfo schema
"InsuranceInfo": {
"description": "Information about the payer, plan, and members.",
"additionalProperties": false,
"oneOf": [
{ ... },
{ ... }
]
}
effectively disallows ALL properties. This is because additionalProperties: false only knows about the properties defined directly alongside it and has no visibility into oneOf subschemas.
To resolve the issue, you can rewrite the InsuranceInfo schema without oneOf, as follows. This schema is basically "Option 2" from the original schema, except the dependentMemberInfo property is defined as optional.
"InsuranceInfo": {
"description": "Information about the payer, plan, and members.",
"additionalProperties": false,
"type": "object",
"required": [
"payer",
"policyHolderInfo"
],
"properties": {
"payer": {
"$ref": "#/components/schemas/Payer"
},
"dependentMemberInfo": {
"$ref": "#/components/schemas/DependentMemberInfo"
},
"policyHolderInfo": {
"$ref": "#/components/schemas/PolicyHolderInfo"
}
}
}

Swashbuckle - Swagger execute button is not working

I am trying to integrate swagger in Asp.Net core 3.1 Web API using Swashbuckle.AspNetCore (5.5.1) with OAS3.
I am having one post method where I need multipart form data (two files and one string value) and for that I have applied below OperationFilter, because I don't want to specify any parameters at action level.
public class ComparePostParamTypes : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var listOfOutputFormats = new List<string> { "Rtf", "Doc", "DocX", "Pdf" };
var optionArray = new OpenApiArray();
optionArray.AddRange(listOfOutputFormats.Select(s => new OpenApiString(s)));
string documentOutputFormatText =
"The format to return";
switch (operation.OperationId)
{
case "File_Post":
operation.Parameters.Clear();
operation.Parameters = new List<OpenApiParameter>
{
new OpenApiParameter
{
Name = "file1", In = ParameterLocation.Query,
Required = true,
Description = "First Document",
Schema = new OpenApiSchema()
{
Type="string",
Format="binary"
}
},
new OpenApiParameter
{
Name = "file2", In = ParameterLocation.Query,
Required = true,
Description = "Second Document",
Schema = new OpenApiSchema()
{
Type="string",
Format="binary"
}
},
new OpenApiParameter
{Name = "outputFormat", In = ParameterLocation.Query, Description = documentOutputFormatText,
Schema = new OpenApiSchema()
{
Type="string",
Enum = optionArray,
Default = new OpenApiString("Rtf"),
}
}
};
break;
}
}
}
This is my controller endpoint
/// <summary>
/// POSTing two documents as a multipart/form-data.
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns>The result in the specified format (see outputFormat parameter)</returns>
/// <remarks>
/// Pass two document and output format</remarks>
/// <response code="200">OK</response>
/// <response code="500">Internal error</response>
/// <response code="403">Forbidden</response>
/// <response code="422">UnprocessableEntity</response>
/// <response code="503">ServiceUnavailable</response>
/// <response code="400">BadRequest</response>
[Produces("application/pdf", "application/msword", "application/zip")]
[Consumes("multipart/form-data")]
[ProducesResponseType(StatusCodes.Status200OK, Type = null)]
[ProducesResponseType(StatusCodes.Status500InternalServerError, Type = null)]
[ProducesResponseType(StatusCodes.Status403Forbidden, Type = null)]
[ProducesResponseType(StatusCodes.Status422UnprocessableEntity, Type = null)]
[ProducesResponseType(StatusCodes.Status503ServiceUnavailable, Type = null)]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = null)]
[HttpPost(Name ="File_Post")]
public IActionResult Post()
{
var builBoundary = Request.GetMultipartBoundary();
return Ok(builBoundary);
}
Correct Swagger UI is rendered
Swagger UI
But when I clicked on execute button after attaching files nothing happened.
This is generated swagger JSON
{
"openapi": "3.0.1",
"info": {
"title": "Demo",
"version": "v1"
},
"paths": {
"/File": {
"post": {
"tags": [
"File"
],
"summary": "POSTing two documents as a multipart/form-data.",
"description": "Pass two document and output format",
"operationId": "File_Post",
"parameters": [
{
"name": "file1",
"in": "query",
"description": "First Document",
"required": true,
"schema": {
"type": "string",
"format": "binary"
}
},
{
"name": "file2",
"in": "query",
"description": "Second Document",
"required": true,
"schema": {
"type": "string",
"format": "binary"
}
},
{
"name": "outputFormat",
"in": "query",
"description": "The format to return",
"schema": {
"enum": [
"Rtf",
"Doc",
"DocX",
"Pdf"
],
"type": "string",
"default": "Rtf"
}
}
],
"responses": {
"200": {
"description": "OK"
},
"500": {
"description": "Internal error"
},
"403": {
"description": "Forbidden"
},
"422": {
"description": "UnprocessableEntity"
},
"503": {
"description": "ServiceUnavailable"
},
"400": {
"description": "BadRequest"
}
}
}
}
},
"components": { }
}
Please tell me what should I do to fix this.
I am able to fix this by updating OperationFilter
public class ComparePostParamTypes : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var listOfOutputFormats = new List<string> { "Rtf", "Doc", "DocX", "Pdf" };
var optionArray = new OpenApiArray();
optionArray.AddRange(listOfOutputFormats.Select(s => new OpenApiString(s)));
string documentOutputFormatText =
"The format to return";
switch (operation.OperationId)
{
case "File_Post":
var multipartBodyPost = new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "object",
Properties =
{
["file1"] = new OpenApiSchema
{
Description = "First Document",
Type = "string",
Format = "binary"
},
["file2"] = new OpenApiSchema
{
Description = "Second Document",
Type = "string",
Format = "binary"
},
["outputFormat"] = new OpenApiSchema
{
Description = documentOutputFormatText,
Type = "string",
Enum = optionArray,
Default = new OpenApiString("Rtf"),
},
},
Required = { "file1", "file2" }
}
};
operation.RequestBody = new OpenApiRequestBody
{
Content =
{
["multipart/form-data"] = multipartBodyPost
}
};
break;
}
}
}
I more details, check this link https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1782

MongoDB Stitch GraphQL Custom Mutation Resolver returning null

GraphQL is a newer feature for MongoDB Stitch, and I know it is in beta, so thank you for your help in advance. I am excited about using GraphQL directly in Stitch so I am hoping that maybe I just overlooked something.
The documentation for the return Payload displays the use of bsonType, but when actually entering the JSON Schema for the payload type it asks for you to use "type" instead of "bsonType". It still works using "bsonType" to me which is odd as long as at least one of the properties uses "type".
Below is the function:
const mongodb = context.services.get("mongodb-atlas");
const collection = mongodb.db("<database>").collection("<collection>");
const query = { _id: BSON.ObjectId(input.id) }
const update = {
"$push": {
"notes": {
"createdBy": context.user.id,
"createdAt": new Date,
"text": input.text
}
}
};
const options = { returnNewDocument: true }
collection.findOneAndUpdate(query, update, options).then(updatedDocument => {
if(updatedDocument) {
console.log(`Successfully updated document: ${updatedDocument}.`)
} else {
console.log("No document matches the provided query.")
}
return {
_id: updatedDocument._id,
notes: updatedDocument.notes
}
})
.catch(err => console.error(`Failed to find and update document: ${err}`))
}
Here is the Input Type in the customer resolver:
"type": "object",
"title": "AddNoteToLeadInput",
"required": [
"id",
"text"
],
"properties": {
"id": {
"type": "string"
},
"text": {
"type": "string"
}
}
}
Below is the Payload Type:
{
"type": "object",
"title": "AddNoteToLeadPayload",
"properties": {
"_id": {
"type": "objectId"
},
"notes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"createdAt": {
"type": "string"
},
"createdBy": {
"type": "string"
},
"text": {
"type": "string"
}
}
}
}
}
}
When entering the wrong "type" the error states:
Expected valid values are:[array boolean integer number null object string]
When entering the wrong "bsonType" the error states:
Expected valid values are:[string object array objectId boolean bool null regex date timestamp int long decimal double number binData]
I've tried every combination I can think of including changing all "bsonType" to "type". I also tried changing the _id to a string when using "type" or objectId when "bsonType". No matter what combination I try when I use the mutation it does what it is supposed to and adds the note into the lead, but the return payload always displays null. I need it to return the _id and note so that it will update the InMemoryCache in Apollo on the front end.
I noticed that you might be missing a return before your call to collection.findOneAndUpdate()
I tried this function (similar to yours) and got GraphiQL to return values (with String for all the input and payload types)
exports = function(input){
const mongodb = context.services.get("mongodb-atlas");
const collection = mongodb.db("todo").collection("dreams");
const query = { _id: input.id }
const update = {
"$push": {
"notes": {
"createdBy": context.user.id,
"createdAt": "6/10/10/10",
"text": input.text
}
}
};
const options = { returnNewDocument: true }
return collection.findOneAndUpdate(query, update, options).then(updatedDocument => {
if(updatedDocument) {
console.log(`Successfully updated document: ${updatedDocument}.`)
} else {
console.log("No document matches the provided query.")
}
return {
_id: updatedDocument._id,
notes: updatedDocument.notes
}
})
.catch(err => console.error(`Failed to find and update document: ${err}`))
}
Hi Bernard – There is an unfortunate bug in the custom resolver form UI at the moment which doesn't allow you to only use bsonType in the input/payload types – we are working on addressing this. In actually you should be able to use either type/bsonType or a mix of the two as long as they agree with your data. I think that the payload type definition you want is likely:
{
"type": "object",
"title": "AddNoteToLeadPayload",
"properties": {
"_id": {
"bsonType": "objectId"
},
"notes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"createdAt": {
"bsonType": "date"
},
"createdBy": {
"type": "string"
},
"text": {
"type": "string"
}
}
}
}
}
}
If that doesn't work, it might be helpful to give us a sample of the data that you would like returned.

elasticsearch 6.2 How to specify child and parent fields within one mapping(_doc)

Since 6.2 no longer support multiple mapping type. I have to migrate existing multi type index into _doc type single mapping. However I am not sure how to map current child properties in this single mapping.
"mappings": {
"_doc": {
"properties": {
"join_field": {
"type": "join",
"relations": {
"question": "answer"
}
},
"text": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
Now I wish to have more fields in answer type as well as in question type.But I have no clue how to do that.

How can I define a managed storage schema for my Google Chrome App that supports a nested object structure?

I know the official reference is here.
I am having trouble understanding if I can have a managed_schema structured like this?
schema = {};
schema.propertyA = {};
schema.propertyA.property1 = "1";
schema.propertyA.property2 = "2";
schema.propertyB = "B";
And if so, how would the uploaded policy config file look like?
You can nest properties in a managed_schema just fine with the "object" type. For your example, the schema would look like this:
{
"type": "object",
"properties": {
"propertyA": {
"type": "object",
"properties": {
"property1": {
"type": "string"
},
"property2": {
"type": "string"
}
}
},
"propertyB": {
"type": "string"
}
}
}
And with this policy schema, the uploaded config file would have this format:
{
"propertyA": {
"Value": {
"property1": "1",
"property2": "2"
}
},
"propertyB": {
"Value": "B"
}
}
I've found this page useful when configuring and testing Chrome apps with the managed storage API.