I have a sample object which is referenced by swagger to create a POST endpoint in my documentation.
I then use the documentation to generate a client for testing. However, the API works slightly differently then how the object is directly presented. I want to override the POST body parameter type of the created model in the documentation from a service type to a string (a reference string to the service). I've included the referenced object below.
#Entity
public class ServiceType {
private String id;
private Service service;
private String type;
public Service getService() {
return service;
}
public void setService(Service service) {
this.service = service;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
The body is generate as:
{
"createdDate": "2019-03-12T15:18:22.568Z",
"id": "string",
"service": {
"createdDate": "2019-03-12T15:18:22.568Z",
"id": "string",
"name": "string",
"routingKey": "string",
"updatedBy": "string",
"updatedDate": "2019-03-12T15:18:22.569Z"
},
"type": "string",
"updatedBy": "string",
"updatedDate": "2019-03-12T15:18:22.569Z"
}
But I want it to be in the format:
{
"createdDate": "2019-03-12T15:18:22.568Z",
"id": "string",
"service": "string",
"type": "string",
"updatedBy": "string",
"updatedDate": "2019-03-12T15:18:22.569Z"
}
Not sure if this is possible. Thanks for the help.
You can use the #ApiModel and #ApiModelProperty annotations to override the default data type for a field. Note that the data type must be a fully-qualified type name (such as java.lang.String). For more information, see Overriding Property Datatypes.
#Entity
#ApiModel
public class ServiceType {
private String id;
#ApiModelProperty(dataType = "java.lang.String")
private Service service;
private String type;
public Service getService() {
return service;
}
public void setService(Service service) {
this.service = service;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Related
I am trying to add data into a mongodb collection using Panache and Quarkus. I am trying to insert a nested document that is like the one below
{
"user_id": 8001,
"name": "John John",
"email":"jj#justiceleague.com",
"entity":6,
"business_unit": 3,
"contact_person":"Bats Nopower",
"contact_person_phone":"+25472000001",
"verification_data":{
"national_id": "987643",
"tax_pin":"A0GYE09753ew",
"driving_licence":"6473412"
},
"country":"KE"
}
However when I insert the data this is how it looks like
{
"_id": {
"$oid": "609472b1b410cd46bc3bc674"
},
"business_unit": 3,
"country": "KE",
"created_date": {
"$date": "2021-05-07T01:50:25.341Z"
},
"email": "jj#justiceleague.com",
"entity": 6,
"name": "John John",
"user_id": 8001,
"verification_data": {
"verification_data": {
"national_id": "987643",
"tax_pin": "A0GYE09753ew",
"driving_licence": "6473412"
}
}
}
verification_data is nested inside another verification_data. Not sure what am missing
This is how my data class looks like
#MongoEntity(collection="basic_info")
public class BasicInfo extends PanacheMongoEntity {
#SerializedName("user_id")
#BsonProperty("user_id")
public Integer userId;
public String name;
public String email;
public Integer entity;
#BsonProperty("business_unit")
public Integer businessUnit;
#BsonProperty("contact_person")
public String contactPerson;
#BsonProperty("contact_person_phone")
public String contactPhone;
#BsonProperty("created_date")
public LocalDateTime createdDate;
public String country;
#BsonProperty("verification_data")
public Object verificationData;
//getters and setters
}
This is how I persist the data
public void addBasicInfo(BasicInfo basicInfo) {
BasicInfo initialData = new BasicInfo();
initialData.setUserId(basicInfo.getUserId());
initialData.setName(basicInfo.getName());
initialData.setEmail(basicInfo.getEmail());
initialData.setEntity(basicInfo.getEntity());
initialData.setBusinessUnit(basicInfo.getBusinessUnit());
initialData.setVerificationData(basicInfo.getVerificationData());
initialData.setCountry(basicInfo.getCountry());
initialData.setCreatedDate(LocalDateTime.now());
initialData.persist();
}
This is how my codec looks like
public class ObjectCodec implements Codec<Object> {
private final Codec<Document> documentCodec;
public ObjectCodec() {
this.documentCodec = MongoClientSettings.getDefaultCodecRegistry().get(Document.class);
}
#Override
public void encode(BsonWriter writer, Object object, EncoderContext encoderContext) {
Document doc = new Document();
doc.put("verification_data", object);
documentCodec.encode(writer, doc, encoderContext);
}
#Override
public Class<Object> getEncoderClass() {
return Object.class;
}
//...
}
Note: I do not know how verification_data will look like before hand that is why am treating it as an Object.
My Controller Code is
public TestClass<DtoV1> getAllAlliance(#RequestHeader(ID_HEADER) String id,Pageable pageable, PagedResourcesAssembler pagedResourcesAssembler)
{
Page<DtoV1> pageResource = serviceV1.findPagedPrefixesById(pageable, id);
PagedResources<DtoV1> pagedResources = pagedResourcesAssembler.toResource(pageResource);
TestClass<DtoV1> testClass = new TestClass<>(pageResource.getContent(),pagedResources.getLinks());
return testClass;
}
My TestClass Wrapper is
enter code herepublic class TestClass<T> {
public String name;
public Collection<T> content;
public List<Link> links;
public String[] st= new String[0];
public TestClass(Collection<T> content,List<Link> links)
{
this.content = content;
this.name="sunil";
this.links = links;
}
#JsonInclude(JsonInclude.Include.NON_EMPTY)
#JsonProperty("_name")
public String getName()
{
return this.name;
}
#JsonInclude(JsonInclude.Include.NON_EMPTY)
#JsonProperty("_st")
public String[] getSt() {
return st;
}
#JsonInclude(JsonInclude.Include.NON_EMPTY)
#JsonProperty("_embedded")
public Collection<T> getContent()
{
return this.content;
}
#JsonInclude(JsonInclude.Include.NON_EMPTY)
#JsonProperty("_links")
public List<Link> getLinks() {
return this.links;
}}
My Result is
{
"_name": "sunil",
"_embedded": [
{
"key": "0000435",
"type": "Test",
"issuing": "temp",
"issued": "temp",
"dateIssued": "1989-10-22",
"links": []
}],
"_links": [
{
"rel": "first",
"href": "http://localhost:8080/v1?page=0&size=20",
"hreflang": null,
"media": null,
"title": null,
"type": null,
"deprecation": null
}]
}
If you see i have created an string empty array st in test class it is not coming but why rest are coming
Expected null and empty values will not come as using #JsonInclude(JsonInclude.Include.NON_EMPTY)
The Problem is Thridparty object . So if go with the concept i believe that we can not ignore null or empty of other class objects if they do not contain ignore null annotation
To do this what we can do we can use mixin with objectmapper.
I have such service:
public interface FireService {
void addTags(String sessionId, List<TagCreateRequest> tags);
}
Here TagCreateRequest is:
#MetaClass(name = "...")
public class TagCreateRequest extends AbstractNotPersistentEntity implements Serializable {
#MetaProperty(mandatory = true)
protected TagType type;
#MetaProperty(mandatory = true)
protected Double time;
#MetaProperty
protected String text;
public void setType(TagType type) {
this.type = type;
}
public TagType getType() {
return type;
}
public void setTime(Double time) {
this.time = time;
}
public Double getTime() {
return time;
}
public void setText(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
My problem is when i'm trying to make REST request to method addTags like this:
http://localhost:8080/app/rest/v2/services/fire_FireService/addTags
{
"sessionId": "1417270d-31cb-be3c-e583-4b172b4183a9",
"tags": [
{
"type": "fire",
"time": 12.333
},
{
"type": "text",
"time": 15.12,
"text": "Test!!!"
}
]
}
I'm getting the EntitySerializationException that tells me that MetaClass for entity is not defined:
EntitySerializationException: Cannot deserialize an entity. MetaClass is not defined
I tried to look how platform determines the MetaClass and found strange thing. If service parameter is Collection, then passed MetaClass is null:
#Component("cuba_RestParseUtils")
public class RestParseUtils {
...
public Object toObject(Class clazz, String value) throws ParseException {
...
if (Collection.class.isAssignableFrom(clazz)) {
return entitySerializationAPI.<Entity>entitiesCollectionFromJson(value, null);
}
...
}
...
}
What should i do in this case?
You must explicitly specify the type of instances in the collection. Use the _entityName field in each TagCreateRequest entity:
{
"sessionId": "1417270d-31cb-be3c-e583-4b172b4183a9",
"tags": [
{
"_entityName": "prj_TagMetaClassName",
"type": "fire",
"time": 12.333
},
{
"_entityName": "prj_TagMetaClassName",
"type": "text",
"time": 15.12,
"text": "Test!!!"
}
]
}
This question already has answers here:
Expected an array of objects but got an object in an object
(2 answers)
Closed 7 years ago.
While developing a web service, I build a GET method to return a JSON list of System objects (a custom object, not the java.lang kind). Against expectations I receive a JSON object with 1 parameter containing the array that I initially expected. What am I missing here?
System Class
#XmlRootElement
public class System
{
private long id;
private String name;
#XmlElement
public long getId()
{
return id;
}
public void setId(long pId)
{
id = pId;
}
#XmlElement
public String getName()
{
return name;
}
public void setName(String pName)
{
name = pName;
}
}
REST service
#Path("/systems")
public class SystemHandler
{
#GET
#Path("/list")
#Produces({MediaType.APPLICATION_JSON})
public List<System> getSystems(#Context SecurityContext sc)
{
List<System> list = null;
//Populate the list
return list;
}
}
Result of /systems/list
{
"system": [
{
"id": "248",
"name": "FOO"
},
{
"id": "617",
"name": "BAR"
}
]
}
While I was expecting
[
{
"id": "248",
"name": "FOO"
},
{
"id": "617",
"name": "BAR"
}
]
Remove the #XmlRootElement annotation, this is telling Jackson to wrap the list in the system property and isn't required.
I'm trying to update an object via REST services using Spring MVC + Swagger Annotations.
The method is something like this:
#ApiOperation(value = "Modifies the entity")
#RequestMapping(value = "/entity", method = RequestMethod.PUT, headers = "Accept=application/json")
#APIMonitor
#ResponseBody
public PubTagger saveEntityDetails(
HttpServletResponse response,
ModelMap model,
#RequestBody final EntityClass entityInfo
)
throws Exception {
...
}
The entity definition is:
{
"id": "long",
"description": "string",
"name": "string",
"properties": [
{
"name": "string",
"value": "string"
}
]
}
It gives me an error
The request sent by the client was syntactically incorrect ()
But it only happens when I fill the objects inside the Properties field. If I leave it empty it succeeds. So I deduce there's something wrong in Spring MVC with nested objects inside lists.
Is there anything I'm missing here? Do I have to specify anything in the model to make it work?
Edit: Posting Entity class
public class Entity {
private Long id;
private String name;
private String description;
private List<Property> properties = new ArrayList<>();
public void setId(final Long id) {
this.id = id;
}
public Entity() {
super();
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
public List<Property> getProperties() {
return properties;
}
public void setProperties(List<Property> properties) {
this.properties = properties;
}
}
Thanks, I found the error.
It was the class Property that only had the Parametrized constructor, without default constructor which made unable to marshall the JSON requestBody into an object.