We have multiple Quarkus (2.8.2.Final) applications, which define (many) REST endpoints.
Here our base types (shared base project) are used. Now the problem is, that all properties of those base types are displayed in the Swagger UI as "Example Value" and "Schema".
Example (Date Period)
{
"null": true,
"value": {
"start": "2022-05-18",
"stop": "2022-05-18"
},
"composite": true,
"extended": true,
"defaultValue": {
"start": "2022-05-18",
"stop": "2022-05-18"
},
"dataType": "STRING",
"start": "2022-05-18",
"stop": "2022-05-18",
"startOrMin": "2022-05-18",
"stopOrMax": "2022-05-18",
"startLowerEqualsStop": true,
"maxValue": "2022-05-18",
"minValue": "2022-05-18"
}
Now I need a possibility to define how the schema looks like.
I tried to use the #Schema annotation (org.eclipse.microprofile.openapi.annotations.media.Schema) and define here the implementation property, but this requires to add new classes which define the structure without the properties, which should be hidden. Additionally, within the "Schemas" section in the Swagger UI, now the actual type is displayed and additionally the new reduced/trimmed class.
Also for more complex types with inheritance some additional classes/schemas are displayed, which is also not what we want, as they are completely useless.
What I want to achieve is, that we simply can define which properties are relevant. Without using annotation on every single field which should be ignored.
The #Schema annotation allows the definition of the properties, but they are added to the scanned ones.
So
#Schema(properties = {
#SchemaProperty(name = "start", implementation = Date.class),
#SchemaProperty(name = "stop", implementation = Date.class)}
)
leads to
{
"start": "2022-05-18",
"stop": "2022-05-18",
"null": true,
"value": {
"start": "2022-05-18",
"stop": "2022-05-18"
},
"composite": true,
"extended": true,
"defaultValue": {
"start": "2022-05-18",
"stop": "2022-05-18"
},
"dataType": "STRING",
"startOrMin": "2022-05-18",
"stopOrMax": "2022-05-18",
"startLowerEqualsStop": true,
"maxValue": "2022-05-18",
"minValue": "2022-05-18"
}
Is it somehow possible to define the schemas to show only relevant properties?
Maybe there is also a possibility to define the Schema in a different way, but I didn't found anything that works.
If I could disable the automatic scan for properties for specific classes, it would also somehow a possibility, but I also didn't found a way to achieve this. But even if this is possible, I actually want to have
{
"start": "2022-05-18",
"stop": "2022-05-18"
}
instead of
"value": {
"start": "2022-05-18",
"stop": "2022-05-18"
}
Related
I am new to monorepo.
The thing is they want me to upload a sourcemap to the rollbar.
But I don't know how to generate one.
When I ask for help they told me to read documents. I read the documents / watch Youtube videos for long time but i am still not clear about generating the source map.
In our monorepo we got lots of project
apps
- ProjectA
- ProjectB
- ProjectC
- ProjectD
The thing is i want to generate source map for the ProjectC.
To generate the source map I think i need to build the project ( tell me if i am wrong )
so I look into the project.json. But I don't see the build command.
{
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/ProjectC",
"projectType": "application",
"targets": {
"lint": {
"executor": "#nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/ProjectC/src/**/*.ts"]
}
},
"test": {
"executor": "#nrwl/jest:jest",
"outputs": ["coverage/apps/ProjectC"],
"options": {
"jestConfig": "apps/ProjectC/jest.config.ts",
"passWithNoTests": true
}
}
},
"tags": []
}
How can i configure so that it will produce a sourcemap file? ProjectC is a vue app.
The thing is in the tsconfig.app.json. I see the configuration like this. But I don't find the source map. Is this file related to generating source map?
{
"extends": "./tsconfig.json",
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"types": ["webpack-env", "jest"],
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
},
"include": ["src/**/*.ts", "src/**/*.vue", "tests/**/*.ts"],
"exclude": ["node_modules"]
}
I have a JSON SCHEMA problem related to dependant elements.
Here is an basic example of elements who depends on "droplist", if you choose "Option1", both "example1" and "example2" are activated. If you choose "Option2", only "example2" is activated.
{
"type": "object",
"properties": {
"droplist": {
"title": "Choose one",
"type": "string",
"enum": [
"Option1",
"Option2"
]
},
"example1": {
"title": "Example field 1",
"type": "string",
"options": {
"dependencies": {
"droplist": "Option1"
}
}
},
"example2": {
"title": "Example field 2",
"type": "string",
"options": {
"dependencies": {
"droplist": ["Option1", "Option2"]
}
}
}
}
}
Well, I want to achieve the following:
Keep the dependant fields, but if I choose "Option1" and both elements "example1" and "example2" appear, I want "example2" with additional {"minLength": 3} property.
If I Choose "Option2", I expect the original element "example2" WITHOUT minLength property.
Is this possible? Adding an extra property to a dependant element.
Summing up, I want element "example2" to appear with or without a property (minLength in this case), like a dynamic one.
Thanks guys.
You can do this by splitting off your definitions to a place where they can be reused -- this is under definitions in versions up to draft7, and $defs thereafter. You are using the dependencies keyword, which was split into dependentSchemas and dependentRequired in draft2019-09, so I assume you are using draft7 (or earlier).
definitions:
option1:
...
option2_without_minLength:
...
option2:
allOf:
- $ref: '#/definitions/option2_without_minLength'
- minLength: 3
properties:
...
... things using $ref: '#/definitions/option1' etc
The settings editor can do this
which produces similar to this in the settings file
"files.exclude": {
"**/.classpath": true,
"**/.factorypath": true,
"**/.project": true,
"**/.settings": true,
"**/.zorg": true
},
In package.json this contribution
"print.folder.exclude": {
"default": [],
"type": "array",
"description": "%print.folder.exclude%"
},
just gets a link to edit the file as json.
Declaring it as an object doesn't help. How do I get the glob list editor?
I raised this as an issue on the vscode GitHub repository.
The maintainers told me how to do it. They updated the documentation which should appear in the next release.
"print.folder.exclude": {
"default": [
"bin",
"obj",
"**/*.bin",
"**/*.exe",
"**/*.dll",
"**/*.hex",
"**/*.pdb",
"**/*.pdf"
],
"type": "array",
"items": {
"type": "string"
},
"description": "%print.folder.exclude%"
},
This produces an array of strings rather than an object, but you get the same editor.
How do I subclass in JSON-Schema?
First I restrict myself to draft-07, because that's all I can find implementations of.
The naive way to do sub-classing is described in
https://json-schema.org/understanding-json-schema/structuring.html#extending
But this works poorly with 'additionalProperties': false?
Why bother with
additionalProperties': false?
Without it - nearly any random garbage input json will be considered valid, since all the
'error' (mistaken json) will just be considered 'additionalProperties'.
Recapping https://json-schema.org/understanding-json-schema/structuring.html#extending
use allOf(baseClass)
then add your own properties
The problem with this - is that it doesn't work with 'additionalProperties' (because of
unclear but appantly unfortunate definitions of additionalProperties that it ONLY applies
to locally defined (in that sub-schema) properties, so one or the other schema will fail validation.
Alternative Approaches:
meta languages/interpretters layered on top of JSONSchema
(such as https://github.com/mokkabonna/json-schema-merge-allof)
This is not a good choice as the scehma can only be used from javascript (or the
language of that meta processor). And not easily interoperable with other tools
https://github.com/java-json-tools/json-schema-validator/wiki/v5%3A-merge
An alternative I will propose as a 'solution' / answer
How do I subclass in JSON-Schema?
You don't, because JSON Schema is not object oriented and schemas are not classes. JSON Schema is designed for validation. A schema is a collection of constraints.
But, let's look at it from an OO perspective anyway.
Composition over inheritance
The first thing to note is that JSON Schema doesn't support an analog to inheritance. You might be familiar with the old OO wisdom, "composition over inheritance". The Go language, chooses not to support inheritance at all, so JSON Schema is in good company with that approach. If you build your system using only composition, you will have no issues with "additionalProperties": false.
Polymorphism
Let's say that thinking in terms of composition is too foreign (it takes time to learn to think differently) or you don't have control over how your types are designed. For whatever reason, you need to model your data using inheritance, you can use the allOf pattern you're familiar with. The allOf pattern isn't quite the same as inheritance, but it's the closest you're going to get.
As you've noted, "additionalProperties": false wreaks havoc in conjunction with the allOf pattern. So, why should you leave this out? The OO answer is polymorphism. Let's say you have a "Person" type and a "Student" type that extends "Person". If you have a Student, you should be able to pass it to a method that accepts a Person. It doesn't matter that Student has a few properties that Person doesn't, when it's being used as a Person, the extra properties are simply ignored. If you use "additionalProperties": false, your types can't be polymorphic.
None of this is the kind of solution you are asking for, but hopefully it gives you a different perspective to consider alternatives to solve your problem in different way that is more idiomatic for JSON Schema.
I struggled with that, especially since I had to use legacy versions of JSON Schema. And I found that the solution is a tiny bit verbose but quite easy to read and understand.
Let's say that you want describe that kind of type:
interface Book {
pageCount: number
}
interface Comic extends Book {
imageCount: number
}
interface Encyclopedia extends Book {
volumeCount: number
}
// This is the schema I want to represent:
type ComicOrEncyclopedia = Comic | Encyclopedia
Here is how I can both handle polymorphism and forbid any extra-prop (while obviously enforcing inherited types in the "child" definitions):
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"bookDefinition": {
"type": "object",
"properties": {
"imageCount": {
"type": "number"
},
"pageCount": {
"type": "number"
},
"volumeCount": {
"type": "number"
}
}
},
"comicDefinition": {
"type": "object",
"allOf": [{ "$ref": "#/definitions/bookDefinition" }],
"properties": {
"imageCount": {},
"pageCount": {},
"volumeCount": {
"not": {}
}
},
"required": ["imageCount", "pageCount"],
"additionalProperties": false
},
"encyclopediaDefinition": {
"type": "object",
"allOf": [{ "$ref": "#/definitions/bookDefinition" }],
"properties": {
"imageCount": {
"not": {}
},
"pageCount": {},
"volumeCount": {}
},
"required": ["pageCount", "volumeCount"],
"additionalProperties": false
}
},
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/comicDefinition" },
{ "$ref": "#/definitions/encyclopediaDefinition" }]
}
This isn't a GREAT answer. But until the definition of JSONSchema is improved (or someone provides a better answer) - this is what I've come up with as workable.
Basically, you define two copies of each type, the first with all the details but no additionalProperties: false flag. Then second, REFERENCING the first, but with the 'additionalProperties: false' set.
The first you can think of as an 'abstract class' and the second as a 'concrete class'.
Then, to 'subclass', you use the https://json-schema.org/understanding-json-schema/structuring.html#extending approach, but referencing the ABSTRACT class, and then add the 'additionalProperties: false'. SADLY, to make this work, you must also REPEAT all the inherited properties (but no need to include their type info - just their names) - due to the sad choice for how JSONSchema draft 7 appears to interpret additionalProperties.
An EXAMPLE - based on https://json-schema.org/understanding-json-schema/structuring.html#extending should help:
https://www.jsonschemavalidator.net/s/3fhU3O1X
(reproduced here in case other site
/link not permanant/reliable)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://TEST",
"definitions": {
"interface-address": {
"type": "object",
"properties": {
"street_address": {
"type": "string"
},
"city": {
"type": "string"
},
"state": {
"type": "string"
}
},
"required": ["street_address", "city", "state"]
},
"concrete-address": {
"allOf": [
{
"$ref": "#/definitions/interface-address"
}
],
"properties": {
"street_address": {},
"city": {},
"state": {}
},
"additionalProperties": false
},
"in-another-file-subclass-address": {
"allOf": [
{
"$ref": "#/definitions/interface-address"
}
],
"additionalProperties": false,
"properties": {
"street_address": {},
"city": {},
"state": {},
"type": {
"enum": ["residential", "business"]
}
},
"required": ["type"]
},
"test-of-address-schemas": {
"type": "object",
"properties": {
"interface-address-allows-bad-fields": {
"$ref": "#/definitions/interface-address"
},
"use-concrete-address-to-only-admit-legit-addresses-without-extra-crap": {
"$ref": "#/definitions/concrete-address"
},
"still-can-subclass-using-interface-not-concrete": {
"$ref": "#/definitions/in-another-file-subclass-address"
}
}
}
},
"anyOf": [
{
"$ref": "#/definitions/test-of-address-schemas"
}
]
}
and example document:
{
"interface-address-allows-bad-fields":{
"street_address":"s",
"city":"s",
"state":"s",
"allow-bad-fields-this-is-why-we-need-additionalProperties":"s"
},
"use-concrete-address-to-only-admit-legit-addresses-without-extra-crap":{
"street_address":"s",
"city":"s",
"state":"s"
},
"still-can-subclass-using-interface-not-concrete":{
"street_address":"s",
"city":"s",
"state":"s",
"type":"business"
}
}
In Azure Data Factory, I need to tap into a HTTP requests via URL using the HTTP connector. I was able to do this as well as setup the dataset. Where I'm having issues is on the pipeline. Here's what I need to do. What is the best way to accomplish this?
Call out to the service base URL and retrieve the header returned of TotalPages.
Using the value for TotalPages, make subsequent requests to the URL with the parameter page (e.g., page=1, page=2, etc.) using the value from TotalPages to form those requests.
Thanks.
Ok. So the issue here is that you cannot nest control structures in Data Factory more than 1 time. The solution is to create two or more pipelines (aka Master and Child).
From the Master pipeline retrieve the number of tasks you will need to execute, and pass them to a for loop. Within the for loop launch for each activity pair a new Child pipeline which will then execute the second activity.
If the Activity is simple enough you can skip the Child Pipeline altogether and do it directly inside the first for loop.
As a Json representation of pipelines in question it should look along these lines:
{
"name": "generic_master",
"properties": {
"activities": [
{
"name": "Web1",
"type": "WebActivity",
"dependsOn": [],
"policy": {
"timeout": "7.00:00:00",
"retry": 0,
"retryIntervalInSeconds": 30,
"secureOutput": false,
"secureInput": false
},
"userProperties": [],
"typeProperties": {
"url": "https://jsonplaceholder.typicode.com/posts/1",
"method": "GET"
}
},
{
"name": "ForEach1",
"type": "ForEach",
"dependsOn": [
{
"activity": "Web1",
"dependencyConditions": [
"Succeeded"
]
}
],
"userProperties": [],
"typeProperties": {
"items": {
"value": "#activity('Web1').output",
"type": "Expression"
},
"activities": [
{
"name": "Execute Pipeline1",
"type": "ExecutePipeline",
"dependsOn": [],
"userProperties": [],
"typeProperties": {
"pipeline": {
"referenceName": "generic_child",
"type": "PipelineReference"
},
"waitOnCompletion": true
}
}
]
}
}
],
"annotations": []
}
}
{
"name": "generic_child",
"properties": {
"activities": [
{
"name": "Web1",
"type": "WebActivity",
"dependsOn": [],
"policy": {
"timeout": "7.00:00:00",
"retry": 0,
"retryIntervalInSeconds": 30,
"secureOutput": false,
"secureInput": false
},
"userProperties": [],
"typeProperties": {
"url": "https://jsonplaceholder.typicode.com/posts/1",
"method": "POST"
}
}
],
"annotations": []
}
}
In order to read the TotalPages values from the HTTP Request's response, you can use a "Lookup" activity to submit the HTTP request and store the TotalPages value in a variable with the "Set variable" activity.
Actions:
Pipeline level:
create a variable called TotalPages
Lookup activity:
tick the first row only box on the Settings tab
As a source dataset, use the data set defined for your HTTP request
Select the GET method.
Set variable activity:
Select the TotalPages variable on the Variables tab
In the value box, click on "Add dynamic content" and enter something like this: #{activity('GetTotalPages').output.firstRow.RegisterSearch['#TotalPages']}
In my case, the lookup activity is called GetTotalPages, and my HTTP request returns the total number of pages in a RegisterSearch array, under a column name #TotalPages