camelCase in Swagger documentation - json

is it possible to change property names to camelCase in Swagger documentation? I'm using .NET Core 2.2 and Swashbuckle.AspNetCore 5.2.1.
I've tried to use DescribeAllParametersInCamelCase() method in Startup.cs but nothing has changed.
Help!
My model:
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
public int MyProperty3 { get; set; }
}
and swagger.json which was generated for it in POST method:
"components": {
"schemas": {
"TestModel": {
"type": "object",
"properties": {
"MyProperty1": {
"type": "integer",
"format": "int32"
},
"MyProperty2": {
"type": "integer",
"format": "int32"
},
"MyProperty3": {
"type": "integer",
"format": "int32"
}
}
}
}
}
How to change it to:
"components": {
"schemas": {
"testModel": {
"type": "object",
"properties": {
"myProperty1": {
"type": "integer",
"format": "int32"
},
"myProperty2": {
"type": "integer",
"format": "int32"
},
"myProperty3": {
"type": "integer",
"format": "int32"
}
}
}
}
}
?

I faced the same issue and here is my workaround :
I implemented a custom filter (ISchemaFilter) that does the following
public class CamelCasingPropertiesFilter : ISchemaFilter {
public void Apply(OpenApiSchema model, SchemaFilterContext context)
{
model.Properties =
model.Properties.ToDictionary(d => d.Key.Substring(0, 1).ToLower() + d.Key.Substring(1), d => d.Value);
}
}
There is maybe a more reliable solution I don't know. The matter is important as the openapi definition serves as a basis for generating api clients. openapi generator will build classes with PascalCase property names, which will be thrown by the api when used ...
Hope it helps !

Related

How to store GeoJSON in PostgreSQL

I'm trying to get a JSON formatted like GeoJSON with API. I get something for GET and can DELETE but when i try to post or put i get this error System.NotSupportedException: Deserialization of reference types without parameterless constructor is not supported. Type 'System.Text.Json.JsonDocument'
Also I'm not getting exactly what I have in PostgreSQL. There is an extra "rootElement"
In PostgreSQL I have a table with columns ID(integer),type(string),properties(json),geometry(json).
I insert this
{
"id": 1,
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [23.2,23]
},
"properties": {
"name": "test2",
"type": "testing"
}
}
And this is my class
public class Test
{
public long ID { get; set; }
public string type { get; set; }
public System.Text.Json.JsonDocument geometry { get; set; }
public System.Text.Json.JsonDocument properties { get; set; }
}
What I get with GET is this
[
{
"id": 2,
"type": "test",
"geometry": {
"rootElement": {
"type": "point",
"coordinates": [
23.2,
23
]
}
},
"properties": {
"rootElement": {
"name": "test2",
"type": "testing"
}
}
}
]

jsonschema2pojo generating all variable of type object but not the data type i provide

I am new to this API. Trying to generate a class of 10-15 fields of different data type. But generated class has the 1st variable of the type I declared but remaining if type Object as below.
// Schema
{
"type":"object",
"properties": {
"foo": {
"type": "string"
},
"bar": {
"type": "String"
},
"baz": {
"type": "String"
}
}
}
//Generated Class
//...
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"foo",
"bar",
"baz"
})
public class Sample{
#JsonProperty("foo")
private String foo;
#JsonProperty("bar")
private Object bar;
#JsonProperty("baz")
private Object baz;
#JsonIgnore
....//
If you notice the 2nd and 3rd variable are declared String but result generated from class is of type object. Can someone help understand what the issue is?
{
"type":"object",
"properties": {
"length": {
"type": "string"
},
"width": {
"type": "string"
},
"height": {
"type": "string"
},
"dimensionalWeight": {
"type": "string"
}
}
}

springfox swagger configuration for JsonNode property in a model class

I have a Model 'NewModel' with the following property
import com.fasterxml.jackson.databind.JsonNode;
#ApiModel(
description = "Data Class to hold new details"
)
public class NewModel {
#ApiModelProperty(
notes = "Value in JSON key:value format. Can be any key:value pair",
example = "{ds:2017:08:05,hh:11}"
)
private final JsonNode value;
(... getters and setters ...)
}
Apart from this, I have some rest controllers which get a JSON in request body. I use this model to get the JSOn from request body.
I have configured springfox swagger using maven, and generated the api definition. But in the generated API definitions, this model has been generated as
"NewModel": {
"type": "object",
"properties": {
"value": {
"example": "{nds:2017:08:05,hh:11}",
"description": "Value of the stamp in JSON key:value format",
"$ref": "#/definitions/JsonNode"
}
},
"description": "Data Class to hold details"
}
And the reference JsonNode definition generated is
"definitions": {
"JsonNode": {
"type": "object",
"properties": {
"array": {
"type": "boolean"
},
"bigDecimal": {
"type": "boolean"
},
"bigInteger": {
"type": "boolean"
},
"binary": {
"type": "boolean"
},
"boolean": {
"type": "boolean"
},
"containerNode": {
"type": "boolean"
},
"double": {
"type": "boolean"
},
"float": {
"type": "boolean"
},
"floatingPointNumber": {
"type": "boolean"
},
"int": {
"type": "boolean"
},
"integralNumber": {
"type": "boolean"
},
"long": {
"type": "boolean"
},
"missingNode": {
"type": "boolean"
},
"nodeType": {
"type": "string",
"enum": [
"ARRAY",
"BINARY",
"BOOLEAN",
"MISSING",
"NULL",
"NUMBER",
"OBJECT",
"POJO",
"STRING"
]
},
"null": {
"type": "boolean"
},
"number": {
"type": "boolean"
},
"object": {
"type": "boolean"
},
"pojo": {
"type": "boolean"
},
"short": {
"type": "boolean"
},
"textual": {
"type": "boolean"
},
"valueNode": {
"type": "boolean"
}
}
}
Now, when I generate a client library with this API definition, the JsonNode Object allowed on the client side has only Boolean variables, and I cannot assign actual JSON strings to it, and hence cannot pass a JSON value to the connecting server (from which I generated the API definitions)
I was wondering is there was a way I could get to pass Json Strings from client to server using the swagger generated libraries. Or any other directions in which I can achieve the required end result.
Thanks (and apologies for the long post)
An attribute in ApiModelProperty, dataType="java.util.Map" should help
public class NewModel {
#ApiModelProperty(
example = "{ds:2017:08:05,hh:11}",
dataType = "java.util.Map"
)
private final JsonNode value;
Perhaps AlternateTypeRuleConvention, which is introduced in Springfox, will help you.
For example, you can do this:
#Bean
public AlternateTypeRuleConvention typeConvention(final TypeResolver resolver) {
return new AlternateTypeRuleConvention() {
#Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
#Override
public List<AlternateTypeRule> rules() {
return Collections.singletonList(
AlternateTypeRules.newRule(resolver.resolve(JsonNode.class), resolver.resolve(jsonNodeApi()))
);
}
};
}
private Type jsonNodeApi() {
return new AlternateTypeBuilder()
.fullyQualifiedClassName(
String.format("%s.generated.%s",
JsonNode.class.getPackage().getName(),
JsonNode.class.getSimpleName()))
.build();
}
AlternateTypeBuilder also allows you to specify custom fields if necessary.

Elasticsearch NEST 2.x Field Names

I am upgrading to NEST 2.3.0 and trying to rewrite all queries that were originally written for NEST 1.x.
I am using the Couchbase transport plugin that pushes data from Couchbase to Elasticsearch.
POCO
public class Park
{
public Park()
{
}
public bool IsPublic { get; set; }
}
Mapping is like this
"mappings": {
"park": {
"_source": {
"includes": [
"doc.*"
],
"excludes": [
"meta.*"
]
},
"properties": {
"meta": {
"properties": {
"rev": {
"type": "string"
},
"flags": {
"type": "long"
},
"expiration": {
"type": "long"
},
"id": {
"type": "string",
"index": "not_analyzed"
}
}
},
"doc": {
"properties": {
"isPublic": {
"type": "boolean"
}
}
}
}
}
}
Sample document in elasticsearch
{
"_index": "parkindex-local-01",
"_type": "park",
"_id": "park_GUID",
"_source": {
"meta": {
"expiration": 0,
"flags": 33554433,
"id": "park_GUID",
"rev": "1-1441a2c278100bc00000000002000001"
},
"doc": {
"isPublic": true,
"id": "park_GUID"
}
}
}
My query in NEST
var termQuery = Query<Park>.Term(p => p.IsPublic, true);
ISearchResponse<T> searchResponse = this.client.Search<T>(s => s.Index("parkindex-local-01")
.Take(size)
.Source(false)
.Query(q => termQuery));
This query goes to Elasticsearch as below
{
"size": 10,
"_source": {
"exclude": [
"*"
]
},
"query": {
"term": {
"isPublic": {
"value": "true"
}
}
}
}
It doesn't retrieve any data, it will work only if I prefix the field name with "doc." so query becomes as below
{
"size": 10,
"_source": {
"exclude": [
"*"
]
},
"query": {
"term": {
"doc.isPublic": {
"value": "true"
}
}
}
}
How do I write the query above in NEST so it can properly interpret the field names, I tried using Nested Query with Path set to "doc", but that gave an error saying field is not of a nested type.
Do I need to change my mapping?
This all used to work in Elasticsearch 1.x and NEST 1.x, I guess this has to do with breaking changes to field names constraints.
Fields can no longer be referenced by shortnames in Elasticsearch 2.0.
isPublic is a property of the doc field, which is mapped as an object type, so referencing by the full path to the property is the correct thing to do.
NEST 2.x has some ways to help with field inference, an example
public class Park
{
public Doc Doc { get; set;}
}
public class Doc
{
public bool IsPublic { get; set;}
}
var termQuery = Query<Park>.Term(p => p.Doc.IsPublic, true);
client.Search<Park>(s => s.Index("parkindex-local-01")
.Take(10)
.Source(false)
.Query(q => termQuery));
results in
{
"size": 10,
"_source": {
"exclude": [
"*"
]
},
"query": {
"term": {
"doc.isPublic": {
"value": true
}
}
}
}
You may also want to take a look at the automapping documentation.

How can I define the sequence of properties in JSON Schema?

I have following java Object:
ProcessBean.java
import java.util.List;
import com.fasterxml.jackson.annotation.JsonRootName;
#JsonRootName(value = "process")
public class ProcessBean{
private Integer id;
private String name;
private String description;
private String user;
private String executePermissions;
private String createdDtm;
private String updatedDtm;
private Process tpProcess;
private List<ProcessParamBean> processParameters;
/* --------Getters and Setters ----------*/
}
I need to find the JSON schema for this object which is used to display these fields on UI. The order of fields in UI is determined by the order of properties in JSON schema generated.
I have generated the schema using following code:
DataSpec.java
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper;
public class DataSpec {
public static <T> String getDataSpec(Class<T> clazz) {
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();
MetauiVisitorContext obj = new MetauiVisitorContext();
visitor.setVisitorContext(obj);
try {
mapper.acceptJsonFormatVisitor(clazz, visitor);
JsonSchema schema = visitor.finalSchema();
return mapper.writeValueAsString(schema);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
}
MetauiVisitorContext.java
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.module.jsonSchema.factories.VisitorContext;
public class MetauiVisitorContext extends VisitorContext{
#Override
public String getSeenSchemaUri(JavaType aSeenSchema) {
return null;
}
}
The resultant schema looks like below:
{
"type": "object",
"id": "urn:jsonschema:com:restservices:api:jsonbeans:ProcessBean",
"properties": {
"updatedDtm": {
"type": "string"
},
"createdDtm": {
"type": "string"
},
"name": {
"type": "string"
},
"tpProcess": {
"type": "object",
"id": "urn:jsonschema:com:restservices:api:jsonbeans:Process",
"properties": {
"name": {
"type": "string"
},
"id": {
"type": "integer"
}
}
},
"description": {
"type": "string"
},
"id": {
"type": "integer"
},
"processParameters": {
"type": "array",
"items": {
"type": "object",
"id": "urn:jsonschema:com:restservices:api:jsonbeans:ProcessParamBean",
"properties": {
"updatedDtm": {
"type": "string"
},
"defaultValue": {
"type": "string"
},
"createdDtm": {
"type": "string"
},
"masterParam": {
"type": "object",
"id": "urn:jsonschema:com:restservices:api:jsonbeans:MasterParamBean",
"properties": {
"updatedDtm": {
"type": "string"
},
"createdDtm": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"id": {
"type": "integer"
}
}
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"processParamId": {
"type": "integer"
},
"id": {
"type": "integer"
},
"userPrompted": {
"type": "boolean"
},
"tags": {
"type": "string"
}
}
}
},
"executePermissions": {
"type": "string"
},
"user": {
"type": "string"
}
}
}
As it can be seen that the order of properties in JSON schema does not match the order of fields defined in Java object which is necessary in my case.
So how can I determine the sequence of the properties?
There is not an intrinsic order of properties in a JSON schema object, as it happens with a regular JSON or javascript object. Indeed, it does not change the validation semantics. The following schemas validate exactly the same collection of objects:
Schema 1:
{
"properties" : {
"prop1" : {
"type" : "string"
},
"prop2" : {
"type" : "number"
}
}
}
Schema 2:
{
"properties" : {
"prop2" : {
"type" : "number"
},
"prop1" : {
"type" : "string"
}
}
}
If you want to preserve some ordering you need to do it within and array. You could achieve this by using an array of objects instead of an object in the items clause. An example:
{
"type" : "array" :
"items" : [{
"properties" : {
"prop2" : {
"type" : "number"
}
}
}, {
"properties" : {
"prop1" : {
"type" : "string"
}
}
}
]
}
This way you get an ordered definition of UI items. Unfortunately, it forces you to nest each single property in an object.
Order is out of scope for json-schema. For that you need to look into json-forms https://jsonforms.io/, standards, which is extension of json-schema. It consist of three separate JSON data :
schema
values
ui-schema
The ui-schema contains the information about the ui and presentation, like order of properties (fields) and the their visual presentation, like "hidden", "read-only".