Springdoc - Child classes fields are not getting added to the swagger spec schema - swagger-ui

I'm using spring-boot v2.6.7 and springdoc v1.6.8. Below is the object modeling. I have added one endpoint which returns the Course as the response. I am expecting swagger spec to generate the types for the Course and the Child type which is EnglishCourse also there's an items field on EnglishCourse which is supertype of CourseItem and there are subtypes for it which are Folder, Lesson, and Test. I expect swagger spec to include a proper schema definition for all the subtypes.
package com.example.springdocdemo.domain
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
import io.swagger.v3.oas.annotations.media.Schema
import java.util.UUID
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
#JsonSubTypes(
value = [
JsonSubTypes.Type(value = EnglishCourse::class, name = "EnglishCourse")
]
)
abstract class Course {
abstract val id: UUID
abstract val name: String
abstract val code: String
}
class EnglishCourse(
val items: List<CourseItem>,
override val id: UUID,
override val code: String,
override val name: String,
) : Course()
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
#JsonSubTypes(
value = [
JsonSubTypes.Type(value = Folder::class, name = "FOLDER"),
JsonSubTypes.Type(value = Lesson::class, name = "LESSON"),
JsonSubTypes.Type(value = Test::class, name = "TEST")
]
)
#Schema(discriminatorProperty = "type", allOf = [Folder::class, Lesson::class, Test::class])
interface CourseItem {
val type: CourseItemType
val id: UUID
}
#Schema
class Folder(
val items: List<CourseItem>,
override val id: UUID,
override val type: CourseItemType,
) : CourseItem {
fun items() = println(items)
}
class Lesson(
val name: String,
override val id: UUID,
override val type: CourseItemType,
) : CourseItem
class Test(
val name: String,
override val id: UUID,
override val type: CourseItemType,
) : CourseItem
enum class CourseItemType {
Folder, Lesson, Test
}
and the below is the schema definition for the Folder type
"Folder": {
"required": [
"id",
"type"
],
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/CourseItem"
}
]
},
It doesn't include fields id and items. Is there any solution for this? The code can be found here: https://github.com/BhaveshSuvalaka/springdoc-issue

maybe try
#Schema(subTypes = {EnglishCourse.class})

Related

How to skip field in every object of list while mapping

I am trying to map Entity with ManyToMany relationship to DTO.
public class SkillEntity {
#Id
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
private String name;
#ManyToMany(mappedBy = "skills")
private Set<UnifiedOfferEntity> unifiedOffers = new HashSet<>();
#Data
public class SkillDTO {
private String name;
private Set<UnifiedOfferDTO> unifiedOffers;
}
And I have problem with mapping that Set. I did custom mapper and it works, I am getting resposne like below but I want to skip "skills" field in UnifiedOfferDTO.
{
"name": "REACT NATIVE",
"unifiedOffers": [
{
"companyName": "QLOC S.A.",
"title": "Tester",
"skills": null,
},
{
"companyName": "Apptension sp. z o.o.",
"title": "Junior Frontend Developer",
"skills": null,
}
]
}
I created typeMap:
modelMapper.typeMap(SkillEntity.class, SkillDTO.class)
.addMappings(m -> m.using(skillEntityUnifiedOffersListConverter)
.map(skillEntity -> skillEntity, SkillDTO::setUnifiedOffers))
and i would like to skip that field "skills" from unifiedOfferDTO but do not know if I should add mapper.skip or something else.

How to set the value null instead of "null" in the example of a schema in Springdoc-openapi?

I am using Springdoc-openapi and have a dto like this:
#Schema(title = "Financial Conditions")
#JsonIgnoreProperties(ignoreUnknown = true)
public class CurrentFinancialConditions {
#Schema(title = "Rate", example = "null")
#JsonProperty("light")
private String conditionsLight;
#Schema(title = "Scores")
private Scores scores;
}
and it gives me the result in swagger-ui:
"current_financial_conditions": {
"scores": {
"liquidity": "some example goes here",
"profitability": "some example goes here",
},
"light": "null"
}
Is it possible to change the example value in the generated docs from "null" to null?

Mapping a variety of JSON responses with the same top - level structure in Swift

I have a variety of JSON responses that I'm getting back from a server via Alamofire; two are included below:
1)
{
"json" : {
"harkUpdate" : {
"more" : [
{
"unread-count" : {
"last" : 1613507864973,
"index" : {
"graph" : {
"graph" : "\/ship\/~dopzod\/urbit-help",
"index" : "\/"
}
}
}
},
{
"seen-index" : {
"index" : {
"graph" : {
"index" : "\/",
"graph" : "\/ship\/~dopzod\/urbit-help"
}
},
"time" : 1613507864973
}
}
]
}
},
"response" : "diff",
"id" : 3
}
{
"json" : {
"graph-update" : {
"keys" : [
{
"name" : "book-club-4717",
"ship" : "sicdev-pilnup"
},
{
"name" : "dm--locrev-finlys",
"ship" : "haddef-sigwen"
},
{
"name" : "smol-bibliotheca",
"ship" : "dasfeb"
},
{
"name" : "interface",
"ship" : "bitpyx-dildus"
},
{
"name" : "jobs-gigs",
"ship" : "nibset-napwyn"
},
{
"name" : "tlon-general",
"ship" : "bolbex-fogdys"
}
]
}
},
"id" : 1,
"response" : "diff"
}
As you can see, they both have an id, a response, and json fields - but the actual json response in them varies.
Normally what I would do is generate classes using something like quicktype.io, or use one of the many ObjectMapping frameworks out there. What I'm trying to get mentally un-blocked with is that all these json responses have a field called "json", which has a different structure. I'm trying to figure out who I can make unique classes for the responses given this structuring. Any help appreciated.
You can declare a basic object which's json property will be a generic type conforming to Codable.
struct JSON<T : Codable>: Codable {
let json: T
let id: Int
let response: String
}
After you define two structs which will represent the first and second json objects. For simplicity I will define only the objects that represent the second JSON:
struct GraphUpdate: Codable {
let graphUpdate: Keys
enum CodingKeys: String, CodingKey {
case graphUpdate = "graph-update"
}
}
struct Keys: Codable {
let keys: [Key]
}
struct Key: Codable {
let name, ship: String
}
And when trying to decode, you have to specify what object you want to decode to:
let item = try? JSONDecoder().decode(JSON<GraphUpdate>.self, from: data)

Avro Schema Generation - Object Reordering

I need to generate an AVRO schema from an existing Java Model. I then want to use that schema to generate Java objects so I can replace my existing model with the generated one, making the schema the source of truth.
I am having a problem which I will try to illustrate with this example.
I have a basic Java class:
public class Car {
private String price;
private String engine;
public Car(String price, String engine) {
this.price = price;
this.engine = engine;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getEngine() {
return engine;
}
public void setEngine(String engine) {
this.engine = engine;
}
}
I want to generate an avro schema which represents this class.
public static void main(String[] args) throws JsonMappingException {
System.out.println(generateAvroSchema());
}
public static String generateAvroSchema() throws JsonMappingException {
ObjectMapper mapper = new ObjectMapper(new AvroFactory());
AvroSchemaGenerator gen = new AvroSchemaGenerator();
mapper.acceptJsonFormatVisitor(Car.class, gen);
Schema schema = gen.getGeneratedSchema().getAvroSchema();
return schema.toString(true);
}
The result of this is:
{
"type" : "record",
"name" : "Car",
"namespace" : "app",
"fields" : [ {
"name" : "engine",
"type" : [ "null", "string" ]
}, {
"name" : "price",
"type" : [ "null", "string" ]
} ]
}
When the schema is generated the object attributes are ordered alphabetically. If I was to use this schema to generate a new java model, the constructor argument ordering would be different from the source.
My question is, is there any configuration I can use when generating the schema to preserve attribute ordering and not default to alphabetical?
Thanks
Ran into this issue as well, solved following https://github.com/fasterxml/jackson-dataformat-csv/issues/40
Basically calling mapper.disable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); on the mapper.

local variable guid is replaced by new GUID Value while reading a json file from URL

I am very new to json
Am having a json file in URL which is,
and am getting all the data into a list as below
System.Net.WebClient wc = new System.Net.WebClient();
string json = wc.DownloadString("http://192.168.1.7:90/eawebportal/poc/elements/index");
List<JsonFormat> myDeserializedObjList = (List<JsonFormat>)Newtonsoft.Json.JsonConvert.DeserializeObject(json, typeof(List<JsonFormat>));
and am getting the list in myDeserializedObjList .Where JsonFormat is a class as below
public class JsonFormat
{
public string guid;
public string type;
public string name;
}
My expected OUTPUT is:
guid= 1-1-1-1-1-1-1 , type= Requirement , name = element name
guid= 2-2-2-2-2-2-2 , type= Requirement , name = element name
but it give output as
guid= 539fe407-b5c8-4e02-ba7a-1410c0a80107 , type= Requirement , name = element name
guid= 539fe407-c0b8-4301-bf22-1410c0a80107 , type= Requirement , name = element name
Why its comin so..??
If I use completely hardcoded data in a console application, it works as expected (see below). So, either the downloaded data file is different than you're showing, or else you have something else in your code that is changing it.
class Program
{
{
string json = #"
[
{ ""guid"" : ""1-1-1-1-1-1-1"", ""type"" : ""Requirement"", ""name"" : ""element name"" },
{ ""guid"" : ""2-2-2-2-2-2-2"", ""type"" : ""Requirement"", ""name"" : ""element name"" },
{ ""guid"" : ""3-3-3-3-3-3-3"", ""type"" : ""Requirement"", ""name"" : ""element name"" },
{ ""guid"" : ""4-4-4-4-4-4-4"", ""type"" : ""Requirement"", ""name"" : ""element name"" }
]";
List<JsonFormat> list = JsonConvert.DeserializeObject<List<JsonFormat>>(json);
foreach (JsonFormat jf in list)
{
Console.WriteLine("guid: " + jf.guid);
Console.WriteLine("type: " + jf.type);
Console.WriteLine("name: " + jf.name);
Console.WriteLine();
}
}
public class JsonFormat
{
public string guid;
public string type;
public string name;
}
}
Output:
guid: 1-1-1-1-1-1-1
type: Requirement
name: element name
guid: 2-2-2-2-2-2-2
type: Requirement
name: element name
guid: 3-3-3-3-3-3-3
type: Requirement
name: element name
guid: 4-4-4-4-4-4-4
type: Requirement
name: element name

Resources