JsonSchemaGenerator adding Minimum - json.net

I'm trying to generate a schema using Newtonsoft JsonSchemaGenerator similar to the following schema
{
"title": "Example Schema",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
}
},
}
I'm trying to create a JsonConverter and set it to the ContractResolver but I can not find a way to bind it to the specific property.
I am tracing the code and I see the GenerateInternal on JsonSchemaGenerator (via GenerateObjectSchema) is looping through Contract.Properties and recursively calling itself but only passing property.PropertyType to itself.
foreach (JsonProperty property in contract.Properties)
{
. . .
JsonSchema propertySchema = GenerateInternal(property.PropertyType, property.Required, !optional);
. . .
}
private JsonSchema GenerateInternal(Type type, Required valueRequired, bool required)
So if I have a class with 2 integer properties with different ranges it won't be able to create different schemas for each.

Related

Is there a way to expand references in Swashbuckle to provide inline schemas?

Is there a mechanism in Swashbuckle that can prevent definitions from being created with referencing to them in parameters/responses/etc.?
By default, you might get a path that looks like this:
"/profile": {
"get": {
"summary": "Get my profile details.",
"produces": [
"application/json",
],
"parameters": [],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/ProfileModel"
}
}
}
}
}
But what I'd like is for it to expand the schema inline like this:
"/profile": {
"get": {
"summary": "Get my profile details.",
"produces": [
"application/json",
],
"parameters": [],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "id"
},
"firstName": {
"type": "string",
"description": "firstName"
},
"surname": {
"type": "string",
"description": "surname"
},
"emailAddress": {
"type": "string",
"description": "emailAddress"
}
}
}
}
}
}
}
I reviewed this StackOverflow question and I don't think it's what I'm looking for (or maybe misinterpreted).
Taken a look through the Swashbuckle README to understand its capabilities but coming up short. Any help here would be most appreciated.
For additional context, looking at the Swashbuckle PDF documentation in section 1.7, I essentially want to bypass or revert the action they describe as
automatically generating a corresponding schema for user-defined reference types and reference the definition via the $ref keyword.
Digging into the codebase a little, it looks like it's not possible at the moment.
However, you can create a custom ISchemaGenerator from the one in source and alter the GenerateConcreteSchema method under the DataType.Object case to not return as reference and this solves the issue.

Cosmos DB Query Projection

I have Cosmos Document of below format:
(Note: Example is just for illustration, the actual document has different properties)
{
"OrderNumer":"12345",
"Version":"5",
"OrderDetails": [
{
"id":1,
"OrderItem": {
"Name": "ABC",
"Description": "ABC Description",
.
.
.
},
"PaymentDetails": {
},
.
.
.
},
{
"id":2,
"OrderItem": {
"Name": "PQR",
"Description": "PQR Description",
.
.
.
},
"PaymentDetails": {
},
.
.
.
},
],
"OrderDate": "12-01-2020",
"CustomerDetails": {
}
.
.
.
}
OrderNumber is a partition key.
I'm trying to project the above document through Cosmos Query to get the entire OrderDetails JSON object and a few properties from the parent into a single JSON with a filter on OrderDetails-> id.
The expected projection should be:
{
"Order":
[
{
"OrderNumer":"12345",
"Version":"5",
"id":1,
"OrderItem": {
"Name": "ABC",
"Description": "ABC Description",
.
.
.
},
"PaymentDetails": {
},
.
.
.
},
{
"OrderNumer":"12345",
"Version":"5",
"id":2,
"OrderItem": {
"Name": "PQR",
"Description": "PQR Description",
.
.
.
},
"PaymentDetails": {
},
.
.
.
},
]
}
As shown in the above JSON, I'm projecting OrderNumber and Version properties within the OrderDetails as Order.
OrderDetails is a massive JSON with a dynamic schema that makes it difficult for us to project its properties individually.
I have tried a few options to project this, but the closest I could reach was below query:
SELECT c.OrderNumber, c.Version, o as Order
FROM c
JOIN o in c.OrderDetails WHERE
c.OrderNumber= '1235' AND ARRAY_CONTAINS([1,2], o.id)
However, the above query does not give desired result as it keeps the OrderNumber and Version in as separate property to Order.
Is there any way I can achieve this?
You can use UDF.
First:create a udf,below is code
function Converted(version,orderNumber,orderItem){
orderItem.Version = version;
orderItem.OrderNumber = orderNumber;
return orderItem;
}
Second:use this sql
select value udf.Converted(c.Version,c.OrderNumber,o) from c join o in c.OrderDetails WHERE c.OrderNumber= '12345' AND ARRAY_CONTAINS([1,2], o.id)
Finally:new JsonObject add this result via code.
Here is result:
[
{
"id": 1,
"OrderItem": {
"Name": "ABC",
"Description": "ABC Description"
},
"PaymentDetails": {},
"Version": "5",
"OrderNumber": "12345"
},
{
"id": 2,
"OrderItem": {
"Name": "PQR",
"Description": "PQR Description"
},
"PaymentDetails": {},
"Version": "5",
"OrderNumber": "12345"
}
]
Does this meet your requirements?
I know this is too late to answer, till now you have resolved your problem but still providing the query to help other people who may have faced a similar issue.
CosmosDB provides flexibility which will help you to modify output JSON structure. Please see the below query for above problem.
Query:
SELECT
[
{
"OrderNumer": c.OrderNumer,
"Version": c.Version,
"id": od.id,
"OrderItem": {
"Name": od.OrderItem.Name,
"Description": od.OrderItem.Description
}
}
] AS Orders
FROM c
JOIN od IN c.OrderDetails
Happy coding!

Access definitions on ref property with newtonsoft.json.schema

I want to have access to the definitions in the schema in order to get the naming of the definition. I am using newtonsoft.json v11.01
I am building a c# converter for jsonschema to make a syntaxtree and compile it in order to get a typed version of the object at runtime.
{
"$id": "https://example.com/arrays.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "xml remarks",
"type": "object",
"properties": {
"fruits": {
"type": "array",
"items": {
"type": "object",
"title": "fruit",
"required": ["naam"],
"properties": {
"naam": {
"type": "string",
"description": "The name of the fruit."
}
}
}
},
"vegetables": {
"type": "array",
"items": { "$ref": "#/definitions/veggie" }
}
},
"definitions": {
"veggie": {
"type": "object",
"required": [ "veggieName", "veggieLike" ],
"properties": {
"veggieName": {
"type": "string",
"description": "The name of the vegetable."
},
"veggieLike": {
"type": "boolean",
"description": "Do I like this vegetable?"
}
}
}
}
}
in the schema a reference is created with the name veggie. This is used in the property vegetable with a reference.
Json schema contains a definition on the root object but is doesn't have it on the property element. On the property element there is nothing identifiable to point to the right definition.
how do i find the right definition for the property?
In general, in order to resolve a json-pointer (a $ref is a "uri-reference", and the part after the # is a "json-pointer"), you need to have access to the root of the json document.
So if you currently have a function that only gets an argument that points to the "properties" section, then you need to give that function a second argument that points to the root of the document.
(It gets more complicated when you're using a schema made up of more than one file; then you need a second argument that points to the roots of all the schema documents)
It's one of the more difficult parts of writing software that interprets json-schema files, especially if your language/library doesn't have support for json-pointers built-in - you'll need to write it yourself in that case.

How to associate nested relationships with attributes for a POST in JSON API

According to the spec, resource identifier objects do not hold attributes.
I want to do a POST to create a new resource which includes other nested resource.
These are the basic resources: club (with name) and many positions (type). Think a football club with positions like goalkeeper, goalkeeper, striker, striker, etc.
When I do this association, I want to set some attributes like is the position required for this particular team. For example I only need 1 goalkeeper but I want to have a team with many reserve goalkeepers. When I model these entities in the DB I'll set the required attribute in a linkage table.
This is not compliant with JSON API:
{
"data": {
"type": "club",
"attributes": {
"name": "Backyard Football Club"
},
"relationships": {
"positions": {
"data": [{
"id": "1",
"type": "position",
"attributes": {
"required": "true"
}
}, {
"id": "1",
"type": "position",
"attributes": {
"required": "false"
}
}
]
}
}
}
}
This is also not valid:
{
"data": {
"type": "club",
"attributes": {
"name": "Backyard Football Club",
"positions": [{
"position_id": "1",
"required": "true"
},
{
"position_id": "1",
"required": "false"
}]
}
}
}
So how is the best way to approach this association?
The best approach here will be to create a separate resource for club_position
Creating a club will return a url to a create club_positions, you will then post club_positions to that url with a relationship identifier to the position and club resource.
Added benefit to this is that club_positions creation can be parallelized.

Swagger 2 - modelling arrays to ensure empty collections rather than null fields

We've done quite a bit of swagger modelling, but one thing I am struggling with is how we could define that all our arrays will never be null, but will be an empty collection if we have no data.
Is there a way of explicitly defining this in Swagger?
Thanks
To define a model with a mandatory array, you can use required property :
{
"type": "object",
"required": [
"nonNullableArray"
],
"properties": {
"nonNullableArray": {
"type": "array",
"items": {
"type": "string"
}
},
"nullableArray": {
"type": "array",
"items": {
"type": "string"
}
}
}
}

Resources