How to skip field in every object of list while mapping - 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.

Related

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.

Unable to save embedded objects in mongodb using gorm(typeMismatch error)

I am trying to create and save a domain object using gorm and mongodb plugin, but I always get type mismatch error on the embedded property("emailTemplates").
My domain is defined as :
import org.apache.commons.mail.Email
import org.bson.types.ObjectId
class EmailTemplate {
ObjectId id
String subject
String message
String locale
String from
List<String> to
List<String> cc
List<String> bcc
static mapWith = "mongo"
static constraints = {
subject(blank: false, maxSize: 78)
message(blank: false)
locale(blank: false)
}
static mapping = {
locale defaultValue: "en_US"
}
}
class Template {
ObjectId id
String namespace
String name
String description
String defaultLocale
Boolean enabled
List emailTemplates
static mapWith = "mongo"
static hasMany = [emailTemplates: EmailTemplate]
static embedded = ["emailTemplates"]
static constraints = {
name(unique: ['namespace'], blank: false, maxSize: 250)
description(blank: true)
enabled(blank: false)
namespace(blank: false)
defaultLocale(blank: false)
}
static mapping = {
id attr: "_id"
defaultLocale defaultValue: "en_US"
enabled defaultValue: true
}
}
And my POST payload json is:
{
"namespace": "some namespave",
"emailTemplates": [
{
"locale": "en_US",
"from": "xyz#gmail.com",
"message": "test",
"subject": "test"
}
],
"name": "a name",
"defaultLocale": "en_US",
"enabled": true,
"description": "test"
}
Right now I do have a workaround where I override the "save" method on the controller(which extends RestfulController) and manually instantiate the domain objects, but I would rather have the default "RestfulController" to work.
I am using mongodb plugin version 6.1.0, mongodb-driver:3.4.2 and my grails version is 3.2.8

Json.Net custom serialization

[
{
"articles": [
[
"2016-03-04",
6
],
[
"2016-03-05",
10
],
[
"2016-03-06",
11
]
],
"accession": "00000446-201301000-00018"
},
{
"articles": [
[
"2016-03-04",
1
],
[
"2016-03-08",
17
],
[
"2016-03-09",
10
]
],
"accession": "00000446-201301000-00019"
}]
List is input { "Accession"= "00000446-201301000-00018", "Date"= "635926464000000000","Rank" =2},{ "Accession" = "00000446-201301000-00019", "Date" = "635931648000000000","Rank" = 2}
I want json data exactly like this,data is coming from list and list is dynamically growing.Form list, I want all dates and rank club to gether for the same accession number.
I want to use newtonsoft json custom serlization to convert my list to json.
What you want to do does not need any Custom Formatter, you just have to re-structure your data, Here is an example for restructuring a list based on Entity class to the new required one.
class Entity
{
public string Accession { get; set; }
public string Date { get; set; }
public int Rank { get; set; }
}
Add this line if you need to read the list from Json
var list = JsonConvert.DeserializeObject<List<Entity>>(input);
Here is the code for changing the structure of data to array based articles.
var translatedAsArray = list.GroupBy(e => e.Accession)
.Select(g =>
new {
//change new 'object[]' to 'new' to make the article an object
//you can convert i.Date, i.Rank and g.Key to anything you want here
Articles = g.Select(i => new object[] { i.Date , i.Rank }),
Accessing = g.Key
}
);
var json = JsonConvert.SerializeObject(translatedAsArray, Formatting.Indented);
Model
public class FinalList
{
public string accession {get;set;}
public List<ArticlesDetails> Articles{get;set;}
}
public class ArticlesDetails
{
public DateTime Date{get;set;}
public int number{get;set;}
}
Use ObjectContent instead of StringContent so we let the formatter (i.e. JsonMediaTypeFormatter) to deal with the serialization and deserialization
In config
config.Formatters.Insert(0, new YourCustomFormatter());
config.Formatters.Insert(1, new JsonMediaTypeFormatter());
and disable post in your custom formatter so that JsonMediaTypeFormatter desrializes the complex data

Breeze# executeQuery returns empty objects

I have Breeze.Sharp application which communicates with legacy WebAPI which doesn't provide metadata.
Query seems to be executed properly - expected number of objects is returned but all of them are empty. Modifying query parameters also works - number of returned objects changes as expected. I was playing around with EntityManager.MetadataStore but nothing helped.
Here is the final code I'm currently using to communicate with WebAPI.
public class DokumentModelBreeze: BaseEntity
{
public string id { get; set; }
public string numer { get; set; }
public decimal suma { get; set; }
}
...
Configuration.Instance.ProbeAssemblies(typeof(DokumentModelBreeze).Assembly);
var manager = new EntityManager("http://localhost:52357/api/");
manager.DataService.HasServerMetadata = false;
var store = manager.MetadataStore;
store.SetResourceName("dokumenty", typeof(DokumentModelBreeze), true);
store.NamingConvention = new CamelCasePropertiesNamingConvention();
var builder = new EntityTypeBuilder<DokumentModelBreeze>(store);
builder.DataProperty(d => d.id).IsPartOfKey();
using(TextWriter writer = File.CreateText("C:/metadata.txt")) {
store.ExportMetadata(writer);
var query = new EntityQuery<DokumentModelBreeze>("dokumenty");
query = query.WithParameter("nrFirmy", 1).Where(p => p.numer=="123");
var results = await manager.ExecuteQuery<DokumentModelBreeze>(query);
List<DokumentModelBreeze> Dokumenty = new List<DokumentModelBreeze>();
foreach(var item in results)
Dokumenty.Add(item);
In the last foreach loop every item is of type DokumentModelBreeze but each member property equals to null or 0 respectively.
I have saved MetadataStore to file, it is included below:
{
"metadataVersion": "1.0.3",
"namingConvention": {
"clientServerNamespaceMap": {},
"name": "camelCaseProperties"
},
"structuralTypes": [
{
"shortName": "BaseEntity",
"namespace": "Breeze.Sharp",
"baseTypeName": "",
"autoGeneratedKeyType": "None"
},
{
"shortName": "DokumentModelBreeze",
"namespace": "BRuNETWPF.ViewModels",
"baseTypeName": "BaseEntity:#Breeze.Sharp",
"autoGeneratedKeyType": "None",
"defaultResourceName": "dokumenty",
"dataProperties": [
{
"name": "id",
"dataType": "String",
"isNullable": false,
"defaultValue": "",
"isPartOfKey": true
},
{
"name": "numer",
"dataType": "String",
"isNullable": false,
"defaultValue": ""
},
{
"name": "suma",
"dataType": "Decimal",
"isNullable": false,
"defaultValue": 0.0
}
]
}
],
"resourceEntityTypeMap": {
"dokumenty": "DokumentModelBreeze:#BRuNETWPF.ViewModels"
}
}
Am I missing something here or perhaps Breeze# doesn't allow to query WebAPI without metadata ?
The same code executed against test WebAPI with exposed metadata works well.
Your GetValue and SetValue properties must be defined like so:
public string id
{
get { return GetValue<string>("id"); }
set { SetValue(value); }
}
It's a pain, I know, but this fixed it for me after one of our awesome tech leads pointed it out :)

Custom Web API Formatting

I've been playing around with asp.net web api, and I noticed that default generated returned json doesn't include the object level key. I was also wondering how to customize the output of the json string. For example:
Getting a User usually returns
{
"Name": "ChaoticLoki",
"Age": 22,
"Sex": "Male"
}
I was hoping I could return something like:
{
"data": {
"Name": "ChaoticLoki",
"Age": 22,
"Sex": "Male",
},
"success": true
}
You can then create a class wrapping the data and status like this
public class JsonResult{
public object data { get; set;}
public boolean success { get; set;}
}
And then in your Web Api methods, you can do
var data = ... //getting from repo
return Json(new JsonResult{data = data, success = true});

Resources